[llvm] 78207e1 - [NFC][XCOFF][AIX] Serialize object file writing for each CsectGroup

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 24 08:39:47 PDT 2019


Author: jasonliu
Date: 2019-10-24T15:38:50Z
New Revision: 78207e1f234eede120beaf730dfb7bb9d4e00a1b

URL: https://github.com/llvm/llvm-project/commit/78207e1f234eede120beaf730dfb7bb9d4e00a1b
DIFF: https://github.com/llvm/llvm-project/commit/78207e1f234eede120beaf730dfb7bb9d4e00a1b.diff

LOG: [NFC][XCOFF][AIX] Serialize object file writing for each CsectGroup

Summary:

Right now we handle each CsectGroup(ProgramCodeCsects, BSSCsects)
individually when assigning indices, writing symbol table, and
writing section raw data. However, there is already a pattern there,
and we could common up those actions for every CsectGroup. This will
 make adding new CsectGroup(Read Write data, Read only data, TC/TOC,
 mergeable string) easier, and less error prone.

Reviewed by: sfertile, daltenty, DiggerLin

Approved by: daltenty

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

Added: 
    

Modified: 
    llvm/lib/MC/XCOFFObjectWriter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 353c21068735..2868972f71ce 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -44,6 +44,7 @@ using namespace llvm;
 namespace {
 
 constexpr unsigned DefaultSectionAlign = 4;
+constexpr int16_t MaxSectionIndex = INT16_MAX;
 
 // Packs the csect's alignment and type into a byte.
 uint8_t getEncodedType(const MCSectionXCOFF *);
@@ -73,6 +74,22 @@ struct ControlSection {
       : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
 };
 
+// Type to be used for a container representing a set of csects with
+// (approximately) the same storage mapping class. For example all the csects
+// with a storage mapping class of `xmc_pr` will get placed into the same
+// container.
+struct CsectGroup {
+  enum LabelDefinitionSupport : bool {
+    LabelDefSupported = true,
+    LabelDefUnsupported = false
+  };
+
+  const LabelDefinitionSupport SupportLabelDef;
+  std::deque<ControlSection> Csects;
+};
+
+using CsectGroups = std::deque<CsectGroup *>;
+
 // Represents the data related to a section excluding the csects that make up
 // the raw data of the section. The csects are stored separately as not all
 // sections contain csects, and some sections contain csects which are better
@@ -94,49 +111,63 @@ struct Section {
   // Virtual sections do not need storage allocated in the object file.
   const bool IsVirtual;
 
+  // XCOFF has special section numbers for symbols:
+  // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
+  // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
+  // relocatable.
+  //  0 Specifies N_UNDEF, an undefined external symbol.
+  // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
+  // hasn't been initialized.
+  static constexpr int16_t UninitializedIndex =
+      XCOFF::ReservedSectionNum::N_DEBUG - 1;
+
+  CsectGroups Groups;
+
   void reset() {
     Address = 0;
     Size = 0;
     FileOffsetToData = 0;
     FileOffsetToRelocations = 0;
     RelocationCount = 0;
-    Index = -1;
+    Index = UninitializedIndex;
+    // Clear any csects we have stored.
+    for (auto *Group : Groups)
+      Group->Csects.clear();
   }
 
-  Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual)
+  Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
+          CsectGroups Groups)
       : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
-        RelocationCount(0), Flags(Flags), Index(-1), IsVirtual(IsVirtual) {
+        RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
+        IsVirtual(IsVirtual), Groups(Groups) {
     strncpy(Name, N, XCOFF::NameSize);
   }
 };
 
 class XCOFFObjectWriter : public MCObjectWriter {
-  // Type to be used for a container representing a set of csects with
-  // (approximately) the same storage mapping class. For example all the csects
-  // with a storage mapping class of `xmc_pr` will get placed into the same
-  // container.
-  using CsectGroup = std::deque<ControlSection>;
+
+  uint32_t SymbolTableEntryCount = 0;
+  uint32_t SymbolTableOffset = 0;
 
   support::endian::Writer W;
   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
   StringTableBuilder Strings;
 
-  // The non-empty sections, in the order they will appear in the section header
-  // table.
-  std::vector<Section *> Sections;
+  // CsectGroups. These store the csects which make up 
diff erent 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 ProgramCodeCsects{CsectGroup::LabelDefSupported};
+  CsectGroup BSSCsects{CsectGroup::LabelDefUnsupported};
 
   // The Predefined sections.
   Section Text;
   Section BSS;
 
-  // CsectGroups. These store the csects which make up 
diff erent 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 ProgramCodeCsects;
-  CsectGroup BSSCsects;
+  // All the XCOFF sections, in the order they will appear in the section header
+  // table.
+  std::array<Section *const, 2> Sections{&Text, &BSS};
 
-  uint32_t SymbolTableEntryCount = 0;
-  uint32_t SymbolTableOffset = 0;
+  CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
 
   virtual void reset() override;
 
@@ -190,18 +221,15 @@ XCOFFObjectWriter::XCOFFObjectWriter(
     std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
     : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
       Strings(StringTableBuilder::XCOFF),
-      Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false),
-      BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true) {}
+      Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
+           CsectGroups{&ProgramCodeCsects}),
+      BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
+          CsectGroups{&BSSCsects}) {}
 
 void XCOFFObjectWriter::reset() {
   // Reset any sections we have written to, and empty the section header table.
   for (auto *Sec : Sections)
     Sec->reset();
-  Sections.clear();
-
-  // Clear any csects we have stored.
-  ProgramCodeCsects.clear();
-  BSSCsects.clear();
 
   // Reset the symbol table and string table.
   SymbolTableEntryCount = 0;
@@ -211,6 +239,27 @@ void XCOFFObjectWriter::reset() {
   MCObjectWriter::reset();
 }
 
+CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
+  switch (MCSec->getMappingClass()) {
+  case XCOFF::XMC_PR:
+    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+           "Only an initialized csect can contain program code.");
+    return ProgramCodeCsects;
+  case XCOFF::XMC_RW:
+    if (XCOFF::XTY_CM == MCSec->getCSectType())
+      return BSSCsects;
+
+    report_fatal_error("Unhandled mapping of read-write csect to section.");
+  case XCOFF::XMC_BS:
+    assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
+           "Mapping invalid csect. CSECT with bss storage class must be "
+           "common type.");
+    return BSSCsects;
+  default:
+    report_fatal_error("Unhandled mapping of csect to section.");
+  }
+}
+
 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
                                                  const MCAsmLayout &Layout) {
   if (TargetObjectWriter->is64Bit())
@@ -231,33 +280,13 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
     if (nameShouldBeInStringTable(MCSec->getSectionName()))
       Strings.add(MCSec->getSectionName());
 
-    switch (MCSec->getMappingClass()) {
-    case XCOFF::XMC_PR:
-      assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
-             "Only an initialized csect can contain program code.");
-      ProgramCodeCsects.emplace_back(MCSec);
-      WrapperMap[MCSec] = &ProgramCodeCsects.back();
-      break;
-    case XCOFF::XMC_RW:
-      if (XCOFF::XTY_CM == MCSec->getCSectType()) {
-        BSSCsects.emplace_back(MCSec);
-        WrapperMap[MCSec] = &BSSCsects.back();
-        break;
-      }
-      report_fatal_error("Unhandled mapping of read-write csect to section.");
-    case XCOFF::XMC_TC0:
-      // TODO FIXME Handle emiting the TOC base.
-      break;
-    case XCOFF::XMC_BS:
-      assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
-             "Mapping invalid csect. CSECT with bss storage class must be "
-             "common type.");
-      BSSCsects.emplace_back(MCSec);
-      WrapperMap[MCSec] = &BSSCsects.back();
-      break;
-    default:
-      report_fatal_error("Unhandled mapping of csect to section.");
-    }
+    // TODO FIXME Handle emiting the TOC base.
+    if (MCSec->getMappingClass() == XCOFF::XMC_TC0)
+      continue;
+
+    CsectGroup &Group = getCsectGroup(MCSec);
+    Group.Csects.emplace_back(MCSec);
+    WrapperMap[MCSec] = &Group.Csects.back();
   }
 
   for (const MCSymbol &S : Asm.symbols()) {
@@ -292,21 +321,28 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
 
 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
                                       const MCAsmLayout &Layout) {
-  // Write the program code control sections one at a time.
-  uint32_t CurrentAddressLocation = Text.Address;
-  for (const auto &Csect : ProgramCodeCsects) {
-    if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
-      W.OS.write_zeros(PaddingSize);
-    Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
-    CurrentAddressLocation = Csect.Address + Csect.Size;
-  }
+  uint32_t CurrentAddressLocation = 0;
+  for (const auto *Section : Sections) {
+    // Nothing to write for this Section.
+    if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
+      continue;
+
+    assert(CurrentAddressLocation == Section->Address &&
+           "We should have no padding between sections.");
+    for (const auto *Group : Section->Groups) {
+      for (const auto &Csect : Group->Csects) {
+        if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
+          W.OS.write_zeros(PaddingSize);
+        Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
+        CurrentAddressLocation = Csect.Address + Csect.Size;
+      }
+    }
 
-  if (Text.Index != -1) {
     // The size of the tail padding in a section is the end virtual address of
     // the current section minus the the end virtual address of the last csect
     // in that section.
     if (uint32_t PaddingSize =
-            Text.Address + Text.Size - CurrentAddressLocation)
+            Section->Address + Section->Size - CurrentAddressLocation)
       W.OS.write_zeros(PaddingSize);
   }
 }
@@ -472,25 +508,28 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
 }
 
 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
-  // Print out symbol table for the program code.
-  for (const auto &Csect : ProgramCodeCsects) {
-    // Write out the control section first and then each symbol in it.
-    writeSymbolTableEntryForControlSection(Csect, Text.Index,
-                                           Csect.MCCsect->getStorageClass());
-    for (const auto &Sym : Csect.Syms)
-      writeSymbolTableEntryForCsectMemberLabel(
-          Sym, Csect, Text.Index, Layout.getSymbolOffset(*Sym.MCSym));
-  }
-
-  // The BSS Section is special in that the csects must contain a single symbol,
-  // and the contained symbol cannot be represented in the symbol table as a
-  // label definition.
-  for (auto &Csect : BSSCsects) {
-    assert(Csect.Syms.size() == 1 &&
-           "Uninitialized csect cannot contain more then 1 symbol.");
-    Symbol &Sym = Csect.Syms.back();
-    writeSymbolTableEntryForControlSection(Csect, BSS.Index,
-                                           Sym.getStorageClass());
+  for (const auto *Section : Sections) {
+    for (const auto *Group : Section->Groups) {
+      if (Group->Csects.empty())
+        continue;
+
+      const bool SupportLabelDef = Group->SupportLabelDef;
+      const int16_t SectionIndex = Section->Index;
+      for (const auto &Csect : Group->Csects) {
+        // Write out the control section first and then each symbol in it.
+        writeSymbolTableEntryForControlSection(
+            Csect, SectionIndex, Csect.MCCsect->getStorageClass());
+        if (!SupportLabelDef) {
+          assert(Csect.Syms.size() == 1 && "Csect should only contain 1 symbol "
+                                           "which is its label definition.");
+          continue;
+        }
+
+        for (const auto Sym : Csect.Syms)
+          writeSymbolTableEntryForCsectMemberLabel(
+              Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
+      }
+    }
   }
 }
 
@@ -500,64 +539,59 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
   // section header table.
   uint32_t Address = 0;
   // Section indices are 1-based in XCOFF.
-  int16_t SectionIndex = 1;
+  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;
 
-  // Text section comes first.
-  if (!ProgramCodeCsects.empty()) {
-    Sections.push_back(&Text);
-    Text.Index = SectionIndex++;
-    for (auto &Csect : ProgramCodeCsects) {
-      const MCSectionXCOFF *MCSec = Csect.MCCsect;
-      Csect.Address = alignTo(Address, MCSec->getAlignment());
-      Csect.Size = Layout.getSectionAddressSize(MCSec);
-      Address = Csect.Address + Csect.Size;
-      Csect.SymbolTableIndex = SymbolTableIndex;
-      // 1 main and 1 auxiliary symbol table entry for the csect.
-      SymbolTableIndex += 2;
-      for (auto &Sym : Csect.Syms) {
-        Sym.SymbolTableIndex = SymbolTableIndex;
-        // 1 main and 1 auxiliary symbol table entry for each contained symbol
+  for (auto *Section : Sections) {
+    const bool IsEmpty =
+        llvm::all_of(Section->Groups, [](const CsectGroup *Group) {
+          return Group->Csects.empty();
+        });
+    if (IsEmpty)
+      continue;
+
+    if (SectionIndex > MaxSectionIndex)
+      report_fatal_error("Section index overflow!");
+    Section->Index = SectionIndex++;
+
+    bool SectionAddressSet = false;
+    for (auto *Group : Section->Groups) {
+      if (Group->Csects.empty())
+        continue;
+
+      const bool SupportLabelDef = Group->SupportLabelDef;
+      for (auto &Csect : Group->Csects) {
+        const MCSectionXCOFF *MCSec = Csect.MCCsect;
+        Csect.Address = alignTo(Address, MCSec->getAlignment());
+        Csect.Size = Layout.getSectionAddressSize(MCSec);
+        Address = Csect.Address + Csect.Size;
+        Csect.SymbolTableIndex = SymbolTableIndex;
+        // 1 main and 1 auxiliary symbol table entry for the csect.
         SymbolTableIndex += 2;
-      }
-    }
-    Address = alignTo(Address, DefaultSectionAlign);
 
-    // The first csect of a section can be aligned by adjusting the virtual
-    // address of its containing section instead of writing zeroes into the
-    // object file.
-    Text.Address = ProgramCodeCsects.front().Address;
+        if (!SupportLabelDef)
+          continue;
 
-    Text.Size = Address - Text.Address;
-  }
+        for (auto &Sym : Csect.Syms) {
+          Sym.SymbolTableIndex = SymbolTableIndex;
+          // 1 main and 1 auxiliary symbol table entry for each contained
+          // symbol.
+          SymbolTableIndex += 2;
+        }
+      }
 
-  // Data section Second. TODO
-
-  // BSS Section third.
-  if (!BSSCsects.empty()) {
-    Sections.push_back(&BSS);
-    BSS.Index = SectionIndex++;
-    for (auto &Csect : BSSCsects) {
-      const MCSectionXCOFF *MCSec = Csect.MCCsect;
-      Csect.Address = alignTo(Address, MCSec->getAlignment());
-      Csect.Size = Layout.getSectionAddressSize(MCSec);
-      Address = Csect.Address + Csect.Size;
-      Csect.SymbolTableIndex = SymbolTableIndex;
-      // 1 main and 1 auxiliary symbol table entry for the csect.
-      SymbolTableIndex += 2;
-
-      assert(Csect.Syms.size() == 1 &&
-             "csect in the BSS can only contain a single symbol.");
-      Csect.Syms[0].SymbolTableIndex = Csect.SymbolTableIndex;
+      if (!SectionAddressSet) {
+        Section->Address = Group->Csects.front().Address;
+        SectionAddressSet = true;
+      }
     }
-    // Pad out Address to the default alignment. This is to match how the system
-    // assembler handles the .bss section. Its size is always a multiple of 4.
-    Address = alignTo(Address, DefaultSectionAlign);
 
-    BSS.Address = BSSCsects.front().Address;
-    BSS.Size = Address - BSS.Address;
+    // Make sure the address of the next section aligned to
+    // DefaultSectionAlign.
+    Address = alignTo(Address, DefaultSectionAlign);
+    Section->Size = Address - Section->Address;
   }
 
   SymbolTableEntryCount = SymbolTableIndex;


        


More information about the llvm-commits mailing list