//===----------------------------------------------------------------------===//
// XCOFF
//===----------------------------------------------------------------------===//
+MCSymbol *
+TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,
+ const TargetMachine &TM) const {
+ if (TM.getDataSections())
+ report_fatal_error("XCOFF unique data sections not yet implemented");
+
+ // We always use a qualname symbol for a GV that represents
+ // a declaration, a function descriptor, or a common symbol.
+ // It is inherently ambiguous when the GO represents the address of a
+ // function, as the GO could either represent a function descriptor or a
+ // function entry point. We choose to always return a function descriptor
+ // here.
+ if (const GlobalObject *GO = dyn_cast<GlobalObject>(GV)) {
+ if (GO->isDeclaration())
+ return cast<MCSectionXCOFF>(getSectionForExternalReference(GO, TM))
+ ->getQualNameSymbol();
+
+ SectionKind GOKind = getKindForGlobal(GO, TM);
+ if (GOKind.isText())
+ return cast<MCSectionXCOFF>(
+ getSectionForFunctionDescriptor(cast<Function>(GO), TM))
+ ->getQualNameSymbol();
+ if (GOKind.isCommon() || GOKind.isBSSLocal())
+ return cast<MCSectionXCOFF>(SectionForGlobal(GO, GOKind, TM))
+ ->getQualNameSymbol();
+ }
+
+ // For all other cases, fall back to getSymbol to return the unqualified name.
+ // This could change for a GV that is a GlobalVariable when we decide to
+ // support -fdata-sections since we could avoid having label symbols if the
+ // linkage name is applied to the csect symbol.
+ return nullptr;
+}
+
MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
report_fatal_error("XCOFF explicit sections not yet implemented.");
const PPCSubtarget *Subtarget = nullptr;
StackMaps SM;
- virtual MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO);
-
public:
explicit PPCAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
class PPCAIXAsmPrinter : public PPCAsmPrinter {
private:
static void ValidateGV(const GlobalVariable *GV);
-protected:
- MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO) override;
public:
PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
void SetupMachineFunction(MachineFunction &MF) override;
- const MCExpr *lowerConstant(const Constant *CV) override;
-
void emitGlobalVariable(const GlobalVariable *GV) override;
void emitFunctionDescriptor() override;
/// Map a machine operand for a TOC pseudo-machine instruction to its
/// corresponding MCSymbol.
-MCSymbol *PPCAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) {
+static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
+ AsmPrinter &AP) {
switch (MO.getType()) {
case MachineOperand::MO_GlobalAddress:
- return getSymbol(MO.getGlobal());
+ return AP.getSymbol(MO.getGlobal());
case MachineOperand::MO_ConstantPoolIndex:
- return GetCPISymbol(MO.getIndex());
+ return AP.GetCPISymbol(MO.getIndex());
case MachineOperand::MO_JumpTableIndex:
- return GetJTISymbol(MO.getIndex());
+ return AP.GetJTISymbol(MO.getIndex());
case MachineOperand::MO_BlockAddress:
- return GetBlockAddressSymbol(MO.getBlockAddress());
+ return AP.GetBlockAddressSymbol(MO.getBlockAddress());
default:
llvm_unreachable("Unexpected operand type to get symbol.");
}
"Invalid operand for LWZtoc.");
// Map the operand to its corresponding MCSymbol.
- const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO);
+ const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
// Create a reference to the GOT entry for the symbol. The GOT entry will be
// synthesized later.
// global address operand to be a reference to the TOC entry we will
// synthesize later.
MCSymbol *TOCEntry =
- lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO));
+ lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));
const MCSymbolRefExpr::VariantKind VK =
IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
"Invalid operand for ADDIStocHA.");
// Map the machine operand to its corresponding MCSymbol.
- MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
+ MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
// Always use TOC on AIX. Map the global address operand to be a reference
// to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
"Invalid operand for LWZtocL.");
// Map the machine operand to its corresponding MCSymbol.
- MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
+ MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
// Always use TOC on AIX. Map the global address operand to be a reference
// to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
"Invalid operand for ADDIStocHA8!");
- const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
+ const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
const bool GlobalToc =
MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
"LDtocL used on symbol that could be accessed directly is "
"invalid. Must match ADDIStocHA8."));
- const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
+ const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
"Interposable definitions must use indirect access."));
const MCExpr *Exp =
- MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO),
+ MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO, *this),
MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext);
TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
report_fatal_error("COMDAT not yet supported by AIX.");
}
-const MCExpr *PPCAIXAsmPrinter::lowerConstant(const Constant *CV) {
- if (const Function *F = dyn_cast<Function>(CV)) {
- MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
- F->isDeclaration()
- ? getObjFileLowering().getSectionForExternalReference(F, TM)
- : getObjFileLowering().getSectionForFunctionDescriptor(F, TM));
-
- return MCSymbolRefExpr::create(Csect->getQualNameSymbol(), OutContext);
- }
- return PPCAsmPrinter::lowerConstant(CV);
-}
-
static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) {
return StringSwitch<bool>(GV->getName())
.Cases("llvm.global_ctors", "llvm.global_dtors", true)
GVSym->setStorageClass(
TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
- SectionKind GVKind;
-
- // Create the containing csect and set it. We set it for externals as well,
- // since this may not have been set elsewhere depending on how they are used.
- MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
- GV->isDeclaration()
- ? getObjFileLowering().getSectionForExternalReference(GV, TM)
- : getObjFileLowering().SectionForGlobal(
- GV, GVKind = getObjFileLowering().getKindForGlobal(GV, TM),
- TM));
-
// External global variables are already handled.
if (GV->isDeclaration())
return;
+ SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly())
report_fatal_error("Encountered a global variable kind that is "
"not supported yet.");
+ MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
+ getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
+
// Switch to the containing csect.
OutStreamer->SwitchSection(Csect);
if (GVKind.isBSSLocal())
OutStreamer->emitXCOFFLocalCommonSymbol(
- GVSym, Size, Csect->getQualNameSymbol(), Align);
+ OutContext.getOrCreateSymbol(GVSym->getUnqualifiedName()), Size,
+ GVSym, Align);
else
- OutStreamer->emitCommonSymbol(Csect->getQualNameSymbol(), Size, Align);
+ OutStreamer->emitCommonSymbol(GVSym, Size, Align);
return;
}
}
}
-MCSymbol *
-PPCAIXAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) {
- const GlobalObject *GO = nullptr;
-
- // If the MO is a function or certain kind of globals, we want to make sure to
- // refer to the csect symbol, otherwise we can just do the default handling.
- if (MO.getType() != MachineOperand::MO_GlobalAddress ||
- !(GO = dyn_cast<const GlobalObject>(MO.getGlobal())))
- return PPCAsmPrinter::getMCSymbolForTOCPseudoMO(MO);
-
- // Do an early error check for globals we don't support. This will go away
- // eventually.
- const auto *GV = dyn_cast<const GlobalVariable>(GO);
- if (GV) {
- ValidateGV(GV);
- }
-
- // If the global object is a global variable without initializer or is a
- // declaration of a function, then XSym is an external referenced symbol.
- // Hence we may need to explictly create a MCSectionXCOFF for it so that we
- // can return its symbol later.
- if (GO->isDeclaration()) {
- return cast<MCSectionXCOFF>(
- getObjFileLowering().getSectionForExternalReference(GO, TM))
- ->getQualNameSymbol();
- }
-
- // Handle initialized global variables and defined functions.
- SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
-
- if (GOKind.isText()) {
- // If the MO is a function, we want to make sure to refer to the function
- // descriptor csect.
- return cast<MCSectionXCOFF>(
- getObjFileLowering().getSectionForFunctionDescriptor(
- cast<const Function>(GO), TM))
- ->getQualNameSymbol();
- } else if (GOKind.isCommon() || GOKind.isBSSLocal()) {
- // If the operand is a common then we should refer to the csect symbol.
- return cast<MCSectionXCOFF>(
- getObjFileLowering().SectionForGlobal(GO, GOKind, TM))
- ->getQualNameSymbol();
- }
-
- // Other global variables are refered to by labels inside of a single csect,
- // so refer to the label directly.
- return getSymbol(GV);
-}
-
/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
/// for a MachineFunction to the given output stream, in a format that the
/// Darwin assembler can deal with.
--- /dev/null
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck --check-prefixes=CHECK,ASM32 %s
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck --check-prefixes=CHECK,ASM64 %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
+; RUN: llvm-readobj -r --expand-relocs -t %t.o | FileCheck --check-prefixes=RELOC,SYM %s
+
+; RUN: not --crash llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \
+; RUN: FileCheck --check-prefix=XCOFF64 %s
+; XCOFF64: LLVM ERROR: 64-bit XCOFF object files are not supported yet.
+
+@common = common global i32 0, align 4
+@pointer = global i32* @common, align 4
+
+
+; CHECK: .comm common[RW],4,2
+; CHECK-NEXT: .csect .data[RW]
+; CHECK-NEXT: .globl pointer
+; ASM32-NEXT: .align 2
+; ASM64-NEXT: .align 3
+; CHECK-NEXT:pointer:
+; ASM32-NEXT: .long common[RW]
+; ASM64-NEXT: .llong common[RW]
+
+
+; RELOC: Relocations [
+; RELOC-NEXT: Section (index: {{[0-9]+}}) .data {
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x0
+; RELOC-NEXT: Symbol: common ([[#COM_INDX:]])
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 32
+; RELOC-NEXT: Type: R_POS (0x0)
+; RELOC-NEXT: }
+; RELOC-NEXT: }
+; RELOC-NEXT: ]
+
+; SYM: Symbol {{[{][[:space:]] *}}Index: [[#INDX:]]{{[[:space:]] *}}Name: .data
+; SYM-NEXT: Value (RelocatableAddress): 0x0
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: [[#INDX+1]]
+; SYM-NEXT: SectionLen: 4
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 2
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: [[#INDX+2]]
+; SYM-NEXT: Name: pointer
+; SYM-NEXT: Value (RelocatableAddress): 0x0
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: [[#INDX+3]]
+; SYM-NEXT: ContainingCsectSymbolIndex: [[#INDX]]
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: [[#COM_INDX]]
+; SYM-NEXT: Name: common
+; SYM-NEXT: Value (RelocatableAddress): 0x4
+; SYM-NEXT: Section: .bss
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: [[#COM_INDX+1]]
+; SYM-NEXT: SectionLen: 4
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 2
+; SYM-NEXT: SymbolType: XTY_CM (0x3)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }