diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -243,6 +243,15 @@ unsigned &Align) const override; static XCOFF::StorageClass getStorageClassForGlobal(const GlobalObject *GO); + + MCSection *getSectionForFunctionDescriptor(const MCSymbol *) const override; + MCSection *getSectionForTOCEntry(const MCSymbol *Sym) const override; + + /// For external functions, this will always return a function descriptor + /// csect. + MCSection * + getSectionForExternalReference(const GlobalObject *GO, + const TargetMachine &TM) const override; }; } // end namespace llvm diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h --- a/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -216,6 +216,9 @@ MCSection *GFIDsSection = nullptr; MCSection *GLJMPSection = nullptr; + // XCOFF specific sections + MCSection *TOCBaseSection = nullptr; + public: void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx, bool LargeCodeModel = false); @@ -391,6 +394,9 @@ MCSection *getGFIDsSection() const { return GFIDsSection; } MCSection *getGLJMPSection() const { return GLJMPSection; } + // XCOFF specific sections + MCSection *getTOCBaseSection() const { return TOCBaseSection; } + MCSection *getEHFrameSection() { return EHFrameSection; } diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h --- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -212,6 +212,27 @@ return nullptr; } + /// On targets that use separate function descriptor symbols, return a section + /// for the descriptor given its symbol. Use only with defined functions. + virtual MCSection *getSectionForFunctionDescriptor(const MCSymbol *S) const { + return nullptr; + } + + /// On targets that support TOC entries, return a section for the entry given + /// the symbol it refers to. + /// TODO: Implement this interface for existing ELF targets. + virtual MCSection *getSectionForTOCEntry(const MCSymbol *S) const { + return nullptr; + } + + /// On targets that associate external references with a section, return such + /// a section for the given external global. + virtual MCSection * + getSectionForExternalReference(const GlobalObject *GO, + const TargetMachine &TM) const { + return nullptr; + } + protected: virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1832,6 +1832,22 @@ report_fatal_error("XCOFF explicit sections not yet implemented."); } +MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference( + const GlobalObject *GO, const TargetMachine &TM) const { + assert(GO->isDeclaration() && + "Tried to get ER section for a defined global."); + + SmallString<128> Name; + getNameWithPrefix(Name, GO, TM); + XCOFF::StorageClass SC = + TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); + + // Externals go into a csect of type ER. + return getContext().getXCOFFSection( + Name, isa(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA, XCOFF::XTY_ER, + SC, SectionKind::getMetadata()); +} + MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { assert(!TM.getFunctionSections() && !TM.getDataSections() && @@ -1951,3 +1967,17 @@ "Unhandled linkage when mapping linkage to StorageClass."); } } + +MCSection *TargetLoweringObjectFileXCOFF::getSectionForFunctionDescriptor( + const MCSymbol *FuncSym) const { + return getContext().getXCOFFSection(FuncSym->getName(), XCOFF::XMC_DS, + XCOFF::XTY_SD, XCOFF::C_HIDEXT, + SectionKind::getData()); +} + +MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry( + const MCSymbol *Sym) const { + return getContext().getXCOFFSection( + cast(Sym)->getUnqualifiedName(), XCOFF::XMC_TC, + XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getData()); +} diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -795,6 +795,13 @@ ReadOnlySection = Ctx->getXCOFFSection( ".rodata", XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getReadOnly()); + + TOCBaseSection = Ctx->getXCOFFSection( + "TOC", XCOFF::StorageMappingClass::XMC_TC0, XCOFF::XTY_SD, + XCOFF::C_HIDEXT, SectionKind::getData()); + + // The TOC-base always has 0 size, but 4 byte alignment. + TOCBaseSection->setAlignment(Align(4)); } void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1561,9 +1561,8 @@ // Get the function descriptor symbol. CurrentFnDescSym = getSymbol(&MF.getFunction()); // Set the containing csect. - MCSectionXCOFF *FnDescSec = OutStreamer->getContext().getXCOFFSection( - CurrentFnDescSym->getName(), XCOFF::XMC_DS, XCOFF::XTY_SD, - XCOFF::C_HIDEXT, SectionKind::getData()); + MCSectionXCOFF *FnDescSec = cast( + getObjFileLowering().getSectionForFunctionDescriptor(CurrentFnDescSym)); cast(CurrentFnDescSym)->setContainingCsect(FnDescSec); return AsmPrinter::SetupMachineFunction(MF); @@ -1585,14 +1584,10 @@ if (const Function *F = dyn_cast(CV)) { MCSymbolXCOFF *FSym = cast(getSymbol(F)); if (!FSym->hasContainingCsect()) { - const XCOFF::StorageClass SC = + MCSectionXCOFF *Csect = cast( F->isDeclaration() - ? TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(F) - : XCOFF::C_HIDEXT; - MCSectionXCOFF *Csect = OutStreamer->getContext().getXCOFFSection( - FSym->getName(), XCOFF::XMC_DS, - F->isDeclaration() ? XCOFF::XTY_ER : XCOFF::XTY_SD, SC, - SectionKind::getData()); + ? getObjFileLowering().getSectionForExternalReference(F, TM) + : getObjFileLowering().getSectionForFunctionDescriptor(FSym)); FSym->setContainingCsect(Csect); } return MCSymbolRefExpr::create( @@ -1604,26 +1599,34 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { ValidateGV(GV); - // External global variables are already handled. - if (!GV->hasInitializer()) - return; - // Create the symbol, set its storage class. MCSymbolXCOFF *GVSym = cast(getSymbol(GV)); GVSym->setStorageClass( TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV)); - SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM); + 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)); + GVSym->setContainingCsect(Csect); + + // External global variables are already handled. + if (GV->isDeclaration()) + return; + if ((!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly()) || GVKind.isMergeable2ByteCString() || GVKind.isMergeable4ByteCString()) report_fatal_error("Encountered a global variable kind that is " "not supported yet."); - // Create the containing csect and switch to it. - MCSectionXCOFF *Csect = cast( - getObjFileLowering().SectionForGlobal(GV, GVKind, TM)); + // Switch to the containing csect. OutStreamer->SwitchSection(Csect); - GVSym->setContainingCsect(Csect); const DataLayout &DL = GV->getParent()->getDataLayout(); @@ -1661,10 +1664,9 @@ OutStreamer->EmitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext), PointerSize); // Emit TOC base address. - const MCSectionXCOFF *TOCBaseSec = OutStreamer->getContext().getXCOFFSection( - StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT, - SectionKind::getData()); - const MCSymbol *TOCBaseSym = TOCBaseSec->getQualNameSymbol(); + const MCSymbol *TOCBaseSym = + cast(getObjFileLowering().getTOCBaseSection()) + ->getQualNameSymbol(); OutStreamer->EmitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext), PointerSize); // Emit a null environment pointer. @@ -1679,23 +1681,16 @@ if (M.empty()) return; - // Emit TOC base. - MCSectionXCOFF *TOCBaseSection = OutStreamer->getContext().getXCOFFSection( - StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT, - SectionKind::getData()); - // The TOC-base always has 0 size, but 4 byte alignment. - TOCBaseSection->setAlignment(Align(4)); // Switch to section to emit TOC base. - OutStreamer->SwitchSection(TOCBaseSection); + OutStreamer->SwitchSection(getObjFileLowering().getTOCBaseSection()); PPCTargetStreamer &TS = static_cast(*OutStreamer->getTargetStreamer()); for (auto &I : TOC) { // Setup the csect for the current TC entry. - MCSectionXCOFF *TCEntry = OutStreamer->getContext().getXCOFFSection( - cast(I.first)->getUnqualifiedName(), XCOFF::XMC_TC, - XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getData()); + MCSectionXCOFF *TCEntry = cast( + getObjFileLowering().getSectionForTOCEntry(I.first)); cast(I.second)->setContainingCsect(TCEntry); OutStreamer->SwitchSection(TCEntry); @@ -1728,19 +1723,9 @@ // Hence we may need to explictly create a MCSectionXCOFF for it so that we // can return its symbol later. if (GO->isDeclaration()) { - if (!XSym->hasContainingCsect()) { - // Make sure the storage class is set. - const XCOFF::StorageClass SC = - TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); - XSym->setStorageClass(SC); - - MCSectionXCOFF *Csect = OutStreamer->getContext().getXCOFFSection( - XSym->getName(), isa(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA, - XCOFF::XTY_ER, SC, SectionKind::getMetadata()); - XSym->setContainingCsect(Csect); - } - - return XSym->getContainingCsect()->getQualNameSymbol(); + return cast( + getObjFileLowering().getSectionForExternalReference(GO, TM)) + ->getQualNameSymbol(); } // Handle initialized global variables and defined functions. @@ -1749,9 +1734,8 @@ if (GOKind.isText()) { // If the MO is a function, we want to make sure to refer to the function // descriptor csect. - return OutStreamer->getContext() - .getXCOFFSection(XSym->getName(), XCOFF::XMC_DS, XCOFF::XTY_SD, - XCOFF::C_HIDEXT, SectionKind::getData()) + return cast( + getObjFileLowering().getSectionForFunctionDescriptor(XSym)) ->getQualNameSymbol(); } else if (GOKind.isCommon() || GOKind.isBSSLocal()) { // If the operand is a common then we should refer to the csect symbol.