Stubs out TLOF for AIX and add support for common vars in assembly output.
authorSean Fertile <sfertile@ca.ibm.com>
Mon, 22 Jul 2019 19:15:29 +0000 (19:15 +0000)
committerSean Fertile <sfertile@ca.ibm.com>
Mon, 22 Jul 2019 19:15:29 +0000 (19:15 +0000)
Stubs out a TargetLoweringObjectFileXCOFF class, implementing only
SelectSectionForGlobal for common symbols. Also adds an override of
EmitGlobalVariable in PPCAIXAsmPrinter which adds a number of defensive errors
and adds support for emitting common globals.

llvm-svn: 366727

12 files changed:
llvm/include/llvm/BinaryFormat/XCOFF.h
llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
llvm/include/llvm/MC/MCContext.h
llvm/include/llvm/MC/MCSectionXCOFF.h
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/lib/MC/MCAsmInfoXCOFF.cpp
llvm/lib/MC/MCContext.cpp
llvm/lib/MC/MCObjectFileInfo.cpp
llvm/lib/MC/MCSectionXCOFF.cpp
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
llvm/test/CodeGen/PowerPC/aix-xcoff-common.ll [new file with mode: 0644]

index 7774ab3..5008bd1 100644 (file)
@@ -139,6 +139,14 @@ enum StorageClass : uint8_t {
   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
 
index a1fb81c..8964d4c 100644 (file)
@@ -206,6 +206,32 @@ public:
                                        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
index 5c2124c..7e24292 100644 (file)
@@ -490,7 +490,7 @@ namespace llvm {
 
     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.
index 2a3f391..4b39fd6 100644 (file)
@@ -23,16 +23,25 @@ class MCSymbol;
 
 // 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 @@ public:
 
   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,
index 23cb1c1..ba2c78c 100644 (file)
@@ -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"
@@ -1819,3 +1820,57 @@ MCSection *TargetLoweringObjectFileWasm::getStaticDtorSection(
   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.");
+}
index 74c21f0..6a9bef6 100644 (file)
@@ -15,4 +15,5 @@ void MCAsmInfoXCOFF::anchor() {}
 MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
   IsLittleEndian = false;
   HasDotTypeDotSizeDirective = false;
+  COMMDirectiveAlignmentIsInBytes = false;
 }
index 0dc2e2d..ecd12fd 100644 (file)
@@ -531,6 +531,7 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
 
 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 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
     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();
index 9f555ab..6dc0e38 100644 (file)
@@ -767,8 +767,9 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
   // 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,
index d1a6373..740365f 100644 (file)
@@ -19,15 +19,29 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
                                           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; }
index bd87ce0..0646ddb 100644 (file)
 #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 @@ public:
       : 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 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
   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<MCSectionXCOFF>(
+      getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
+  OutStreamer->SwitchSection(CSect);
+
+  // Create the symbol and emit it.
+  MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(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.
index ce00f84..213e2f5 100644 (file)
@@ -185,11 +185,12 @@ static std::string computeFSAdditions(StringRef FS, CodeGenOpt::Level OL,
 }
 
 static std::unique_ptr<TargetLoweringObjectFile> 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<TargetLoweringObjectFileMachO>();
 
+  if (TT.isOSAIX())
+    return llvm::make_unique<TargetLoweringObjectFileXCOFF>();
+
   return llvm::make_unique<PPC64LinuxTargetObjectFile>();
 }
 
diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-common.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-common.ll
new file mode 100644 (file)
index 0000000..0774e9f
--- /dev/null
@@ -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