diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h --- a/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -139,6 +139,14 @@ C_TCSYM = 134 // Reserved }; +enum SymbolType { + XTY_ER = 0, ///< External reference. + XTY_SD = 1, ///< Csect definition for initialized storage. + XTY_LD = 2, ///< Label definition. + ///< Defines an entry point to an initialized csect. + XTY_CM = 3 ///< Common csect definition. For uninitialized storage. +}; + } // end namespace XCOFF } // end namespace llvm 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 @@ -206,6 +206,32 @@ const TargetMachine &TM) const override; }; +class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile { +public: + TargetLoweringObjectFileXCOFF() = default; + ~TargetLoweringObjectFileXCOFF() override = default; + + MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + + MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; + + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; + + MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + + const MCExpr *lowerRelativeReference(const GlobalValue *LHS, + const GlobalValue *RHS, + const TargetMachine &TM) const override; +}; + } // end namespace llvm #endif // LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -490,7 +490,7 @@ MCSectionXCOFF *getXCOFFSection(StringRef Section, XCOFF::StorageMappingClass MappingClass, - SectionKind K, + XCOFF::SymbolType CSectType, SectionKind K, const char *BeginSymName = nullptr); // Create and save a copy of STI and return a reference to the copy. diff --git a/llvm/include/llvm/MC/MCSectionXCOFF.h b/llvm/include/llvm/MC/MCSectionXCOFF.h --- a/llvm/include/llvm/MC/MCSectionXCOFF.h +++ b/llvm/include/llvm/MC/MCSectionXCOFF.h @@ -23,16 +23,25 @@ // This class represents an XCOFF `Control Section`, more commonly referred to // as a csect. A csect represents the smallest possible unit of data/code which -// will be relocated as a single block. +// will be relocated as a single block. A csect can either be: +// 1) Initialized: The Type will be XTY_SD, and the symbols inside the csect +// will have a label definition representing their offset within the csect. +// 2) Uninitialized: The Type will be XTY_CM, it will contain a single symbol, +// and may not contain label definitions. class MCSectionXCOFF final : public MCSection { friend class MCContext; StringRef Name; XCOFF::StorageMappingClass MappingClass; + XCOFF::SymbolType Type; MCSectionXCOFF(StringRef Section, XCOFF::StorageMappingClass SMC, - SectionKind K, MCSymbol *Begin) - : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC) {} + XCOFF::SymbolType ST, SectionKind K, MCSymbol *Begin) + : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC), + Type(ST) { + assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM) && + "Unexpected type for csect."); + } public: ~MCSectionXCOFF(); @@ -43,6 +52,7 @@ StringRef getSectionName() const { return Name; } XCOFF::StorageMappingClass getMappingClass() const { return MappingClass; } + XCOFF::SymbolType getCSectType() const { return Type; } void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, raw_ostream &OS, 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 @@ -43,6 +43,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" @@ -1809,3 +1810,57 @@ llvm_unreachable("@llvm.global_dtors should have been lowered already"); return nullptr; } + +//===----------------------------------------------------------------------===// +// XCOFF +//===----------------------------------------------------------------------===// +MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal( + const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { + llvm_unreachable("XCOFF explicit sections not yet implemented."); +} + +MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal( + const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { + assert(!TM.getFunctionSections() && !TM.getDataSections() && + "XCOFF unique sections not yet implemented."); + + // Common symbols go into a csect with matching name which will get mapped + // into the .bss section. + if (Kind.isCommon()) { + SmallString<128> Name; + getNameWithPrefix(Name, GO, TM); + return getContext().getXCOFFSection(Name, XCOFF::XMC_RW, XCOFF::XTY_CM, + Kind, /* BeginSymbolName */ nullptr); + } + + report_fatal_error("XCOFF other section types not yet implemented."); +} + +bool TargetLoweringObjectFileXCOFF::shouldPutJumpTableInFunctionSection( + bool UsesLabelDifference, const Function &F) const { + llvm_unreachable("TLOF XCOFF not yet implemented."); +} + +void TargetLoweringObjectFileXCOFF::Initialize(MCContext &Ctx, + const TargetMachine &TgtM) { + TargetLoweringObjectFile::Initialize(Ctx, TgtM); + TTypeEncoding = 0; + PersonalityEncoding = 0; + LSDAEncoding = 0; +} + +MCSection *TargetLoweringObjectFileXCOFF::getStaticCtorSection( + unsigned Priority, const MCSymbol *KeySym) const { + llvm_unreachable("XCOFF ctor section not yet implemented."); +} + +MCSection *TargetLoweringObjectFileXCOFF::getStaticDtorSection( + unsigned Priority, const MCSymbol *KeySym) const { + llvm_unreachable("XCOFF dtor section not yet implemented."); +} + +const MCExpr *TargetLoweringObjectFileXCOFF::lowerRelativeReference( + const GlobalValue *LHS, const GlobalValue *RHS, + const TargetMachine &TM) const { + llvm_unreachable("XCOFF not yet implemented."); +} diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp --- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp @@ -15,4 +15,5 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() { IsLittleEndian = false; HasDotTypeDotSizeDirective = false; + COMMDirectiveAlignmentIsInBytes = false; } diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -531,6 +531,7 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section, XCOFF::StorageMappingClass SMC, + XCOFF::SymbolType Type, SectionKind Kind, const char *BeginSymName) { // Do the lookup. If we have a hit, return it. @@ -548,7 +549,7 @@ Begin = createTempSymbol(BeginSymName, false); MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) - MCSectionXCOFF(CachedName, SMC, Kind, Begin); + MCSectionXCOFF(CachedName, SMC, Type, Kind, Begin); Entry.second = Result; auto *F = new MCDataFragment(); 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 @@ -767,8 +767,9 @@ // get placed into this csect. The choice of csect name is not a property of // the ABI or object file format. For example, the XL compiler uses an unnamed // csect for program code. - TextSection = Ctx->getXCOFFSection( - ".text", XCOFF::StorageMappingClass::XMC_PR, SectionKind::getText()); + TextSection = + Ctx->getXCOFFSection(".text", XCOFF::StorageMappingClass::XMC_PR, + XCOFF::XTY_SD, SectionKind::getText()); } void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -19,15 +19,29 @@ raw_ostream &OS, const MCExpr *Subsection) const { if (getKind().isText()) { + if (getMappingClass() != XCOFF::XMC_PR) + llvm_unreachable("Unsupported storage-mapping class for .text csect"); + OS << "\t.csect " << getSectionName() << "[" << "PR" << "]" << '\n'; return; } + if (getKind().isCommon()) { + if (getMappingClass() != XCOFF::XMC_RW) + llvm_unreachable("Unsupported storage-mapping class for common csect"); + if (getCSectType() != XCOFF::XTY_CM) + llvm_unreachable("wrong csect type for common csect"); + // Don't have to print a directive for switching to section for commons. + // '.comm' and '.lcomm' directives for the variable will create the needed + // csect. + return; + } + report_fatal_error("Printing for this SectionKind is unimplemented."); } bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); } -bool MCSectionXCOFF::isVirtualSection() const { return !getKind().isCommon(); } +bool MCSectionXCOFF::isVirtualSection() const { return XCOFF::XTY_CM == Type; } 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 @@ -51,9 +51,11 @@ #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" @@ -164,6 +166,8 @@ : PPCAsmPrinter(TM, std::move(Streamer)) {} StringRef getPassName() const override { return "AIX PPC Assembly Printer"; } + + void EmitGlobalVariable(const GlobalVariable *GV) override; }; } // end anonymous namespace @@ -1643,6 +1647,35 @@ return AsmPrinter::doFinalization(M); } +void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { + // Early error checking limiting what is supported. + if (GV->isThreadLocal()) + report_fatal_error("Thread local not yet supported on AIX."); + + if (GV->hasSection()) + report_fatal_error("Custom section for Data not yet supported."); + + if (GV->hasComdat()) + report_fatal_error("COMDAT not yet supported on AIX."); + + SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM); + if (!GVKind.isCommon()) + report_fatal_error("Only common variables are supported on AIX."); + + // Create the containing csect and switch to it. + MCSectionXCOFF *CSect = dyn_cast( + getObjFileLowering().SectionForGlobal(GV, GVKind, TM)); + OutStreamer->SwitchSection(CSect); + + // Create the symbol and emit it. + MCSymbolXCOFF *XSym = dyn_cast(getSymbol(GV)); + auto DL = GV->getParent()->getDataLayout(); + unsigned Align = + GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV); + uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); + OutStreamer->EmitCommonSymbol(XSym, Size, Align); +} + /// 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. diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -185,11 +185,12 @@ } static std::unique_ptr createTLOF(const Triple &TT) { - // If it isn't a Mach-O file then it's going to be a linux ELF - // object file. if (TT.isOSDarwin()) return llvm::make_unique(); + if (TT.isOSAIX()) + return llvm::make_unique(); + return llvm::make_unique(); } diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-common.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-common.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-common.ll @@ -0,0 +1,24 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s + +@a = common global i32 0, align 4 +@b = common global i64 0, align 8 +@c = common global i16 0, align 2 + +@d = common local_unnamed_addr global double 0.000000e+00, align 8 +@f = common local_unnamed_addr global float 0.000000e+00, align 4 +@comm = common local_unnamed_addr global double 0.000000e+00, align 8 + +@over_aligned = common local_unnamed_addr global double 0.000000e+00, align 32 + +@array = common local_unnamed_addr global [32 x i8] zeroinitializer, align 1 + +; CHECK: .csect .text[PR] +; CHECK-NEXT: .file +; CHECK-NEXT: .comm a,4,2 +; CHECK-NEXT: .comm b,8,3 +; CHECK-NEXT: .comm c,2,1 +; CHECK-NEXT: .comm d,8,3 +; CHECK-NEXT: .comm f,4,2 +; CHECK-NEXT: .comm comm,8,3 +; CHECK-NEXT: .comm over_aligned,8,5 +; CHECK-NEXT: .comm array,32,0