Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -263,6 +263,10 @@ MCSection * getSectionForExternalReference(const GlobalObject *GO, const TargetMachine &TM) const override; + + /// For functions, this will always return a function descriptor symbol. + MCSymbol *getTargetSymbol(const GlobalValue *GV, + const TargetMachine &TM) const override; }; } // end namespace llvm Index: llvm/include/llvm/Target/TargetLoweringObjectFile.h =================================================================== --- llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -242,6 +242,13 @@ return nullptr; } + /// Targets that have a special convention for their symbols could use + /// this hook to return a specialized symbol. + virtual MCSymbol *getTargetSymbol(const GlobalValue *GV, + const TargetMachine &TM) const { + return nullptr; + } + protected: virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1879,6 +1879,40 @@ //===----------------------------------------------------------------------===// // 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(GV)) { + if (GO->isDeclaration()) + return cast(getSectionForExternalReference(GO, TM)) + ->getQualNameSymbol(); + + SectionKind GOKind = getKindForGlobal(GO, TM); + if (GOKind.isText()) + return cast( + getSectionForFunctionDescriptor(cast(GO), TM)) + ->getQualNameSymbol(); + if (GOKind.isCommon() || GOKind.isBSSLocal()) + return cast(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."); Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -83,8 +83,6 @@ const PPCSubtarget *Subtarget = nullptr; StackMaps SM; - virtual MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO); - public: explicit PPCAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) @@ -150,8 +148,6 @@ 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 Streamer) @@ -161,8 +157,6 @@ void SetupMachineFunction(MachineFunction &MF) override; - const MCExpr *lowerConstant(const Constant *CV) override; - void emitGlobalVariable(const GlobalVariable *GV) override; void emitFunctionDescriptor() override; @@ -494,16 +488,17 @@ /// 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."); } @@ -664,7 +659,7 @@ "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. @@ -723,7 +718,7 @@ // 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; @@ -749,7 +744,7 @@ "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 @@ -779,7 +774,7 @@ "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 @@ -807,7 +802,7 @@ 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()); @@ -851,7 +846,7 @@ "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); @@ -881,7 +876,7 @@ "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); @@ -1563,18 +1558,6 @@ report_fatal_error("COMDAT not yet supported by AIX."); } -const MCExpr *PPCAIXAsmPrinter::lowerConstant(const Constant *CV) { - if (const Function *F = dyn_cast(CV)) { - MCSectionXCOFF *Csect = cast( - 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(GV->getName()) .Cases("llvm.global_ctors", "llvm.global_dtors", true) @@ -1596,25 +1579,18 @@ 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( - 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( + getObjFileLowering().SectionForGlobal(GV, GVKind, TM)); + // Switch to the containing csect. OutStreamer->SwitchSection(Csect); @@ -1628,9 +1604,10 @@ 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; } @@ -1697,55 +1674,6 @@ } } -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(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(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( - 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( - getObjFileLowering().getSectionForFunctionDescriptor( - cast(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( - 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. Index: llvm/lib/Target/TargetMachine.cpp =================================================================== --- llvm/lib/Target/TargetMachine.cpp +++ llvm/lib/Target/TargetMachine.cpp @@ -258,6 +258,10 @@ MCSymbol *TargetMachine::getSymbol(const GlobalValue *GV) const { const TargetLoweringObjectFile *TLOF = getObjFileLowering(); + // XCOFF symbols could have special naming convention. + if (MCSymbol *TargetSymbol = TLOF->getTargetSymbol(GV, *this)) + return TargetSymbol; + SmallString<128> NameStr; getNameWithPrefix(NameStr, GV, TLOF->getMangler()); return TLOF->getContext().getOrCreateSymbol(NameStr); Index: llvm/test/CodeGen/PowerPC/aix-xcoff-lower-comm.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/aix-xcoff-lower-comm.ll @@ -0,0 +1,95 @@ +; 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: }