[llvm-branch-commits] [llvm] [GOFF] Add writing of section symbols (PR #133799)

Neumann Hon via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Apr 1 23:13:48 PDT 2025


================
@@ -223,21 +196,222 @@ void GOFFOstream::finalizeRecord() {
 }
 
 namespace {
+// A GOFFSymbol holds all the data required for writing an ESD record.
+class GOFFSymbol {
+public:
+  std::string Name;
+  uint32_t EsdId;
+  uint32_t ParentEsdId;
+  uint64_t Offset = 0; // Offset of the symbol into the section. LD only.
+                       // Offset is only 32 bit, the larger type is used to
+                       // enable error checking.
+  GOFF::ESDSymbolType SymbolType;
+  GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_ProgramManagementBinder;
+
+  GOFF::BehavioralAttributes BehavAttrs;
+  GOFF::SymbolFlags SymbolFlags;
+  uint32_t SortKey = 0;
+  uint32_t SectionLength = 0;
+  uint32_t ADAEsdId = 0;
+  uint32_t EASectionEDEsdId = 0;
+  uint32_t EASectionOffset = 0;
+  uint8_t FillByteValue = 0;
+
+  GOFFSymbol() : EsdId(0), ParentEsdId(0) {}
+
+  GOFFSymbol(StringRef Name, uint32_t EsdID, const SDAttr &Attr)
+      : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(0),
+        SymbolType(GOFF::ESD_ST_SectionDefinition) {
+    BehavAttrs.setTaskingBehavior(Attr.TaskingBehavior);
+    BehavAttrs.setBindingScope(Attr.BindingScope);
+  }
+
+  GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
+             const EDAttr &Attr)
+      : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
+        SymbolType(GOFF::ESD_ST_ElementDefinition) {
+    this->NameSpace = Attr.NameSpace;
+    // TODO Do we need/should set the "mangled" flag?
+    SymbolFlags.setFillBytePresence(1);
+    SymbolFlags.setReservedQwords(Attr.ReservedQwords);
+    BehavAttrs.setReadOnly(Attr.IsReadOnly);
+    BehavAttrs.setExecutable(Attr.Executable);
+    BehavAttrs.setAmode(Attr.Amode);
+    BehavAttrs.setRmode(Attr.Rmode);
+    BehavAttrs.setTextStyle(Attr.TextStyle);
+    BehavAttrs.setBindingAlgorithm(Attr.BindAlgorithm);
+    BehavAttrs.setLoadingBehavior(Attr.LoadBehavior);
+    BehavAttrs.setAlignment(Attr.Alignment);
+  }
+
+  GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
+             const LDAttr &Attr)
+      : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
+        SymbolType(GOFF::ESD_ST_LabelDefinition) {
+    this->NameSpace = Attr.NameSpace;
+    SymbolFlags.setRenameable(Attr.IsRenamable);
+    BehavAttrs.setExecutable(Attr.Executable);
+    BehavAttrs.setBindingStrength(Attr.BindingStrength);
+    BehavAttrs.setLinkageType(Attr.Linkage);
+    BehavAttrs.setAmode(Attr.Amode);
+    BehavAttrs.setBindingScope(Attr.BindingScope);
+  }
+
+  GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
+             const PRAttr &Attr)
+      : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
+        SymbolType(GOFF::ESD_ST_PartReference) {
+    this->NameSpace = Attr.NameSpace;
+    SymbolFlags.setRenameable(Attr.IsRenamable);
+    BehavAttrs.setExecutable(Attr.Executable);
+    BehavAttrs.setAlignment(Attr.Alignment);
+    BehavAttrs.setAmode(Attr.Amode);
+    BehavAttrs.setLinkageType(Attr.Linkage);
+    BehavAttrs.setBindingScope(Attr.BindingScope);
+    BehavAttrs.setDuplicateSymbolSeverity(Attr.DuplicateSymbolSeverity);
+    BehavAttrs.setReadOnly(Attr.IsReadOnly);
+  }
+};
+
 class GOFFWriter {
   GOFFOstream OS;
   [[maybe_unused]] MCAssembler &Asm;
 
+  /// Mapping from MCSectionGOFF/MCSymbolGOFF to GOFF symbols and attributes.
+  GOFFSymbolMapper SymbolMapper;
+
+  /// Counter for symbol id's.
+  uint32_t EsdIdCounter = 0;
+
+  /// Id's of some special symbols.
+  uint32_t RootSDEsdId = 0;
+  uint32_t ADAEsdId = 0;
+
   void writeHeader();
+  void writeSymbol(const GOFFSymbol &Symbol);
   void writeEnd();
 
+  GOFFSymbol createGOFFSymbol(StringRef Name, const SDAttr &Attr);
+  GOFFSymbol createGOFFSymbol(StringRef Name, const EDAttr &Attr,
+                              uint32_t ParentEsdId);
+  GOFFSymbol createGOFFSymbol(StringRef Name, const LDAttr &Attr,
+                              uint32_t ParentEsdId);
+  GOFFSymbol createGOFFSymbol(StringRef Name, const PRAttr &Attr,
+                              uint32_t ParentEsdId);
+
+  void defineRootSymbol(const MCSectionGOFF *Text);
+  void defineSectionSymbols(const MCSectionGOFF &Section);
+  void defineSymbols();
+
 public:
   GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
   uint64_t writeObject();
 };
 } // namespace
 
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
-    : OS(OS), Asm(Asm) {}
+    : OS(OS), Asm(Asm), SymbolMapper(Asm) {}
+
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const SDAttr &Attr) {
+  return GOFFSymbol(Name, ++EsdIdCounter, Attr);
+}
+
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const EDAttr &Attr,
+                                        uint32_t ParentEsdId) {
+  return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
+}
+
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const LDAttr &Attr,
+                                        uint32_t ParentEsdId) {
+  return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
+}
+
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const PRAttr &Attr,
+                                        uint32_t ParentEsdId) {
+  return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
+}
+
+void GOFFWriter::defineRootSymbol(const MCSectionGOFF *Text) {
+  // There is always a text section except for DWARF unit tests.
+  SymbolMapper.determineRootSD("");
+  GOFFSymbol RootSD =
+      createGOFFSymbol(SymbolMapper.getRootSDName(), SymbolMapper.getRootSD());
+  writeSymbol(RootSD);
+  RootSDEsdId = RootSD.EsdId;
+}
+
+void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
+  auto [GOFFSectionData, Found] = SymbolMapper.getSection(Section);
+  if (Found) {
+    uint32_t SDEsdId = RootSDEsdId;
+    if (!GOFFSectionData.IsSDRootSD) {
+      GOFFSymbol SD = createGOFFSymbol(GOFFSectionData.SDName,
+                                       GOFFSectionData.SDAttributes);
+      SDEsdId = SD.EsdId;
+      writeSymbol(SD);
+    }
+
+    GOFFSymbol ED = createGOFFSymbol(GOFFSectionData.EDName,
+                                     GOFFSectionData.EDAttributes, SDEsdId);
+    if (GOFFSectionData.Tag == GOFFSectionData::None ||
+        GOFFSectionData.Tag == GOFFSectionData::LD) {
+      ED.SectionLength = Asm.getSectionAddressSize(Section);
+    }
+    writeSymbol(ED);
+
+    if (GOFFSectionData.Tag == GOFFSectionData::LD) {
+      GOFFSymbol LD = createGOFFSymbol(GOFFSectionData.LDorPRName,
+                                       GOFFSectionData.LDAttributes, ED.EsdId);
+      if (Section.isText())
+        LD.ADAEsdId = ADAEsdId;
+      writeSymbol(LD);
+    }
+
+    if (GOFFSectionData.Tag == GOFFSectionData::PR) {
+      GOFFSymbol PR = createGOFFSymbol(GOFFSectionData.LDorPRName,
+                                       GOFFSectionData.PRAttributes, ED.EsdId);
+      PR.SectionLength = Asm.getSectionAddressSize(Section);
+      if (Section.getName() == ".ada") {
+        // We cannot have a zero-length section for data.  If we do,
+        // artificially inflate it. Use 2 bytes to avoid odd alignments. Note:
+        // if this is ever changed, you will need to update the code in
+        // SystemZAsmPrinter::emitCEEMAIN and SystemZAsmPrinter::emitCELQMAIN to
+        // generate -1 if there is no ADA
+        if (!PR.SectionLength)
+          PR.SectionLength = 2;
+        ADAEsdId = PR.EsdId;
+      }
+      writeSymbol(PR);
+    }
+    return;
+  }
+  // TODO It is possible to get here. This will be handled later.
+}
+
+void GOFFWriter::defineSymbols() {
+  // Search for .text and .ada sections. These should be the first sections in
+  // the list, so the loop should be cheap.
+  MCSectionGOFF *Text = nullptr;
+  MCSectionGOFF *ADA = nullptr;
+  for (MCSection &S : Asm) {
+    if (S.getName() == ".text")
+      Text = &cast<MCSectionGOFF>(S);
+    if (S.getName() == ".ada")
+      ADA = &cast<MCSectionGOFF>(S);
+  }
+  defineRootSymbol(Text);
+  if (ADA)
+    defineSectionSymbols(*ADA);
+  if (Text)
+    defineSectionSymbols(*Text);
----------------
Everybody0523 wrote:

Actually, judging by the testcase `section.ll` it seems more likely the above comment is incorrect and this is fine.

If that's the case then nevermind 😅

https://github.com/llvm/llvm-project/pull/133799


More information about the llvm-branch-commits mailing list