[AIX][XCOFF] Generate undefined symbol in symbol table for external function call
authorjasonliu <jasonliu.development@gmail.com>
Mon, 25 Nov 2019 15:02:01 +0000 (15:02 +0000)
committerjasonliu <jasonliu.development@gmail.com>
Mon, 25 Nov 2019 15:02:01 +0000 (15:02 +0000)
Summary:
This patch sets up the infrastructure for

 1. Associate MCSymbolXCOFF with an MCSectionXCOFF when it could not
    get implicitly associated.
 2. Generate undefined symbols. The patch itself generates undefined symbol
    for external function call only. Generate undefined symbol for external
    global variable and external function descriptors will be handled in
    separate patch(s) after this is land.

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

llvm/include/llvm/MC/MCSectionXCOFF.h
llvm/include/llvm/MC/MCSymbolXCOFF.h
llvm/lib/MC/XCOFFObjectWriter.cpp
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/test/CodeGen/PowerPC/aix-undef-func-call.ll [new file with mode: 0644]

index 604f17d..611eb69 100644 (file)
@@ -44,7 +44,7 @@ class MCSectionXCOFF final : public MCSection {
                  MCSymbolXCOFF *QualName, MCSymbol *Begin)
       : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC),
         Type(ST), StorageClass(SC), QualName(QualName) {
-    assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM) &&
+    assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM || ST == XCOFF::XTY_ER) &&
            "Invalid or unhandled type for csect.");
     assert(QualName != nullptr && "QualName is needed.");
     QualName->setStorageClass(SC);
index 98ecd24..8bc7817 100644 (file)
@@ -48,6 +48,8 @@ public:
     return ContainingCsect;
   }
 
+  bool hasContainingCsect() const { return ContainingCsect != nullptr; }
+
 private:
   Optional<XCOFF::StorageClass> StorageClass;
   MCSectionXCOFF *ContainingCsect = nullptr;
index 95f9504..ca96a0e 100644 (file)
@@ -149,6 +149,7 @@ class XCOFFObjectWriter : public MCObjectWriter {
   // CsectGroups. These store the csects which make up different parts of
   // the sections. Should have one for each set of csects that get mapped into
   // the same section and get handled in a 'similar' way.
+  CsectGroup UndefinedCsects;
   CsectGroup ProgramCodeCsects;
   CsectGroup ReadOnlyCsects;
   CsectGroup DataCsects;
@@ -227,6 +228,8 @@ XCOFFObjectWriter::XCOFFObjectWriter(
           CsectGroups{&BSSCsects}) {}
 
 void XCOFFObjectWriter::reset() {
+  UndefinedCsects.clear();
+
   // Reset any sections we have written to, and empty the section header table.
   for (auto *Sec : Sections)
     Sec->reset();
@@ -291,6 +294,8 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
     assert(WrapperMap.find(MCSec) == WrapperMap.end() &&
            "Cannot add a csect twice.");
+    assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
+           "An undefined csect should not get registered.");
 
     // If the name does not fit in the storage provided in the symbol table
     // entry, add it to the string table.
@@ -310,14 +315,20 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
 
     // Map the symbol into its containing csect.
     const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect();
-    assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
-           "Expected containing csect to exist in map");
 
-    // If the symbol is the Csect itself, we don't need to put the symbol
-    // into Csect's Syms.
+    // If the symbol is the csect itself, we don't need to put the symbol
+    // into csect's Syms.
     if (XSym == ContainingCsect->getQualNameSymbol())
       continue;
 
+    if (XSym->isUndefined(false)) {
+      UndefinedCsects.emplace_back(ContainingCsect);
+      continue;
+    }
+
+    assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
+           "Expected containing csect to exist in map");
+
     // Lookup the containing csect and add the symbol to it.
     WrapperMap[ContainingCsect]->Syms.emplace_back(XSym);
 
@@ -530,6 +541,11 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
 }
 
 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
+  for (const auto &Csect : UndefinedCsects) {
+    writeSymbolTableEntryForControlSection(
+        Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
+  }
+
   for (const auto *Section : Sections) {
     // Nothing to write for this Section.
     if (Section->Index == Section::UninitializedIndex)
@@ -554,15 +570,25 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
 }
 
 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
+  // The first symbol table entry is for the file name. We are not emitting it
+  // yet, so start at index 0.
+  uint32_t SymbolTableIndex = 0;
+
+  // Calculate undefined symbol's indices.
+  for (auto &Csect : UndefinedCsects) {
+    Csect.Size = 0;
+    Csect.Address = 0;
+    Csect.SymbolTableIndex = SymbolTableIndex;
+    // 1 main and 1 auxiliary symbol table entry for each contained symbol.
+    SymbolTableIndex += 2;
+  }
+
   // The address corrresponds to the address of sections and symbols in the
   // object file. We place the shared address 0 immediately after the
   // section header table.
   uint32_t Address = 0;
   // Section indices are 1-based in XCOFF.
   int32_t SectionIndex = 1;
-  // The first symbol table entry is for the file name. We are not emitting it
-  // yet, so start at index 0.
-  uint32_t SymbolTableIndex = 0;
 
   for (auto *Section : Sections) {
     const bool IsEmpty =
index 4d9288c..ff704b7 100644 (file)
@@ -5325,8 +5325,20 @@ SDValue PPCTargetLowering::FinishCall(
     // C-linkage name.
     GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee);
     auto &Context = DAG.getMachineFunction().getMMI().getContext();
-    MCSymbol *S = Context.getOrCreateSymbol(Twine(".") +
-                                            Twine(G->getGlobal()->getName()));
+
+    MCSymbolXCOFF *S = cast<MCSymbolXCOFF>(Context.getOrCreateSymbol(
+        Twine(".") + Twine(G->getGlobal()->getName())));
+
+    const GlobalValue *GV = G->getGlobal();
+    if (GV && GV->isDeclaration() && !S->hasContainingCsect()) {
+      // On AIX, undefined symbol need to associate with a MCSectionXCOFF to
+      // get the correct storage mapping class. In this case, XCOFF::XMC_PR.
+      MCSectionXCOFF *Sec =
+          Context.getXCOFFSection(S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER,
+                                  XCOFF::C_EXT, SectionKind::getMetadata());
+      S->setContainingCsect(Sec);
+    }
+
     Callee = DAG.getMCSymbol(S, PtrVT);
     // Replace the GlobalAddressSDNode Callee with the MCSymbolSDNode.
     Ops[1] = Callee;
diff --git a/llvm/test/CodeGen/PowerPC/aix-undef-func-call.ll b/llvm/test/CodeGen/PowerPC/aix-undef-func-call.ll
new file mode 100644 (file)
index 0000000..31d707c
--- /dev/null
@@ -0,0 +1,29 @@
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
+; RUN: llvm-readobj  --symbols %t.o | FileCheck %s
+
+define void @bar() {
+entry:
+  call void bitcast (void (...)* @foo to void ()*)()
+  ret void
+}
+
+declare void @foo(...)
+
+;CHECK: Symbol {
+;CHECK:   Name: .foo
+;CHECK-NEXT:   Value (RelocatableAddress): 0x0
+;CHECK-NEXT:   Section: N_UNDEF
+;CHECK-NEXT:   Type: 0x0
+;CHECK-NEXT:   StorageClass: C_EXT (0x2)
+;CHECK-NEXT:   NumberOfAuxEntries: 1
+;CHECK-NEXT:   CSECT Auxiliary Entry {
+;CHECK:          SectionLen: 0
+;CHECK-NEXT:     ParameterHashIndex: 0x0
+;CHECK-NEXT:     TypeChkSectNum: 0x0
+;CHECK-NEXT:     SymbolAlignmentLog2: 0
+;CHECK-NEXT:     SymbolType: XTY_ER (0x0)
+;CHECK-NEXT:     StorageMappingClass: XMC_PR (0x0)
+;CHECK-NEXT:     StabInfoIndex: 0x0
+;CHECK-NEXT:     StabSectNum: 0x0
+;CHECK-NEXT:   }
+;CHECK-NEXT: }