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

Kai Nacke via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Apr 8 13:12:31 PDT 2025


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

>From 77c230f82a61769714bee98b2e848820850d9cb5 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 24 Mar 2025 16:26:19 -0400
Subject: [PATCH 01/15] [GOFF] Add writing of section symbols

The GOFF format uses symbol definitions to represent sections and
symbols. Introducing a section can require up to 3 symbol definitions.
However, most of these details are not needed by the AsmPrinter.
To mapped from a section (a MCSectionGOFF) to the symbol definitions,
a new class called MCGOFFSymbolMapper is used. The same information
can also be used by the assembly output, which justifies this
centralized approach. Writing the mapped symbols is then straight
forward.
---
 llvm/include/llvm/BinaryFormat/GOFF.h     |  85 +++++++
 llvm/include/llvm/MC/MCGOFFSymbolMapper.h | 148 +++++++++++
 llvm/lib/MC/CMakeLists.txt                |   1 +
 llvm/lib/MC/GOFFObjectWriter.cpp          | 290 +++++++++++++++++++---
 llvm/lib/MC/MCGOFFSymbolMapper.cpp        | 203 +++++++++++++++
 llvm/lib/MC/MCObjectFileInfo.cpp          |   2 +-
 llvm/test/CodeGen/SystemZ/zos-ppa2.ll     |   2 +-
 llvm/test/MC/GOFF/section.ll              |  73 ++++++
 8 files changed, 765 insertions(+), 39 deletions(-)
 create mode 100644 llvm/include/llvm/MC/MCGOFFSymbolMapper.h
 create mode 100644 llvm/lib/MC/MCGOFFSymbolMapper.cpp
 create mode 100644 llvm/test/MC/GOFF/section.ll

diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
index 443bcfc9479a8..43d80e0c247e9 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -169,6 +169,91 @@ enum SubsectionKind : uint8_t {
   SK_PPA1 = 2,
   SK_PPA2 = 4,
 };
+
+// The standard System/390 convention is to name the high-order (leftmost) bit
+// in a byte as bit zero. The Flags type helps to set bits in byte according
+// to this numeration order.
+class Flags {
+  uint8_t Val;
+
+  constexpr static uint8_t bits(uint8_t BitIndex, uint8_t Length, uint8_t Value,
+                                uint8_t OldValue) {
+    uint8_t Pos = 8 - BitIndex - Length;
+    uint8_t Mask = ((1 << Length) - 1) << Pos;
+    Value = Value << Pos;
+    return (OldValue & ~Mask) | Value;
+  }
+
+public:
+  constexpr Flags() : Val(0) {}
+  constexpr Flags(uint8_t BitIndex, uint8_t Length, uint8_t Value)
+      : Val(bits(BitIndex, Length, Value, 0)) {}
+
+  template <typename T>
+  constexpr void set(uint8_t BitIndex, uint8_t Length, T NewValue) {
+    Val = bits(BitIndex, Length, static_cast<uint8_t>(NewValue), Val);
+  }
+
+  template <typename T>
+  constexpr T get(uint8_t BitIndex, uint8_t Length) const {
+    return static_cast<T>((Val >> (8 - BitIndex - Length)) &
+                          ((1 << Length) - 1));
+  }
+
+  constexpr operator uint8_t() const { return Val; }
+};
+
+// Structure for the flag field of a symbol. See
+// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record,
+// offset 41, for the definition.
+struct SymbolFlags {
+  Flags SymFlags;
+
+#define GOFF_SYMBOL_FLAG(NAME, TYPE, BITINDEX, LENGTH)                         \
+  void set##NAME(TYPE Val) { SymFlags.set<TYPE>(BITINDEX, LENGTH, Val); }      \
+  TYPE get##NAME() const { return SymFlags.get<TYPE>(BITINDEX, LENGTH); }
+
+  GOFF_SYMBOL_FLAG(FillBytePresence, bool, 0, 1)
+  GOFF_SYMBOL_FLAG(Mangled, bool, 1, 1)
+  GOFF_SYMBOL_FLAG(Renameable, bool, 2, 1)
+  GOFF_SYMBOL_FLAG(RemovableClass, bool, 3, 1)
+  GOFF_SYMBOL_FLAG(ReservedQwords, ESDReserveQwords, 5, 3)
+
+#undef GOFF_SYMBOL_FLAG
+
+constexpr operator uint8_t() const { return static_cast<uint8_t>(SymFlags); }
+};
+
+// Structure for the behavioral attributes. See
+// https://www.ibm.com/docs/en/zos/3.1.0?topic=record-external-symbol-definition-behavioral-attributes
+// for the definition.
+struct BehavioralAttributes {
+  Flags Attr[10];
+
+#define GOFF_BEHAVIORAL_ATTRIBUTE(NAME, TYPE, ATTRIDX, BITINDEX, LENGTH)       \
+  void set##NAME(TYPE Val) { Attr[ATTRIDX].set<TYPE>(BITINDEX, LENGTH, Val); } \
+  TYPE get##NAME() const { return Attr[ATTRIDX].get<TYPE>(BITINDEX, LENGTH); }
+
+  GOFF_BEHAVIORAL_ATTRIBUTE(Amode, GOFF::ESDAmode, 0, 0, 8)
+  GOFF_BEHAVIORAL_ATTRIBUTE(Rmode, GOFF::ESDRmode, 1, 0, 8)
+  GOFF_BEHAVIORAL_ATTRIBUTE(TextStyle, GOFF::ESDTextStyle, 2, 0, 4)
+  GOFF_BEHAVIORAL_ATTRIBUTE(BindingAlgorithm, GOFF::ESDBindingAlgorithm, 2, 4,
+                            4)
+  GOFF_BEHAVIORAL_ATTRIBUTE(TaskingBehavior, GOFF::ESDTaskingBehavior, 3, 0, 3)
+  GOFF_BEHAVIORAL_ATTRIBUTE(ReadOnly, bool, 3, 4, 1)
+  GOFF_BEHAVIORAL_ATTRIBUTE(Executable, GOFF::ESDExecutable, 3, 5, 3)
+  GOFF_BEHAVIORAL_ATTRIBUTE(DuplicateSymbolSeverity,
+                            GOFF::ESDDuplicateSymbolSeverity, 4, 2, 2)
+  GOFF_BEHAVIORAL_ATTRIBUTE(BindingStrength, GOFF::ESDBindingStrength, 4, 4, 4)
+  GOFF_BEHAVIORAL_ATTRIBUTE(LoadingBehavior, GOFF::ESDLoadingBehavior, 5, 0, 2)
+  GOFF_BEHAVIORAL_ATTRIBUTE(COMMON, bool, 5, 2, 1)
+  GOFF_BEHAVIORAL_ATTRIBUTE(IndirectReference, bool, 5, 3, 1)
+  GOFF_BEHAVIORAL_ATTRIBUTE(BindingScope, GOFF::ESDBindingScope, 5, 4, 4)
+  GOFF_BEHAVIORAL_ATTRIBUTE(LinkageType, GOFF::ESDLinkageType, 6, 2, 1)
+  GOFF_BEHAVIORAL_ATTRIBUTE(Alignment, GOFF::ESDAlignment, 6, 3, 5)
+
+#undef GOFF_BEHAVIORAL_ATTRIBUTE
+};
 } // end namespace GOFF
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
new file mode 100644
index 0000000000000..dbdc1408dab2f
--- /dev/null
+++ b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
@@ -0,0 +1,148 @@
+//===- MCGOFFSymbolMapper.h - Maps MC section/symbol to GOFF symbols ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Maps a section or a symbol to the GOFF symbols it is composed of, and their
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCGOFFSYMBOLMAPPER_H
+#define LLVM_MC_MCGOFFSYMBOLMAPPER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/Support/Alignment.h"
+#include <string>
+#include <utility>
+
+namespace llvm {
+class MCAssembler;
+class MCContext;
+class MCSectionGOFF;
+
+// An "External Symbol Definition" in the GOFF file has a type, and depending on
+// the type a different subset of the fields is used.
+//
+// Unlike other formats, a 2 dimensional structure is used to define the
+// location of data. For example, the equivalent of the ELF .text section is
+// made up of a Section Definition (SD) and a class (Element Definition; ED).
+// The name of the SD symbol depends on the application, while the class has the
+// predefined name C_CODE64.
+//
+// Data can be placed into this structure in 2 ways. First, the data (in a text
+// record) can be associated with an ED symbol. To refer to data, a Label
+// Definition (LD) is used to give an offset into the data a name. When binding,
+// the whole data is pulled into the resulting executable, and the addresses
+// given by the LD symbols are resolved.
+//
+// The alternative is to use a Part Defiition (PR). In this case, the data (in a
+// text record) is associated with the part. When binding, only the data of
+// referenced PRs is pulled into the resulting binary.
+//
+// Both approaches are used, which means that the equivalent of a section in ELF
+// results in 3 GOFF symbol, either SD/ED/LD or SD/ED/PR. Moreover, certain
+// sections are fine with just defining SD/ED symbols. The SymbolMapper takes
+// care of all those details.
+
+// Attributes for SD symbols.
+struct SDAttr {
+  GOFF::ESDTaskingBehavior TaskingBehavior = GOFF::ESD_TA_Unspecified;
+  GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
+};
+
+// Attributes for ED symbols.
+struct EDAttr {
+  bool IsReadOnly = false;
+  GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
+  GOFF::ESDAmode Amode;
+  GOFF::ESDRmode Rmode;
+  GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
+  GOFF::ESDTextStyle TextStyle = GOFF::ESD_TS_ByteOriented;
+  GOFF::ESDBindingAlgorithm BindAlgorithm = GOFF::ESD_BA_Concatenate;
+  GOFF::ESDLoadingBehavior LoadBehavior = GOFF::ESD_LB_Initial;
+  GOFF::ESDReserveQwords ReservedQwords = GOFF::ESD_RQ_0;
+  GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Doubleword;
+};
+
+// Attributes for LD symbols.
+struct LDAttr {
+  bool IsRenamable = false;
+  GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
+  GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
+  GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
+  GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
+  GOFF::ESDAmode Amode;
+  GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
+};
+
+// Attributes for PR symbols.
+struct PRAttr {
+  bool IsRenamable = false;
+  bool IsReadOnly = false; // ???? Not documented.
+  GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
+  GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
+  GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
+  GOFF::ESDAmode Amode;
+  GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
+  GOFF::ESDDuplicateSymbolSeverity DuplicateSymbolSeverity =
+      GOFF::ESD_DSS_NoWarning;
+  GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Byte;
+  uint32_t SortKey = 0;
+};
+
+struct GOFFSectionData {
+  // Name and attributes of SD symbol.
+  StringRef SDName;
+  SDAttr SDAttributes;
+
+  // Name and attributes of ED symbol.
+  StringRef EDName;
+  EDAttr EDAttributes;
+
+  // Name and attributes of LD or PR symbol.
+  StringRef LDorPRName;
+  LDAttr LDAttributes;
+  PRAttr PRAttributes;
+
+  // Indicates if there is a LD or PR symbol.
+  enum { None, LD, PR } Tag;
+
+  // Indicates if the SD symbol is to root symbol (aka the Csect Code).
+  bool IsSDRootSD;
+};
+
+class GOFFSymbolMapper {
+  MCContext &Ctx;
+
+  std::string RootSDName;
+  SDAttr RootSDAttributes;
+
+  std::string ADALDName;
+
+  StringRef BaseName;
+
+  bool IsCsectCodeNameEmpty;
+  bool Is64Bit;
+  bool UsesXPLINK;
+
+public:
+  GOFFSymbolMapper(MCContext &Ctx);
+  GOFFSymbolMapper(MCAssembler &Asm);
+
+  // Required order: .text first, then .ada.
+  std::pair<GOFFSectionData, bool> getSection(const MCSectionGOFF &Section);
+
+  void setBaseName();
+  void determineRootSD(StringRef CSectCodeName);
+  llvm::StringRef getRootSDName() const;
+  const SDAttr &getRootSD() const;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index f49f14c848b90..967ec73a2be5b 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -26,6 +26,7 @@ add_llvm_component_library(LLVMMC
   MCExpr.cpp
   MCFragment.cpp
   MCGOFFStreamer.cpp
+  MCGOFFSymbolMapper.cpp
   MCInst.cpp
   MCInstPrinter.cpp
   MCInstrAnalysis.cpp
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index efaf5ff006ddc..92603c6fb1002 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -13,7 +13,11 @@
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
+#include "llvm/MC/MCGOFFSymbolMapper.h"
+#include "llvm/MC/MCSectionGOFF.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/raw_ostream.h"
@@ -23,44 +27,13 @@ using namespace llvm;
 #define DEBUG_TYPE "goff-writer"
 
 namespace {
-
-// The standard System/390 convention is to name the high-order (leftmost) bit
-// in a byte as bit zero. The Flags type helps to set bits in a byte according
-// to this numeration order.
-class Flags {
-  uint8_t Val;
-
-  constexpr static uint8_t bits(uint8_t BitIndex, uint8_t Length, uint8_t Value,
-                                uint8_t OldValue) {
-    assert(BitIndex < 8 && "Bit index out of bounds!");
-    assert(Length + BitIndex <= 8 && "Bit length too long!");
-
-    uint8_t Mask = ((1 << Length) - 1) << (8 - BitIndex - Length);
-    Value = Value << (8 - BitIndex - Length);
-    assert((Value & Mask) == Value && "Bits set outside of range!");
-
-    return (OldValue & ~Mask) | Value;
-  }
-
-public:
-  constexpr Flags() : Val(0) {}
-  constexpr Flags(uint8_t BitIndex, uint8_t Length, uint8_t Value)
-      : Val(bits(BitIndex, Length, Value, 0)) {}
-
-  void set(uint8_t BitIndex, uint8_t Length, uint8_t Value) {
-    Val = bits(BitIndex, Length, Value, Val);
-  }
-
-  constexpr operator uint8_t() const { return Val; }
-};
-
 // Common flag values on records.
 
 // Flag: This record is continued.
-constexpr uint8_t RecContinued = Flags(7, 1, 1);
+constexpr uint8_t RecContinued = GOFF::Flags(7, 1, 1);
 
 // Flag: This record is a continuation.
-constexpr uint8_t RecContinuation = Flags(6, 1, 1);
+constexpr uint8_t RecContinuation = GOFF::Flags(6, 1, 1);
 
 // The GOFFOstream is responsible to write the data into the fixed physical
 // records of the format. A user of this class announces the begin of a new
@@ -223,13 +196,113 @@ 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();
@@ -237,7 +310,108 @@ class GOFFWriter {
 } // 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);
+
+  // Process the other sections.
+  for (MCSection &S : Asm) {
+    auto &Section = cast<MCSectionGOFF>(S);
+    if (Text != &Section && ADA != &Section)
+      defineSectionSymbols(Section);
+  }
+}
 
 void GOFFWriter::writeHeader() {
   OS.newRecord(GOFF::RT_HDR);
@@ -253,6 +427,45 @@ void GOFFWriter::writeHeader() {
   OS.write_zeros(6);       // Reserved
 }
 
+void GOFFWriter::writeSymbol(const GOFFSymbol &Symbol) {
+  if (Symbol.Offset >= (((uint64_t)1) << 31))
+    report_fatal_error("ESD offset outof range");
+
+  // All symbol names are in EBCDIC.
+  SmallString<256> Name;
+  ConverterEBCDIC::convertToEBCDIC(Symbol.Name, Name);
+
+  // Check length here since this number is technically signed but we need uint
+  // for writing to records.
+  if (Name.size() >= GOFF::MaxDataLength)
+    report_fatal_error("Symbol max name length exceeded");
+  uint16_t NameLength = Name.size();
+
+  OS.newRecord(GOFF::RT_ESD);
+  OS.writebe<uint8_t>(Symbol.SymbolType);   // Symbol Type
+  OS.writebe<uint32_t>(Symbol.EsdId);       // ESDID
+  OS.writebe<uint32_t>(Symbol.ParentEsdId); // Parent or Owning ESDID
+  OS.writebe<uint32_t>(0);                  // Reserved
+  OS.writebe<uint32_t>(
+      static_cast<uint32_t>(Symbol.Offset));     // Offset or Address
+  OS.writebe<uint32_t>(0);                       // Reserved
+  OS.writebe<uint32_t>(Symbol.SectionLength);    // Length
+  OS.writebe<uint32_t>(Symbol.EASectionEDEsdId); // Extended Attribute ESDID
+  OS.writebe<uint32_t>(Symbol.EASectionOffset);  // Extended Attribute Offset
+  OS.writebe<uint32_t>(0);                       // Reserved
+  OS.writebe<uint8_t>(Symbol.NameSpace);         // Name Space ID
+  OS.writebe<uint8_t>(Symbol.SymbolFlags);       // Flags
+  OS.writebe<uint8_t>(Symbol.FillByteValue);     // Fill-Byte Value
+  OS.writebe<uint8_t>(0);                        // Reserved
+  OS.writebe<uint32_t>(Symbol.ADAEsdId);         // ADA ESDID
+  OS.writebe<uint32_t>(Symbol.SortKey);          // Sort Priority
+  OS.writebe<uint64_t>(0);                       // Reserved
+  for (auto F : Symbol.BehavAttrs.Attr)
+    OS.writebe<uint8_t>(F);          // Behavioral Attributes
+  OS.writebe<uint16_t>(NameLength);  // Name Length
+  OS.write(Name.data(), NameLength); // Name
+}
+
 void GOFFWriter::writeEnd() {
   uint8_t F = GOFF::END_EPR_None;
   uint8_t AMODE = 0;
@@ -261,9 +474,9 @@ void GOFFWriter::writeEnd() {
   // TODO Set Flags/AMODE/ESDID for entry point.
 
   OS.newRecord(GOFF::RT_END);
-  OS.writebe<uint8_t>(Flags(6, 2, F)); // Indicator flags
-  OS.writebe<uint8_t>(AMODE);          // AMODE
-  OS.write_zeros(3);                   // Reserved
+  OS.writebe<uint8_t>(GOFF::Flags(6, 2, F)); // Indicator flags
+  OS.writebe<uint8_t>(AMODE);                // AMODE
+  OS.write_zeros(3);                         // Reserved
   // The record count is the number of logical records. In principle, this value
   // is available as OS.logicalRecords(). However, some tools rely on this field
   // being zero.
@@ -273,6 +486,9 @@ void GOFFWriter::writeEnd() {
 
 uint64_t GOFFWriter::writeObject() {
   writeHeader();
+
+  defineSymbols();
+
   writeEnd();
 
   // Make sure all records are written.
diff --git a/llvm/lib/MC/MCGOFFSymbolMapper.cpp b/llvm/lib/MC/MCGOFFSymbolMapper.cpp
new file mode 100644
index 0000000000000..57012c34a94f1
--- /dev/null
+++ b/llvm/lib/MC/MCGOFFSymbolMapper.cpp
@@ -0,0 +1,203 @@
+//===- MCGOFFSymbolMapper.cpp - Maps MC section/symbol to GOFF symbols ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Maps a section or a symbol to the GOFF symbols it is composed of, and their
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCGOFFSymbolMapper.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionGOFF.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Path.h"
+
+using namespace llvm;
+
+namespace {
+const StringLiteral CODE[2]{"C_CODE", "C_CODE64"};
+const StringLiteral WSA[2]{"C_WSA", "C_WSA64"};
+const StringLiteral PPA2[2]{"C_@@PPA2", "C_@@QPPA2"};
+
+const GOFF::ESDAmode AMODE[2]{GOFF::ESD_AMODE_ANY, GOFF::ESD_AMODE_64};
+const GOFF::ESDRmode RMODE[2]{GOFF::ESD_RMODE_31, GOFF::ESD_RMODE_64};
+
+const GOFF::ESDLinkageType LINKAGE[2]{GOFF::ESD_LT_OS, GOFF::ESD_LT_XPLink};
+} // namespace
+
+GOFFSymbolMapper::GOFFSymbolMapper(MCContext &Ctx) : Ctx(Ctx) {
+  IsCsectCodeNameEmpty = true;
+  Is64Bit = true;
+  UsesXPLINK = true;
+}
+
+GOFFSymbolMapper::GOFFSymbolMapper(MCAssembler &Asm)
+    : GOFFSymbolMapper(Asm.getContext()) {
+  if (!Asm.getWriter().getFileNames().empty())
+    BaseName =
+        sys::path::stem((*(Asm.getWriter().getFileNames().begin())).first);
+}
+
+void GOFFSymbolMapper::determineRootSD(StringRef CSectCodeName) {
+  IsCsectCodeNameEmpty = CSectCodeName.empty();
+  if (IsCsectCodeNameEmpty) {
+    RootSDName = BaseName.str().append("#C");
+  } else {
+    RootSDName = CSectCodeName;
+  }
+  RootSDAttributes = {GOFF::ESD_TA_Rent, IsCsectCodeNameEmpty
+                                             ? GOFF::ESD_BSC_Section
+                                             : GOFF::ESD_BSC_Unspecified};
+}
+
+llvm::StringRef GOFFSymbolMapper::getRootSDName() const { return RootSDName; }
+
+const SDAttr &GOFFSymbolMapper::getRootSD() const { return RootSDAttributes; }
+
+std::pair<GOFFSectionData, bool>
+GOFFSymbolMapper::getSection(const MCSectionGOFF &Section) {
+  // Look up GOFFSection from name in MCSectionGOFF.
+  // Customize result, e.g. csect names, 32/64 bit, etc.
+  GOFFSectionData GOFFSec;
+  if (Section.getName() == ".text") {
+    GOFFSec.SDName = RootSDName;
+    GOFFSec.SDAttributes = RootSDAttributes;
+    GOFFSec.IsSDRootSD = true;
+    GOFFSec.EDName = CODE[Is64Bit];
+    // The GOFF alignment is encoded as log_2 value.
+    uint8_t Log = Log2(Section.getAlign());
+    assert(Log <= GOFF::ESD_ALIGN_4Kpage && "Alignment too large");
+    GOFFSec.EDAttributes = {true,
+                            GOFF::ESD_EXE_CODE,
+                            AMODE[Is64Bit],
+                            RMODE[Is64Bit],
+                            GOFF::ESD_NS_NormalName,
+                            GOFF::ESD_TS_ByteOriented,
+                            GOFF::ESD_BA_Concatenate,
+                            GOFF::ESD_LB_Initial,
+                            GOFF::ESD_RQ_0,
+                            static_cast<GOFF::ESDAlignment>(Log)};
+    GOFFSec.LDorPRName = GOFFSec.SDName;
+    GOFFSec.LDAttributes = {false,
+                            GOFF::ESD_EXE_CODE,
+                            GOFF::ESD_NS_NormalName,
+                            GOFF::ESD_BST_Strong,
+                            LINKAGE[UsesXPLINK],
+                            AMODE[Is64Bit],
+                            IsCsectCodeNameEmpty ? GOFF::ESD_BSC_Section
+                                                 : GOFF::ESD_BSC_Library};
+    GOFFSec.Tag = GOFFSectionData::LD;
+  } else if (Section.getName() == ".ada") {
+    assert(!RootSDName.empty() && "RootSD must be defined already");
+    GOFFSec.SDName = RootSDName;
+    GOFFSec.SDAttributes = RootSDAttributes;
+    GOFFSec.IsSDRootSD = true;
+    GOFFSec.EDName = WSA[Is64Bit];
+    GOFFSec.EDAttributes = {false,
+                            GOFF::ESD_EXE_DATA,
+                            AMODE[Is64Bit],
+                            RMODE[Is64Bit],
+                            GOFF::ESD_NS_Parts,
+                            GOFF::ESD_TS_ByteOriented,
+                            GOFF::ESD_BA_Merge,
+                            GOFF::ESD_LB_Deferred,
+                            GOFF::ESD_RQ_1,
+                            Is64Bit ? GOFF::ESD_ALIGN_Quadword
+                                    : GOFF::ESD_ALIGN_Doubleword};
+    ADALDName = BaseName.str().append("#S");
+    GOFFSec.LDorPRName = ADALDName;
+    GOFFSec.PRAttributes = {false,
+                            false,
+                            GOFF::ESD_EXE_DATA,
+                            GOFF::ESD_NS_Parts,
+                            GOFF::ESD_LT_XPLink,
+                            AMODE[Is64Bit],
+                            GOFF::ESD_BSC_Section,
+                            GOFF::ESD_DSS_NoWarning,
+                            Is64Bit ? GOFF::ESD_ALIGN_Quadword
+                                    : GOFF::ESD_ALIGN_Doubleword,
+                            0};
+    GOFFSec.Tag = GOFFSectionData::PR;
+  } else if (Section.getName().starts_with(".gcc_exception_table")) {
+    GOFFSec.SDName = RootSDName;
+    GOFFSec.SDAttributes = RootSDAttributes;
+    GOFFSec.IsSDRootSD = true;
+    GOFFSec.EDName = WSA[Is64Bit];
+    GOFFSec.EDAttributes = {false,
+                            GOFF::ESD_EXE_DATA,
+                            AMODE[Is64Bit],
+                            RMODE[Is64Bit],
+                            GOFF::ESD_NS_Parts,
+                            GOFF::ESD_TS_ByteOriented,
+                            GOFF::ESD_BA_Merge,
+                            UsesXPLINK ? GOFF::ESD_LB_Initial
+                                       : GOFF::ESD_LB_Deferred,
+                            GOFF::ESD_RQ_0,
+                            GOFF::ESD_ALIGN_Doubleword};
+    GOFFSec.LDorPRName = Section.getName();
+    GOFFSec.PRAttributes = {true,
+                            false,
+                            GOFF::ESD_EXE_Unspecified,
+                            GOFF::ESD_NS_Parts,
+                            LINKAGE[UsesXPLINK],
+                            AMODE[Is64Bit],
+                            GOFF::ESD_BSC_Section,
+                            GOFF::ESD_DSS_NoWarning,
+                            GOFF::ESD_ALIGN_Fullword,
+                            0};
+    GOFFSec.Tag = GOFFSectionData::PR;
+  } else if (Section.getName() == ".ppa2list") {
+    GOFFSec.SDName = RootSDName;
+    GOFFSec.SDAttributes = RootSDAttributes;
+    GOFFSec.IsSDRootSD = true;
+    GOFFSec.EDName = PPA2[Is64Bit];
+    GOFFSec.EDAttributes = {true,
+                            GOFF::ESD_EXE_DATA,
+                            AMODE[Is64Bit],
+                            RMODE[Is64Bit],
+                            GOFF::ESD_NS_Parts,
+                            GOFF::ESD_TS_ByteOriented,
+                            GOFF::ESD_BA_Merge,
+                            GOFF::ESD_LB_Initial,
+                            GOFF::ESD_RQ_0,
+                            GOFF::ESD_ALIGN_Doubleword};
+    GOFFSec.LDorPRName = ".&ppa2";
+    GOFFSec.PRAttributes = {true,
+                            false,
+                            GOFF::ESD_EXE_Unspecified,
+                            GOFF::ESD_NS_Parts,
+                            GOFF::ESD_LT_OS,
+                            AMODE[Is64Bit],
+                            GOFF::ESD_BSC_Section,
+                            GOFF::ESD_DSS_NoWarning,
+                            GOFF::ESD_ALIGN_Doubleword,
+                            0};
+    GOFFSec.Tag = GOFFSectionData::PR;
+  } else if (Section.getName() == ".idrl") {
+    GOFFSec.SDName = RootSDName;
+    GOFFSec.SDAttributes = RootSDAttributes;
+    GOFFSec.IsSDRootSD = true;
+    GOFFSec.EDName = "B_IDRL";
+    GOFFSec.EDAttributes = {true,
+                            GOFF::ESD_EXE_Unspecified,
+                            AMODE[Is64Bit],
+                            RMODE[Is64Bit],
+                            GOFF::ESD_NS_NormalName,
+                            GOFF::ESD_TS_Structured,
+                            GOFF::ESD_BA_Concatenate,
+                            GOFF::ESD_LB_NoLoad,
+                            GOFF::ESD_RQ_0,
+                            GOFF::ESD_ALIGN_Doubleword};
+    GOFFSec.Tag = GOFFSectionData::None;
+  } else
+    return std::pair(GOFFSec, false);
+  return std::pair(GOFFSec, true);
+}
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index ab7552ca01061..a514a07ef7d3e 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -557,7 +557,7 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
       Ctx->getGOFFSection(".ppa2list", SectionKind::getData(), nullptr);
 
   ADASection = Ctx->getGOFFSection(".ada", SectionKind::getData(), nullptr);
-  IDRLSection = Ctx->getGOFFSection("B_IDRL", SectionKind::getData(), nullptr);
+  IDRLSection = Ctx->getGOFFSection(".idrl", SectionKind::getData(), nullptr);
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
diff --git a/llvm/test/CodeGen/SystemZ/zos-ppa2.ll b/llvm/test/CodeGen/SystemZ/zos-ppa2.ll
index 07025091fb240..82f416ddb8bf9 100644
--- a/llvm/test/CodeGen/SystemZ/zos-ppa2.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-ppa2.ll
@@ -19,7 +19,7 @@
 ; CHECK:    .quad   L#PPA2-CELQSTRT                 * A(PPA2-CELQSTRT)
 ; CHECK: L#PPA1_void_test_0:
 ; CHECK:    .long   L#PPA2-L#PPA1_void_test_0       * Offset to PPA2
-; CHECK:    .section    "B_IDRL"
+; CHECK:    .section    ".idrl"
 ; CHECK:    .byte   0
 ; CHECK:    .byte   3
 ; CHECK:    .short  30
diff --git a/llvm/test/MC/GOFF/section.ll b/llvm/test/MC/GOFF/section.ll
new file mode 100644
index 0000000000000..a0c64f0b83013
--- /dev/null
+++ b/llvm/test/MC/GOFF/section.ll
@@ -0,0 +1,73 @@
+; RUN: llc <%s --mtriple s390x-ibm-zos --filetype=obj -o - | \
+; RUN:   od -Ax -tx1 -v | FileCheck --ignore-case %s
+; REQUIRES: systemz-registered-target
+
+source_filename = "test.ll"
+
+declare void @other(...)
+
+define void @me() {
+entry:
+  tail call void @other()
+  ret void
+}
+
+; Header record:
+;  03 is prefix byte
+;  f. is header type
+;  .0 is flag
+;  00 is version
+; The 1 at offset 0x33 is the architecture level.
+; CHECK: 000000 03 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 000030 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+; ESD record, type SD.
+;  03 is prefix byte
+;  0. is header type
+;  .0 is flag
+;  00 is version
+;  00 is type = SD
+; The 01 at offset 0x57 is the id of the symbol.
+; The 60 at offset 0x89 is the tasking behavior.
+; The 01 at offset 0x91 is the binding scope.
+; The name begins at offset 0x97, and is test#C.
+; CHECK: 0000050 03 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00
+; CHECK: 0000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 0000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 0000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60
+; CHECK: 0000090 00 01 00 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
+
+; ESD record, type ED.
+; The name is C_WSA64.
+; CHECK: 00000a0 03 00 00 01 00 00 00 02 00 00 00 01 00 00 00 00
+; CHECK: 00000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 00000c0 00 00 00 00 00 00 00 00 03 81 00 00 00 00 00 00
+; CHECK: 00000d0 00 00 00 00 00 00 00 00 00 00 00 00 04 04 01 01
+; CHECK: 00000e0 00 40 04 00 00 00 00 07 c3 6d e6 e2 c1 f6 f4 00
+
+; ESD record, type PR.
+; The name is test#S.
+; CHECK: 00000f0 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 00
+; CHECK: 0000100 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
+; CHECK: 0000110 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
+; CHECK: 0000120 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 01
+; CHECK: 0000130 00 01 24 00 00 00 00 06 a3 85 a2 a3 7b e2 00 00
+
+; ESD record, type ED.
+; The name is C_CODE64.
+; CHECK: 0000140 03 00 00 01 00 00 00 04 00 00 00 01 00 00 00 00
+; CHECK: 0000150 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
+; CHECK: 0000160 00 00 00 00 00 00 00 00 01 80 00 00 00 00 00 00
+; CHECK: 0000170 00 00 00 00 00 00 00 00 00 00 00 00 04 04 00 0a
+; CHECK: 0000180 00 00 04 00 00 00 00 08 c3 6d c3 d6 c4 c5 f6 f4
+
+; ESD record, type LD.
+; The name is test#C.
+; CHECK: 0000190 03 00 00 02 00 00 00 05 00 00 00 04 00 00 00 00
+; CHECK: 00001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 00001b0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 03
+; CHECK: 00001c0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
+; CHECK: 00001d0 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00

>From bb71a074a822a18140f6d312dbdde259fe6c6a71 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 2 Apr 2025 11:25:15 -0400
Subject: [PATCH 02/15] Update llvm/include/llvm/MC/MCGOFFSymbolMapper.h

Co-authored-by: Neumann Hon <neumann.hon at ibm.com>
---
 llvm/include/llvm/MC/MCGOFFSymbolMapper.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
index dbdc1408dab2f..1402f8ad9713e 100644
--- a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
+++ b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
@@ -45,7 +45,7 @@ class MCSectionGOFF;
 // referenced PRs is pulled into the resulting binary.
 //
 // Both approaches are used, which means that the equivalent of a section in ELF
-// results in 3 GOFF symbol, either SD/ED/LD or SD/ED/PR. Moreover, certain
+// results in 3 GOFF symbols, either SD/ED/LD or SD/ED/PR. Moreover, certain
 // sections are fine with just defining SD/ED symbols. The SymbolMapper takes
 // care of all those details.
 

>From a0a2a1f52137923a78470c4d74822f0518b45082 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 2 Apr 2025 11:27:57 -0400
Subject: [PATCH 03/15] Update llvm/include/llvm/MC/MCGOFFSymbolMapper.h

Co-authored-by: Neumann Hon <neumann.hon at ibm.com>
---
 llvm/include/llvm/MC/MCGOFFSymbolMapper.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
index 1402f8ad9713e..252fc20454536 100644
--- a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
+++ b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
@@ -40,7 +40,7 @@ class MCSectionGOFF;
 // the whole data is pulled into the resulting executable, and the addresses
 // given by the LD symbols are resolved.
 //
-// The alternative is to use a Part Defiition (PR). In this case, the data (in a
+// The alternative is to use a Part Definition (PR). In this case, the data (in a
 // text record) is associated with the part. When binding, only the data of
 // referenced PRs is pulled into the resulting binary.
 //

>From 18cd9eb5e1a042800648dff3d5872552797c9108 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 2 Apr 2025 11:28:22 -0400
Subject: [PATCH 04/15] Update llvm/lib/MC/GOFFObjectWriter.cpp

Co-authored-by: Neumann Hon <neumann.hon at ibm.com>
---
 llvm/lib/MC/GOFFObjectWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 92603c6fb1002..062e62f31be40 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -429,7 +429,7 @@ void GOFFWriter::writeHeader() {
 
 void GOFFWriter::writeSymbol(const GOFFSymbol &Symbol) {
   if (Symbol.Offset >= (((uint64_t)1) << 31))
-    report_fatal_error("ESD offset outof range");
+    report_fatal_error("ESD offset out of range");
 
   // All symbol names are in EBCDIC.
   SmallString<256> Name;

>From f2be856fba17f7b9f8ba462b2cfbada00af5cd49 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 2 Apr 2025 11:46:30 -0400
Subject: [PATCH 05/15] More updates

---
 llvm/include/llvm/BinaryFormat/GOFF.h     | 8 ++++----
 llvm/include/llvm/MC/MCGOFFSymbolMapper.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
index 43d80e0c247e9..bfa41d100a3b7 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -174,7 +174,7 @@ enum SubsectionKind : uint8_t {
 // in a byte as bit zero. The Flags type helps to set bits in byte according
 // to this numeration order.
 class Flags {
-  uint8_t Val;
+  uint8_t Val = 0;
 
   constexpr static uint8_t bits(uint8_t BitIndex, uint8_t Length, uint8_t Value,
                                 uint8_t OldValue) {
@@ -185,7 +185,7 @@ class Flags {
   }
 
 public:
-  constexpr Flags() : Val(0) {}
+  constexpr Flags() = default;
   constexpr Flags(uint8_t BitIndex, uint8_t Length, uint8_t Value)
       : Val(bits(BitIndex, Length, Value, 0)) {}
 
@@ -204,7 +204,7 @@ class Flags {
 };
 
 // Structure for the flag field of a symbol. See
-// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record,
+// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record ,
 // offset 41, for the definition.
 struct SymbolFlags {
   Flags SymFlags;
@@ -221,7 +221,7 @@ struct SymbolFlags {
 
 #undef GOFF_SYMBOL_FLAG
 
-constexpr operator uint8_t() const { return static_cast<uint8_t>(SymFlags); }
+  constexpr operator uint8_t() const { return static_cast<uint8_t>(SymFlags); }
 };
 
 // Structure for the behavioral attributes. See
diff --git a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
index 252fc20454536..c1aba6f1a413c 100644
--- a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
+++ b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
@@ -32,7 +32,7 @@ class MCSectionGOFF;
 // location of data. For example, the equivalent of the ELF .text section is
 // made up of a Section Definition (SD) and a class (Element Definition; ED).
 // The name of the SD symbol depends on the application, while the class has the
-// predefined name C_CODE64.
+// predefined name C_CODE/C_CODE64 in AMODE31 and AMODE64 respectively.
 //
 // Data can be placed into this structure in 2 ways. First, the data (in a text
 // record) can be associated with an ED symbol. To refer to data, a Label

>From 3cf7324ec5b335d75d1b887a49d0992abc31a6d2 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 2 Apr 2025 19:44:01 -0400
Subject: [PATCH 06/15] Remove the class GOFFSymbolMapper

---
 llvm/include/llvm/BinaryFormat/GOFF.h         |   4 +-
 .../CodeGen/TargetLoweringObjectFileImpl.h    |   2 +
 llvm/include/llvm/MC/MCContext.h              |  35 ++-
 ...CGOFFSymbolMapper.h => MCGOFFAttributes.h} |  89 +++-----
 llvm/include/llvm/MC/MCGOFFStreamer.h         |   5 +
 llvm/include/llvm/MC/MCObjectFileInfo.h       |   4 -
 llvm/include/llvm/MC/MCSectionGOFF.h          |  71 +++++-
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  |  59 ++++-
 llvm/lib/MC/CMakeLists.txt                    |   1 -
 llvm/lib/MC/GOFFObjectWriter.cpp              |  80 ++++---
 llvm/lib/MC/MCContext.cpp                     |  72 ++++++-
 llvm/lib/MC/MCGOFFStreamer.cpp                |  18 ++
 llvm/lib/MC/MCGOFFSymbolMapper.cpp            | 203 ------------------
 llvm/lib/MC/MCObjectFileInfo.cpp              |  58 +++--
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp |   7 +-
 llvm/test/MC/GOFF/section.ll                  |   1 -
 16 files changed, 362 insertions(+), 347 deletions(-)
 rename llvm/include/llvm/MC/{MCGOFFSymbolMapper.h => MCGOFFAttributes.h} (69%)
 delete mode 100644 llvm/lib/MC/MCGOFFSymbolMapper.cpp

diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
index bfa41d100a3b7..49d2809cb6524 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -204,8 +204,8 @@ class Flags {
 };
 
 // Structure for the flag field of a symbol. See
-// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record ,
-// offset 41, for the definition.
+// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record
+// at offset 41 for the definition.
 struct SymbolFlags {
   Flags SymFlags;
 
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 10f0594c267ae..b2ff064297809 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -320,6 +320,8 @@ class TargetLoweringObjectFileGOFF : public TargetLoweringObjectFile {
   TargetLoweringObjectFileGOFF();
   ~TargetLoweringObjectFileGOFF() override = default;
 
+  void getModuleMetadata(Module &M) override;
+
   MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
                                     const TargetMachine &TM) const override;
   MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index e97c890ce9135..a35df1bba4bc1 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -19,8 +19,10 @@
 #include "llvm/BinaryFormat/XCOFF.h"
 #include "llvm/MC/MCAsmMacro.h"
 #include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCPseudoProbe.h"
 #include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCSymbolTableEntry.h"
 #include "llvm/MC/SectionKind.h"
 #include "llvm/Support/Allocator.h"
@@ -54,7 +56,6 @@ class MCSection;
 class MCSectionCOFF;
 class MCSectionDXContainer;
 class MCSectionELF;
-class MCSectionGOFF;
 class MCSectionMachO;
 class MCSectionSPIRV;
 class MCSectionWasm;
@@ -599,8 +600,36 @@ class MCContext {
                                                    unsigned Flags,
                                                    unsigned EntrySize);
 
-  MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind,
-                                MCSection *Parent, uint32_t Subsection = 0);
+private:
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef SDName,
+                                GOFF::SDAttr SDAttributes, StringRef EDName,
+                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
+                                GOFF::LDAttr LDAttributes,
+                                GOFF::PRAttr PRAttributes,
+                                MCSectionGOFF::SectionFlags Flags);
+
+public:
+  // Create a section with SD/ED/LD symbols.
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef SDName,
+                                GOFF::SDAttr SDAttributes, StringRef EDName,
+                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
+                                GOFF::LDAttr LDAttributes);
+  // Create a section with SD/ED/PR symbols.
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef SDName,
+                                GOFF::SDAttr SDAttributes, StringRef EDName,
+                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
+                                GOFF::PRAttr PRAttributes);
+  // Create a section with root-SD/ED/LD symbols, using the root-SD name for LD.
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
+                                GOFF::EDAttr EDAttributes,
+                                GOFF::LDAttr LDAttributes);
+  // Create a section with root-SD/ED/PR symbols.
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
+                                GOFF::EDAttr EDAttributes, StringRef PRName,
+                                GOFF::PRAttr PRAttributes);
+  // Create a section with root-SD/ED symbols.
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
+                                GOFF::EDAttr EDAttributes);
 
   MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
                                 StringRef COMDATSymName, int Selection,
diff --git a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h b/llvm/include/llvm/MC/MCGOFFAttributes.h
similarity index 69%
rename from llvm/include/llvm/MC/MCGOFFSymbolMapper.h
rename to llvm/include/llvm/MC/MCGOFFAttributes.h
index c1aba6f1a413c..6a27438b6e81a 100644
--- a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h
+++ b/llvm/include/llvm/MC/MCGOFFAttributes.h
@@ -1,4 +1,4 @@
-//===- MCGOFFSymbolMapper.h - Maps MC section/symbol to GOFF symbols ------===//
+//===- MCGOFFAttributes.h - Attributes of GOFF symbols --------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,25 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Maps a section or a symbol to the GOFF symbols it is composed of, and their
-// attributes.
+// Defines the various attribute collections defining GOFF symbols.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_MC_MCGOFFSYMBOLMAPPER_H
-#define LLVM_MC_MCGOFFSYMBOLMAPPER_H
+#ifndef LLVM_MC_MCGOFFATTRIBUTES_H
+#define LLVM_MC_MCGOFFATTRIBUTES_H
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/GOFF.h"
-#include "llvm/Support/Alignment.h"
-#include <string>
-#include <utility>
 
 namespace llvm {
-class MCAssembler;
-class MCContext;
-class MCSectionGOFF;
-
+namespace GOFF {
 // An "External Symbol Definition" in the GOFF file has a type, and depending on
 // the type a different subset of the fields is used.
 //
@@ -40,8 +33,8 @@ class MCSectionGOFF;
 // the whole data is pulled into the resulting executable, and the addresses
 // given by the LD symbols are resolved.
 //
-// The alternative is to use a Part Definition (PR). In this case, the data (in a
-// text record) is associated with the part. When binding, only the data of
+// The alternative is to use a Part Definition (PR). In this case, the data (in
+// a text record) is associated with the part. When binding, only the data of
 // referenced PRs is pulled into the resulting binary.
 //
 // Both approaches are used, which means that the equivalent of a section in ELF
@@ -95,54 +88,40 @@ struct PRAttr {
   uint32_t SortKey = 0;
 };
 
-struct GOFFSectionData {
-  // Name and attributes of SD symbol.
-  StringRef SDName;
-  SDAttr SDAttributes;
-
-  // Name and attributes of ED symbol.
-  StringRef EDName;
-  EDAttr EDAttributes;
-
-  // Name and attributes of LD or PR symbol.
-  StringRef LDorPRName;
-  LDAttr LDAttributes;
-  PRAttr PRAttributes;
+// Class names and other values depending on AMODE64 or AMODE31, and other
+// environment properties.
+template <bool Is64Bit>
+constexpr StringLiteral CODE =
+    Is64Bit ? StringLiteral("C_CODE64") : StringLiteral("C_CODE");
 
-  // Indicates if there is a LD or PR symbol.
-  enum { None, LD, PR } Tag;
-
-  // Indicates if the SD symbol is to root symbol (aka the Csect Code).
-  bool IsSDRootSD;
-};
+template <bool Is64Bit>
+constexpr StringLiteral WSA =
+    Is64Bit ? StringLiteral("C_WSA64") : StringLiteral("C_WSA");
 
-class GOFFSymbolMapper {
-  MCContext &Ctx;
+template <bool Is64Bit>
+constexpr StringLiteral DATA =
+    Is64Bit ? StringLiteral("C_DATA64") : StringLiteral("C_DATA");
 
-  std::string RootSDName;
-  SDAttr RootSDAttributes;
+template <bool Is64Bit>
+constexpr StringLiteral PPA2 =
+    Is64Bit ? StringLiteral("C_@@QPPA2") : StringLiteral("C_@@PPA2");
 
-  std::string ADALDName;
+template <bool Is64Bit>
+constexpr GOFF::ESDAmode AMODE =
+    Is64Bit ? GOFF::ESD_AMODE_64 : GOFF::ESD_AMODE_ANY;
 
-  StringRef BaseName;
+template <bool Is64Bit>
+constexpr GOFF::ESDRmode RMODE =
+    Is64Bit ? GOFF::ESD_RMODE_64 : GOFF::ESD_RMODE_31;
 
-  bool IsCsectCodeNameEmpty;
-  bool Is64Bit;
-  bool UsesXPLINK;
-
-public:
-  GOFFSymbolMapper(MCContext &Ctx);
-  GOFFSymbolMapper(MCAssembler &Asm);
-
-  // Required order: .text first, then .ada.
-  std::pair<GOFFSectionData, bool> getSection(const MCSectionGOFF &Section);
-
-  void setBaseName();
-  void determineRootSD(StringRef CSectCodeName);
-  llvm::StringRef getRootSDName() const;
-  const SDAttr &getRootSD() const;
-};
+template <bool IsXPLINK>
+constexpr GOFF::ESDLinkageType LINKAGE =
+    IsXPLINK ? GOFF::ESD_LT_XPLink : GOFF::ESD_LT_OS;
 
+template <bool IsXPLINK>
+constexpr GOFF::ESDLoadingBehavior LOADBEHAVIOR =
+    IsXPLINK ? GOFF::ESD_LB_Initial : GOFF::ESD_LB_Deferred;
+} // namespace GOFF
 } // namespace llvm
 
 #endif
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 78c1f5b60434b..779d44a8930b3 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -16,6 +16,9 @@ namespace llvm {
 class GOFFObjectWriter;
 
 class MCGOFFStreamer : public MCObjectStreamer {
+  std::string RootSDName;
+  std::string ADAPRName;
+
 public:
   MCGOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
                  std::unique_ptr<MCObjectWriter> OW,
@@ -25,6 +28,8 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   ~MCGOFFStreamer() override;
 
+  void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override;
+
   GOFFObjectWriter &getWriter();
 
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index fb575fe721015..56697ee3ae962 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -230,8 +230,6 @@ class MCObjectFileInfo {
   MCSection *GLJMPSection = nullptr;
 
   // GOFF specific sections.
-  MCSection *PPA1Section = nullptr;
-  MCSection *PPA2Section = nullptr;
   MCSection *PPA2ListSection = nullptr;
   MCSection *ADASection = nullptr;
   MCSection *IDRLSection = nullptr;
@@ -438,8 +436,6 @@ class MCObjectFileInfo {
   MCSection *getGLJMPSection() const { return GLJMPSection; }
 
   // GOFF specific sections.
-  MCSection *getPPA1Section() const { return PPA1Section; }
-  MCSection *getPPA2Section() const { return PPA2Section; }
   MCSection *getPPA2ListSection() const { return PPA2ListSection; }
   MCSection *getADASection() const { return ADASection; }
   MCSection *getIDRLSection() const { return IDRLSection; }
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index 11c0f95364037..0683c4690b0ba 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -15,7 +15,9 @@
 #ifndef LLVM_MC_MCSECTIONGOFF_H
 #define LLVM_MC_MCSECTIONGOFF_H
 
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -25,13 +27,38 @@ class MCExpr;
 
 class MCSectionGOFF final : public MCSection {
 private:
-  MCSection *Parent;
-  uint32_t Subsection;
+  // The names of the GOFF symbols.
+  StringRef SDName;
+  StringRef EDName;
+  StringRef LDorPRName;
+
+  // The attributes of the GOFF symbols.
+  GOFF::SDAttr SDAttributes;
+  GOFF::EDAttr EDAttributes;
+  GOFF::LDAttr LDAttributes;
+  GOFF::PRAttr PRAttributes;
+
+public:
+  enum SectionFlags {
+    UsesRootSD = 1,     // Uses the common root SD.
+    HasLD = 2,          // Has a LD symbol.
+    HasPR = 4,          // Has a PR symbol.
+    LDorPRNameIsSD = 8, // The LD or PR name is the same as the SD name.
+    LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ 8)
+  };
+
+private:
+  SectionFlags Flags;
+  bool IsADA;
 
   friend class MCContext;
-  MCSectionGOFF(StringRef Name, SectionKind K, MCSection *P, uint32_t Sub)
-      : MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
-        Parent(P), Subsection(Sub) {}
+  MCSectionGOFF(StringRef SynName, SectionKind K, SectionFlags Flags,
+                StringRef SDName, GOFF::SDAttr SDAttributes, StringRef EDName,
+                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
+                GOFF::LDAttr LDAttributes, GOFF::PRAttr PRAttributes)
+      : MCSection(SV_GOFF, SynName, K.isText(), /*IsVirtual=*/false, nullptr),
+        SDName(SDName), EDName(EDName), LDorPRName(LDorPRName),
+        SDAttributes(SDAttributes), EDAttributes(EDAttributes), Flags(Flags) {}
 
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
@@ -42,8 +69,38 @@ class MCSectionGOFF final : public MCSection {
 
   bool useCodeAlign() const override { return false; }
 
-  MCSection *getParent() const { return Parent; }
-  uint32_t getSubsection() const { return Subsection; }
+  // Accessors to the various symbol names.
+  StringRef getSDName() const { return SDName; };
+  StringRef getEDName() const { return EDName; };
+  StringRef getLDorPRName() const {
+    assert(Flags & (HasLD | HasPR) && "LD/PR name not available");
+    return (Flags & LDorPRNameIsSD) ? SDName : LDorPRName;
+  };
+
+  // Setters for the SD and LD/PR symbol names.
+  void setSDName(StringRef Name) { SDName = Name; }
+  void setLDorPRName(StringRef Name) { LDorPRName = Name; }
+
+  // Accessors to the various attributes.
+  GOFF::SDAttr getSDAttributes() const { return SDAttributes; }
+  GOFF::EDAttr getEDAttributes() const { return EDAttributes; }
+  GOFF::LDAttr getLDAttributes() const {
+    assert(Flags & HasLD && "LD not available");
+    return LDAttributes;
+  }
+  GOFF::PRAttr getPRAttributes() const {
+    assert(Flags & HasPR && "PR not available");
+    return PRAttributes;
+  }
+
+  // Query various flags.
+  bool usesRootSD() const { return Flags & UsesRootSD; }
+  bool hasLD() const { return Flags & HasLD; }
+  bool hasPR() const { return Flags & HasPR; }
+  bool isLDorPRNameTheSD() const { return Flags & LDorPRNameIsSD; }
+
+  bool isADA() const { return IsADA; }
+  void setADA() { IsADA = true; }
 
   static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; }
 };
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 00e4533559c28..529e86c0b893a 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -47,6 +47,7 @@
 #include "llvm/MC/MCAsmInfoDarwin.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCSectionGOFF.h"
@@ -2759,6 +2760,12 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA(
 //===----------------------------------------------------------------------===//
 TargetLoweringObjectFileGOFF::TargetLoweringObjectFileGOFF() = default;
 
+void TargetLoweringObjectFileGOFF::getModuleMetadata(Module &M) {
+  // Set the main file name if not set previously by the tool.
+  if (getContext().getMainFileName().empty())
+    getContext().setMainFileName(M.getSourceFileName());
+}
+
 MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   return SelectSectionForGlobal(GO, Kind, TM);
@@ -2767,15 +2774,55 @@ MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
 MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
     const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
   std::string Name = ".gcc_exception_table." + F.getName().str();
-  return getContext().getGOFFSection(Name, SectionKind::getData(), nullptr, 0);
+  constexpr bool Is64Bit = true;
+  constexpr bool UsesXPLINK = true;
+  return getContext().getGOFFSection(
+      SectionKind::getData(), GOFF::WSA<true>,
+      GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>,
+                   GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_Parts,
+                   GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
+                   GOFF::LOADBEHAVIOR<UsesXPLINK>, GOFF::ESD_RQ_0,
+                   GOFF::ESD_ALIGN_Doubleword},
+      Name,
+      GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
+                   GOFF::LINKAGE<UsesXPLINK>, GOFF::AMODE<Is64Bit>,
+                   GOFF::ESD_BSC_Section, GOFF::ESD_DSS_NoWarning,
+                   GOFF::ESD_ALIGN_Fullword, 0});
 }
 
 MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   auto *Symbol = TM.getSymbol(GO);
-  if (Kind.isBSS())
-    return getContext().getGOFFSection(Symbol->getName(), SectionKind::getBSS(),
-                                       nullptr, 0);
-
-  return getContext().getObjectFileInfo()->getTextSection();
+  constexpr bool Is64Bit = true;
+  constexpr bool UsesXPLINK = true;
+
+  if (Kind.isBSS() || Kind.isData()) {
+    GOFF::ESDBindingScope PRBindingScope =
+        GO->hasExternalLinkage()
+            ? (GO->hasDefaultVisibility() ? GOFF::ESD_BSC_ImportExport
+                                          : GOFF::ESD_BSC_Library)
+            : GOFF::ESD_BSC_Section;
+    GOFF::ESDBindingScope SDBindingScope =
+        PRBindingScope == GOFF::ESD_BSC_Section ? GOFF::ESD_BSC_Section
+                                                : GOFF::ESD_BSC_Unspecified;
+    return getContext().getGOFFSection(
+        Kind, Symbol->getName(),
+        GOFF::SDAttr{GOFF::ESD_TA_Unspecified, SDBindingScope},
+        GOFF::WSA<Is64Bit>,
+        GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>,
+                     GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_Parts,
+                     GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
+                     GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0,
+                     static_cast<GOFF::ESDAlignment>(GO->getAlignment())
+
+        },
+        Symbol->getName(),
+        GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
+                     GOFF::LINKAGE<UsesXPLINK>, GOFF::AMODE<Is64Bit>,
+                     PRBindingScope, GOFF::ESD_DSS_NoWarning,
+                     static_cast<GOFF::ESDAlignment>(GO->getAlignment()), 0
+
+        });
+  }
+  return TextSection;
 }
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index 967ec73a2be5b..f49f14c848b90 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -26,7 +26,6 @@ add_llvm_component_library(LLVMMC
   MCExpr.cpp
   MCFragment.cpp
   MCGOFFStreamer.cpp
-  MCGOFFSymbolMapper.cpp
   MCInst.cpp
   MCInstPrinter.cpp
   MCInstrAnalysis.cpp
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 062e62f31be40..cb8820d82f65f 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -13,7 +13,7 @@
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
-#include "llvm/MC/MCGOFFSymbolMapper.h"
+#include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/Support/Casting.h"
@@ -219,7 +219,7 @@ class GOFFSymbol {
 
   GOFFSymbol() : EsdId(0), ParentEsdId(0) {}
 
-  GOFFSymbol(StringRef Name, uint32_t EsdID, const SDAttr &Attr)
+  GOFFSymbol(StringRef Name, uint32_t EsdID, const GOFF::SDAttr &Attr)
       : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(0),
         SymbolType(GOFF::ESD_ST_SectionDefinition) {
     BehavAttrs.setTaskingBehavior(Attr.TaskingBehavior);
@@ -227,7 +227,7 @@ class GOFFSymbol {
   }
 
   GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
-             const EDAttr &Attr)
+             const GOFF::EDAttr &Attr)
       : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
         SymbolType(GOFF::ESD_ST_ElementDefinition) {
     this->NameSpace = Attr.NameSpace;
@@ -245,7 +245,7 @@ class GOFFSymbol {
   }
 
   GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
-             const LDAttr &Attr)
+             const GOFF::LDAttr &Attr)
       : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
         SymbolType(GOFF::ESD_ST_LabelDefinition) {
     this->NameSpace = Attr.NameSpace;
@@ -258,7 +258,7 @@ class GOFFSymbol {
   }
 
   GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
-             const PRAttr &Attr)
+             const GOFF::PRAttr &Attr)
       : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
         SymbolType(GOFF::ESD_ST_PartReference) {
     this->NameSpace = Attr.NameSpace;
@@ -277,9 +277,6 @@ 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;
 
@@ -291,12 +288,12 @@ class GOFFWriter {
   void writeSymbol(const GOFFSymbol &Symbol);
   void writeEnd();
 
-  GOFFSymbol createGOFFSymbol(StringRef Name, const SDAttr &Attr);
-  GOFFSymbol createGOFFSymbol(StringRef Name, const EDAttr &Attr,
+  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::SDAttr &Attr);
+  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::EDAttr &Attr,
                               uint32_t ParentEsdId);
-  GOFFSymbol createGOFFSymbol(StringRef Name, const LDAttr &Attr,
+  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::LDAttr &Attr,
                               uint32_t ParentEsdId);
-  GOFFSymbol createGOFFSymbol(StringRef Name, const PRAttr &Attr,
+  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::PRAttr &Attr,
                               uint32_t ParentEsdId);
 
   void defineRootSymbol(const MCSectionGOFF *Text);
@@ -310,66 +307,64 @@ class GOFFWriter {
 } // namespace
 
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
-    : OS(OS), Asm(Asm), SymbolMapper(Asm) {}
+    : OS(OS), Asm(Asm) {}
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const SDAttr &Attr) {
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::SDAttr &Attr) {
   return GOFFSymbol(Name, ++EsdIdCounter, Attr);
 }
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const EDAttr &Attr,
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::EDAttr &Attr,
                                         uint32_t ParentEsdId) {
   return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
 }
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const LDAttr &Attr,
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::LDAttr &Attr,
                                         uint32_t ParentEsdId) {
   return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
 }
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const PRAttr &Attr,
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::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("");
+  // There is always a text section except for DWARF unit tests, so be lenient.
   GOFFSymbol RootSD =
-      createGOFFSymbol(SymbolMapper.getRootSDName(), SymbolMapper.getRootSD());
+      Text ? createGOFFSymbol(Text->getSDName(), Text->getSDAttributes())
+           : createGOFFSymbol("", GOFF::SDAttr{GOFF::ESD_TA_Unspecified,
+                                               GOFF::ESD_BSC_Unspecified});
   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);
+    if (!Section.usesRootSD()) {
+      GOFFSymbol SD =
+          createGOFFSymbol(Section.getSDName(), Section.getSDAttributes());
       SDEsdId = SD.EsdId;
       writeSymbol(SD);
     }
 
-    GOFFSymbol ED = createGOFFSymbol(GOFFSectionData.EDName,
-                                     GOFFSectionData.EDAttributes, SDEsdId);
-    if (GOFFSectionData.Tag == GOFFSectionData::None ||
-        GOFFSectionData.Tag == GOFFSectionData::LD) {
+    GOFFSymbol ED = createGOFFSymbol(Section.getEDName(),
+                                     Section.getEDAttributes(), SDEsdId);
+    if ((!Section.hasLD() && !Section.hasPR()) || Section.hasLD()) {
       ED.SectionLength = Asm.getSectionAddressSize(Section);
     }
     writeSymbol(ED);
 
-    if (GOFFSectionData.Tag == GOFFSectionData::LD) {
-      GOFFSymbol LD = createGOFFSymbol(GOFFSectionData.LDorPRName,
-                                       GOFFSectionData.LDAttributes, ED.EsdId);
+    if (Section.hasLD()) {
+      GOFFSymbol LD = createGOFFSymbol(Section.getLDorPRName(),
+                                       Section.getLDAttributes(), ED.EsdId);
       if (Section.isText())
         LD.ADAEsdId = ADAEsdId;
       writeSymbol(LD);
     }
 
-    if (GOFFSectionData.Tag == GOFFSectionData::PR) {
-      GOFFSymbol PR = createGOFFSymbol(GOFFSectionData.LDorPRName,
-                                       GOFFSectionData.PRAttributes, ED.EsdId);
+    if (Section.hasPR()) {
+      GOFFSymbol PR = createGOFFSymbol(Section.getLDorPRName(),
+                                       Section.getPRAttributes(), ED.EsdId);
       PR.SectionLength = Asm.getSectionAddressSize(Section);
       if (Section.getName() == ".ada") {
         // We cannot have a zero-length section for data.  If we do,
@@ -383,21 +378,18 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
       }
       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.
+  // Search for .text and .ada sections.
   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);
+    auto &Section = cast<MCSectionGOFF>(S);
+    if (Section.isText())
+      Text = &Section;
+    if (Section.isADA())
+      ADA = &Section;
   }
   defineRootSymbol(Text);
   if (ADA)
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 09d4b518cc1c5..38b54ef50489d 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -671,24 +671,82 @@ MCContext::getELFUniqueIDForEntsize(StringRef SectionName, unsigned Flags,
                                       : std::nullopt;
 }
 
-MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind,
-                                         MCSection *Parent,
-                                         uint32_t Subsection) {
+MCSectionGOFF *
+MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
+                          GOFF::SDAttr SDAttributes, StringRef EDName,
+                          GOFF::EDAttr EDAttributes, StringRef LDorPRName,
+                          GOFF::LDAttr LDAttributes, GOFF::PRAttr PRAttributes,
+                          MCSectionGOFF::SectionFlags Flags) {
+  std::string SynName = Twine(SDName)
+                            .concat("/")
+                            .concat(EDName)
+                            .concat("/")
+                            .concat(LDorPRName)
+                            .str();
   // Do the lookup. If we don't have a hit, return a new section.
-  auto IterBool =
-      GOFFUniquingMap.insert(std::make_pair(Section.str(), nullptr));
+  auto IterBool = GOFFUniquingMap.insert(std::make_pair(SynName, nullptr));
   auto Iter = IterBool.first;
   if (!IterBool.second)
     return Iter->second;
 
-  StringRef CachedName = Iter->first;
+  StringRef CachedSynName = Iter->first;
   MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
-      MCSectionGOFF(CachedName, Kind, Parent, Subsection);
+      MCSectionGOFF(CachedSynName, Kind, Flags, SDName, SDAttributes, EDName,
+                    EDAttributes, LDorPRName, LDAttributes, PRAttributes);
   Iter->second = GOFFSection;
   allocInitialFragment(*GOFFSection);
   return GOFFSection;
 }
 
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
+                                         GOFF::SDAttr SDAttributes,
+                                         StringRef EDName,
+                                         GOFF::EDAttr EDAttributes,
+                                         StringRef LDorPRName,
+                                         GOFF::LDAttr LDAttributes) {
+  return getGOFFSection(Kind, SDName, SDAttributes, EDName, EDAttributes,
+                        LDorPRName, LDAttributes, GOFF::PRAttr{},
+                        MCSectionGOFF::HasLD);
+}
+
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
+                                         GOFF::SDAttr SDAttributes,
+                                         StringRef EDName,
+                                         GOFF::EDAttr EDAttributes,
+                                         StringRef LDorPRName,
+                                         GOFF::PRAttr PRAttributes) {
+  return getGOFFSection(Kind, SDName, SDAttributes, EDName, EDAttributes,
+                        LDorPRName, GOFF::LDAttr{}, PRAttributes,
+                        MCSectionGOFF::HasPR);
+}
+
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
+                                         GOFF::EDAttr EDAttributes,
+                                         GOFF::LDAttr LDAttributes) {
+  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes, "",
+                        LDAttributes, GOFF::PRAttr{},
+                        MCSectionGOFF::UsesRootSD |
+                            MCSectionGOFF::LDorPRNameIsSD |
+                            MCSectionGOFF::HasLD);
+}
+
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
+                                         GOFF::EDAttr EDAttributes,
+                                         StringRef LDorPRName,
+                                         GOFF::PRAttr PRAttributes) {
+  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes,
+                        LDorPRName, GOFF::LDAttr{}, PRAttributes,
+                        MCSectionGOFF::UsesRootSD | MCSectionGOFF::HasPR);
+}
+
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
+                                         GOFF::EDAttr EDAttributes) {
+  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes, "",
+                        GOFF::LDAttr{}, GOFF::PRAttr{},
+                        MCSectionGOFF::UsesRootSD |
+                            MCSectionGOFF::LDorPRNameIsSD);
+}
+
 MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
                                          unsigned Characteristics,
                                          StringRef COMDATSymName, int Selection,
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index c9e4c21c857ce..9b97c147ef5b3 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -26,6 +26,24 @@ GOFFObjectWriter &MCGOFFStreamer::getWriter() {
   return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
 }
 
+void MCGOFFStreamer::initSections(bool NoExecStack,
+                                  const MCSubtargetInfo &STI) {
+  MCContext &Ctx = getContext();
+
+  // Initialize the special names for the code and ada section.
+  StringRef FileName = Ctx.getMainFileName();
+  RootSDName = Twine(FileName).concat("#C").str();
+  ADAPRName = Twine(FileName).concat("#S").str();
+  MCSectionGOFF *TextSection = static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getTextSection());
+  MCSectionGOFF *ADASection = static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getADASection());
+  TextSection->setSDName(RootSDName);
+  ADASection->setLDorPRName(ADAPRName);
+  ADASection->setADA();
+
+  // Switch to the code section.
+  switchSection(TextSection);
+}
+
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
                                      std::unique_ptr<MCAsmBackend> &&MAB,
                                      std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/MC/MCGOFFSymbolMapper.cpp b/llvm/lib/MC/MCGOFFSymbolMapper.cpp
deleted file mode 100644
index 57012c34a94f1..0000000000000
--- a/llvm/lib/MC/MCGOFFSymbolMapper.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-//===- MCGOFFSymbolMapper.cpp - Maps MC section/symbol to GOFF symbols ----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Maps a section or a symbol to the GOFF symbols it is composed of, and their
-// attributes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCGOFFSymbolMapper.h"
-#include "llvm/BinaryFormat/GOFF.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSectionGOFF.h"
-#include "llvm/Support/Alignment.h"
-#include "llvm/Support/Path.h"
-
-using namespace llvm;
-
-namespace {
-const StringLiteral CODE[2]{"C_CODE", "C_CODE64"};
-const StringLiteral WSA[2]{"C_WSA", "C_WSA64"};
-const StringLiteral PPA2[2]{"C_@@PPA2", "C_@@QPPA2"};
-
-const GOFF::ESDAmode AMODE[2]{GOFF::ESD_AMODE_ANY, GOFF::ESD_AMODE_64};
-const GOFF::ESDRmode RMODE[2]{GOFF::ESD_RMODE_31, GOFF::ESD_RMODE_64};
-
-const GOFF::ESDLinkageType LINKAGE[2]{GOFF::ESD_LT_OS, GOFF::ESD_LT_XPLink};
-} // namespace
-
-GOFFSymbolMapper::GOFFSymbolMapper(MCContext &Ctx) : Ctx(Ctx) {
-  IsCsectCodeNameEmpty = true;
-  Is64Bit = true;
-  UsesXPLINK = true;
-}
-
-GOFFSymbolMapper::GOFFSymbolMapper(MCAssembler &Asm)
-    : GOFFSymbolMapper(Asm.getContext()) {
-  if (!Asm.getWriter().getFileNames().empty())
-    BaseName =
-        sys::path::stem((*(Asm.getWriter().getFileNames().begin())).first);
-}
-
-void GOFFSymbolMapper::determineRootSD(StringRef CSectCodeName) {
-  IsCsectCodeNameEmpty = CSectCodeName.empty();
-  if (IsCsectCodeNameEmpty) {
-    RootSDName = BaseName.str().append("#C");
-  } else {
-    RootSDName = CSectCodeName;
-  }
-  RootSDAttributes = {GOFF::ESD_TA_Rent, IsCsectCodeNameEmpty
-                                             ? GOFF::ESD_BSC_Section
-                                             : GOFF::ESD_BSC_Unspecified};
-}
-
-llvm::StringRef GOFFSymbolMapper::getRootSDName() const { return RootSDName; }
-
-const SDAttr &GOFFSymbolMapper::getRootSD() const { return RootSDAttributes; }
-
-std::pair<GOFFSectionData, bool>
-GOFFSymbolMapper::getSection(const MCSectionGOFF &Section) {
-  // Look up GOFFSection from name in MCSectionGOFF.
-  // Customize result, e.g. csect names, 32/64 bit, etc.
-  GOFFSectionData GOFFSec;
-  if (Section.getName() == ".text") {
-    GOFFSec.SDName = RootSDName;
-    GOFFSec.SDAttributes = RootSDAttributes;
-    GOFFSec.IsSDRootSD = true;
-    GOFFSec.EDName = CODE[Is64Bit];
-    // The GOFF alignment is encoded as log_2 value.
-    uint8_t Log = Log2(Section.getAlign());
-    assert(Log <= GOFF::ESD_ALIGN_4Kpage && "Alignment too large");
-    GOFFSec.EDAttributes = {true,
-                            GOFF::ESD_EXE_CODE,
-                            AMODE[Is64Bit],
-                            RMODE[Is64Bit],
-                            GOFF::ESD_NS_NormalName,
-                            GOFF::ESD_TS_ByteOriented,
-                            GOFF::ESD_BA_Concatenate,
-                            GOFF::ESD_LB_Initial,
-                            GOFF::ESD_RQ_0,
-                            static_cast<GOFF::ESDAlignment>(Log)};
-    GOFFSec.LDorPRName = GOFFSec.SDName;
-    GOFFSec.LDAttributes = {false,
-                            GOFF::ESD_EXE_CODE,
-                            GOFF::ESD_NS_NormalName,
-                            GOFF::ESD_BST_Strong,
-                            LINKAGE[UsesXPLINK],
-                            AMODE[Is64Bit],
-                            IsCsectCodeNameEmpty ? GOFF::ESD_BSC_Section
-                                                 : GOFF::ESD_BSC_Library};
-    GOFFSec.Tag = GOFFSectionData::LD;
-  } else if (Section.getName() == ".ada") {
-    assert(!RootSDName.empty() && "RootSD must be defined already");
-    GOFFSec.SDName = RootSDName;
-    GOFFSec.SDAttributes = RootSDAttributes;
-    GOFFSec.IsSDRootSD = true;
-    GOFFSec.EDName = WSA[Is64Bit];
-    GOFFSec.EDAttributes = {false,
-                            GOFF::ESD_EXE_DATA,
-                            AMODE[Is64Bit],
-                            RMODE[Is64Bit],
-                            GOFF::ESD_NS_Parts,
-                            GOFF::ESD_TS_ByteOriented,
-                            GOFF::ESD_BA_Merge,
-                            GOFF::ESD_LB_Deferred,
-                            GOFF::ESD_RQ_1,
-                            Is64Bit ? GOFF::ESD_ALIGN_Quadword
-                                    : GOFF::ESD_ALIGN_Doubleword};
-    ADALDName = BaseName.str().append("#S");
-    GOFFSec.LDorPRName = ADALDName;
-    GOFFSec.PRAttributes = {false,
-                            false,
-                            GOFF::ESD_EXE_DATA,
-                            GOFF::ESD_NS_Parts,
-                            GOFF::ESD_LT_XPLink,
-                            AMODE[Is64Bit],
-                            GOFF::ESD_BSC_Section,
-                            GOFF::ESD_DSS_NoWarning,
-                            Is64Bit ? GOFF::ESD_ALIGN_Quadword
-                                    : GOFF::ESD_ALIGN_Doubleword,
-                            0};
-    GOFFSec.Tag = GOFFSectionData::PR;
-  } else if (Section.getName().starts_with(".gcc_exception_table")) {
-    GOFFSec.SDName = RootSDName;
-    GOFFSec.SDAttributes = RootSDAttributes;
-    GOFFSec.IsSDRootSD = true;
-    GOFFSec.EDName = WSA[Is64Bit];
-    GOFFSec.EDAttributes = {false,
-                            GOFF::ESD_EXE_DATA,
-                            AMODE[Is64Bit],
-                            RMODE[Is64Bit],
-                            GOFF::ESD_NS_Parts,
-                            GOFF::ESD_TS_ByteOriented,
-                            GOFF::ESD_BA_Merge,
-                            UsesXPLINK ? GOFF::ESD_LB_Initial
-                                       : GOFF::ESD_LB_Deferred,
-                            GOFF::ESD_RQ_0,
-                            GOFF::ESD_ALIGN_Doubleword};
-    GOFFSec.LDorPRName = Section.getName();
-    GOFFSec.PRAttributes = {true,
-                            false,
-                            GOFF::ESD_EXE_Unspecified,
-                            GOFF::ESD_NS_Parts,
-                            LINKAGE[UsesXPLINK],
-                            AMODE[Is64Bit],
-                            GOFF::ESD_BSC_Section,
-                            GOFF::ESD_DSS_NoWarning,
-                            GOFF::ESD_ALIGN_Fullword,
-                            0};
-    GOFFSec.Tag = GOFFSectionData::PR;
-  } else if (Section.getName() == ".ppa2list") {
-    GOFFSec.SDName = RootSDName;
-    GOFFSec.SDAttributes = RootSDAttributes;
-    GOFFSec.IsSDRootSD = true;
-    GOFFSec.EDName = PPA2[Is64Bit];
-    GOFFSec.EDAttributes = {true,
-                            GOFF::ESD_EXE_DATA,
-                            AMODE[Is64Bit],
-                            RMODE[Is64Bit],
-                            GOFF::ESD_NS_Parts,
-                            GOFF::ESD_TS_ByteOriented,
-                            GOFF::ESD_BA_Merge,
-                            GOFF::ESD_LB_Initial,
-                            GOFF::ESD_RQ_0,
-                            GOFF::ESD_ALIGN_Doubleword};
-    GOFFSec.LDorPRName = ".&ppa2";
-    GOFFSec.PRAttributes = {true,
-                            false,
-                            GOFF::ESD_EXE_Unspecified,
-                            GOFF::ESD_NS_Parts,
-                            GOFF::ESD_LT_OS,
-                            AMODE[Is64Bit],
-                            GOFF::ESD_BSC_Section,
-                            GOFF::ESD_DSS_NoWarning,
-                            GOFF::ESD_ALIGN_Doubleword,
-                            0};
-    GOFFSec.Tag = GOFFSectionData::PR;
-  } else if (Section.getName() == ".idrl") {
-    GOFFSec.SDName = RootSDName;
-    GOFFSec.SDAttributes = RootSDAttributes;
-    GOFFSec.IsSDRootSD = true;
-    GOFFSec.EDName = "B_IDRL";
-    GOFFSec.EDAttributes = {true,
-                            GOFF::ESD_EXE_Unspecified,
-                            AMODE[Is64Bit],
-                            RMODE[Is64Bit],
-                            GOFF::ESD_NS_NormalName,
-                            GOFF::ESD_TS_Structured,
-                            GOFF::ESD_BA_Concatenate,
-                            GOFF::ESD_LB_NoLoad,
-                            GOFF::ESD_RQ_0,
-                            GOFF::ESD_ALIGN_Doubleword};
-    GOFFSec.Tag = GOFFSectionData::None;
-  } else
-    return std::pair(GOFFSec, false);
-  return std::pair(GOFFSec, true);
-}
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index a514a07ef7d3e..8def94ad51038 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -13,6 +13,7 @@
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSectionDXContainer.h"
@@ -546,18 +547,51 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
 }
 
 void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
-  TextSection = Ctx->getGOFFSection(".text", SectionKind::getText(), nullptr);
-  BSSSection = Ctx->getGOFFSection(".bss", SectionKind::getBSS(), nullptr);
-  PPA1Section = Ctx->getGOFFSection(".ppa1", SectionKind::getMetadata(),
-                                    TextSection, GOFF::SK_PPA1);
-  PPA2Section = Ctx->getGOFFSection(".ppa2", SectionKind::getMetadata(),
-                                    TextSection, GOFF::SK_PPA2);
-
-  PPA2ListSection =
-      Ctx->getGOFFSection(".ppa2list", SectionKind::getData(), nullptr);
-
-  ADASection = Ctx->getGOFFSection(".ada", SectionKind::getData(), nullptr);
-  IDRLSection = Ctx->getGOFFSection(".idrl", SectionKind::getData(), nullptr);
+  // Some values depend on AMODE31 or AMODE64, or other properties.
+  constexpr bool Is64Bit = true;
+  constexpr bool UsesXPLINK = true;
+
+  TextSection = Ctx->getGOFFSection(
+      SectionKind::getText(), GOFF::CODE<Is64Bit>,
+      GOFF::EDAttr{true, GOFF::ESD_EXE_CODE, GOFF::AMODE<Is64Bit>,
+                   GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_NormalName,
+                   GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Concatenate,
+                   GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
+                   GOFF::ESD_ALIGN_Doubleword},
+      GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, GOFF::ESD_NS_NormalName,
+                   GOFF::ESD_BST_Strong, GOFF::LINKAGE<UsesXPLINK>,
+                   GOFF::AMODE<Is64Bit>, GOFF::ESD_BSC_Section});
+
+  PPA2ListSection = Ctx->getGOFFSection(
+      SectionKind::getData(), GOFF::PPA2<Is64Bit>,
+      GOFF::EDAttr{
+          true, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>, GOFF::RMODE<Is64Bit>,
+          GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
+          GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword},
+      ".&ppa2",
+      GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
+                   GOFF::ESD_LT_OS, GOFF::AMODE<Is64Bit>, GOFF::ESD_BSC_Section,
+                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Doubleword, 0});
+
+  ADASection = Ctx->getGOFFSection(
+      SectionKind::getData(), GOFF::WSA<Is64Bit>,
+      GOFF::EDAttr{
+          false, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>, GOFF::RMODE<Is64Bit>,
+          GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
+          GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1, GOFF::ESD_ALIGN_Quadword},
+      "",
+      GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
+                   GOFF::ESD_LT_XPLink, GOFF::AMODE<Is64Bit>,
+                   GOFF::ESD_BSC_Section, GOFF::ESD_DSS_NoWarning,
+                   GOFF::ESD_ALIGN_Quadword, 0});
+
+  IDRLSection = Ctx->getGOFFSection(
+      SectionKind::getData(), "B_IDRL",
+      GOFF::EDAttr{true, GOFF::ESD_EXE_Unspecified, GOFF::AMODE<Is64Bit>,
+                   GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_NormalName,
+                   GOFF::ESD_TS_Structured, GOFF::ESD_BA_Concatenate,
+                   GOFF::ESD_LB_NoLoad, GOFF::ESD_RQ_0,
+                   GOFF::ESD_ALIGN_Doubleword});
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 448753fa43dc1..e18630b710e10 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -21,6 +21,7 @@
 #include "TargetInfo/SystemZTargetInfo.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/IR/Mangler.h"
@@ -1229,7 +1230,8 @@ void SystemZAsmPrinter::emitFunctionBodyEnd() {
     OutStreamer->emitLabel(FnEndSym);
 
     OutStreamer->pushSection();
-    OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
+    OutStreamer->switchSection(getObjFileLowering().getTextSection(),
+                               GOFF::SK_PPA1);
     emitPPA1(FnEndSym);
     OutStreamer->popSection();
 
@@ -1534,7 +1536,8 @@ void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
 
 void SystemZAsmPrinter::emitPPA2(Module &M) {
   OutStreamer->pushSection();
-  OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
+  OutStreamer->switchSection(getObjFileLowering().getTextSection(),
+                             GOFF::SK_PPA2);
   MCContext &OutContext = OutStreamer->getContext();
   // Make CELQSTRT symbol.
   const char *StartSymbolName = "CELQSTRT";
diff --git a/llvm/test/MC/GOFF/section.ll b/llvm/test/MC/GOFF/section.ll
index a0c64f0b83013..16c3580fcf924 100644
--- a/llvm/test/MC/GOFF/section.ll
+++ b/llvm/test/MC/GOFF/section.ll
@@ -1,6 +1,5 @@
 ; RUN: llc <%s --mtriple s390x-ibm-zos --filetype=obj -o - | \
 ; RUN:   od -Ax -tx1 -v | FileCheck --ignore-case %s
-; REQUIRES: systemz-registered-target
 
 source_filename = "test.ll"
 

>From 686b6284b3682b330f99839e3928ca46c5a44c6a Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 2 Apr 2025 19:48:21 -0400
Subject: [PATCH 07/15] Update formatting

---
 llvm/lib/MC/MCGOFFStreamer.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 9b97c147ef5b3..b05cd46ef3fcf 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -34,8 +34,10 @@ void MCGOFFStreamer::initSections(bool NoExecStack,
   StringRef FileName = Ctx.getMainFileName();
   RootSDName = Twine(FileName).concat("#C").str();
   ADAPRName = Twine(FileName).concat("#S").str();
-  MCSectionGOFF *TextSection = static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getTextSection());
-  MCSectionGOFF *ADASection = static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getADASection());
+  MCSectionGOFF *TextSection =
+      static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getTextSection());
+  MCSectionGOFF *ADASection =
+      static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getADASection());
   TextSection->setSDName(RootSDName);
   ADASection->setLDorPRName(ADAPRName);
   ADASection->setADA();

>From c7fcda945d4f8382a96977798a5eb251110e6b2a Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Thu, 3 Apr 2025 16:02:12 -0400
Subject: [PATCH 08/15] More updates

---
 llvm/include/llvm/MC/MCContext.h              |  3 +-
 llvm/include/llvm/MC/MCGOFFAttributes.h       | 40 +++++--------
 llvm/include/llvm/MC/MCSectionGOFF.h          |  9 ++-
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  | 32 ++++-------
 llvm/lib/MC/GOFFObjectWriter.cpp              | 38 +++----------
 llvm/lib/MC/MCContext.cpp                     | 12 ++--
 llvm/lib/MC/MCGOFFStreamer.cpp                | 10 ++--
 llvm/lib/MC/MCObjectFileInfo.cpp              | 56 +++++++++----------
 8 files changed, 75 insertions(+), 125 deletions(-)

diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index a35df1bba4bc1..d143189e83904 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -619,9 +619,10 @@ class MCContext {
                                 GOFF::SDAttr SDAttributes, StringRef EDName,
                                 GOFF::EDAttr EDAttributes, StringRef LDorPRName,
                                 GOFF::PRAttr PRAttributes);
-  // Create a section with root-SD/ED/LD symbols, using the root-SD name for LD.
+  // Create a section with root-SD/ED/LD symbols.
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
                                 GOFF::EDAttr EDAttributes,
+                                StringRef LDorPRName,
                                 GOFF::LDAttr LDAttributes);
   // Create a section with root-SD/ED/PR symbols.
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
diff --git a/llvm/include/llvm/MC/MCGOFFAttributes.h b/llvm/include/llvm/MC/MCGOFFAttributes.h
index 6a27438b6e81a..02a336dc2a67a 100644
--- a/llvm/include/llvm/MC/MCGOFFAttributes.h
+++ b/llvm/include/llvm/MC/MCGOFFAttributes.h
@@ -89,38 +89,24 @@ struct PRAttr {
 };
 
 // Class names and other values depending on AMODE64 or AMODE31, and other
-// environment properties.
-template <bool Is64Bit>
-constexpr StringLiteral CODE =
-    Is64Bit ? StringLiteral("C_CODE64") : StringLiteral("C_CODE");
+// environment properties. For now, only the 64 bit XPLINK case is defined.
 
-template <bool Is64Bit>
-constexpr StringLiteral WSA =
-    Is64Bit ? StringLiteral("C_WSA64") : StringLiteral("C_WSA");
+// GOFF classes.
+constexpr StringLiteral CLASS_CODE = "C_CODE64";
+constexpr StringLiteral CLASS_WSA = "C_WSA64";
+constexpr StringLiteral CLASS_DATA = "C_DATA64";
+constexpr StringLiteral CLASS_PPA2 = "C_@@QPPA2";
 
-template <bool Is64Bit>
-constexpr StringLiteral DATA =
-    Is64Bit ? StringLiteral("C_DATA64") : StringLiteral("C_DATA");
+// Addres and residency mode.
+constexpr GOFF::ESDAmode AMODE = GOFF::ESD_AMODE_64;
+constexpr GOFF::ESDRmode RMODE = GOFF::ESD_RMODE_64;
 
-template <bool Is64Bit>
-constexpr StringLiteral PPA2 =
-    Is64Bit ? StringLiteral("C_@@QPPA2") : StringLiteral("C_@@PPA2");
+// Linkage.
+constexpr GOFF::ESDLinkageType LINKAGE = GOFF::ESD_LT_XPLink;
 
-template <bool Is64Bit>
-constexpr GOFF::ESDAmode AMODE =
-    Is64Bit ? GOFF::ESD_AMODE_64 : GOFF::ESD_AMODE_ANY;
+// Loadding behavior.
+constexpr GOFF::ESDLoadingBehavior LOADBEHAVIOR = GOFF::ESD_LB_Initial;
 
-template <bool Is64Bit>
-constexpr GOFF::ESDRmode RMODE =
-    Is64Bit ? GOFF::ESD_RMODE_64 : GOFF::ESD_RMODE_31;
-
-template <bool IsXPLINK>
-constexpr GOFF::ESDLinkageType LINKAGE =
-    IsXPLINK ? GOFF::ESD_LT_XPLink : GOFF::ESD_LT_OS;
-
-template <bool IsXPLINK>
-constexpr GOFF::ESDLoadingBehavior LOADBEHAVIOR =
-    IsXPLINK ? GOFF::ESD_LB_Initial : GOFF::ESD_LB_Deferred;
 } // namespace GOFF
 } // namespace llvm
 
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index 0683c4690b0ba..be0210bdd623b 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -49,7 +49,6 @@ class MCSectionGOFF final : public MCSection {
 
 private:
   SectionFlags Flags;
-  bool IsADA;
 
   friend class MCContext;
   MCSectionGOFF(StringRef SynName, SectionKind K, SectionFlags Flags,
@@ -78,7 +77,10 @@ class MCSectionGOFF final : public MCSection {
   };
 
   // Setters for the SD and LD/PR symbol names.
-  void setSDName(StringRef Name) { SDName = Name; }
+  void setSDName(StringRef Name) {
+    assert(!(Flags & UsesRootSD) && "Uses root SD");
+    SDName = Name;
+  }
   void setLDorPRName(StringRef Name) { LDorPRName = Name; }
 
   // Accessors to the various attributes.
@@ -99,9 +101,6 @@ class MCSectionGOFF final : public MCSection {
   bool hasPR() const { return Flags & HasPR; }
   bool isLDorPRNameTheSD() const { return Flags & LDorPRNameIsSD; }
 
-  bool isADA() const { return IsADA; }
-  void setADA() { IsADA = true; }
-
   static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; }
 };
 } // end namespace llvm
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 529e86c0b893a..0bd996a2e1d10 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2774,27 +2774,21 @@ MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
 MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
     const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
   std::string Name = ".gcc_exception_table." + F.getName().str();
-  constexpr bool Is64Bit = true;
-  constexpr bool UsesXPLINK = true;
   return getContext().getGOFFSection(
-      SectionKind::getData(), GOFF::WSA<true>,
-      GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>,
-                   GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_Parts,
-                   GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
-                   GOFF::LOADBEHAVIOR<UsesXPLINK>, GOFF::ESD_RQ_0,
+      SectionKind::getData(), GOFF::CLASS_WSA,
+      GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
+                   GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
+                   GOFF::ESD_BA_Merge, GOFF::LOADBEHAVIOR, GOFF::ESD_RQ_0,
                    GOFF::ESD_ALIGN_Doubleword},
       Name,
       GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
-                   GOFF::LINKAGE<UsesXPLINK>, GOFF::AMODE<Is64Bit>,
-                   GOFF::ESD_BSC_Section, GOFF::ESD_DSS_NoWarning,
-                   GOFF::ESD_ALIGN_Fullword, 0});
+                   GOFF::LINKAGE, GOFF::AMODE, GOFF::ESD_BSC_Section,
+                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Fullword, 0});
 }
 
 MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   auto *Symbol = TM.getSymbol(GO);
-  constexpr bool Is64Bit = true;
-  constexpr bool UsesXPLINK = true;
 
   if (Kind.isBSS() || Kind.isData()) {
     GOFF::ESDBindingScope PRBindingScope =
@@ -2807,19 +2801,17 @@ MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
                                                 : GOFF::ESD_BSC_Unspecified;
     return getContext().getGOFFSection(
         Kind, Symbol->getName(),
-        GOFF::SDAttr{GOFF::ESD_TA_Unspecified, SDBindingScope},
-        GOFF::WSA<Is64Bit>,
-        GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>,
-                     GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_Parts,
-                     GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
-                     GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0,
+        GOFF::SDAttr{GOFF::ESD_TA_Unspecified, SDBindingScope}, GOFF::CLASS_WSA,
+        GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
+                     GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
+                     GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0,
                      static_cast<GOFF::ESDAlignment>(GO->getAlignment())
 
         },
         Symbol->getName(),
         GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
-                     GOFF::LINKAGE<UsesXPLINK>, GOFF::AMODE<Is64Bit>,
-                     PRBindingScope, GOFF::ESD_DSS_NoWarning,
+                     GOFF::LINKAGE, GOFF::AMODE, PRBindingScope,
+                     GOFF::ESD_DSS_NoWarning,
                      static_cast<GOFF::ESDAlignment>(GO->getAlignment()), 0
 
         });
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index cb8820d82f65f..891ee9d3fb907 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -284,6 +284,8 @@ class GOFFWriter {
   uint32_t RootSDEsdId = 0;
   uint32_t ADAEsdId = 0;
 
+  MCSectionGOFF *ADA = nullptr;
+
   void writeHeader();
   void writeSymbol(const GOFFSymbol &Symbol);
   void writeEnd();
@@ -296,7 +298,6 @@ class GOFFWriter {
   GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::PRAttr &Attr,
                               uint32_t ParentEsdId);
 
-  void defineRootSymbol(const MCSectionGOFF *Text);
   void defineSectionSymbols(const MCSectionGOFF &Section);
   void defineSymbols();
 
@@ -328,22 +329,14 @@ GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::PRAttr &Attr
   return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
 }
 
-void GOFFWriter::defineRootSymbol(const MCSectionGOFF *Text) {
-  // There is always a text section except for DWARF unit tests, so be lenient.
-  GOFFSymbol RootSD =
-      Text ? createGOFFSymbol(Text->getSDName(), Text->getSDAttributes())
-           : createGOFFSymbol("", GOFF::SDAttr{GOFF::ESD_TA_Unspecified,
-                                               GOFF::ESD_BSC_Unspecified});
-  writeSymbol(RootSD);
-  RootSDEsdId = RootSD.EsdId;
-}
-
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
     uint32_t SDEsdId = RootSDEsdId;
     if (!Section.usesRootSD()) {
       GOFFSymbol SD =
           createGOFFSymbol(Section.getSDName(), Section.getSDAttributes());
       SDEsdId = SD.EsdId;
+      if (RootSDEsdId == 0)
+        RootSDEsdId = SDEsdId;
       writeSymbol(SD);
     }
 
@@ -366,7 +359,7 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
       GOFFSymbol PR = createGOFFSymbol(Section.getLDorPRName(),
                                        Section.getPRAttributes(), ED.EsdId);
       PR.SectionLength = Asm.getSectionAddressSize(Section);
-      if (Section.getName() == ".ada") {
+      if (&Section == 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
@@ -381,27 +374,12 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
 }
 
 void GOFFWriter::defineSymbols() {
-  // Search for .text and .ada sections.
-  MCSectionGOFF *Text = nullptr;
-  MCSectionGOFF *ADA = nullptr;
+  // Process all sections.
   for (MCSection &S : Asm) {
     auto &Section = cast<MCSectionGOFF>(S);
-    if (Section.isText())
-      Text = &Section;
-    if (Section.isADA())
+    if (!ADA)
       ADA = &Section;
-  }
-  defineRootSymbol(Text);
-  if (ADA)
-    defineSectionSymbols(*ADA);
-  if (Text)
-    defineSectionSymbols(*Text);
-
-  // Process the other sections.
-  for (MCSection &S : Asm) {
-    auto &Section = cast<MCSectionGOFF>(S);
-    if (Text != &Section && ADA != &Section)
-      defineSectionSymbols(Section);
+    defineSectionSymbols(Section);
   }
 }
 
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 38b54ef50489d..56ca85d115792 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -722,12 +722,11 @@ MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
                                          GOFF::EDAttr EDAttributes,
+                                         StringRef LDorPRName,
                                          GOFF::LDAttr LDAttributes) {
-  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes, "",
-                        LDAttributes, GOFF::PRAttr{},
-                        MCSectionGOFF::UsesRootSD |
-                            MCSectionGOFF::LDorPRNameIsSD |
-                            MCSectionGOFF::HasLD);
+  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes,
+                        LDorPRName, LDAttributes, GOFF::PRAttr{},
+                        MCSectionGOFF::UsesRootSD | MCSectionGOFF::HasLD);
 }
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
@@ -743,8 +742,7 @@ MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
                                          GOFF::EDAttr EDAttributes) {
   return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes, "",
                         GOFF::LDAttr{}, GOFF::PRAttr{},
-                        MCSectionGOFF::UsesRootSD |
-                            MCSectionGOFF::LDorPRNameIsSD);
+                        MCSectionGOFF::UsesRootSD);
 }
 
 MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index b05cd46ef3fcf..c67b4da6b3d74 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -17,6 +17,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Path.h"
 
 using namespace llvm;
 
@@ -31,18 +32,19 @@ void MCGOFFStreamer::initSections(bool NoExecStack,
   MCContext &Ctx = getContext();
 
   // Initialize the special names for the code and ada section.
-  StringRef FileName = Ctx.getMainFileName();
+  StringRef FileName = sys::path::stem(Ctx.getMainFileName());
   RootSDName = Twine(FileName).concat("#C").str();
   ADAPRName = Twine(FileName).concat("#S").str();
   MCSectionGOFF *TextSection =
       static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getTextSection());
   MCSectionGOFF *ADASection =
       static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getADASection());
-  TextSection->setSDName(RootSDName);
+  ADASection->setSDName(RootSDName);
   ADASection->setLDorPRName(ADAPRName);
-  ADASection->setADA();
+  TextSection->setLDorPRName(RootSDName);
 
-  // Switch to the code section.
+  // Switch to the ADA section first, then code section.
+  switchSection(ADASection);
   switchSection(TextSection);
 }
 
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 8def94ad51038..2115641f74497 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -547,51 +547,45 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
 }
 
 void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
-  // Some values depend on AMODE31 or AMODE64, or other properties.
-  constexpr bool Is64Bit = true;
-  constexpr bool UsesXPLINK = true;
-
   TextSection = Ctx->getGOFFSection(
-      SectionKind::getText(), GOFF::CODE<Is64Bit>,
-      GOFF::EDAttr{true, GOFF::ESD_EXE_CODE, GOFF::AMODE<Is64Bit>,
-                   GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_NormalName,
-                   GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Concatenate,
-                   GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
-                   GOFF::ESD_ALIGN_Doubleword},
+      SectionKind::getText(), GOFF::CLASS_CODE,
+      GOFF::EDAttr{true, GOFF::ESD_EXE_CODE, GOFF::AMODE, GOFF::RMODE,
+                   GOFF::ESD_NS_NormalName, GOFF::ESD_TS_ByteOriented,
+                   GOFF::ESD_BA_Concatenate, GOFF::ESD_LB_Initial,
+                   GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword}, "",
       GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, GOFF::ESD_NS_NormalName,
-                   GOFF::ESD_BST_Strong, GOFF::LINKAGE<UsesXPLINK>,
-                   GOFF::AMODE<Is64Bit>, GOFF::ESD_BSC_Section});
+                   GOFF::ESD_BST_Strong, GOFF::LINKAGE, GOFF::AMODE,
+                   GOFF::ESD_BSC_Section});
 
   PPA2ListSection = Ctx->getGOFFSection(
-      SectionKind::getData(), GOFF::PPA2<Is64Bit>,
-      GOFF::EDAttr{
-          true, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>, GOFF::RMODE<Is64Bit>,
-          GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
-          GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword},
+      SectionKind::getData(), GOFF::CLASS_PPA2,
+      GOFF::EDAttr{true, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
+                   GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
+                   GOFF::ESD_BA_Merge, GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
+                   GOFF::ESD_ALIGN_Doubleword},
       ".&ppa2",
       GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
-                   GOFF::ESD_LT_OS, GOFF::AMODE<Is64Bit>, GOFF::ESD_BSC_Section,
+                   GOFF::ESD_LT_OS, GOFF::AMODE, GOFF::ESD_BSC_Section,
                    GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Doubleword, 0});
 
   ADASection = Ctx->getGOFFSection(
-      SectionKind::getData(), GOFF::WSA<Is64Bit>,
-      GOFF::EDAttr{
-          false, GOFF::ESD_EXE_DATA, GOFF::AMODE<Is64Bit>, GOFF::RMODE<Is64Bit>,
-          GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
-          GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1, GOFF::ESD_ALIGN_Quadword},
+      SectionKind::getData(), "",
+      GOFF::SDAttr{GOFF::ESD_TA_Rent, GOFF::ESD_BSC_Section}, GOFF::CLASS_WSA,
+      GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
+                   GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
+                   GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1,
+                   GOFF::ESD_ALIGN_Quadword},
       "",
       GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
-                   GOFF::ESD_LT_XPLink, GOFF::AMODE<Is64Bit>,
-                   GOFF::ESD_BSC_Section, GOFF::ESD_DSS_NoWarning,
-                   GOFF::ESD_ALIGN_Quadword, 0});
+                   GOFF::ESD_LT_XPLink, GOFF::AMODE, GOFF::ESD_BSC_Section,
+                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Quadword, 0});
 
   IDRLSection = Ctx->getGOFFSection(
       SectionKind::getData(), "B_IDRL",
-      GOFF::EDAttr{true, GOFF::ESD_EXE_Unspecified, GOFF::AMODE<Is64Bit>,
-                   GOFF::RMODE<Is64Bit>, GOFF::ESD_NS_NormalName,
-                   GOFF::ESD_TS_Structured, GOFF::ESD_BA_Concatenate,
-                   GOFF::ESD_LB_NoLoad, GOFF::ESD_RQ_0,
-                   GOFF::ESD_ALIGN_Doubleword});
+      GOFF::EDAttr{true, GOFF::ESD_EXE_Unspecified, GOFF::AMODE, GOFF::RMODE,
+                   GOFF::ESD_NS_NormalName, GOFF::ESD_TS_Structured,
+                   GOFF::ESD_BA_Concatenate, GOFF::ESD_LB_NoLoad,
+                   GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword});
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {

>From 1ca5fdc6356d1d6643e38e11ed82c7ce88551ff5 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 4 Apr 2025 17:04:34 -0400
Subject: [PATCH 09/15] Fix failing tests

Changes the `printSwitchToSection()` to be more HLASM-ish, and updates the test cases. That was necessary because the emitted name has changed.
However, zos-landingpad.ll is still failing due to a bug.
---
 llvm/include/llvm/MC/MCContext.h              |  3 +-
 llvm/include/llvm/MC/MCSectionGOFF.h          |  9 +-
 llvm/lib/MC/GOFFObjectWriter.cpp              | 90 ++++++++++---------
 llvm/lib/MC/MCObjectFileInfo.cpp              |  7 +-
 .../CodeGen/SystemZ/zos-ada-relocations.ll    |  4 +-
 llvm/test/CodeGen/SystemZ/zos-intrinsics.ll   |  4 +-
 llvm/test/CodeGen/SystemZ/zos-landingpad.ll   |  3 +-
 llvm/test/CodeGen/SystemZ/zos-ppa2.ll         |  4 +-
 llvm/test/CodeGen/SystemZ/zos-simple-test.ll  |  7 +-
 llvm/test/MC/GOFF/empty-goff.s                | 10 +--
 llvm/test/MC/GOFF/section.ll                  |  5 +-
 11 files changed, 82 insertions(+), 64 deletions(-)

diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index d143189e83904..30d4d6c197e69 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -621,8 +621,7 @@ class MCContext {
                                 GOFF::PRAttr PRAttributes);
   // Create a section with root-SD/ED/LD symbols.
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
-                                GOFF::EDAttr EDAttributes,
-                                StringRef LDorPRName,
+                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
                                 GOFF::LDAttr LDAttributes);
   // Create a section with root-SD/ED/PR symbols.
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index be0210bdd623b..ac60a61b0a142 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -57,13 +57,18 @@ class MCSectionGOFF final : public MCSection {
                 GOFF::LDAttr LDAttributes, GOFF::PRAttr PRAttributes)
       : MCSection(SV_GOFF, SynName, K.isText(), /*IsVirtual=*/false, nullptr),
         SDName(SDName), EDName(EDName), LDorPRName(LDorPRName),
-        SDAttributes(SDAttributes), EDAttributes(EDAttributes), Flags(Flags) {}
+        SDAttributes(SDAttributes), EDAttributes(EDAttributes),
+        LDAttributes(LDAttributes), PRAttributes(PRAttributes), Flags(Flags) {}
 
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
                             raw_ostream &OS,
                             uint32_t /*Subsection*/) const override {
-    OS << "\t.section\t\"" << getName() << "\"\n";
+    if (!usesRootSD())
+      OS << getSDName() << " CSECT\n";
+    OS << getEDName() << " CATTR\n";
+    if ((hasLD() || hasPR()) && !getLDorPRName().empty())
+      OS << getLDorPRName() << " XATTR\n";
   }
 
   bool useCodeAlign() const override { return false; }
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 891ee9d3fb907..2aa3ffb0bf9a5 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -12,8 +12,8 @@
 
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCGOFFObjectWriter.h"
 #include "llvm/MC/MCGOFFAttributes.h"
+#include "llvm/MC/MCGOFFObjectWriter.h"
 #include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/Support/Casting.h"
@@ -310,67 +310,71 @@ class GOFFWriter {
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
     : OS(OS), Asm(Asm) {}
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::SDAttr &Attr) {
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
+                                        const GOFF::SDAttr &Attr) {
   return GOFFSymbol(Name, ++EsdIdCounter, Attr);
 }
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::EDAttr &Attr,
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
+                                        const GOFF::EDAttr &Attr,
                                         uint32_t ParentEsdId) {
   return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
 }
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::LDAttr &Attr,
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
+                                        const GOFF::LDAttr &Attr,
                                         uint32_t ParentEsdId) {
   return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
 }
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const GOFF::PRAttr &Attr,
+GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
+                                        const GOFF::PRAttr &Attr,
                                         uint32_t ParentEsdId) {
   return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
 }
 
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
-    uint32_t SDEsdId = RootSDEsdId;
-    if (!Section.usesRootSD()) {
-      GOFFSymbol SD =
-          createGOFFSymbol(Section.getSDName(), Section.getSDAttributes());
-      SDEsdId = SD.EsdId;
-      if (RootSDEsdId == 0)
-        RootSDEsdId = SDEsdId;
-      writeSymbol(SD);
-    }
+  uint32_t SDEsdId = RootSDEsdId;
+  if (!Section.usesRootSD()) {
+    GOFFSymbol SD =
+        createGOFFSymbol(Section.getSDName(), Section.getSDAttributes());
+    SDEsdId = SD.EsdId;
+    if (RootSDEsdId == 0)
+      RootSDEsdId = SDEsdId;
+    writeSymbol(SD);
+  }
 
-    GOFFSymbol ED = createGOFFSymbol(Section.getEDName(),
-                                     Section.getEDAttributes(), SDEsdId);
-    if ((!Section.hasLD() && !Section.hasPR()) || Section.hasLD()) {
-      ED.SectionLength = Asm.getSectionAddressSize(Section);
-    }
-    writeSymbol(ED);
-
-    if (Section.hasLD()) {
-      GOFFSymbol LD = createGOFFSymbol(Section.getLDorPRName(),
-                                       Section.getLDAttributes(), ED.EsdId);
-      if (Section.isText())
-        LD.ADAEsdId = ADAEsdId;
-      writeSymbol(LD);
-    }
+  GOFFSymbol ED =
+      createGOFFSymbol(Section.getEDName(), Section.getEDAttributes(), SDEsdId);
+  if ((!Section.hasLD() && !Section.hasPR()) || Section.hasLD()) {
+    ED.SectionLength = Asm.getSectionAddressSize(Section);
+  }
+  writeSymbol(ED);
+
+  if (Section.hasLD()) {
+    GOFFSymbol LD = createGOFFSymbol(Section.getLDorPRName(),
+                                     Section.getLDAttributes(), ED.EsdId);
+    if (Section.isText())
+      LD.ADAEsdId = ADAEsdId;
+    writeSymbol(LD);
+  }
 
-    if (Section.hasPR()) {
-      GOFFSymbol PR = createGOFFSymbol(Section.getLDorPRName(),
-                                       Section.getPRAttributes(), ED.EsdId);
-      PR.SectionLength = Asm.getSectionAddressSize(Section);
-      if (&Section == 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);
+  if (Section.hasPR()) {
+    GOFFSymbol PR = createGOFFSymbol(Section.getLDorPRName(),
+                                     Section.getPRAttributes(), ED.EsdId);
+    PR.SectionLength = Asm.getSectionAddressSize(Section);
+    if (&Section == 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);
+  }
 }
 
 void GOFFWriter::defineSymbols() {
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 2115641f74497..ada59a0de86e6 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -552,7 +552,8 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
       GOFF::EDAttr{true, GOFF::ESD_EXE_CODE, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_NormalName, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Concatenate, GOFF::ESD_LB_Initial,
-                   GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword}, "",
+                   GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword},
+      "#C",
       GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, GOFF::ESD_NS_NormalName,
                    GOFF::ESD_BST_Strong, GOFF::LINKAGE, GOFF::AMODE,
                    GOFF::ESD_BSC_Section});
@@ -569,13 +570,13 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
                    GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Doubleword, 0});
 
   ADASection = Ctx->getGOFFSection(
-      SectionKind::getData(), "",
+      SectionKind::getData(), "#C",
       GOFF::SDAttr{GOFF::ESD_TA_Rent, GOFF::ESD_BSC_Section}, GOFF::CLASS_WSA,
       GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1,
                    GOFF::ESD_ALIGN_Quadword},
-      "",
+      "#S",
       GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
                    GOFF::ESD_LT_XPLink, GOFF::AMODE, GOFF::ESD_BSC_Section,
                    GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Quadword, 0});
diff --git a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll
index 068b56d8cef8b..59ad4ff93c5e9 100644
--- a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll
@@ -55,7 +55,9 @@ entry:
 
 declare signext i32 @callout(i32 signext)
 
-; CHECK:     .section    ".ada"
+; CHECK: #C CSECT
+; CHECK: C_WSA64 CATTR
+; CHECK: #S XATTR
 ; CHECK:  .set L#DoFunc at indirect0, DoFunc
 ; CHECK:      .indirect_symbol   L#DoFunc at indirect0
 ; CHECK:  .quad V(L#DoFunc at indirect0)          * Offset 0 pointer to function descriptor DoFunc
diff --git a/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll b/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll
index b1f0c9e5b8e54..b9aedf6517d4b 100644
--- a/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll
@@ -30,7 +30,9 @@ declare double @llvm.sin.f64(double)
 declare fp128 @llvm.exp2.f128(fp128)
 
 ; Check the calls in the ADA.
-; CHECK: .section ".ada"
+; CHECK: #C CSECT
+; CHECK: C_WSA64 CATTR
+; CHECK: #S XATTR
 
 ; Check that there is no call to sqrt.
 ; CHECK-NOT:  .quad   R(@@WSQT at B)
diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
index 63c332eb423e3..f447731c849e1 100644
--- a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
@@ -37,5 +37,6 @@ lpad:
 ; CHECK: Personality routine
 ; CHECK: LSDA location
 ; Check that the exception table is emitted into .lsda section.
-; CHECK: .section ".gcc_exception_table.test1"
+; CHECK: C_WSA64 CATTR
+; CHECK: GCC_except_table0 XATTR
 ; CHECK: GCC_except_table0:
diff --git a/llvm/test/CodeGen/SystemZ/zos-ppa2.ll b/llvm/test/CodeGen/SystemZ/zos-ppa2.ll
index 82f416ddb8bf9..8f3847da32e31 100644
--- a/llvm/test/CodeGen/SystemZ/zos-ppa2.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-ppa2.ll
@@ -1,6 +1,6 @@
 ; RUN: llc -mtriple s390x-ibm-zos -mcpu=z15 -asm-verbose=true < %s | FileCheck %s
 
-; CHECK:    .section    ".ppa2"
+; CHECK: C_CODE64 CATTR
 ; CHECK: L#PPA2:
 ; CHECK:    .byte   3
 ; CHECK:    .byte   231
@@ -19,7 +19,7 @@
 ; CHECK:    .quad   L#PPA2-CELQSTRT                 * A(PPA2-CELQSTRT)
 ; CHECK: L#PPA1_void_test_0:
 ; CHECK:    .long   L#PPA2-L#PPA1_void_test_0       * Offset to PPA2
-; CHECK:    .section    ".idrl"
+; CHECK: B_IDRL CATTR
 ; CHECK:    .byte   0
 ; CHECK:    .byte   3
 ; CHECK:    .short  30
diff --git a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
index a46079818b130..40a4b91b9f1da 100644
--- a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
@@ -5,9 +5,12 @@
 @a = global i32 0, align 4
 
 define signext i32 @main() {
-; CHECK: .section ".text"
+; CHECK: C_CODE64 CATTR
+; CHECK: #C XATTR
 ; CHECK: main:
-; CHECK: .section "a"
+; CHECK: a CSECT
+; CHECK: C_WSA64 CATTR
+; CHECK: a XATTR
 entry:
   ret i32 0
 }
diff --git a/llvm/test/MC/GOFF/empty-goff.s b/llvm/test/MC/GOFF/empty-goff.s
index f6d402863d71c..ba1b0e0a49077 100644
--- a/llvm/test/MC/GOFF/empty-goff.s
+++ b/llvm/test/MC/GOFF/empty-goff.s
@@ -17,8 +17,8 @@
 *  03 is prefix byte
 *  4. is header type
 *  .0 is version
-* CHECK: 000050 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-* CHECK: 000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-* CHECK: 000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-* CHECK: 000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-* CHECK: 000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+* CHECK: {{([[:xdigit:]]{6})}} 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+* CHECK: {{([[:xdigit:]]{6})}} 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+* CHECK: {{([[:xdigit:]]{6})}} 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+* CHECK: {{([[:xdigit:]]{6})}} 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+* CHECK: {{([[:xdigit:]]{6})}} 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/llvm/test/MC/GOFF/section.ll b/llvm/test/MC/GOFF/section.ll
index 16c3580fcf924..9e943a71cbf4a 100644
--- a/llvm/test/MC/GOFF/section.ll
+++ b/llvm/test/MC/GOFF/section.ll
@@ -57,11 +57,12 @@ entry:
 
 ; ESD record, type ED.
 ; The name is C_CODE64.
+; The regular expression matches the low byte of the length.
 ; CHECK: 0000140 03 00 00 01 00 00 00 04 00 00 00 01 00 00 00 00
-; CHECK: 0000150 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
+; CHECK: 0000150 00 00 00 00 00 00 00 00 00 00 00 {{..}} 00 00 00 00
 ; CHECK: 0000160 00 00 00 00 00 00 00 00 01 80 00 00 00 00 00 00
 ; CHECK: 0000170 00 00 00 00 00 00 00 00 00 00 00 00 04 04 00 0a
-; CHECK: 0000180 00 00 04 00 00 00 00 08 c3 6d c3 d6 c4 c5 f6 f4
+; CHECK: 0000180 00 00 03 00 00 00 00 08 c3 6d c3 d6 c4 c5 f6 f4
 
 ; ESD record, type LD.
 ; The name is test#C.

>From 682f07b525d9b24d1d6256cf812522eed6376524 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 4 Apr 2025 20:17:43 -0400
Subject: [PATCH 10/15] Rework based on reviewer comment.

---
 .../CodeGen/TargetLoweringObjectFileImpl.h    |   2 +
 llvm/include/llvm/MC/MCContext.h              |  58 ++++-----
 llvm/include/llvm/MC/MCGOFFStreamer.h         |   1 +
 llvm/include/llvm/MC/MCObjectFileInfo.h       |  14 ++-
 llvm/include/llvm/MC/MCSectionGOFF.h          | 112 +++++++++---------
 llvm/include/llvm/MC/MCSymbolGOFF.h           |  23 ++++
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  |  52 +++++---
 llvm/lib/MC/GOFFObjectWriter.cpp              |  96 +++++----------
 llvm/lib/MC/MCContext.cpp                     |  77 ++++--------
 llvm/lib/MC/MCGOFFStreamer.cpp                |  34 +++---
 llvm/lib/MC/MCObjectFileInfo.cpp              |  49 ++++----
 11 files changed, 258 insertions(+), 260 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index b2ff064297809..dd4339824c49e 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -316,6 +316,8 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
 };
 
 class TargetLoweringObjectFileGOFF : public TargetLoweringObjectFile {
+  std::string DefaultRootSDName;
+  std::string DefaultADAPRName;
 public:
   TargetLoweringObjectFileGOFF();
   ~TargetLoweringObjectFileGOFF() override = default;
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 30d4d6c197e69..67d7d5e2642be 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -270,6 +270,21 @@ class MCContext {
     }
   };
 
+  struct GOFFSectionKey {
+    std::string SectionName;
+    GOFF::ESDSymbolType SymbolType;
+
+    GOFFSectionKey(StringRef SectionName, GOFF::ESDSymbolType SymbolType)
+        : SectionName(SectionName), SymbolType(SymbolType) {}
+
+    bool operator<(const GOFFSectionKey &Other) const {
+      if (SymbolType == Other.SymbolType) {
+        return SectionName < Other.SectionName;
+      }
+      return SymbolType < Other.SymbolType;
+    }
+  };
+
   struct WasmSectionKey {
     std::string SectionName;
     StringRef GroupName;
@@ -323,7 +338,7 @@ class MCContext {
   StringMap<MCSectionMachO *> MachOUniquingMap;
   std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap;
   StringMap<MCSectionELF *> ELFUniquingMap;
-  std::map<std::string, MCSectionGOFF *> GOFFUniquingMap;
+  std::map<GOFFSectionKey, MCSectionGOFF *> GOFFUniquingMap;
   std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap;
   std::map<XCOFFSectionKey, MCSectionXCOFF *> XCOFFUniquingMap;
   StringMap<MCSectionDXContainer *> DXCUniquingMap;
@@ -601,35 +616,22 @@ class MCContext {
                                                    unsigned EntrySize);
 
 private:
-  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef SDName,
-                                GOFF::SDAttr SDAttributes, StringRef EDName,
-                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
-                                GOFF::LDAttr LDAttributes,
-                                GOFF::PRAttr PRAttributes,
-                                MCSectionGOFF::SectionFlags Flags);
+  MCSectionGOFF *getGOFFSection(SectionKind Kind,
+                                GOFF::ESDSymbolType SymbolType, StringRef Name,
+                                GOFF::SDAttr SDAttributes,
+                                GOFF::EDAttr EDAttributes,
+                                GOFF::PRAttr PRAttributes, MCSection *Parent);
 
 public:
-  // Create a section with SD/ED/LD symbols.
-  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef SDName,
-                                GOFF::SDAttr SDAttributes, StringRef EDName,
-                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
-                                GOFF::LDAttr LDAttributes);
-  // Create a section with SD/ED/PR symbols.
-  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef SDName,
-                                GOFF::SDAttr SDAttributes, StringRef EDName,
-                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
-                                GOFF::PRAttr PRAttributes);
-  // Create a section with root-SD/ED/LD symbols.
-  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
-                                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
-                                GOFF::LDAttr LDAttributes);
-  // Create a section with root-SD/ED/PR symbols.
-  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
-                                GOFF::EDAttr EDAttributes, StringRef PRName,
-                                GOFF::PRAttr PRAttributes);
-  // Create a section with root-SD/ED symbols.
-  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef EDName,
-                                GOFF::EDAttr EDAttributes);
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
+                                GOFF::SDAttr SDAttributes,
+                                MCSection *Parent = nullptr);
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
+                                GOFF::EDAttr EDAttributes,
+                                MCSection *Parent = nullptr);
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
+                                GOFF::PRAttr PRAttributes,
+                                MCSection *Parent = nullptr);
 
   MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
                                 StringRef COMDATSymName, int Selection,
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 779d44a8930b3..771d77b50209a 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -29,6 +29,7 @@ class MCGOFFStreamer : public MCObjectStreamer {
   ~MCGOFFStreamer() override;
 
   void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override;
+  void changeSection(MCSection *Section, uint32_t Subsection = 0) override;
 
   GOFFObjectWriter &getWriter();
 
diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index 56697ee3ae962..b5ec42fdd352e 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -230,8 +230,11 @@ class MCObjectFileInfo {
   MCSection *GLJMPSection = nullptr;
 
   // GOFF specific sections.
-  MCSection *PPA2ListSection = nullptr;
-  MCSection *ADASection = nullptr;
+  MCSection *RootSDSection = nullptr;
+  MCSection *PPA2ListEDSection = nullptr;
+  MCSection *PPA2ListPRSection = nullptr;
+  MCSection *ADAEDSection = nullptr;
+  MCSection *ADAPRSection = nullptr;
   MCSection *IDRLSection = nullptr;
 
   // XCOFF specific sections
@@ -436,8 +439,11 @@ class MCObjectFileInfo {
   MCSection *getGLJMPSection() const { return GLJMPSection; }
 
   // GOFF specific sections.
-  MCSection *getPPA2ListSection() const { return PPA2ListSection; }
-  MCSection *getADASection() const { return ADASection; }
+  MCSection *getRootSDSection() const { return RootSDSection; }
+  MCSection *getPPA2ListEDSection() const { return PPA2ListEDSection; }
+  MCSection *getPPA2ListSection() const { return PPA2ListPRSection; }
+  MCSection *getADAEDSection() const { return ADAEDSection; }
+  MCSection *getADASection() const { return ADAPRSection; }
   MCSection *getIDRLSection() const { return IDRLSection; }
 
   // XCOFF specific sections
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index ac60a61b0a142..e922101187905 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -15,10 +15,10 @@
 #ifndef LLVM_MC_MCSECTIONGOFF_H
 #define LLVM_MC_MCSECTIONGOFF_H
 
-#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCSection.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
@@ -26,85 +26,85 @@ namespace llvm {
 class MCExpr;
 
 class MCSectionGOFF final : public MCSection {
-private:
-  // The names of the GOFF symbols.
-  StringRef SDName;
-  StringRef EDName;
-  StringRef LDorPRName;
+  // Parent of this section. Implies that the parent is emitted first.
+  MCSectionGOFF *Parent;
 
   // The attributes of the GOFF symbols.
   GOFF::SDAttr SDAttributes;
   GOFF::EDAttr EDAttributes;
-  GOFF::LDAttr LDAttributes;
   GOFF::PRAttr PRAttributes;
 
-public:
-  enum SectionFlags {
-    UsesRootSD = 1,     // Uses the common root SD.
-    HasLD = 2,          // Has a LD symbol.
-    HasPR = 4,          // Has a PR symbol.
-    LDorPRNameIsSD = 8, // The LD or PR name is the same as the SD name.
-    LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ 8)
-  };
+  // The type of this section.
+  GOFF::ESDSymbolType SymbolType;
+
+  // Indicates that the ED symbol needs to set the length of the section.
+  unsigned RequiresLength : 1;
 
-private:
-  SectionFlags Flags;
+  // Indicates that the PR symbol needs to set the length of the section to a
+  // non-zero value.
+  unsigned RequiresNonZeroLength : 1;
 
   friend class MCContext;
-  MCSectionGOFF(StringRef SynName, SectionKind K, SectionFlags Flags,
-                StringRef SDName, GOFF::SDAttr SDAttributes, StringRef EDName,
-                GOFF::EDAttr EDAttributes, StringRef LDorPRName,
-                GOFF::LDAttr LDAttributes, GOFF::PRAttr PRAttributes)
-      : MCSection(SV_GOFF, SynName, K.isText(), /*IsVirtual=*/false, nullptr),
-        SDName(SDName), EDName(EDName), LDorPRName(LDorPRName),
-        SDAttributes(SDAttributes), EDAttributes(EDAttributes),
-        LDAttributes(LDAttributes), PRAttributes(PRAttributes), Flags(Flags) {}
+  MCSectionGOFF(StringRef Name, SectionKind K, GOFF::ESDSymbolType SymbolType,
+                GOFF::SDAttr SDAttributes, GOFF::EDAttr EDAttributes,
+                GOFF::PRAttr PRAttributes, MCSectionGOFF *Parent = nullptr)
+      : MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
+        Parent(Parent), SDAttributes(SDAttributes), EDAttributes(EDAttributes),
+        PRAttributes(PRAttributes), SymbolType(SymbolType) {}
 
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
                             raw_ostream &OS,
                             uint32_t /*Subsection*/) const override {
-    if (!usesRootSD())
-      OS << getSDName() << " CSECT\n";
-    OS << getEDName() << " CATTR\n";
-    if ((hasLD() || hasPR()) && !getLDorPRName().empty())
-      OS << getLDorPRName() << " XATTR\n";
+    ;
+    switch (SymbolType) {
+    case GOFF::ESD_ST_SectionDefinition:
+      OS << Name << " CSECT\n";
+      break;
+    case GOFF::ESD_ST_ElementDefinition:
+      OS << Name << " CATTR\n";
+      break;
+    case GOFF::ESD_ST_PartReference:
+      OS << Name << " XATTR\n";
+      break;
+    default:
+      llvm_unreachable("Wrong section type");
+    }
   }
 
   bool useCodeAlign() const override { return false; }
 
-  // Accessors to the various symbol names.
-  StringRef getSDName() const { return SDName; };
-  StringRef getEDName() const { return EDName; };
-  StringRef getLDorPRName() const {
-    assert(Flags & (HasLD | HasPR) && "LD/PR name not available");
-    return (Flags & LDorPRNameIsSD) ? SDName : LDorPRName;
-  };
-
-  // Setters for the SD and LD/PR symbol names.
-  void setSDName(StringRef Name) {
-    assert(!(Flags & UsesRootSD) && "Uses root SD");
-    SDName = Name;
+  // Return the id of the section. It is the 1-based ordinal number.
+  unsigned getId() const { return getOrdinal() + 1; }
+
+  // Return the parent section.
+  MCSectionGOFF *getParent() const { return Parent; }
+
+  // Returns the type of this section.
+  GOFF::ESDSymbolType getSymbolType() const { return SymbolType; }
+
+  bool isSD() const { return SymbolType == GOFF::ESD_ST_SectionDefinition; }
+  bool isED() const { return SymbolType == GOFF::ESD_ST_ElementDefinition; }
+  bool isPR() const { return SymbolType == GOFF::ESD_ST_PartReference; }
+
+  // Accessors to the attributes.
+  GOFF::SDAttr getSDAttributes() const {
+    assert(SymbolType == GOFF::ESD_ST_SectionDefinition && "Not PR symbol");
+    return SDAttributes;
   }
-  void setLDorPRName(StringRef Name) { LDorPRName = Name; }
-
-  // Accessors to the various attributes.
-  GOFF::SDAttr getSDAttributes() const { return SDAttributes; }
-  GOFF::EDAttr getEDAttributes() const { return EDAttributes; }
-  GOFF::LDAttr getLDAttributes() const {
-    assert(Flags & HasLD && "LD not available");
-    return LDAttributes;
+  GOFF::EDAttr getEDAttributes() const {
+    assert(SymbolType == GOFF::ESD_ST_ElementDefinition && "Not PR symbol");
+    return EDAttributes;
   }
   GOFF::PRAttr getPRAttributes() const {
-    assert(Flags & HasPR && "PR not available");
+    assert(SymbolType == GOFF::ESD_ST_PartReference && "Not PR symbol");
     return PRAttributes;
   }
 
-  // Query various flags.
-  bool usesRootSD() const { return Flags & UsesRootSD; }
-  bool hasLD() const { return Flags & HasLD; }
-  bool hasPR() const { return Flags & HasPR; }
-  bool isLDorPRNameTheSD() const { return Flags & LDorPRNameIsSD; }
+  bool requiresLength() const { return RequiresLength; }
+  bool requiresNonZeroLength() const { return RequiresNonZeroLength; }
+
+  void setName(StringRef SectionName) { Name = SectionName; }
 
   static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; }
 };
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 9ca53a5653108..c46f5bd4234b5 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -13,15 +13,38 @@
 #ifndef LLVM_MC_MCSYMBOLGOFF_H
 #define LLVM_MC_MCSYMBOLGOFF_H
 
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCGOFFAttributes.h"
+#include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCSymbolTableEntry.h"
 
 namespace llvm {
 
 class MCSymbolGOFF : public MCSymbol {
+  // Associated data area of the section. Needs to be emitted first.
+  MCSectionGOFF *ADA;
+
+  GOFF::LDAttr LDAttributes;
+
+  enum SymbolFlags : uint16_t {
+    SF_LD = 0x01, // LD attributes are set.
+  };
+
 public:
   MCSymbolGOFF(const MCSymbolTableEntry *Name, bool IsTemporary)
       : MCSymbol(SymbolKindGOFF, Name, IsTemporary) {}
+
+  void setLDAttributes(GOFF::LDAttr Attr) {
+    modifyFlags(SF_LD, SF_LD);
+    LDAttributes = Attr;
+  }
+  GOFF::LDAttr getLDAttributes() const { return LDAttributes; }
+  bool hasLDAttributes() const { return getFlags() & SF_LD; }
+
+  void setADA(MCSectionGOFF *AssociatedDataArea) { ADA = AssociatedDataArea; }
+  MCSectionGOFF *getADA() const { return ADA; }
+
   static bool classof(const MCSymbol *S) { return S->isGOFF(); }
 };
 } // end namespace llvm
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 0bd996a2e1d10..a64a22ebcf67d 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -57,6 +57,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/MC/SectionKind.h"
 #include "llvm/ProfileData/InstrProf.h"
@@ -2761,9 +2762,21 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA(
 TargetLoweringObjectFileGOFF::TargetLoweringObjectFileGOFF() = default;
 
 void TargetLoweringObjectFileGOFF::getModuleMetadata(Module &M) {
-  // Set the main file name if not set previously by the tool.
-  if (getContext().getMainFileName().empty())
-    getContext().setMainFileName(M.getSourceFileName());
+  // Construct the default names for the root SD and the ADA PR symbol.
+  DefaultRootSDName = Twine(M.getSourceFileName()).concat("#C").str();
+  DefaultADAPRName = Twine(M.getSourceFileName()).concat("#S").str();
+  MCSectionGOFF *RootSD = static_cast<MCSectionGOFF *>(RootSDSection);
+  MCSectionGOFF *ADAPR = static_cast<MCSectionGOFF *>(ADAPRSection);
+  RootSD->setName(DefaultRootSDName);
+  ADAPR->setName(DefaultADAPRName);
+  // Initialize the label for the text section.
+  MCSymbolGOFF *TextLD = static_cast<MCSymbolGOFF *>(
+      getContext().getOrCreateSymbol(RootSD->getName()));
+  TextLD->setLDAttributes(GOFF::LDAttr{
+      false, GOFF::ESD_EXE_CODE, GOFF::ESD_NS_NormalName, GOFF::ESD_BST_Strong,
+      GOFF::LINKAGE, GOFF::AMODE, GOFF::ESD_BSC_Section});
+  TextLD->setADA(ADAPR);
+  TextSection->setBeginSymbol(TextLD);
 }
 
 MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
@@ -2774,16 +2787,20 @@ MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
 MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
     const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
   std::string Name = ".gcc_exception_table." + F.getName().str();
-  return getContext().getGOFFSection(
-      SectionKind::getData(), GOFF::CLASS_WSA,
+
+  MCSectionGOFF *WSA = getContext().getGOFFSection(
+      SectionKind::getMetadata(), GOFF::CLASS_WSA,
       GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Merge, GOFF::LOADBEHAVIOR, GOFF::ESD_RQ_0,
                    GOFF::ESD_ALIGN_Doubleword},
-      Name,
+      RootSDSection);
+  return getContext().getGOFFSection(
+      SectionKind::getData(), Name,
       GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
                    GOFF::LINKAGE, GOFF::AMODE, GOFF::ESD_BSC_Section,
-                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Fullword, 0});
+                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Fullword, 0},
+      WSA);
 }
 
 MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
@@ -2799,22 +2816,23 @@ MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
     GOFF::ESDBindingScope SDBindingScope =
         PRBindingScope == GOFF::ESD_BSC_Section ? GOFF::ESD_BSC_Section
                                                 : GOFF::ESD_BSC_Unspecified;
-    return getContext().getGOFFSection(
-        Kind, Symbol->getName(),
-        GOFF::SDAttr{GOFF::ESD_TA_Unspecified, SDBindingScope}, GOFF::CLASS_WSA,
+    MCSectionGOFF *SD = getContext().getGOFFSection(
+        SectionKind::getMetadata(), Symbol->getName(),
+        GOFF::SDAttr{GOFF::ESD_TA_Unspecified, SDBindingScope});
+    MCSectionGOFF *ED = getContext().getGOFFSection(
+        SectionKind::getMetadata(), GOFF::CLASS_WSA,
         GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
                      GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
                      GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0,
-                     static_cast<GOFF::ESDAlignment>(GO->getAlignment())
-
-        },
-        Symbol->getName(),
+                     static_cast<GOFF::ESDAlignment>(GO->getAlignment())},
+        SD);
+    return getContext().getGOFFSection(
+        Kind, Symbol->getName(),
         GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
                      GOFF::LINKAGE, GOFF::AMODE, PRBindingScope,
                      GOFF::ESD_DSS_NoWarning,
-                     static_cast<GOFF::ESDAlignment>(GO->getAlignment()), 0
-
-        });
+                     static_cast<GOFF::ESDAlignment>(GO->getAlignment()), 0},
+        ED);
   }
   return TextSection;
 }
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 2aa3ffb0bf9a5..b70fab6185a03 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -15,6 +15,7 @@
 #include "llvm/MC/MCGOFFAttributes.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"
@@ -280,25 +281,12 @@ class GOFFWriter {
   /// Counter for symbol id's.
   uint32_t EsdIdCounter = 0;
 
-  /// Id's of some special symbols.
-  uint32_t RootSDEsdId = 0;
-  uint32_t ADAEsdId = 0;
-
-  MCSectionGOFF *ADA = nullptr;
-
   void writeHeader();
   void writeSymbol(const GOFFSymbol &Symbol);
   void writeEnd();
 
-  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::SDAttr &Attr);
-  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::EDAttr &Attr,
-                              uint32_t ParentEsdId);
-  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::LDAttr &Attr,
-                              uint32_t ParentEsdId);
-  GOFFSymbol createGOFFSymbol(StringRef Name, const GOFF::PRAttr &Attr,
-                              uint32_t ParentEsdId);
-
   void defineSectionSymbols(const MCSectionGOFF &Section);
+  void defineLabel(const MCSymbolGOFF &Symbol);
   void defineSymbols();
 
 public:
@@ -310,60 +298,26 @@ class GOFFWriter {
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
     : OS(OS), Asm(Asm) {}
 
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
-                                        const GOFF::SDAttr &Attr) {
-  return GOFFSymbol(Name, ++EsdIdCounter, Attr);
-}
-
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
-                                        const GOFF::EDAttr &Attr,
-                                        uint32_t ParentEsdId) {
-  return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
-}
-
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
-                                        const GOFF::LDAttr &Attr,
-                                        uint32_t ParentEsdId) {
-  return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
-}
-
-GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name,
-                                        const GOFF::PRAttr &Attr,
-                                        uint32_t ParentEsdId) {
-  return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr);
-}
-
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
-  uint32_t SDEsdId = RootSDEsdId;
-  if (!Section.usesRootSD()) {
-    GOFFSymbol SD =
-        createGOFFSymbol(Section.getSDName(), Section.getSDAttributes());
-    SDEsdId = SD.EsdId;
-    if (RootSDEsdId == 0)
-      RootSDEsdId = SDEsdId;
+  if (Section.isSD()) {
+    GOFFSymbol SD(Section.getName(), Section.getId(),
+                  Section.getSDAttributes());
     writeSymbol(SD);
   }
 
-  GOFFSymbol ED =
-      createGOFFSymbol(Section.getEDName(), Section.getEDAttributes(), SDEsdId);
-  if ((!Section.hasLD() && !Section.hasPR()) || Section.hasLD()) {
-    ED.SectionLength = Asm.getSectionAddressSize(Section);
-  }
-  writeSymbol(ED);
-
-  if (Section.hasLD()) {
-    GOFFSymbol LD = createGOFFSymbol(Section.getLDorPRName(),
-                                     Section.getLDAttributes(), ED.EsdId);
-    if (Section.isText())
-      LD.ADAEsdId = ADAEsdId;
-    writeSymbol(LD);
+  if (Section.isED()) {
+    GOFFSymbol ED(Section.getName(), Section.getId(),
+                  Section.getParent()->getId(), Section.getEDAttributes());
+    if (Section.requiresLength())
+      ED.SectionLength = Asm.getSectionAddressSize(Section);
+    writeSymbol(ED);
   }
 
-  if (Section.hasPR()) {
-    GOFFSymbol PR = createGOFFSymbol(Section.getLDorPRName(),
-                                     Section.getPRAttributes(), ED.EsdId);
+  if (Section.isPR()) {
+    GOFFSymbol PR(Section.getName(), Section.getId(),
+                  Section.getParent()->getId(), Section.getPRAttributes());
     PR.SectionLength = Asm.getSectionAddressSize(Section);
-    if (&Section == ADA) {
+    if (Section.requiresNonZeroLength()) {
       // 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
@@ -371,19 +325,33 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
       // generate -1 if there is no ADA
       if (!PR.SectionLength)
         PR.SectionLength = 2;
-      ADAEsdId = PR.EsdId;
     }
     writeSymbol(PR);
   }
 }
 
+void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
+  GOFFSymbol LD(Symbol.getName(), ++EsdIdCounter, 0, Symbol.getLDAttributes());
+  if (Symbol.getADA())
+    LD.ADAEsdId = Symbol.getADA()->getId();
+  writeSymbol(LD);
+}
+
 void GOFFWriter::defineSymbols() {
   // Process all sections.
   for (MCSection &S : Asm) {
     auto &Section = cast<MCSectionGOFF>(S);
-    if (!ADA)
-      ADA = &Section;
     defineSectionSymbols(Section);
+    EsdIdCounter = std::max(EsdIdCounter, Section.getId());
+  }
+
+  // Process all symbols
+  for (const MCSymbol &Sym : Asm.symbols()) {
+    if (Sym.isTemporary())
+      continue;
+    auto &Symbol = cast<MCSymbolGOFF>(Sym);
+    if (Symbol.hasLDAttributes()) {
+    }
   }
 }
 
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 56ca85d115792..fa4c090d0fe24 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/BinaryFormat/XCOFF.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -672,77 +673,45 @@ MCContext::getELFUniqueIDForEntsize(StringRef SectionName, unsigned Flags,
 }
 
 MCSectionGOFF *
-MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
-                          GOFF::SDAttr SDAttributes, StringRef EDName,
-                          GOFF::EDAttr EDAttributes, StringRef LDorPRName,
-                          GOFF::LDAttr LDAttributes, GOFF::PRAttr PRAttributes,
-                          MCSectionGOFF::SectionFlags Flags) {
-  std::string SynName = Twine(SDName)
-                            .concat("/")
-                            .concat(EDName)
-                            .concat("/")
-                            .concat(LDorPRName)
-                            .str();
+MCContext::getGOFFSection(SectionKind Kind, GOFF::ESDSymbolType SymbolType,
+                          StringRef Name, GOFF::SDAttr SDAttributes,
+                          GOFF::EDAttr EDAttributes, GOFF::PRAttr PRAttributes,
+                          MCSection *Parent) {
+  GOFFSectionKey T{Name, SymbolType};
   // Do the lookup. If we don't have a hit, return a new section.
-  auto IterBool = GOFFUniquingMap.insert(std::make_pair(SynName, nullptr));
+  auto IterBool = GOFFUniquingMap.insert(std::make_pair(T, nullptr));
   auto Iter = IterBool.first;
   if (!IterBool.second)
     return Iter->second;
 
-  StringRef CachedSynName = Iter->first;
+  StringRef CachedName = Iter->first.SectionName;
   MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
-      MCSectionGOFF(CachedSynName, Kind, Flags, SDName, SDAttributes, EDName,
-                    EDAttributes, LDorPRName, LDAttributes, PRAttributes);
+      MCSectionGOFF(CachedName, Kind, SymbolType, SDAttributes, EDAttributes,
+                    PRAttributes, static_cast<MCSectionGOFF *>(Parent));
   Iter->second = GOFFSection;
   allocInitialFragment(*GOFFSection);
   return GOFFSection;
 }
 
-MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
                                          GOFF::SDAttr SDAttributes,
-                                         StringRef EDName,
-                                         GOFF::EDAttr EDAttributes,
-                                         StringRef LDorPRName,
-                                         GOFF::LDAttr LDAttributes) {
-  return getGOFFSection(Kind, SDName, SDAttributes, EDName, EDAttributes,
-                        LDorPRName, LDAttributes, GOFF::PRAttr{},
-                        MCSectionGOFF::HasLD);
+                                         MCSection *Parent) {
+  return getGOFFSection(Kind, GOFF::ESD_ST_SectionDefinition, Name,
+                        SDAttributes, GOFF::EDAttr{}, GOFF::PRAttr{}, Parent);
 }
 
-MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef SDName,
-                                         GOFF::SDAttr SDAttributes,
-                                         StringRef EDName,
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
                                          GOFF::EDAttr EDAttributes,
-                                         StringRef LDorPRName,
-                                         GOFF::PRAttr PRAttributes) {
-  return getGOFFSection(Kind, SDName, SDAttributes, EDName, EDAttributes,
-                        LDorPRName, GOFF::LDAttr{}, PRAttributes,
-                        MCSectionGOFF::HasPR);
+                                         MCSection *Parent) {
+  return getGOFFSection(Kind, GOFF::ESD_ST_ElementDefinition, Name,
+                        GOFF::SDAttr{}, EDAttributes, GOFF::PRAttr{}, Parent);
 }
 
-MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
-                                         GOFF::EDAttr EDAttributes,
-                                         StringRef LDorPRName,
-                                         GOFF::LDAttr LDAttributes) {
-  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes,
-                        LDorPRName, LDAttributes, GOFF::PRAttr{},
-                        MCSectionGOFF::UsesRootSD | MCSectionGOFF::HasLD);
-}
-
-MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
-                                         GOFF::EDAttr EDAttributes,
-                                         StringRef LDorPRName,
-                                         GOFF::PRAttr PRAttributes) {
-  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes,
-                        LDorPRName, GOFF::LDAttr{}, PRAttributes,
-                        MCSectionGOFF::UsesRootSD | MCSectionGOFF::HasPR);
-}
-
-MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef EDName,
-                                         GOFF::EDAttr EDAttributes) {
-  return getGOFFSection(Kind, "", GOFF::SDAttr{}, EDName, EDAttributes, "",
-                        GOFF::LDAttr{}, GOFF::PRAttr{},
-                        MCSectionGOFF::UsesRootSD);
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
+                                         GOFF::PRAttr PRAttributes,
+                                         MCSection *Parent) {
+  return getGOFFSection(Kind, GOFF::ESD_ST_SectionDefinition, Name,
+                        GOFF::SDAttr{}, GOFF::EDAttr{}, PRAttributes, Parent);
 }
 
 MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index c67b4da6b3d74..114e48ed57751 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -27,25 +27,27 @@ GOFFObjectWriter &MCGOFFStreamer::getWriter() {
   return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
 }
 
-void MCGOFFStreamer::initSections(bool NoExecStack,
+void MCGOFFStreamer::initSections(bool /*NoExecStack*/,
                                   const MCSubtargetInfo &STI) {
   MCContext &Ctx = getContext();
+  // Emit the text section.
+  switchSection(Ctx.getObjectFileInfo()->getTextSection());
+}
+
+namespace {
+// Make sure that all section are registered in the correct order.
+void registerSectionHierarchy(MCAssembler &Asm, MCSectionGOFF *Section) {
+  if (Section->isRegistered())
+    return;
+  if (Section->getParent())
+    registerSectionHierarchy(Asm, Section->getParent());
+  registerSectionHierarchy(Asm, Section);
+}
+} // namespace
 
-  // Initialize the special names for the code and ada section.
-  StringRef FileName = sys::path::stem(Ctx.getMainFileName());
-  RootSDName = Twine(FileName).concat("#C").str();
-  ADAPRName = Twine(FileName).concat("#S").str();
-  MCSectionGOFF *TextSection =
-      static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getTextSection());
-  MCSectionGOFF *ADASection =
-      static_cast<MCSectionGOFF *>(Ctx.getObjectFileInfo()->getADASection());
-  ADASection->setSDName(RootSDName);
-  ADASection->setLDorPRName(ADAPRName);
-  TextSection->setLDorPRName(RootSDName);
-
-  // Switch to the ADA section first, then code section.
-  switchSection(ADASection);
-  switchSection(TextSection);
+void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
+  registerSectionHierarchy(getAssembler(), static_cast<MCSectionGOFF *>(Section));
+  MCObjectStreamer::changeSection(Section, Subsection);
 }
 
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index ada59a0de86e6..9daa197288cb8 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -547,46 +547,53 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
 }
 
 void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
+  RootSDSection = Ctx->getGOFFSection(
+      SectionKind::getMetadata(), "#C",
+      GOFF::SDAttr{GOFF::ESD_TA_Rent, GOFF::ESD_BSC_Section});
+
+  ADAEDSection = Ctx->getGOFFSection(
+      SectionKind::getMetadata(), GOFF::CLASS_WSA,
+      GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
+                   GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
+                   GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1,
+                   GOFF::ESD_ALIGN_Quadword},
+      RootSDSection);
+  ADAPRSection = Ctx->getGOFFSection(
+      SectionKind::getData(), "#S",
+      GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
+                   GOFF::ESD_LT_XPLink, GOFF::AMODE, GOFF::ESD_BSC_Section,
+                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Quadword, 0},
+      ADAEDSection);
+
   TextSection = Ctx->getGOFFSection(
       SectionKind::getText(), GOFF::CLASS_CODE,
       GOFF::EDAttr{true, GOFF::ESD_EXE_CODE, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_NormalName, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Concatenate, GOFF::ESD_LB_Initial,
                    GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword},
-      "#C",
-      GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, GOFF::ESD_NS_NormalName,
-                   GOFF::ESD_BST_Strong, GOFF::LINKAGE, GOFF::AMODE,
-                   GOFF::ESD_BSC_Section});
+      RootSDSection);
 
-  PPA2ListSection = Ctx->getGOFFSection(
-      SectionKind::getData(), GOFF::CLASS_PPA2,
+  PPA2ListEDSection = Ctx->getGOFFSection(
+      SectionKind::getMetadata(), GOFF::CLASS_PPA2,
       GOFF::EDAttr{true, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Merge, GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
                    GOFF::ESD_ALIGN_Doubleword},
-      ".&ppa2",
+      RootSDSection);
+  PPA2ListPRSection = Ctx->getGOFFSection(
+      SectionKind::getData(), ".&ppa2",
       GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
                    GOFF::ESD_LT_OS, GOFF::AMODE, GOFF::ESD_BSC_Section,
-                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Doubleword, 0});
-
-  ADASection = Ctx->getGOFFSection(
-      SectionKind::getData(), "#C",
-      GOFF::SDAttr{GOFF::ESD_TA_Rent, GOFF::ESD_BSC_Section}, GOFF::CLASS_WSA,
-      GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
-                   GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
-                   GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1,
-                   GOFF::ESD_ALIGN_Quadword},
-      "#S",
-      GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
-                   GOFF::ESD_LT_XPLink, GOFF::AMODE, GOFF::ESD_BSC_Section,
-                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Quadword, 0});
+                   GOFF::ESD_DSS_NoWarning, GOFF::ESD_ALIGN_Doubleword, 0},
+      PPA2ListEDSection);
 
   IDRLSection = Ctx->getGOFFSection(
       SectionKind::getData(), "B_IDRL",
       GOFF::EDAttr{true, GOFF::ESD_EXE_Unspecified, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_NormalName, GOFF::ESD_TS_Structured,
                    GOFF::ESD_BA_Concatenate, GOFF::ESD_LB_NoLoad,
-                   GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword});
+                   GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword},
+      RootSDSection);
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {

>From 5d522fddfbd5edf87b7565702cd96fb5aaae47fc Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 7 Apr 2025 16:14:11 -0400
Subject: [PATCH 11/15] More work on reviewer comments

Most comments are resolved except:
- I kept the RootSDSection variable
- The attributes are not yet in a union
- I still need to extend the unique section key for hashmap
---
 llvm/include/llvm/MC/MCContext.h                  |  9 +++------
 llvm/include/llvm/MC/MCGOFFStreamer.h             |  2 --
 llvm/include/llvm/MC/MCObjectFileInfo.h           | 13 ++++---------
 llvm/include/llvm/MC/MCSectionGOFF.h              | 13 ++++++-------
 llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 10 +++++++---
 llvm/lib/MC/GOFFObjectWriter.cpp                  |  8 +++++---
 llvm/lib/MC/MCContext.cpp                         |  9 ++++-----
 llvm/lib/MC/MCGOFFStreamer.cpp                    |  3 ++-
 llvm/lib/MC/MCObjectFileInfo.cpp                  |  8 ++++----
 llvm/test/CodeGen/SystemZ/zos-landingpad.ll       |  5 +++--
 llvm/test/CodeGen/SystemZ/zos-simple-test.ll      |  4 ++--
 llvm/test/MC/GOFF/ppa1.ll                         |  3 ++-
 llvm/test/MC/GOFF/section.ll                      | 10 +++++-----
 13 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 67d7d5e2642be..99f3d75cd8f78 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -624,14 +624,11 @@ class MCContext {
 
 public:
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
-                                GOFF::SDAttr SDAttributes,
-                                MCSection *Parent = nullptr);
+                                GOFF::SDAttr SDAttributes);
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
-                                GOFF::EDAttr EDAttributes,
-                                MCSection *Parent = nullptr);
+                                GOFF::EDAttr EDAttributes, MCSection *Parent);
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
-                                GOFF::PRAttr PRAttributes,
-                                MCSection *Parent = nullptr);
+                                GOFF::PRAttr PRAttributes, MCSection *Parent);
 
   MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
                                 StringRef COMDATSymName, int Selection,
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 771d77b50209a..68af26ef17c70 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -16,8 +16,6 @@ namespace llvm {
 class GOFFObjectWriter;
 
 class MCGOFFStreamer : public MCObjectStreamer {
-  std::string RootSDName;
-  std::string ADAPRName;
 
 public:
   MCGOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index b5ec42fdd352e..55c979b127f59 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -231,10 +231,8 @@ class MCObjectFileInfo {
 
   // GOFF specific sections.
   MCSection *RootSDSection = nullptr;
-  MCSection *PPA2ListEDSection = nullptr;
-  MCSection *PPA2ListPRSection = nullptr;
-  MCSection *ADAEDSection = nullptr;
-  MCSection *ADAPRSection = nullptr;
+  MCSection *PPA2ListSection = nullptr;
+  MCSection *ADASection = nullptr;
   MCSection *IDRLSection = nullptr;
 
   // XCOFF specific sections
@@ -439,11 +437,8 @@ class MCObjectFileInfo {
   MCSection *getGLJMPSection() const { return GLJMPSection; }
 
   // GOFF specific sections.
-  MCSection *getRootSDSection() const { return RootSDSection; }
-  MCSection *getPPA2ListEDSection() const { return PPA2ListEDSection; }
-  MCSection *getPPA2ListSection() const { return PPA2ListPRSection; }
-  MCSection *getADAEDSection() const { return ADAEDSection; }
-  MCSection *getADASection() const { return ADAPRSection; }
+  MCSection *getPPA2ListSection() const { return PPA2ListSection; }
+  MCSection *getADASection() const { return ADASection; }
   MCSection *getIDRLSection() const { return IDRLSection; }
 
   // XCOFF specific sections
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index e922101187905..a09fe0980dd76 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -37,11 +37,9 @@ class MCSectionGOFF final : public MCSection {
   // The type of this section.
   GOFF::ESDSymbolType SymbolType;
 
-  // Indicates that the ED symbol needs to set the length of the section.
-  unsigned RequiresLength : 1;
-
   // Indicates that the PR symbol needs to set the length of the section to a
-  // non-zero value.
+  // non-zero value. This is only a problem with the ADA PR - the binder will
+  // generate an error in this case.
   unsigned RequiresNonZeroLength : 1;
 
   friend class MCContext;
@@ -55,16 +53,17 @@ class MCSectionGOFF final : public MCSection {
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
                             raw_ostream &OS,
-                            uint32_t /*Subsection*/) const override {
-    ;
+                            uint32_t Subsection) const override {
     switch (SymbolType) {
     case GOFF::ESD_ST_SectionDefinition:
       OS << Name << " CSECT\n";
       break;
     case GOFF::ESD_ST_ElementDefinition:
+      getParent()->printSwitchToSection(MAI, T, OS, Subsection);
       OS << Name << " CATTR\n";
       break;
     case GOFF::ESD_ST_PartReference:
+      getParent()->printSwitchToSection(MAI, T, OS, Subsection);
       OS << Name << " XATTR\n";
       break;
     default:
@@ -101,7 +100,7 @@ class MCSectionGOFF final : public MCSection {
     return PRAttributes;
   }
 
-  bool requiresLength() const { return RequiresLength; }
+  void setRequiresNonZeroLength() { RequiresNonZeroLength = true; }
   bool requiresNonZeroLength() const { return RequiresNonZeroLength; }
 
   void setName(StringRef SectionName) { Name = SectionName; }
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index a64a22ebcf67d..9ca89bf272418 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -66,6 +66,7 @@
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/Triple.h"
@@ -2763,12 +2764,15 @@ TargetLoweringObjectFileGOFF::TargetLoweringObjectFileGOFF() = default;
 
 void TargetLoweringObjectFileGOFF::getModuleMetadata(Module &M) {
   // Construct the default names for the root SD and the ADA PR symbol.
-  DefaultRootSDName = Twine(M.getSourceFileName()).concat("#C").str();
-  DefaultADAPRName = Twine(M.getSourceFileName()).concat("#S").str();
+  StringRef FileName = sys::path::stem(M.getSourceFileName());
+  DefaultRootSDName = Twine(FileName).concat("#C").str();
+  DefaultADAPRName = Twine(FileName).concat("#S").str();
   MCSectionGOFF *RootSD = static_cast<MCSectionGOFF *>(RootSDSection);
-  MCSectionGOFF *ADAPR = static_cast<MCSectionGOFF *>(ADAPRSection);
+  MCSectionGOFF *ADAPR = static_cast<MCSectionGOFF *>(ADASection);
   RootSD->setName(DefaultRootSDName);
   ADAPR->setName(DefaultADAPRName);
+  // The length of the ADA needs to be adjusted in case it is 0.
+  ADAPR->setRequiresNonZeroLength();
   // Initialize the label for the text section.
   MCSymbolGOFF *TextLD = static_cast<MCSymbolGOFF *>(
       getContext().getOrCreateSymbol(RootSD->getName()));
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index b70fab6185a03..fd5f52d2b7523 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -308,8 +308,7 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
   if (Section.isED()) {
     GOFFSymbol ED(Section.getName(), Section.getId(),
                   Section.getParent()->getId(), Section.getEDAttributes());
-    if (Section.requiresLength())
-      ED.SectionLength = Asm.getSectionAddressSize(Section);
+    ED.SectionLength = Asm.getSectionAddressSize(Section);
     writeSymbol(ED);
   }
 
@@ -331,7 +330,9 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
 }
 
 void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
-  GOFFSymbol LD(Symbol.getName(), ++EsdIdCounter, 0, Symbol.getLDAttributes());
+  GOFFSymbol LD(Symbol.getName(), ++EsdIdCounter,
+                static_cast<MCSectionGOFF &>(Symbol.getSection()).getId(),
+                Symbol.getLDAttributes());
   if (Symbol.getADA())
     LD.ADAEsdId = Symbol.getADA()->getId();
   writeSymbol(LD);
@@ -351,6 +352,7 @@ void GOFFWriter::defineSymbols() {
       continue;
     auto &Symbol = cast<MCSymbolGOFF>(Sym);
     if (Symbol.hasLDAttributes()) {
+      defineLabel(Symbol);
     }
   }
 }
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index fa4c090d0fe24..11ac998c80512 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -694,10 +694,9 @@ MCContext::getGOFFSection(SectionKind Kind, GOFF::ESDSymbolType SymbolType,
 }
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
-                                         GOFF::SDAttr SDAttributes,
-                                         MCSection *Parent) {
+                                         GOFF::SDAttr SDAttributes) {
   return getGOFFSection(Kind, GOFF::ESD_ST_SectionDefinition, Name,
-                        SDAttributes, GOFF::EDAttr{}, GOFF::PRAttr{}, Parent);
+                        SDAttributes, GOFF::EDAttr{}, GOFF::PRAttr{}, nullptr);
 }
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
@@ -710,8 +709,8 @@ MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
                                          GOFF::PRAttr PRAttributes,
                                          MCSection *Parent) {
-  return getGOFFSection(Kind, GOFF::ESD_ST_SectionDefinition, Name,
-                        GOFF::SDAttr{}, GOFF::EDAttr{}, PRAttributes, Parent);
+  return getGOFFSection(Kind, GOFF::ESD_ST_PartReference, Name, GOFF::SDAttr{},
+                        GOFF::EDAttr{}, PRAttributes, Parent);
 }
 
 MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 114e48ed57751..cf0adae68189c 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -31,6 +31,7 @@ void MCGOFFStreamer::initSections(bool /*NoExecStack*/,
                                   const MCSubtargetInfo &STI) {
   MCContext &Ctx = getContext();
   // Emit the text section.
+  switchSection(Ctx.getObjectFileInfo()->getADASection());
   switchSection(Ctx.getObjectFileInfo()->getTextSection());
 }
 
@@ -41,7 +42,7 @@ void registerSectionHierarchy(MCAssembler &Asm, MCSectionGOFF *Section) {
     return;
   if (Section->getParent())
     registerSectionHierarchy(Asm, Section->getParent());
-  registerSectionHierarchy(Asm, Section);
+  Asm.registerSection(*Section);
 }
 } // namespace
 
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 9daa197288cb8..a1ed984639406 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -551,14 +551,14 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
       SectionKind::getMetadata(), "#C",
       GOFF::SDAttr{GOFF::ESD_TA_Rent, GOFF::ESD_BSC_Section});
 
-  ADAEDSection = Ctx->getGOFFSection(
+  MCSectionGOFF *ADAEDSection = Ctx->getGOFFSection(
       SectionKind::getMetadata(), GOFF::CLASS_WSA,
       GOFF::EDAttr{false, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Merge, GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1,
                    GOFF::ESD_ALIGN_Quadword},
       RootSDSection);
-  ADAPRSection = Ctx->getGOFFSection(
+  ADASection = Ctx->getGOFFSection(
       SectionKind::getData(), "#S",
       GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_NS_Parts,
                    GOFF::ESD_LT_XPLink, GOFF::AMODE, GOFF::ESD_BSC_Section,
@@ -573,14 +573,14 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
                    GOFF::ESD_RQ_0, GOFF::ESD_ALIGN_Doubleword},
       RootSDSection);
 
-  PPA2ListEDSection = Ctx->getGOFFSection(
+  MCSectionGOFF *PPA2ListEDSection = Ctx->getGOFFSection(
       SectionKind::getMetadata(), GOFF::CLASS_PPA2,
       GOFF::EDAttr{true, GOFF::ESD_EXE_DATA, GOFF::AMODE, GOFF::RMODE,
                    GOFF::ESD_NS_Parts, GOFF::ESD_TS_ByteOriented,
                    GOFF::ESD_BA_Merge, GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
                    GOFF::ESD_ALIGN_Doubleword},
       RootSDSection);
-  PPA2ListPRSection = Ctx->getGOFFSection(
+  PPA2ListSection = Ctx->getGOFFSection(
       SectionKind::getData(), ".&ppa2",
       GOFF::PRAttr{true, false, GOFF::ESD_EXE_Unspecified, GOFF::ESD_NS_Parts,
                    GOFF::ESD_LT_OS, GOFF::AMODE, GOFF::ESD_BSC_Section,
diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
index f447731c849e1..6a76c2fe50878 100644
--- a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
@@ -37,6 +37,7 @@ lpad:
 ; CHECK: Personality routine
 ; CHECK: LSDA location
 ; Check that the exception table is emitted into .lsda section.
-; CHECK: C_WSA64 CATTR
-; CHECK: GCC_except_table0 XATTR
+; CHECK:  <stdin>#C CSECT
+; CHECK:  C_WSA64 CATTR
+; CHECK:  .gcc_exception_table.test1 XATTR
 ; CHECK: GCC_except_table0:
diff --git a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
index 40a4b91b9f1da..d1c83060410e5 100644
--- a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
@@ -5,10 +5,10 @@
 @a = global i32 0, align 4
 
 define signext i32 @main() {
+; CHECK: <stdin>#C CSECT
 ; CHECK: C_CODE64 CATTR
-; CHECK: #C XATTR
 ; CHECK: main:
-; CHECK: a CSECT
+; CHECK: <stdin>#C CSECT
 ; CHECK: C_WSA64 CATTR
 ; CHECK: a XATTR
 entry:
diff --git a/llvm/test/MC/GOFF/ppa1.ll b/llvm/test/MC/GOFF/ppa1.ll
index fe2dc77bba2f5..95e036dedecd2 100644
--- a/llvm/test/MC/GOFF/ppa1.ll
+++ b/llvm/test/MC/GOFF/ppa1.ll
@@ -12,7 +12,8 @@
 ; CHECK: *   Bit 1: 1 = Leaf function
 ; CHECK: *   Bit 2: 0 = Does not use alloca
 ; CHECK: L#func_end0:
-; CHECK: .section        ".ppa1"
+; CHECK: <stdin>#C CSECT
+; CHECK: C_CODE64 CATTR
 ; CHECK: L#PPA1_void_test_0:                     * PPA1
 ; CHECK:        .byte   2                               * Version
 ; CHECK:        .byte   206                             * LE Signature X'CE'
diff --git a/llvm/test/MC/GOFF/section.ll b/llvm/test/MC/GOFF/section.ll
index 9e943a71cbf4a..004c5540f0709 100644
--- a/llvm/test/MC/GOFF/section.ll
+++ b/llvm/test/MC/GOFF/section.ll
@@ -66,8 +66,8 @@ entry:
 
 ; ESD record, type LD.
 ; The name is test#C.
-; CHECK: 0000190 03 00 00 02 00 00 00 05 00 00 00 04 00 00 00 00
-; CHECK: 00001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK: 00001b0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 03
-; CHECK: 00001c0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
-; CHECK: 00001d0 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
+; CHECK: 00002d0 03 00 00 02 00 00 00 08 00 00 00 04 00 00 00 00
+; CHECK: 00002e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 00002f0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 03
+; CHECK: 0000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
+; CHECK: 0000310 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00

>From 74e804c18789ff961d0639249c9ce814c98099ba Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 7 Apr 2025 18:47:40 -0400
Subject: [PATCH 12/15] Emit CSECT/CATTR

This adds the logic to emit the CSECT and CATTR assembler instructions.
---
 llvm/include/llvm/MC/MCSectionGOFF.h          |  26 +---
 llvm/include/llvm/MC/MCSymbolGOFF.h           |   5 +-
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  |   5 +-
 llvm/lib/MC/CMakeLists.txt                    |   1 +
 llvm/lib/MC/MCSectionGOFF.cpp                 | 145 ++++++++++++++++++
 .../CodeGen/SystemZ/zos-ada-relocations.ll    |   5 +-
 llvm/test/CodeGen/SystemZ/zos-intrinsics.ll   |   5 +-
 llvm/test/CodeGen/SystemZ/zos-landingpad.ll   |   5 +-
 llvm/test/CodeGen/SystemZ/zos-simple-test.ll  |  12 +-
 llvm/test/MC/GOFF/ppa1.ll                     |   4 +-
 10 files changed, 175 insertions(+), 38 deletions(-)
 create mode 100644 llvm/lib/MC/MCSectionGOFF.cpp

diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index a09fe0980dd76..36d27dab3d4e3 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -42,34 +42,23 @@ class MCSectionGOFF final : public MCSection {
   // generate an error in this case.
   unsigned RequiresNonZeroLength : 1;
 
+  // Set to true if the section definition was already emitted.
+  mutable unsigned Emitted : 1;
+
   friend class MCContext;
+  friend class MCSymbolGOFF;
   MCSectionGOFF(StringRef Name, SectionKind K, GOFF::ESDSymbolType SymbolType,
                 GOFF::SDAttr SDAttributes, GOFF::EDAttr EDAttributes,
                 GOFF::PRAttr PRAttributes, MCSectionGOFF *Parent = nullptr)
       : MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
         Parent(Parent), SDAttributes(SDAttributes), EDAttributes(EDAttributes),
-        PRAttributes(PRAttributes), SymbolType(SymbolType) {}
+        PRAttributes(PRAttributes), SymbolType(SymbolType),
+        RequiresNonZeroLength(0), Emitted(0) {}
 
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
                             raw_ostream &OS,
-                            uint32_t Subsection) const override {
-    switch (SymbolType) {
-    case GOFF::ESD_ST_SectionDefinition:
-      OS << Name << " CSECT\n";
-      break;
-    case GOFF::ESD_ST_ElementDefinition:
-      getParent()->printSwitchToSection(MAI, T, OS, Subsection);
-      OS << Name << " CATTR\n";
-      break;
-    case GOFF::ESD_ST_PartReference:
-      getParent()->printSwitchToSection(MAI, T, OS, Subsection);
-      OS << Name << " XATTR\n";
-      break;
-    default:
-      llvm_unreachable("Wrong section type");
-    }
-  }
+                            uint32_t Subsection) const override;
 
   bool useCodeAlign() const override { return false; }
 
@@ -100,7 +89,6 @@ class MCSectionGOFF final : public MCSection {
     return PRAttributes;
   }
 
-  void setRequiresNonZeroLength() { RequiresNonZeroLength = true; }
   bool requiresNonZeroLength() const { return RequiresNonZeroLength; }
 
   void setName(StringRef SectionName) { Name = SectionName; }
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index c46f5bd4234b5..d8c570d2de240 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -42,7 +42,10 @@ class MCSymbolGOFF : public MCSymbol {
   GOFF::LDAttr getLDAttributes() const { return LDAttributes; }
   bool hasLDAttributes() const { return getFlags() & SF_LD; }
 
-  void setADA(MCSectionGOFF *AssociatedDataArea) { ADA = AssociatedDataArea; }
+  void setADA(MCSectionGOFF *AssociatedDataArea) {
+    ADA = AssociatedDataArea;
+    AssociatedDataArea->RequiresNonZeroLength = true;
+  }
   MCSectionGOFF *getADA() const { return ADA; }
 
   static bool classof(const MCSymbol *S) { return S->isGOFF(); }
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 9ca89bf272418..265d5b18e78a3 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2765,14 +2765,15 @@ TargetLoweringObjectFileGOFF::TargetLoweringObjectFileGOFF() = default;
 void TargetLoweringObjectFileGOFF::getModuleMetadata(Module &M) {
   // Construct the default names for the root SD and the ADA PR symbol.
   StringRef FileName = sys::path::stem(M.getSourceFileName());
+  if (FileName.size() > 1 && FileName.starts_with('<') &&
+      FileName.ends_with('>'))
+    FileName = FileName.substr(1, FileName.size() - 2);
   DefaultRootSDName = Twine(FileName).concat("#C").str();
   DefaultADAPRName = Twine(FileName).concat("#S").str();
   MCSectionGOFF *RootSD = static_cast<MCSectionGOFF *>(RootSDSection);
   MCSectionGOFF *ADAPR = static_cast<MCSectionGOFF *>(ADASection);
   RootSD->setName(DefaultRootSDName);
   ADAPR->setName(DefaultADAPRName);
-  // The length of the ADA needs to be adjusted in case it is 0.
-  ADAPR->setRequiresNonZeroLength();
   // Initialize the label for the text section.
   MCSymbolGOFF *TextLD = static_cast<MCSymbolGOFF *>(
       getContext().getOrCreateSymbol(RootSD->getName()));
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index f49f14c848b90..d662c42c522fc 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -46,6 +46,7 @@ add_llvm_component_library(LLVMMC
   MCSectionCOFF.cpp
   MCSectionDXContainer.cpp
   MCSectionELF.cpp
+  MCSectionGOFF.cpp
   MCSectionMachO.cpp
   MCSectionWasm.cpp
   MCSectionXCOFF.cpp
diff --git a/llvm/lib/MC/MCSectionGOFF.cpp b/llvm/lib/MC/MCSectionGOFF.cpp
new file mode 100644
index 0000000000000..3ff2a239ff51d
--- /dev/null
+++ b/llvm/lib/MC/MCSectionGOFF.cpp
@@ -0,0 +1,145 @@
+//===- MCSectionGOFF.cpp - GOFF Code Section Representation ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSectionGOFF.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+void emitRMode(raw_ostream &OS, GOFF::ESDRmode Rmode, bool UseParenthesis) {
+  if (Rmode != GOFF::ESD_RMODE_None) {
+    OS << "RMODE" << (UseParenthesis ? '(' : ' ');
+    switch (Rmode) {
+    case GOFF::ESD_RMODE_24:
+      OS << "24";
+      break;
+    case GOFF::ESD_RMODE_31:
+      OS << "31";
+      break;
+    case GOFF::ESD_RMODE_64:
+      OS << "64";
+      break;
+    case GOFF::ESD_RMODE_None:
+      break;
+    }
+    if (UseParenthesis)
+      OS << ')';
+  }
+}
+
+void emitCATTR(raw_ostream &OS, StringRef Name, StringRef ParentName,
+               bool EmitAmodeAndRmode, GOFF::ESDAmode Amode,
+               GOFF::ESDRmode Rmode, GOFF::ESDAlignment Alignment,
+               GOFF::ESDLoadingBehavior LoadBehavior,
+               GOFF::ESDExecutable Executable, bool IsReadOnly,
+               StringRef PartName) {
+  if (EmitAmodeAndRmode && Amode != GOFF::ESD_AMODE_None) {
+    OS << ParentName << " AMODE ";
+    switch (Amode) {
+    case GOFF::ESD_AMODE_24:
+      OS << "24";
+      break;
+    case GOFF::ESD_AMODE_31:
+      OS << "31";
+      break;
+    case GOFF::ESD_AMODE_ANY:
+      OS << "ANY";
+      break;
+    case GOFF::ESD_AMODE_64:
+      OS << "64";
+      break;
+    case GOFF::ESD_AMODE_MIN:
+      OS << "ANY64";
+      break;
+    case GOFF::ESD_AMODE_None:
+      break;
+    }
+    OS << "\n";
+  }
+  if (EmitAmodeAndRmode && Rmode != GOFF::ESD_RMODE_None) {
+    OS << ParentName << ' ';
+    emitRMode(OS, Rmode, /*UseParenthesis=*/false);
+    OS << "\n";
+  }
+  OS << Name << " CATTR ";
+  OS << "ALIGN(" << static_cast<unsigned>(Alignment) << ")";
+  switch (LoadBehavior) {
+  case GOFF::ESD_LB_Deferred:
+    OS << ",DEFLOAD";
+    break;
+  case GOFF::ESD_LB_NoLoad:
+    OS << ",NOLOAD";
+    break;
+  default:
+    break;
+  }
+  switch (Executable) {
+  case GOFF::ESD_EXE_CODE:
+    OS << ",EXECUTABLE";
+    break;
+  case GOFF::ESD_EXE_DATA:
+    OS << ",NOTEXECUTABLE";
+    break;
+  default:
+    break;
+  }
+  if (IsReadOnly)
+    OS << ",READONLY";
+  if (Rmode != GOFF::ESD_RMODE_None) {
+    OS << ',';
+    emitRMode(OS, Rmode, /*UseParenthesis=*/true);
+  }
+  if (!PartName.empty())
+    OS << ",PART(" << PartName << ")";
+  OS << '\n';
+}
+} // namespace
+
+void MCSectionGOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+                                         raw_ostream &OS,
+                                         uint32_t Subsection) const {
+  switch (SymbolType) {
+  case GOFF::ESD_ST_SectionDefinition: {
+    OS << Name << " CSECT\n";
+    Emitted = true;
+    break;
+  }
+  case GOFF::ESD_ST_ElementDefinition: {
+    bool ParentEmitted = getParent()->Emitted;
+    getParent()->printSwitchToSection(MAI, T, OS, Subsection);
+    if (!Emitted) {
+      emitCATTR(OS, Name, getParent()->getName(), !ParentEmitted,
+                EDAttributes.Amode, EDAttributes.Rmode, EDAttributes.Alignment,
+                EDAttributes.LoadBehavior, EDAttributes.Executable,
+                EDAttributes.IsReadOnly, StringRef());
+      Emitted = true;
+    } else
+      OS << Name << " CATTR ,\n";
+    break;
+  }
+  case GOFF::ESD_ST_PartReference: {
+    MCSectionGOFF *ED = getParent();
+    bool SDEmitted = ED->getParent()->Emitted;
+    ED->getParent()->printSwitchToSection(MAI, T, OS, Subsection);
+    if (!Emitted) {
+      emitCATTR(OS, ED->getName(), ED->getParent()->getName(), !SDEmitted,
+                PRAttributes.Amode, getParent()->EDAttributes.Rmode,
+                PRAttributes.Alignment, getParent()->EDAttributes.LoadBehavior,
+                PRAttributes.Executable, PRAttributes.IsReadOnly, Name);
+      ED->Emitted = true;
+      Emitted = true;
+    } else
+      OS << ED->getName() << " CATTR ,\n";
+    break;
+  }
+  default:
+    llvm_unreachable("Wrong section type");
+  }
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll
index 59ad4ff93c5e9..8a31dab9c7686 100644
--- a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll
@@ -55,9 +55,8 @@ entry:
 
 declare signext i32 @callout(i32 signext)
 
-; CHECK: #C CSECT
-; CHECK: C_WSA64 CATTR
-; CHECK: #S XATTR
+; CHECK: stdin#C CSECT
+; CHECK: C_WSA64 CATTR ALIGN(4),DEFLOAD,NOTEXECUTABLE,RMODE(64),PART(stdin#S)
 ; CHECK:  .set L#DoFunc at indirect0, DoFunc
 ; CHECK:      .indirect_symbol   L#DoFunc at indirect0
 ; CHECK:  .quad V(L#DoFunc at indirect0)          * Offset 0 pointer to function descriptor DoFunc
diff --git a/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll b/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll
index b9aedf6517d4b..f413fc5ce7671 100644
--- a/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-intrinsics.ll
@@ -30,9 +30,8 @@ declare double @llvm.sin.f64(double)
 declare fp128 @llvm.exp2.f128(fp128)
 
 ; Check the calls in the ADA.
-; CHECK: #C CSECT
-; CHECK: C_WSA64 CATTR
-; CHECK: #S XATTR
+; CHECK: stdin#C CSECT
+; CHECK: C_WSA64 CATTR ALIGN(4),DEFLOAD,NOTEXECUTABLE,RMODE(64),PART(stdin#S)
 
 ; Check that there is no call to sqrt.
 ; CHECK-NOT:  .quad   R(@@WSQT at B)
diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
index 6a76c2fe50878..d216f292396a8 100644
--- a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
@@ -37,7 +37,6 @@ lpad:
 ; CHECK: Personality routine
 ; CHECK: LSDA location
 ; Check that the exception table is emitted into .lsda section.
-; CHECK:  <stdin>#C CSECT
-; CHECK:  C_WSA64 CATTR
-; CHECK:  .gcc_exception_table.test1 XATTR
+; CHECK:  stdin#C CSECT
+; CHECK:  C_WSA64 CATTR ALIGN(2),DEFLOAD,RMODE(64),PART(.gcc_exception_table.test1)
 ; CHECK: GCC_except_table0:
diff --git a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
index d1c83060410e5..35ef34f2313f3 100644
--- a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll
@@ -5,12 +5,14 @@
 @a = global i32 0, align 4
 
 define signext i32 @main() {
-; CHECK: <stdin>#C CSECT
-; CHECK: C_CODE64 CATTR
+; CHECK: stdin#C CSECT
+; CHECK: stdin#C AMODE 64
+; CHECK: stdin#C RMODE 64
+; CHECK: C_CODE64 CATTR ALIGN(3),EXECUTABLE,READONLY,RMODE(64)
 ; CHECK: main:
-; CHECK: <stdin>#C CSECT
-; CHECK: C_WSA64 CATTR
-; CHECK: a XATTR
+; CHECK: stdin#C CSECT
+; CHECK: C_WSA64 CATTR ALIGN(4),DEFLOAD,NOTEXECUTABLE,RMODE(64),PART(a)
+; CHECK: a:
 entry:
   ret i32 0
 }
diff --git a/llvm/test/MC/GOFF/ppa1.ll b/llvm/test/MC/GOFF/ppa1.ll
index 95e036dedecd2..222e4c448a668 100644
--- a/llvm/test/MC/GOFF/ppa1.ll
+++ b/llvm/test/MC/GOFF/ppa1.ll
@@ -12,8 +12,8 @@
 ; CHECK: *   Bit 1: 1 = Leaf function
 ; CHECK: *   Bit 2: 0 = Does not use alloca
 ; CHECK: L#func_end0:
-; CHECK: <stdin>#C CSECT
-; CHECK: C_CODE64 CATTR
+; CHECK: stdin#C CSECT
+; CHECK: C_CODE64 CATTR ,
 ; CHECK: L#PPA1_void_test_0:                     * PPA1
 ; CHECK:        .byte   2                               * Version
 ; CHECK:        .byte   206                             * LE Signature X'CE'

>From c541729ef3f846825110956e8e591e6424699d7c Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Tue, 8 Apr 2025 13:44:40 -0400
Subject: [PATCH 13/15] Fix key for hashmap and introduce union

---
 llvm/include/llvm/MC/MCContext.h            | 25 +++------------
 llvm/include/llvm/MC/MCSectionGOFF.h        | 34 +++++++++++++++------
 llvm/lib/MC/MCContext.cpp                   | 33 ++++++++++----------
 llvm/test/CodeGen/SystemZ/zos-landingpad.ll |  2 +-
 4 files changed, 46 insertions(+), 48 deletions(-)

diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 99f3d75cd8f78..ff4ed76aa6ee4 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -270,21 +270,6 @@ class MCContext {
     }
   };
 
-  struct GOFFSectionKey {
-    std::string SectionName;
-    GOFF::ESDSymbolType SymbolType;
-
-    GOFFSectionKey(StringRef SectionName, GOFF::ESDSymbolType SymbolType)
-        : SectionName(SectionName), SymbolType(SymbolType) {}
-
-    bool operator<(const GOFFSectionKey &Other) const {
-      if (SymbolType == Other.SymbolType) {
-        return SectionName < Other.SectionName;
-      }
-      return SymbolType < Other.SymbolType;
-    }
-  };
-
   struct WasmSectionKey {
     std::string SectionName;
     StringRef GroupName;
@@ -338,7 +323,7 @@ class MCContext {
   StringMap<MCSectionMachO *> MachOUniquingMap;
   std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap;
   StringMap<MCSectionELF *> ELFUniquingMap;
-  std::map<GOFFSectionKey, MCSectionGOFF *> GOFFUniquingMap;
+  std::map<std::string, MCSectionGOFF *> GOFFUniquingMap;
   std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap;
   std::map<XCOFFSectionKey, MCSectionXCOFF *> XCOFFUniquingMap;
   StringMap<MCSectionDXContainer *> DXCUniquingMap;
@@ -616,11 +601,9 @@ class MCContext {
                                                    unsigned EntrySize);
 
 private:
-  MCSectionGOFF *getGOFFSection(SectionKind Kind,
-                                GOFF::ESDSymbolType SymbolType, StringRef Name,
-                                GOFF::SDAttr SDAttributes,
-                                GOFF::EDAttr EDAttributes,
-                                GOFF::PRAttr PRAttributes, MCSection *Parent);
+  template <typename TAttr>
+  MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
+                                TAttr SDAttributes, MCSection *Parent);
 
 public:
   MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index 36d27dab3d4e3..c239a8ad3ee15 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -30,9 +30,11 @@ class MCSectionGOFF final : public MCSection {
   MCSectionGOFF *Parent;
 
   // The attributes of the GOFF symbols.
-  GOFF::SDAttr SDAttributes;
-  GOFF::EDAttr EDAttributes;
-  GOFF::PRAttr PRAttributes;
+  union {
+    GOFF::SDAttr SDAttributes;
+    GOFF::EDAttr EDAttributes;
+    GOFF::PRAttr PRAttributes;
+  };
 
   // The type of this section.
   GOFF::ESDSymbolType SymbolType;
@@ -47,13 +49,27 @@ class MCSectionGOFF final : public MCSection {
 
   friend class MCContext;
   friend class MCSymbolGOFF;
-  MCSectionGOFF(StringRef Name, SectionKind K, GOFF::ESDSymbolType SymbolType,
-                GOFF::SDAttr SDAttributes, GOFF::EDAttr EDAttributes,
-                GOFF::PRAttr PRAttributes, MCSectionGOFF *Parent = nullptr)
+
+  MCSectionGOFF(StringRef Name, SectionKind K, GOFF::SDAttr SDAttributes,
+                MCSectionGOFF *Parent)
+      : MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
+        Parent(Parent), SDAttributes(SDAttributes),
+        SymbolType(GOFF::ESD_ST_SectionDefinition), RequiresNonZeroLength(0),
+        Emitted(0) {}
+
+  MCSectionGOFF(StringRef Name, SectionKind K, GOFF::EDAttr EDAttributes,
+                MCSectionGOFF *Parent)
+      : MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
+        Parent(Parent), EDAttributes(EDAttributes),
+        SymbolType(GOFF::ESD_ST_ElementDefinition), RequiresNonZeroLength(0),
+        Emitted(0) {}
+
+  MCSectionGOFF(StringRef Name, SectionKind K, GOFF::PRAttr PRAttributes,
+                MCSectionGOFF *Parent)
       : MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
-        Parent(Parent), SDAttributes(SDAttributes), EDAttributes(EDAttributes),
-        PRAttributes(PRAttributes), SymbolType(SymbolType),
-        RequiresNonZeroLength(0), Emitted(0) {}
+        Parent(Parent), PRAttributes(PRAttributes),
+        SymbolType(GOFF::ESD_ST_PartReference), RequiresNonZeroLength(0),
+        Emitted(0) {}
 
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 11ac998c80512..c00a870051c49 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -672,22 +672,24 @@ MCContext::getELFUniqueIDForEntsize(StringRef SectionName, unsigned Flags,
                                       : std::nullopt;
 }
 
-MCSectionGOFF *
-MCContext::getGOFFSection(SectionKind Kind, GOFF::ESDSymbolType SymbolType,
-                          StringRef Name, GOFF::SDAttr SDAttributes,
-                          GOFF::EDAttr EDAttributes, GOFF::PRAttr PRAttributes,
-                          MCSection *Parent) {
-  GOFFSectionKey T{Name, SymbolType};
+template <typename TAttr>
+MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
+                                         TAttr Attributes, MCSection *Parent) {
+  std::string UniqueName(Name);
+  if (Parent) {
+    UniqueName.append("/").append(Parent->getName());
+    if (auto *P = static_cast<MCSectionGOFF *>(Parent)->getParent())
+      UniqueName.append("/").append(P->getName());
+  }
   // Do the lookup. If we don't have a hit, return a new section.
-  auto IterBool = GOFFUniquingMap.insert(std::make_pair(T, nullptr));
+  auto IterBool = GOFFUniquingMap.insert(std::make_pair(UniqueName, nullptr));
   auto Iter = IterBool.first;
   if (!IterBool.second)
     return Iter->second;
 
-  StringRef CachedName = Iter->first.SectionName;
-  MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
-      MCSectionGOFF(CachedName, Kind, SymbolType, SDAttributes, EDAttributes,
-                    PRAttributes, static_cast<MCSectionGOFF *>(Parent));
+  StringRef CachedName = StringRef(Iter->first.c_str(), Name.size());
+  MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate()) MCSectionGOFF(
+      CachedName, Kind, Attributes, static_cast<MCSectionGOFF *>(Parent));
   Iter->second = GOFFSection;
   allocInitialFragment(*GOFFSection);
   return GOFFSection;
@@ -695,22 +697,19 @@ MCContext::getGOFFSection(SectionKind Kind, GOFF::ESDSymbolType SymbolType,
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
                                          GOFF::SDAttr SDAttributes) {
-  return getGOFFSection(Kind, GOFF::ESD_ST_SectionDefinition, Name,
-                        SDAttributes, GOFF::EDAttr{}, GOFF::PRAttr{}, nullptr);
+  return getGOFFSection<GOFF::SDAttr>(Kind, Name, SDAttributes, nullptr);
 }
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
                                          GOFF::EDAttr EDAttributes,
                                          MCSection *Parent) {
-  return getGOFFSection(Kind, GOFF::ESD_ST_ElementDefinition, Name,
-                        GOFF::SDAttr{}, EDAttributes, GOFF::PRAttr{}, Parent);
+  return getGOFFSection<GOFF::EDAttr>(Kind, Name, EDAttributes, Parent);
 }
 
 MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
                                          GOFF::PRAttr PRAttributes,
                                          MCSection *Parent) {
-  return getGOFFSection(Kind, GOFF::ESD_ST_PartReference, Name, GOFF::SDAttr{},
-                        GOFF::EDAttr{}, PRAttributes, Parent);
+  return getGOFFSection<GOFF::PRAttr>(Kind, Name, PRAttributes, Parent);
 }
 
 MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
index d216f292396a8..fd58656e549d1 100644
--- a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
@@ -38,5 +38,5 @@ lpad:
 ; CHECK: LSDA location
 ; Check that the exception table is emitted into .lsda section.
 ; CHECK:  stdin#C CSECT
-; CHECK:  C_WSA64 CATTR ALIGN(2),DEFLOAD,RMODE(64),PART(.gcc_exception_table.test1)
+; CHECK:  C_WSA64 CATTR ALIGN(2),RMODE(64),PART(.gcc_exception_table.test1)
 ; CHECK: GCC_except_table0:

>From 469206d463cf9941c7f20291a3a521f3ea2c2408 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Tue, 8 Apr 2025 15:33:37 -0400
Subject: [PATCH 14/15] Use getOrdinal/getIndex as the GOFF symbol id.

---
 llvm/include/llvm/MC/MCSectionGOFF.h |  3 ---
 llvm/lib/MC/GOFFObjectWriter.cpp     | 23 +++++++++++------------
 2 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index c239a8ad3ee15..1bb8a7a0b7155 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -78,9 +78,6 @@ class MCSectionGOFF final : public MCSection {
 
   bool useCodeAlign() const override { return false; }
 
-  // Return the id of the section. It is the 1-based ordinal number.
-  unsigned getId() const { return getOrdinal() + 1; }
-
   // Return the parent section.
   MCSectionGOFF *getParent() const { return Parent; }
 
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index fd5f52d2b7523..a0fe350585376 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -278,9 +278,6 @@ class GOFFWriter {
   GOFFOstream OS;
   [[maybe_unused]] MCAssembler &Asm;
 
-  /// Counter for symbol id's.
-  uint32_t EsdIdCounter = 0;
-
   void writeHeader();
   void writeSymbol(const GOFFSymbol &Symbol);
   void writeEnd();
@@ -300,21 +297,21 @@ GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
 
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
   if (Section.isSD()) {
-    GOFFSymbol SD(Section.getName(), Section.getId(),
+    GOFFSymbol SD(Section.getName(), Section.getOrdinal(),
                   Section.getSDAttributes());
     writeSymbol(SD);
   }
 
   if (Section.isED()) {
-    GOFFSymbol ED(Section.getName(), Section.getId(),
-                  Section.getParent()->getId(), Section.getEDAttributes());
+    GOFFSymbol ED(Section.getName(), Section.getOrdinal(),
+                  Section.getParent()->getOrdinal(), Section.getEDAttributes());
     ED.SectionLength = Asm.getSectionAddressSize(Section);
     writeSymbol(ED);
   }
 
   if (Section.isPR()) {
-    GOFFSymbol PR(Section.getName(), Section.getId(),
-                  Section.getParent()->getId(), Section.getPRAttributes());
+    GOFFSymbol PR(Section.getName(), Section.getOrdinal(),
+                  Section.getParent()->getOrdinal(), Section.getPRAttributes());
     PR.SectionLength = Asm.getSectionAddressSize(Section);
     if (Section.requiresNonZeroLength()) {
       // We cannot have a zero-length section for data.  If we do,
@@ -330,20 +327,21 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
 }
 
 void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
-  GOFFSymbol LD(Symbol.getName(), ++EsdIdCounter,
-                static_cast<MCSectionGOFF &>(Symbol.getSection()).getId(),
+  GOFFSymbol LD(Symbol.getName(), Symbol.getIndex(),
+                static_cast<MCSectionGOFF &>(Symbol.getSection()).getOrdinal(),
                 Symbol.getLDAttributes());
   if (Symbol.getADA())
-    LD.ADAEsdId = Symbol.getADA()->getId();
+    LD.ADAEsdId = Symbol.getADA()->getOrdinal();
   writeSymbol(LD);
 }
 
 void GOFFWriter::defineSymbols() {
+  unsigned Ordinal = 0;
   // Process all sections.
   for (MCSection &S : Asm) {
     auto &Section = cast<MCSectionGOFF>(S);
+    Section.setOrdinal(++Ordinal);
     defineSectionSymbols(Section);
-    EsdIdCounter = std::max(EsdIdCounter, Section.getId());
   }
 
   // Process all symbols
@@ -352,6 +350,7 @@ void GOFFWriter::defineSymbols() {
       continue;
     auto &Symbol = cast<MCSymbolGOFF>(Sym);
     if (Symbol.hasLDAttributes()) {
+      Symbol.setIndex(++Ordinal);
       defineLabel(Symbol);
     }
   }

>From f859b78c9bf4ac47ac4e97b6259cd991e67da986 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Tue, 8 Apr 2025 16:12:10 -0400
Subject: [PATCH 15/15] Remove initSections()

Also updates the test to match ideas, to make it easier to move those blocks around.
---
 llvm/include/llvm/MC/MCGOFFStreamer.h |  1 -
 llvm/lib/MC/MCGOFFStreamer.cpp        |  8 -----
 llvm/test/MC/GOFF/section.ll          | 44 +++++++++++++--------------
 3 files changed, 22 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 68af26ef17c70..366d7dc08c679 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -26,7 +26,6 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   ~MCGOFFStreamer() override;
 
-  void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override;
   void changeSection(MCSection *Section, uint32_t Subsection = 0) override;
 
   GOFFObjectWriter &getWriter();
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index cf0adae68189c..2686a6f96e98b 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -27,14 +27,6 @@ GOFFObjectWriter &MCGOFFStreamer::getWriter() {
   return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
 }
 
-void MCGOFFStreamer::initSections(bool /*NoExecStack*/,
-                                  const MCSubtargetInfo &STI) {
-  MCContext &Ctx = getContext();
-  // Emit the text section.
-  switchSection(Ctx.getObjectFileInfo()->getADASection());
-  switchSection(Ctx.getObjectFileInfo()->getTextSection());
-}
-
 namespace {
 // Make sure that all section are registered in the correct order.
 void registerSectionHierarchy(MCAssembler &Asm, MCSectionGOFF *Section) {
diff --git a/llvm/test/MC/GOFF/section.ll b/llvm/test/MC/GOFF/section.ll
index 004c5540f0709..73bc9ae42c3b5 100644
--- a/llvm/test/MC/GOFF/section.ll
+++ b/llvm/test/MC/GOFF/section.ll
@@ -33,41 +33,41 @@ entry:
 ; The 60 at offset 0x89 is the tasking behavior.
 ; The 01 at offset 0x91 is the binding scope.
 ; The name begins at offset 0x97, and is test#C.
-; CHECK: 0000050 03 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00
+; CHECK: 0000050 03 00 00 00 [[ROOTSD:00 00 00 01]] 00 00 00 00 00 00 00 00
 ; CHECK: 0000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK: 0000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK: 0000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60
 ; CHECK: 0000090 00 01 00 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
 
+; ESD record, type ED.
+; The name is C_CODE64.
+; The regular expression matches the low byte of the length.
+; CHECK: 00000a0 03 00 00 01 [[C_CODE64:00 00 00 02]] [[ROOTSD]] 00 00 00 00
+; CHECK: 00000b0 00 00 00 00 00 00 00 00 00 00 00 {{..}} 00 00 00 00
+; CHECK: 00000c0 00 00 00 00 00 00 00 00 01 80 00 00 00 00 00 00
+; CHECK: 00000d0 00 00 00 00 00 00 00 00 00 00 00 00 04 04 00 0a
+; CHECK: 00000e0 00 00 03 00 00 00 00 08 c3 6d c3 d6 c4 c5 f6 f4
+
 ; ESD record, type ED.
 ; The name is C_WSA64.
-; CHECK: 00000a0 03 00 00 01 00 00 00 02 00 00 00 01 00 00 00 00
-; CHECK: 00000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK: 00000c0 00 00 00 00 00 00 00 00 03 81 00 00 00 00 00 00
-; CHECK: 00000d0 00 00 00 00 00 00 00 00 00 00 00 00 04 04 01 01
-; CHECK: 00000e0 00 40 04 00 00 00 00 07 c3 6d e6 e2 c1 f6 f4 00
+; CHECK: 00001e0 03 00 00 01 [[C_WSA64:00 00 00 05]] [[ROOTSD]] 00 00 00 00
+; CHECK: 00001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK: 0000200 00 00 00 00 00 00 00 00 03 81 00 00 00 00 00 00
+; CHECK: 0000210 00 00 00 00 00 00 00 00 00 00 00 00 04 04 01 01
+; CHECK: 0000220 00 40 04 00 00 00 00 07 c3 6d e6 e2 c1 f6 f4 00
 
 ; ESD record, type PR.
 ; The name is test#S.
-; CHECK: 00000f0 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 00
-; CHECK: 0000100 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
-; CHECK: 0000110 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
-; CHECK: 0000120 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 01
-; CHECK: 0000130 00 01 24 00 00 00 00 06 a3 85 a2 a3 7b e2 00 00
-
-; ESD record, type ED.
-; The name is C_CODE64.
-; The regular expression matches the low byte of the length.
-; CHECK: 0000140 03 00 00 01 00 00 00 04 00 00 00 01 00 00 00 00
-; CHECK: 0000150 00 00 00 00 00 00 00 00 00 00 00 {{..}} 00 00 00 00
-; CHECK: 0000160 00 00 00 00 00 00 00 00 01 80 00 00 00 00 00 00
-; CHECK: 0000170 00 00 00 00 00 00 00 00 00 00 00 00 04 04 00 0a
-; CHECK: 0000180 00 00 03 00 00 00 00 08 c3 6d c3 d6 c4 c5 f6 f4
+; CHECK: 0000230 03 00 00 03 [[TESTS:00 00 00 06]] [[C_WSA64]] 00 00 00 00
+; CHECK: 0000240 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
+; CHECK: 0000250 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
+; CHECK: 0000260 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 01
+; CHECK: 0000270 00 01 24 00 00 00 00 06 a3 85 a2 a3 7b e2 00 00
 
 ; ESD record, type LD.
 ; The name is test#C.
-; CHECK: 00002d0 03 00 00 02 00 00 00 08 00 00 00 04 00 00 00 00
+; CHECK: 00002d0 03 00 00 02 [[TESTC:00 00 00 08]] [[C_CODE64]] 00 00 00 00
 ; CHECK: 00002e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK: 00002f0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 03
+; CHECK: 00002f0 00 00 00 00 00 00 00 00 01 00 00 00 [[TESTS]]
 ; CHECK: 0000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK: 0000310 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00



More information about the llvm-branch-commits mailing list