[llvm] 9874064 - [AIX] Emit TOC entries for ASM printing

David Tenty via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 27 14:21:01 PST 2019


Author: David Tenty
Date: 2019-11-27T17:20:55-05:00
New Revision: 98740643f794254342e22d106eafb73cf459f465

URL: https://github.com/llvm/llvm-project/commit/98740643f794254342e22d106eafb73cf459f465
DIFF: https://github.com/llvm/llvm-project/commit/98740643f794254342e22d106eafb73cf459f465.diff

LOG: [AIX] Emit TOC entries for ASM printing

Summary:
Emit the correct .toc psuedo op when we change to the TOC and emit
TC entries. Make sure TOC psuedos get the right symbols via overriding
getMCSymbolForTOCPseudoMO on AIX. Add a test for TOC assembly writing
and update tests to include TOC entries.

Also make sure external globals have a csect set and handle external function descriptor (originally authored by Jason Liu) so we can emit TOC entries for them.

Reviewers: DiggerLin, sfertile, Xiangling_L, jasonliu, hubert.reinterpretcast

Reviewed By: jasonliu

Subscribers: arphaman, wuzish, nemanjai, hiraditya, kbarton, jsji, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D70461

Added: 
    llvm/test/CodeGen/PowerPC/aix-xcoff-data-only-notoc.ll
    llvm/test/CodeGen/PowerPC/aix-xcoff-toc.ll

Modified: 
    llvm/include/llvm/MC/MCAsmInfo.h
    llvm/include/llvm/MC/MCSymbolXCOFF.h
    llvm/lib/BinaryFormat/XCOFF.cpp
    llvm/lib/MC/MCSectionXCOFF.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll
    llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll
    llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll
    llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll
    llvm/test/CodeGen/PowerPC/lower-globaladdr64-aix-asm.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index 589f1dfe90b8..5a6dff64caef 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -333,6 +333,10 @@ class MCAsmInfo {
   /// protected visibility.  Defaults to MCSA_Protected
   MCSymbolAttr ProtectedVisibilityAttr = MCSA_Protected;
 
+  // This attribute is used to indicate symbols such as commons on AIX may have
+  // a storage mapping class embedded in the name.
+  bool SymbolsHaveSMC = false;
+
   //===--- Dwarf Emission Directives -----------------------------------===//
 
   /// True if target supports emission of debugging information.  Defaults to
@@ -587,6 +591,8 @@ class MCAsmInfo {
     return ProtectedVisibilityAttr;
   }
 
+  bool getSymbolsHaveSMC() const { return SymbolsHaveSMC; }
+
   bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
 
   bool doesSupportExceptionHandling() const {

diff  --git a/llvm/include/llvm/MC/MCSymbolXCOFF.h b/llvm/include/llvm/MC/MCSymbolXCOFF.h
index 8bc781740439..07dfb5d29977 100644
--- a/llvm/include/llvm/MC/MCSymbolXCOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolXCOFF.h
@@ -9,6 +9,7 @@
 #define LLVM_MC_MCSYMBOLXCOFF_H
 
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/XCOFF.h"
 #include "llvm/MC/MCSymbol.h"
 
@@ -50,6 +51,17 @@ class MCSymbolXCOFF : public MCSymbol {
 
   bool hasContainingCsect() const { return ContainingCsect != nullptr; }
 
+  StringRef getUnqualifiedName() const {
+    const StringRef name = getName();
+    if (name.back() == ']') {
+      StringRef lhs, rhs;
+      std::tie(lhs, rhs) = name.rsplit('[');
+      assert(!rhs.empty() && "Invalid SMC format in XCOFF symbol.");
+      return lhs;
+    }
+    return name;
+  }
+
 private:
   Optional<XCOFF::StorageClass> StorageClass;
   MCSectionXCOFF *ContainingCsect = nullptr;

diff  --git a/llvm/lib/BinaryFormat/XCOFF.cpp b/llvm/lib/BinaryFormat/XCOFF.cpp
index 001b8077cd3d..29ccbaea3584 100644
--- a/llvm/lib/BinaryFormat/XCOFF.cpp
+++ b/llvm/lib/BinaryFormat/XCOFF.cpp
@@ -24,6 +24,10 @@ StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
     return "BS";
   case XCOFF::XMC_RO:
     return "RO";
+  case XCOFF::XMC_UA:
+    return "UA";
+  case XCOFF::XMC_TC:
+    return "TC";
   default:
     report_fatal_error("Unhandled storage-mapping class.");
   }

diff  --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index f646168d3a4a..8377e295532a 100644
--- a/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -40,6 +40,8 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
     case XCOFF::XMC_DS:
       OS << "\t.csect " << QualName->getName() << '\n';
       break;
+    case XCOFF::XMC_TC:
+      break;
     case XCOFF::XMC_TC0:
       OS << "\t.toc\n";
       break;

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
index 1216cd727289..a61c34ca6f14 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
@@ -87,4 +87,5 @@ PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) {
   assert(!IsLittleEndian && "Little-endian XCOFF not supported.");
   CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4;
   ZeroDirective = "\t.space\t";
+  SymbolsHaveSMC = true;
 }

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index a9717bfc3082..3cc1f4023166 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -30,6 +30,7 @@
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -108,8 +109,11 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
       : PPCTargetStreamer(S), OS(OS) {}
 
   void emitTCEntry(const MCSymbol &S) override {
+    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
     OS << "\t.tc ";
-    OS << S.getName();
+    OS << (MAI->getSymbolsHaveSMC()
+               ? cast<MCSymbolXCOFF>(S).getUnqualifiedName()
+               : S.getName());
     OS << "[TC],";
     OS << S.getName();
     OS << '\n';
@@ -243,7 +247,7 @@ class PPCTargetXCOFFStreamer : public PPCTargetStreamer {
   PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
 
   void emitTCEntry(const MCSymbol &S) override {
-    report_fatal_error("TOC entries not supported yet.");
+    // Object writing TOC entries not supported yet.
   }
 
   void emitMachine(StringRef CPU) override {

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 33198efb05f8..08e305d69e7e 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -43,6 +43,7 @@
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
@@ -82,6 +83,8 @@ class PPCAsmPrinter : public AsmPrinter {
   const PPCSubtarget *Subtarget = nullptr;
   StackMaps SM;
 
+  virtual MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO);
+
 public:
   explicit PPCAsmPrinter(TargetMachine &TM,
                          std::unique_ptr<MCStreamer> Streamer)
@@ -161,6 +164,11 @@ class PPCDarwinAsmPrinter : public PPCAsmPrinter {
 };
 
 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<MCStreamer> Streamer)
       : PPCAsmPrinter(TM, std::move(Streamer)) {}
@@ -514,17 +522,16 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
 
 /// Map a machine operand for a TOC pseudo-machine instruction to its
 /// corresponding MCSymbol.
-static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
-                                           AsmPrinter &AP) {
+MCSymbol *PPCAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) {
   switch (MO.getType()) {
   case MachineOperand::MO_GlobalAddress:
-    return AP.getSymbol(MO.getGlobal());
+    return getSymbol(MO.getGlobal());
   case MachineOperand::MO_ConstantPoolIndex:
-    return AP.GetCPISymbol(MO.getIndex());
+    return GetCPISymbol(MO.getIndex());
   case MachineOperand::MO_JumpTableIndex:
-    return AP.GetJTISymbol(MO.getIndex());
+    return GetJTISymbol(MO.getIndex());
   case MachineOperand::MO_BlockAddress:
-    return AP.GetBlockAddressSymbol(MO.getBlockAddress());
+    return GetBlockAddressSymbol(MO.getBlockAddress());
   default:
     llvm_unreachable("Unexpected operand type to get symbol.");
   }
@@ -688,7 +695,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
            "Invalid operand for LWZtoc.");
 
     // Map the operand to its corresponding MCSymbol.
-    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO);
 
     // Create a reference to the GOT entry for the symbol. The GOT entry will be
     // synthesized later.
@@ -749,7 +756,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     // global address operand to be a reference to the TOC entry we will
     // synthesize later.
     MCSymbol *TOCEntry =
-        lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));
+        lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO));
 
     const MCSymbolRefExpr::VariantKind VK =
         IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
@@ -775,7 +782,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
            "Invalid operand for ADDIStocHA.");
 
     // Map the machine operand to its corresponding MCSymbol.
-    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
 
     // 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
@@ -805,7 +812,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
            "Invalid operand for LWZtocL.");
 
     // Map the machine operand to its corresponding MCSymbol.
-    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
 
     // 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
@@ -835,7 +842,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
            "Invalid operand for ADDIStocHA8!");
 
-    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
 
     const bool GlobalToc =
         MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
@@ -881,7 +888,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
         "LDtocL used on symbol that could be accessed directly is "
         "invalid. Must match ADDIStocHA8."));
 
-    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
 
     if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
       MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
@@ -911,7 +918,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
         "Interposable definitions must use indirect access."));
 
     const MCExpr *Exp =
-        MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO, *this),
+        MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO),
                                 MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext);
     TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
     EmitToStreamer(*OutStreamer, TmpInst);
@@ -1736,7 +1743,7 @@ void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
   return AsmPrinter::SetupMachineFunction(MF);
 }
 
-void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+void PPCAIXAsmPrinter::ValidateGV(const GlobalVariable *GV) {
   // Early error checking limiting what is supported.
   if (GV->isThreadLocal())
     report_fatal_error("Thread local not yet supported on AIX.");
@@ -1746,6 +1753,19 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
 
   if (GV->hasComdat())
     report_fatal_error("COMDAT not yet supported by AIX.");
+}
+
+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<MCSymbolXCOFF>(getSymbol(GV));
+  GVSym->setStorageClass(
+      TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
 
   SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
   if ((!GVKind.isCommon() && !GVKind.isBSS() && !GVKind.isData() &&
@@ -1759,11 +1779,6 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
   MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
       getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
   OutStreamer->SwitchSection(Csect);
-
-  // Create the symbol, set its storage class, and emit it.
-  MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));
-  GVSym->setStorageClass(
-      TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
   GVSym->setContainingCsect(Csect);
 
   const DataLayout &DL = GV->getParent()->getDataLayout();
@@ -1802,7 +1817,10 @@ void PPCAIXAsmPrinter::EmitFunctionDescriptor() {
   OutStreamer->EmitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
                          PointerSize);
   // Emit TOC base address.
-  MCSymbol *TOCBaseSym = OutContext.getOrCreateSymbol(StringRef("TOC[TC0]"));
+  const MCSectionXCOFF *TOCBaseSec = OutStreamer->getContext().getXCOFFSection(
+      StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT,
+      SectionKind::getData());
+  const MCSymbol *TOCBaseSym = TOCBaseSec->getQualNameSymbol();
   OutStreamer->EmitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),
                          PointerSize);
   // Emit a null environment pointer.
@@ -1823,8 +1841,80 @@ void PPCAIXAsmPrinter::EmitEndOfAsmFile(Module &M) {
       SectionKind::getData());
   // Switch to section to emit TOC base.
   OutStreamer->SwitchSection(TOCBaseSection);
+
+  PPCTargetStreamer &TS =
+      static_cast<PPCTargetStreamer &>(*OutStreamer->getTargetStreamer());
+
+  for (auto &I : TOC) {
+    // Setup the csect for the current TC entry.
+    MCSectionXCOFF *TCEntry = OutStreamer->getContext().getXCOFFSection(
+        cast<MCSymbolXCOFF>(I.first)->getUnqualifiedName(), XCOFF::XMC_TC,
+        XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getData());
+    cast<MCSymbolXCOFF>(I.second)->setContainingCsect(TCEntry);
+    OutStreamer->SwitchSection(TCEntry);
+
+    OutStreamer->EmitLabel(I.second);
+    TS.emitTCEntry(*I.first);
+  }
 }
 
+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<const GlobalObject>(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<const GlobalVariable>(GO);
+  if (GV) {
+    ValidateGV(GV);
+  }
+
+  MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(getSymbol(GO));
+
+  // 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() && !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<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA,
+        XCOFF::XTY_ER, SC, SectionKind::getMetadata());
+    XSym->setContainingCsect(Csect);
+
+    return Csect->getQualNameSymbol();
+  }
+
+  // Handle initialized global variables.
+  if (GV) {
+    SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
+
+    // If the operand is a common then we should refer to the csect symbol.
+    if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+      MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
+          getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
+      return Csect->getQualNameSymbol();
+    }
+
+    // Other global variables are refered to by labels inside of a single csect,
+    // so refer to the label directly.
+    return getSymbol(GV);
+  }
+
+  // If the MO is a function, we want to make sure to refer to the function
+  // descriptor csect.
+  return XSym->getContainingCsect()->getQualNameSymbol();
+}
 
 /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
 /// for a MachineFunction to the given output stream, in a format that the

diff  --git a/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll b/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll
index 2d6353876a33..b4b9f029ed0b 100644
--- a/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll
@@ -69,4 +69,4 @@ __here:
 ; 64LARGE-ASM:         ld [[REG2:[0-9]+]], LC0 at l([[REG1]])
 
 ; CHECK: .toc
-; CHECK-NOT: .tc
+; CHECK: .tc Ltmp0[TC],Ltmp0

diff  --git a/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll b/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll
index 8803a1e4569f..1db8a55fb28e 100644
--- a/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll
@@ -84,4 +84,4 @@ entry:
 ; 64LARGE-ASM:         blr
 
 ; CHECK: .toc
-; CHECK-NOT: .tc
+; CHECK: .tc .LCPI0_0[TC],.LCPI0_0

diff  --git a/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll b/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll
index 5efb956b1529..a5ec1942a315 100644
--- a/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll
@@ -185,4 +185,4 @@
 ; 64LARGE-ASM:      .long   LBB0_5-.LJTI0_0
 
 ; CHECK: .toc
-; CHECK-NOT: .tc
+; CHECK: .tc .LJTI0_0[TC],.LJTI0_0

diff  --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-data-only-notoc.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-data-only-notoc.ll
new file mode 100644
index 000000000000..bc23b2915748
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-data-only-notoc.ll
@@ -0,0 +1,12 @@
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck %s
+
+ at a = external global i32, align 4
+ at b = external global i64, align 8
+ at c = external global i16, align 2
+ at globa = common global i32 0, align 4
+
+ at ptr = internal global void (...)* null, align 4
+
+; CHECK-NOT: .toc
+

diff  --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-toc.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-toc.ll
new file mode 100644
index 000000000000..4d6d7dc5bb42
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-toc.ll
@@ -0,0 +1,48 @@
+; RUN: llc  -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck --check-prefixes CHECK,CHECK32 %s
+; RUN: llc  -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck --check-prefixes CHECK,CHECK64  %s
+
+ at a = external global i32, align 4
+ at b = external global i64, align 8
+ at c = external global i16, align 2
+ at globa = common global i32 0, align 4
+
+ at ptr = internal global void (...)* null, align 4
+
+declare void @foo()
+
+define void @bar() {
+  %1 = alloca i8*, align 8
+  store i32 0, i32* @a, align 4
+  store i64 0, i64* @b, align 8
+  store i16 0, i16* @c, align 2
+  store i32 0, i32* @globa, align 4
+  store void (...)* bitcast (void ()* @bar to void (...)*), void (...)** @ptr, align 4
+  store i8* bitcast (void ()* @foo to i8*), i8** %1, align 8
+  ret void
+}
+
+; CHECK-NOT: .comm a
+; CHECK-NOT: .lcomm a
+; CHECK-NOT: .comm b
+; CHECK-NOT: .lcomm b
+; CHECK-NOT: .comm c
+; CHECK-NOT: .lcomm c
+; CHECK: .comm globa[RW],4,2
+; CHECK32: .lcomm ptr,4,ptr[BS],2
+; CHECK64: .lcomm ptr,8,ptr[BS],2
+; CHECK:      .toc
+; CHECK-NEXT: LC0:
+; CHECK-NEXT: .tc   a[TC],a[UA]
+; CHECK-NEXT: LC1:
+; CHECK-NEXT: .tc   b[TC],b[UA]
+; CHECK-NEXT: LC2:
+; CHECK-NEXT: .tc   c[TC],c[UA]
+; CHECK-NEXT: LC3:
+; CHECK-NEXT: .tc   globa[TC],globa[RW]
+; CHECK-NEXT: LC4:
+; CHECK-NEXT: .tc   ptr[TC],ptr[BS]
+; CHECK-NEXT: LC5:
+; CHECK-NEXT: .tc   bar[TC],bar[DS]
+; CHECK-NEXT: LC6:
+; CHECK-NEXT: .tc   foo[TC],foo[DS]
+

diff  --git a/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll b/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll
index e48f43a2d4b3..e3254175dbe9 100644
--- a/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll
+++ b/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll
@@ -41,5 +41,5 @@ define void @test_store(i32 %0) {
 ; LARGE: stw [[REG3:[0-9]+]], 0([[REG2]])
 ; LARGE: blr
 
-; TODO Update test when TOC-entry emission lands.
-; CHECK-NOT: .tc
+; CHECK: .tc a[TC],a
+; CHECK: .tc b[TC],b

diff  --git a/llvm/test/CodeGen/PowerPC/lower-globaladdr64-aix-asm.ll b/llvm/test/CodeGen/PowerPC/lower-globaladdr64-aix-asm.ll
index 371fa0ec279e..6d1863bc9537 100644
--- a/llvm/test/CodeGen/PowerPC/lower-globaladdr64-aix-asm.ll
+++ b/llvm/test/CodeGen/PowerPC/lower-globaladdr64-aix-asm.ll
@@ -41,5 +41,5 @@ define void @test_store(i32 zeroext %0) {
 ; LARGE: stw [[REG3:[0-9]+]], 0([[REG2]])
 ; LARGE: blr
 
-; TODO Update test when TOC-entry emission lands.
-; CHECK-NOT: .tc
+; CHECK: .tc a[TC],a
+; CHECK: .tc b[TC],b


        


More information about the llvm-commits mailing list