From 09fb75f1390bc79ecac03c6a16225df3b2367b8a Mon Sep 17 00:00:00 2001 From: David Tenty Date: Thu, 8 Aug 2019 15:40:35 +0000 Subject: [PATCH] Enable assembly output of local commons for AIX Summary: This patch enable assembly output of local commons for AIX using .lcomm directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the AIX version of .lcomm assembly directives which include a csect name. Handle the case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds a test for generating .lcomm on AIX Targets. Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile Reviewed By: sfertile Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64825 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368306 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCStreamer.h | 9 +++++++++ include/llvm/MC/MCXCOFFStreamer.h | 2 ++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 7 ++++--- lib/MC/MCAsmInfoXCOFF.cpp | 1 + lib/MC/MCAsmStreamer.cpp | 20 ++++++++++++++++++++ lib/MC/MCSectionXCOFF.cpp | 8 +++++--- lib/MC/MCStreamer.cpp | 4 ++++ lib/MC/MCXCOFFStreamer.cpp | 5 +++++ lib/Target/PowerPC/PPCAsmPrinter.cpp | 8 ++++++-- test/CodeGen/PowerPC/aix-xcoff-lcomm.ll | 10 ++++++++++ 10 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 test/CodeGen/PowerPC/aix-xcoff-lcomm.ll diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index b8943aeb38c..cd3795a55a3 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -537,6 +537,15 @@ public: /// \param Symbol - Symbol the image relative relocation should point to. virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset); + /// Emits an lcomm directive with XCOFF csect information. + /// + /// \param Symbol - The symbol we are emiting. + /// \param Size - The size of the block of storage. + /// \param ByteAlignment - The alignment of the symbol in bytes. Must be a power + /// of 2. + virtual void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + /// Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: diff --git a/include/llvm/MC/MCXCOFFStreamer.h b/include/llvm/MC/MCXCOFFStreamer.h index 159ae481874..b13b0031d18 100644 --- a/include/llvm/MC/MCXCOFFStreamer.h +++ b/include/llvm/MC/MCXCOFFStreamer.h @@ -26,6 +26,8 @@ public: uint64_t Size = 0, unsigned ByteAlignment = 0, SMLoc Loc = SMLoc()) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; + void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign) override; }; } // end namespace llvm diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index ac7c4c50ae4..7eb4901016a 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1836,11 +1836,12 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal( // Common symbols go into a csect with matching name which will get mapped // into the .bss section. - if (Kind.isCommon()) { + if (Kind.isBSSLocal() || Kind.isCommon()) { SmallString<128> Name; getNameWithPrefix(Name, GO, TM); - return getContext().getXCOFFSection(Name, XCOFF::XMC_RW, XCOFF::XTY_CM, - Kind, /* BeginSymbolName */ nullptr); + return getContext().getXCOFFSection( + Name, Kind.isBSSLocal() ? XCOFF::XMC_BS : XCOFF::XMC_RW, XCOFF::XTY_CM, + Kind, /* BeginSymbolName */ nullptr); } if (Kind.isText()) diff --git a/lib/MC/MCAsmInfoXCOFF.cpp b/lib/MC/MCAsmInfoXCOFF.cpp index 6a9bef6adff..92dc505c0a1 100644 --- a/lib/MC/MCAsmInfoXCOFF.cpp +++ b/lib/MC/MCAsmInfoXCOFF.cpp @@ -16,4 +16,5 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() { IsLittleEndian = false; HasDotTypeDotSizeDirective = false; COMMDirectiveAlignmentIsInBytes = false; + LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment; } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index c0890b59fe3..967ee8b3c5f 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -162,6 +162,8 @@ public: void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; + void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign) override; void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; @@ -757,6 +759,24 @@ void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) { EmitEOL(); } +// We need an XCOFF specific version of this directive as the AIX syntax +// requires a QualName argument identifying the csect name and storage mapping +// class to appear before the alignment if we are specifying it. +void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment && + "We only support writing log base-2 alignment format with XCOFF"); + assert(isPowerOf2_32(ByteAlignment) && "alignment must be a power of 2"); + + OS << "\t.lcomm\t"; + Symbol->print(OS, MAI); + OS << ',' << Size; + OS << ',' << Symbol->getName(); + OS << ',' << Log2_32(ByteAlignment); + + EmitEOL(); +} + void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { assert(MAI->hasDotTypeDotSizeDirective()); OS << "\t.size\t"; diff --git a/lib/MC/MCSectionXCOFF.cpp b/lib/MC/MCSectionXCOFF.cpp index 9cee1cc11e4..a3f79c35e84 100644 --- a/lib/MC/MCSectionXCOFF.cpp +++ b/lib/MC/MCSectionXCOFF.cpp @@ -28,9 +28,11 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, return; } - if (getKind().isCommon()) { - if (getMappingClass() != XCOFF::XMC_RW) - llvm_unreachable("Unsupported storage-mapping class for common csect"); + if (getKind().isBSSLocal() || getKind().isCommon()) { + if (getMappingClass() != XCOFF::XMC_RW && + getMappingClass() != XCOFF::XMC_BS) + llvm_unreachable("Generated a storage-mapping class for a common/bss " + "csect we don't understand how to switch to."); if (getCSectType() != XCOFF::XTY_CM) llvm_unreachable("wrong csect type for .bss csect"); // Don't have to print a directive for switching to section for commons. diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 254eb2cd7b6..2e36fe77b59 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -1055,6 +1055,10 @@ void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { void MCStreamer::EmitCOFFSymbolType(int Type) { llvm_unreachable("this directive only supported on COFF targets"); } +void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign) { + llvm_unreachable("this directive only supported on XCOFF targets"); +} void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} void MCStreamer::emitELFSymverDirective(StringRef AliasName, const MCSymbol *Aliasee) {} diff --git a/lib/MC/MCXCOFFStreamer.cpp b/lib/MC/MCXCOFFStreamer.cpp index 071de024a3f..7d526cc3c04 100644 --- a/lib/MC/MCXCOFFStreamer.cpp +++ b/lib/MC/MCXCOFFStreamer.cpp @@ -57,3 +57,8 @@ MCStreamer *llvm::createXCOFFStreamer(MCContext &Context, S->getAssembler().setRelaxAll(true); return S; } + +void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign) { + llvm_unreachable("Not implemented yet."); +} \ No newline at end of file diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 890a0dd3521..8081b4bda2b 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1659,7 +1659,7 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { report_fatal_error("COMDAT not yet supported by AIX."); SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM); - if (!GVKind.isCommon()) + if (!GVKind.isCommon() && !GVKind.isBSSLocal()) report_fatal_error("Only common variables are supported on AIX for now."); // Create the containing csect and switch to it. @@ -1673,7 +1673,11 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { unsigned Align = GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV); uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); - OutStreamer->EmitCommonSymbol(XSym, Size, Align); + + if (GVKind.isBSSLocal()) + OutStreamer->EmitXCOFFLocalCommonSymbol(XSym, Size, Align); + else + OutStreamer->EmitCommonSymbol(XSym, Size, Align); } /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code diff --git a/test/CodeGen/PowerPC/aix-xcoff-lcomm.ll b/test/CodeGen/PowerPC/aix-xcoff-lcomm.ll new file mode 100644 index 00000000000..02f7d515b5a --- /dev/null +++ b/test/CodeGen/PowerPC/aix-xcoff-lcomm.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s + +@a = internal global i32 0, align 4 +@b = internal global i64 0, align 8 +@c = internal global i16 0, align 2 + +; CHECK: .lcomm a,4,a,2 +; CHECK-NEXT: .lcomm b,8,b,3 +; CHECK-NEXT: .lcomm c,2,c,1 -- 2.40.0