[llvm] [z/OS][GOFF] Implement support for writing ESD + TXT records by the GOFFObjectWriter (PR #85851)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 19 12:30:55 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mc

Author: Neumann Hon (Everybody0523)

<details>
<summary>Changes</summary>

This PR implements generation of ESD/TXT Records in GOFF Writer. 

A few notes on GOFF and the overall design:

### GOFF Structure
GOFF (GOFF Object File Format) is is the object file format used on z/OS. GOFF files are built out of 80-byte records.

There are 5 types of records. They are:

1. HDR (Header)
2. ESD (External Symbol)
3. TXT (Text)
4. RLD (Relocation Data)
5. END (End).

The HDR and END records are present in every file, and are implemented already [by this commit](https://github.com/llvm/llvm-project/commit/3adc2a0b84d0fbccead5d77d1b7d7a9b0bec175d). 

ESD and TXT records have a notion of "ownership", which means that an ESD symbol can be "owned" another ESD symbol. TXT records are always owned by an ESD symbol.

GOFF doesn't truly have "sections" or "symbols" in the way other object file formats do, although it does have something vaguely analogous, which will be discussed below.

### MCSymbol handling
An MCSymbol _mostly_ maps to one (or more) ESD Record. Some types of symbols may cause more than one symbol to be generated. In addition, every compilation unit has a few special symbols that are used by the binder.

### MCSection handling
GOFF "sections" are defined by a triple of ESD Symbols. Specifically, each section is defined by an SD symbol, an ED symbol, and a PR or LD symbol. The PR/LD symbol's parent should be the ED symbol and the ED symbol's parent should be the SD symbol. Furthermore, the PR/LD symbol should own a TXT record. The contents of the section reside in that TXT record. The SD symbol need not be unique to the section; in fact it is quite common that multiple GOFF sections are are "rooted" and the initial SD node (ie. the first ESD entry).

Some examples of "sections" are:

- Global Variables. Each global variable with external linkage has its own section.
- The "code section". The code section is a code csect with the default name `<filename>#C` The bodies of all functions reside in this section. 
- The ADA section. This is a section that contains a pointer to the body of each function as well as metadata relevant to that function.

---

Patch is 67.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85851.diff


16 Files Affected:

- (modified) llvm/include/llvm/BinaryFormat/GOFF.h (+10-6) 
- (modified) llvm/include/llvm/CodeGen/AsmPrinter.h (+4-1) 
- (modified) llvm/include/llvm/MC/MCAssembler.h (+7) 
- (modified) llvm/include/llvm/MC/MCContext.h (+2-1) 
- (modified) llvm/include/llvm/MC/MCGOFFStreamer.h (+7-4) 
- (modified) llvm/include/llvm/MC/MCSymbolGOFF.h (+54-1) 
- (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+6-2) 
- (modified) llvm/lib/MC/GOFFObjectWriter.cpp (+806-1) 
- (modified) llvm/lib/MC/MCGOFFStreamer.cpp (+76) 
- (modified) llvm/lib/MC/MCObjectFileInfo.cpp (+3) 
- (modified) llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCExpr.cpp (+4) 
- (modified) llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCExpr.h (+2) 
- (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+94-5) 
- (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.h (+4) 
- (added) llvm/test/MC/GOFF/basic-goff-64.ll (+252) 
- (modified) llvm/test/MC/GOFF/empty-goff.s (+20-19) 


``````````diff
diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
index 443bcfc9479a8b..b0cd2484536ea2 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -29,6 +29,8 @@ constexpr uint8_t RecordLength = 80;
 constexpr uint8_t RecordPrefixLength = 3;
 constexpr uint8_t PayloadLength = 77;
 constexpr uint8_t RecordContentLength = RecordLength - RecordPrefixLength;
+constexpr uint8_t ESDMetadataLength = 69;
+constexpr uint8_t TXTMetadataLength = 21;
 
 /// \brief Maximum data length before starting a new card for RLD and TXT data.
 ///
@@ -65,12 +67,7 @@ enum ESDNameSpaceId : uint8_t {
   ESD_NS_Parts = 3
 };
 
-enum ESDReserveQwords : uint8_t {
-  ESD_RQ_0 = 0,
-  ESD_RQ_1 = 1,
-  ESD_RQ_2 = 2,
-  ESD_RQ_3 = 3
-};
+enum ESDReserveQwords : uint8_t { ESD_RQ_0 = 0, ESD_RQ_1 = 1 };
 
 enum ESDAmode : uint8_t {
   ESD_AMODE_None = 0,
@@ -157,6 +154,12 @@ enum ESDAlignment : uint8_t {
   ESD_ALIGN_4Kpage = 12,
 };
 
+enum TXTRecordStyle : uint8_t {
+  TXT_RS_Byte = 0,
+  TXT_RS_Structured = 1,
+  TXT_RS_Unstructured = 2,
+};
+
 enum ENDEntryPointRequest : uint8_t {
   END_EPR_None = 0,
   END_EPR_EsdidOffset = 1,
@@ -166,6 +169,7 @@ enum ENDEntryPointRequest : uint8_t {
 
 // \brief Subsections of the primary C_CODE section in the object file.
 enum SubsectionKind : uint8_t {
+  SK_ReadOnly = 1,
   SK_PPA1 = 2,
   SK_PPA2 = 4,
 };
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a7fbf4aeb74494..0fb696bbb68b13 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -897,10 +897,13 @@ class AsmPrinter : public MachineFunctionPass {
   virtual void emitModuleCommandLines(Module &M);
 
   GCMetadataPrinter *getOrCreateGCPrinter(GCStrategy &S);
+
+protected:
   virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA);
-  void emitGlobalIFunc(Module &M, const GlobalIFunc &GI);
 
 private:
+  void emitGlobalIFunc(Module &M, const GlobalIFunc &GI);
+
   /// This method decides whether the specified basic block requires a label.
   bool shouldEmitLabelForBasicBlock(const MachineBasicBlock &MBB) const;
 
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 3fa5f2fe655e86..7c1b6bdb3ffb60 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -136,6 +136,9 @@ class MCAssembler {
   // Optional compiler version.
   std::string CompilerVersion;
 
+  /// GOFF Csect names.
+  std::pair<std::string, std::string> CsectNames;
+
   MCDwarfLineTableParams LTParams;
 
   /// The set of function symbols for which a .thumb_func directive has
@@ -488,6 +491,10 @@ class MCAssembler {
     FileNames.emplace_back(std::string(FileName), Symbols.size());
   }
 
+  std::pair<std::string, std::string> const &getCsectNames() {
+    return CsectNames;
+  }
+
   void setCompilerVersion(std::string CompilerVers) {
     if (CompilerVersion.empty())
       CompilerVersion = std::move(CompilerVers);
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 3f585d4d2efaf5..e9c7c96298d683 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -623,7 +623,8 @@ class MCContext {
                                                    unsigned EntrySize);
 
   MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind,
-                                MCSection *Parent, const MCExpr *SubsectionId);
+                                MCSection *Parent = nullptr,
+                                const MCExpr *SubsectionId = nullptr);
 
   MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
                                 SectionKind Kind, StringRef COMDATSymName,
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 2345509b161da5..52cde0632483a0 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -24,12 +24,15 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   ~MCGOFFStreamer() override;
 
-  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
-    return false;
-  }
+  // state management
+  void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override;
+
+  void switchSection(MCSection *Section,
+                     const MCExpr *Subsection = nullptr) override;
+  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         Align ByteAlignment) override {}
-  void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override {}
+  void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
                     uint64_t Size = 0, Align ByteAlignment = Align(1),
                     SMLoc Loc = SMLoc()) override {}
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index cc4e2bbe246e2d..bb3c3b07947aa3 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -18,10 +18,63 @@
 namespace llvm {
 
 class MCSymbolGOFF : public MCSymbol {
+  Align Alignment;
+
+  mutable StringRef AliasName; // ADA indirect
+
+  enum SymbolFlags : uint16_t {
+    SF_NoRent = 0x01,    // Symbol is no-reentrant.
+    SF_Alias = 0x02,     // Symbol is alias.
+    SF_Hidden = 0x04,    // Symbol is hidden, aka not exported.
+    SF_Weak = 0x08,      // Symbol is weak.
+    SF_OSLinkage = 0x10, // Symbol uses OS linkage.
+  };
+
+  // Shift value for GOFF::ESDExecutable. 3 possible values. 2 bits.
+  static constexpr uint8_t GOFF_Executable_Shift = 6;
+  static constexpr uint8_t GOFF_Executable_Bitmask = 0x03;
+
 public:
   MCSymbolGOFF(const StringMapEntry<bool> *Name, bool IsTemporary)
-      : MCSymbol(SymbolKindGOFF, Name, IsTemporary) {}
+      : MCSymbol(SymbolKindGOFF, Name, IsTemporary), AliasName() {}
   static bool classof(const MCSymbol *S) { return S->isGOFF(); }
+
+  bool hasAliasName() const { return !AliasName.empty(); }
+  void setAliasName(StringRef Name) { AliasName = Name; }
+  StringRef getAliasName() const { return AliasName; }
+
+  void setTemporary(bool Value) { IsTemporary = Value; }
+
+  void setOSLinkage(bool Value = true) const {
+    modifyFlags(Value ? SF_OSLinkage : 0, SF_OSLinkage);
+  }
+  bool isOSLinkage() const { return getFlags() & SF_OSLinkage; }
+
+  void setAlignment(Align Value) { Alignment = Value; }
+  Align getAlignment() const { return Alignment; }
+
+  void setExecutable(GOFF::ESDExecutable Value) const {
+    modifyFlags(Value << GOFF_Executable_Shift,
+                GOFF_Executable_Bitmask << GOFF_Executable_Shift);
+  }
+  GOFF::ESDExecutable getExecutable() const {
+    return static_cast<GOFF::ESDExecutable>(
+        (getFlags() >> GOFF_Executable_Shift) & GOFF_Executable_Bitmask);
+  }
+
+  void setHidden(bool Value = true) {
+    modifyFlags(Value ? SF_Hidden : 0, SF_Hidden);
+  }
+  bool isHidden() const { return getFlags() & SF_Hidden; }
+  bool isExported() const { return !isHidden(); }
+
+  void setWeak(bool Value = true) { modifyFlags(Value ? SF_Weak : 0, SF_Weak); }
+  bool isWeak() const { return getFlags() & SF_Weak; }
+
+  void setAlias(bool Value = true) {
+    modifyFlags(Value ? SF_Alias : 0, SF_Alias);
+  }
+  bool isAlias() const { return getFlags() & SF_Alias; }
 };
 } // end namespace llvm
 
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 15b59421a0f44a..3b4f7faa99d590 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2744,9 +2744,13 @@ MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
 MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   auto *Symbol = TM.getSymbol(GO);
+  if (Kind.isData())
+    return getContext().getGOFFSection(Symbol->getName(),
+                                       SectionKind::getData());
+
   if (Kind.isBSS())
-    return getContext().getGOFFSection(Symbol->getName(), SectionKind::getBSS(),
-                                       nullptr, nullptr);
+    return getContext().getGOFFSection(Symbol->getName(),
+                                       SectionKind::getBSS());
 
   return getContext().getObjectFileInfo()->getTextSection();
 }
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index addeb6db959693..60ab410e9765e2 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -13,8 +13,13 @@
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
+#include "llvm/MC/MCSectionGOFF.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ConvertEBCDIC.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Path.h"
@@ -217,13 +222,112 @@ void GOFFOstream::write_impl(const char *Ptr, size_t Size) {
   }
 }
 
+/// \brief Wrapper class for symbols used exclusively for the symbol table in a
+/// GOFF file.
+class GOFFSymbol {
+public:
+  std::string Name;
+  uint32_t EsdId;
+  uint32_t ParentEsdId;
+  const MCSymbolGOFF *MCSym;
+  GOFF::ESDSymbolType SymbolType;
+
+  GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
+  GOFF::ESDAmode Amode = GOFF::ESD_AMODE_64;
+  GOFF::ESDRmode Rmode = GOFF::ESD_RMODE_64;
+  GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
+  GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
+  GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Byte;
+  GOFF::ESDTextStyle TextStyle = GOFF::ESD_TS_ByteOriented;
+  GOFF::ESDBindingAlgorithm BindAlgorithm = GOFF::ESD_BA_Concatenate;
+  GOFF::ESDLoadingBehavior LoadBehavior = GOFF::ESD_LB_Initial;
+  GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
+  GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
+  GOFF::ESDReserveQwords ReservedQwords = GOFF::ESD_RQ_0;
+
+  uint32_t SortKey = 0;
+  uint32_t SectionLength = 0;
+  uint32_t ADAEsdId = 0;
+  bool Indirect = false;
+  bool ForceRent = false;
+  bool Renamable = false;
+  bool ReadOnly = false;
+  uint32_t EASectionEsdId = 0;
+  uint32_t EASectionOffset = 0;
+
+  GOFFSymbol(StringRef Name, GOFF::ESDSymbolType Type, uint32_t EsdID,
+             uint32_t ParentEsdID)
+      : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
+        MCSym(nullptr), SymbolType(Type) {}
+  GOFFSymbol() {}
+
+  bool isForceRent() const { return ForceRent; }
+  bool isReadOnly() const { return ReadOnly; }
+  bool isRemovable() const { return false; }
+  bool isExecutable() const { return Executable == GOFF::ESD_EXE_CODE; }
+  bool isExecUnspecified() const {
+    return Executable == GOFF::ESD_EXE_Unspecified;
+  }
+  bool isWeakRef() const { return BindingStrength == GOFF::ESD_BST_Weak; }
+  bool isExternal() const {
+    return (BindingScope == GOFF::ESD_BSC_Library) ||
+           (BindingScope == GOFF::ESD_BSC_ImportExport);
+  }
+
+  void setAlignment(Align A) {
+    // The GOFF alignment is encoded as log_2 value.
+    uint8_t Log = Log2(A);
+    if (Log <= GOFF::ESD_ALIGN_4Kpage)
+      Alignment = static_cast<GOFF::ESDAlignment>(Log);
+    else
+      llvm_unreachable("Unsupported alignment");
+  }
+};
+
+/// \brief Wrapper class for sections used exclusively for representing sections
+/// of the GOFF output that have actual bytes.  This could be a ED or a PR.
+/// Relocations will always have a P-pointer to the ESDID of one of these.
+struct GOFFSection {
+  uint32_t PEsdId;
+  uint32_t REsdId;
+  uint32_t SDEsdId;
+  const MCSectionGOFF *MC;
+
+  GOFFSection(uint32_t PEsdId, uint32_t REsdId, uint32_t SDEsdId)
+      : PEsdId(PEsdId), REsdId(REsdId), SDEsdId(SDEsdId), MC(nullptr) {}
+  GOFFSection(uint32_t PEsdId, uint32_t REsdId, uint32_t SDEsdId,
+              const MCSectionGOFF *MC)
+      : PEsdId(PEsdId), REsdId(REsdId), SDEsdId(SDEsdId), MC(MC) {}
+};
+
+// An MCSymbol may map to up to two GOFF Symbols. The first is the
+// "true" underlying symbol, the second one represents any indirect
+// references to that symbol.
 class GOFFObjectWriter : public MCObjectWriter {
+  typedef DenseMap<MCSymbol const *, uint32_t> SymbolMapType;
+  typedef DenseMap<MCSection const *, GOFFSection> SectionMapType;
+
   // The target specific GOFF writer instance.
   std::unique_ptr<MCGOFFObjectTargetWriter> TargetObjectWriter;
 
+  /// Lookup table for MCSymbols to GOFFSymbols.  Needed to determine EsdIds
+  /// of symbols in Relocations.
+  SymbolMapType SymbolMap;
+
+  /// Lookup table for MCSections to GOFFSections.  Needed to determine
+  /// SymbolType on GOFFSymbols that reside in GOFFSections.
+  SectionMapType SectionMap;
+
   // The stream used to write the GOFF records.
   GOFFOstream OS;
 
+  uint32_t EsdCounter = 1;
+
+  // The "root" SD node. This should have ESDID = 1
+  GOFFSymbol RootSD;
+  uint32_t EntryEDEsdId;
+  uint32_t CodeLDEsdId;
+
 public:
   GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
                    raw_pwrite_stream &OS)
@@ -231,20 +335,290 @@ class GOFFObjectWriter : public MCObjectWriter {
 
   ~GOFFObjectWriter() override {}
 
+private:
   // Write GOFF records.
   void writeHeader();
+
+  void writeSymbol(const GOFFSymbol &Symbol, const MCAsmLayout &Layout);
+
+  void writeADAandCodeSectionSymbols(MCAssembler &Asm,
+                                     const MCAsmLayout &Layout);
+  // Write out all ESD Symbols that own a section. GOFF doesn't have
+  // "sections" in the way other object file formats like ELF do; instead
+  // a GOFF section is defined as a triple of ESD Symbols (SD, ED, PR/LD).
+  // The PR/LD symbol should own a TXT record that contains the actual
+  // data of the section.
+  void writeSectionSymbols(MCAssembler &Asm, const MCAsmLayout &Layout);
+
+  void writeText(const MCSectionGOFF *MCSec, uint32_t EsdId, bool IsStructured,
+                 MCAssembler &Asm, const MCAsmLayout &Layout);
+
   void writeEnd();
 
+public:
   // Implementation of the MCObjectWriter interface.
   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
                         const MCFragment *Fragment, const MCFixup &Fixup,
                         MCValue Target, uint64_t &FixedValue) override {}
   void executePostLayoutBinding(MCAssembler &Asm,
-                                const MCAsmLayout &Layout) override {}
+                                const MCAsmLayout &Layout) override;
   uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+
+private:
+  GOFFSection *createGOFFSection(GOFFSymbol *Pptr, GOFFSymbol *Rptr,
+                                 GOFFSymbol *SD, const MCSectionGOFF *MC);
+  GOFFSymbol createGOFFSymbol(StringRef Name, GOFF::ESDSymbolType Type,
+                              uint32_t ParentEsdId);
+  GOFFSymbol createSDSymbol(StringRef Name);
+  GOFFSymbol createEDSymbol(StringRef Name, uint32_t ParentEsdId);
+  GOFFSymbol createLDSymbol(StringRef Name, uint32_t ParentEsdId);
+  GOFFSymbol createERSymbol(StringRef Name, uint32_t ParentEsdId,
+                            const MCSymbolGOFF *Source = nullptr);
+  GOFFSymbol createPRSymbol(StringRef Name, uint32_t ParentEsdId);
+
+  GOFFSymbol createWSASymbol(uint32_t ParentEsdId, bool ReserveQWords = false);
+
+  // Define the root SD node as well as the symbols that make up the
+  // ADA section.
+  void defineRootSD(MCAssembler &Asm, const MCAsmLayout &Layout);
+
+  void defineSectionSymbols(const MCAssembler &Asm,
+                            const MCSectionGOFF &Section,
+                            const MCAsmLayout &Layout);
+  void writeSymbolDefinedInModule(const MCSymbolGOFF &Symbol, MCAssembler &Asm,
+                                  const MCAsmLayout &Layout);
+  void writeSymbolDeclaredInModule(const MCSymbolGOFF &Symbol, MCAssembler &Asm,
+                                   const MCAsmLayout &Layout);
+
+  // In XPLINK, the ESD Record owning the ADA is always the 4th record, behind
+  // the HDR record, the Root SD, and the ED symbol for the ADA, meaning it
+  // always has EsdId = 3.
+  static constexpr uint32_t ADAEsdId = 3u;
 };
 } // end anonymous namespace
 
+GOFFSymbol GOFFObjectWriter::createGOFFSymbol(StringRef Name,
+                                              GOFF::ESDSymbolType Type,
+                                              uint32_t ParentEsdId) {
+  return GOFFSymbol(Name, Type, EsdCounter++, ParentEsdId);
+}
+
+GOFFSymbol GOFFObjectWriter::createSDSymbol(StringRef Name) {
+  return createGOFFSymbol(Name, GOFF::ESD_ST_SectionDefinition, 0);
+}
+
+GOFFSymbol GOFFObjectWriter::createEDSymbol(StringRef Name,
+                                            uint32_t ParentEsdId) {
+  GOFFSymbol ED =
+      createGOFFSymbol(Name, GOFF::ESD_ST_ElementDefinition, ParentEsdId);
+
+  ED.Alignment = GOFF::ESD_ALIGN_Doubleword;
+  return ED;
+}
+
+GOFFSymbol GOFFObjectWriter::createLDSymbol(StringRef Name,
+                                            uint32_t ParentEsdId) {
+  return createGOFFSymbol(Name, GOFF::ESD_ST_LabelDefinition, ParentEsdId);
+}
+
+GOFFSymbol GOFFObjectWriter::createERSymbol(StringRef Name,
+                                            uint32_t ParentEsdId,
+                                            const MCSymbolGOFF *Source) {
+  GOFFSymbol ER =
+      createGOFFSymbol(Name, GOFF::ESD_ST_ExternalReference, ParentEsdId);
+
+  if (Source) {
+    ER.Linkage = Source->isOSLinkage() ? GOFF::ESDLinkageType::ESD_LT_OS
+                                       : GOFF::ESDLinkageType::ESD_LT_XPLink;
+    ER.Executable = Source->getExecutable();
+    ER.BindingScope = Source->isExternal()
+                          ? GOFF::ESDBindingScope::ESD_BSC_Library
+                          : GOFF::ESDBindingScope::ESD_BSC_Section;
+    ER.BindingStrength = Source->isWeak()
+                             ? GOFF::ESDBindingStrength::ESD_BST_Weak
+                             : GOFF::ESDBindingStrength::ESD_BST_Strong;
+  }
+
+  return ER;
+}
+
+GOFFSymbol GOFFObjectWriter::createPRSymbol(StringRef Name,
+                                            uint32_t ParentEsdId) {
+  return createGOFFSymbol(Name, GOFF::ESD_ST_PartReference, ParentEsdId);
+}
+
+GOFFSymbol GOFFObjectWriter::createWSASymbol(uint32_t ParentEsdId,
+                                             bool ReserveQwords) {
+  const char *WSAClassName = "C_WSA64";
+  GOFFSymbol WSA = createEDSymbol(WSAClassName, ParentEsdId);
+
+  WSA.Executable = GOFF::ESD_EXE_DATA;
+  WSA.TextStyle = GOFF::ESD_TS_ByteOriented;
+  WSA.BindAlgorithm = GOFF::ESD_BA_Merge;
+  WSA.Alignment = GOFF::ESD_ALIGN_Quadword;
+  WSA.LoadBehavior = GOFF::ESD_LB_Deferred;
+  WSA.NameSpace = GOFF::ESD_NS_Parts;
+  WSA.SectionLength = 0;
+  WSA.ReservedQwords = ReserveQwords ? GOFF::ESD_RQ_1 : GOFF::ESD_RQ_0;
+
+  return WSA;
+}
+
+static uint32_t getADASectionLength(MCAssembler &Asm,
+                                    const MCAsmLayout &Layout) {
+  for (MCSection &S : Asm)
+    if (S.getName().equals(".ada"))
+      return Layout.getSectionAddressSize(&S);
+  return 0;
+}
+
+void GOFFObjectWriter::defineRootSD(MCAssembler &Asm,
+                                    const MCAsmLayout &Layout) {
+  StringRef FileName = "";
+  if (!Asm.getFileNames().empty())
+    FileName = sys::path::stem((*(Asm.getFileNames().begin())).first);
+  std::pair<std::string, std::string> CsectNames = Asm.getCsectNames();
+  if (CsectNames.first.empty()) {
+    RootSD = createSDSymbol(FileName.str().append("#C"));
+    RootSD.BindingScope = GOFF::ESD_BSC_Section;
+  } else {
+    RootSD = createSDSymbol(CsectNames.first);
+  }
+  RootSD.Executable = GOFF::ESD_EXE_CODE;
+}
+
+void GOFFObjectWriter::writeSymbolDefinedInModule(const MCSymbolGOFF &Symbol,
+                                                  MCAssembler &Asm,
+                                                  const MCAsmLayout &Layout) {
+  MCSection &Section = Symbol.getSection();
+  SectionKind Kind = Section.getKind();
+  auto &Sec = cast<MCSectionGOFF>(Section);
+
+  StringRef SymbolName = Symbol.getName();...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list