[llvm] [GOFF] Emit symbols for functions. (PR #144437)

Kai Nacke via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 11:55:38 PST 2025


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

>From 6261752c43e16feb0ac3b42915c8de943cc96601 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 16 Jun 2025 17:27:16 -0400
Subject: [PATCH 01/18] [GOFF] Emit symbols for functions.

A function entry is mapped to a LD symbol with an offset to the begin of the section.
---
 llvm/include/llvm/MC/MCGOFFStreamer.h      |  7 +--
 llvm/include/llvm/MC/MCSymbolGOFF.h        | 22 ++++++++-
 llvm/lib/MC/CMakeLists.txt                 |  1 +
 llvm/lib/MC/GOFFObjectWriter.cpp           |  1 +
 llvm/lib/MC/MCGOFFStreamer.cpp             | 57 ++++++++++++++++++++++
 llvm/lib/MC/MCSymbolGOFF.cpp               | 39 +++++++++++++++
 llvm/test/CodeGen/SystemZ/zos-section-1.ll | 34 ++++++++-----
 7 files changed, 143 insertions(+), 18 deletions(-)
 create mode 100644 llvm/lib/MC/MCSymbolGOFF.cpp

diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 8888d9e7bdbb3..6fa6e6481347f 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -28,9 +28,10 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   GOFFObjectWriter &getWriter();
 
-  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
-    return false;
-  }
+  void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
+
+  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
+
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         Align ByteAlignment) override {}
 };
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 11d4df4aea634..b58b520cc5c49 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -28,7 +28,10 @@ class MCSymbolGOFF : public MCSymbol {
   GOFF::LDAttr LDAttributes;
 
   enum SymbolFlags : uint16_t {
-    SF_LD = 0x01, // LD attributes are set.
+    SF_LD = 0x01,     // LD attributes are set.
+                      // Leave place for EX attributes.
+    SF_Hidden = 0x04, // Symbol is hidden, aka not exported.
+    SF_Weak = 0x08,   // Symbol is weak.
   };
 
 public:
@@ -39,7 +42,8 @@ class MCSymbolGOFF : public MCSymbol {
     modifyFlags(SF_LD, SF_LD);
     LDAttributes = Attr;
   }
-  GOFF::LDAttr getLDAttributes() const { return LDAttributes; }
+  const GOFF::LDAttr &getLDAttributes() const { return LDAttributes; }
+  GOFF::LDAttr &getLDAttributes() { return LDAttributes; }
   bool hasLDAttributes() const { return getFlags() & SF_LD; }
 
   void setADA(MCSectionGOFF *AssociatedDataArea) {
@@ -47,6 +51,20 @@ class MCSymbolGOFF : public MCSymbol {
     AssociatedDataArea->RequiresNonZeroLength = true;
   }
   MCSectionGOFF *getADA() const { return ADA; }
+
+  bool isExternal() const { return IsExternal; }
+  void setExternal(bool Value) const { IsExternal = Value; }
+
+  void setHidden(bool Value = true) {
+    modifyFlags(Value ? SF_Hidden : 0, SF_Hidden);
+  }
+  bool isHidden() const { return getFlags() & SF_Hidden; }
+  bool isExported() const { return !isHidden(); }
+
+  void setWeak(bool Value = true) { modifyFlags(Value ? SF_Weak : 0, SF_Weak); }
+  bool isWeak() const { return getFlags() & SF_Weak; }
+
+  void initAttributes();
 };
 } // end namespace llvm
 
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index 70c4577aeec0a..1388f130bb806 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -50,6 +50,7 @@ add_llvm_component_library(LLVMMC
   MCSubtargetInfo.cpp
   MCSymbol.cpp
   MCSymbolELF.cpp
+  MCSymbolGOFF.cpp
   MCSymbolXCOFF.cpp
   MCTargetOptions.cpp
   MCTargetOptionsCommandFlags.cpp
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index a3eaaa743039d..b42ba148ef65b 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -328,6 +328,7 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
                 Section.getEDAttributes().NameSpace, Symbol.getLDAttributes());
   if (Symbol.getADA())
     LD.ADAEsdId = Symbol.getADA()->getOrdinal();
+  LD.Offset = Asm.getSymbolOffset(Symbol);
   writeSymbol(LD);
 }
 
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index ad6397bce70f0..c76e8cd1dc3c8 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -15,7 +15,9 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/MC/TargetRegistry.h"
 
 using namespace llvm;
@@ -37,6 +39,61 @@ void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
   }
 }
 
+void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+  MCObjectStreamer::emitLabel(Symbol, Loc);
+  static_cast<MCSymbolGOFF *>(Symbol)->initAttributes();
+}
+
+bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
+                                         MCSymbolAttr Attribute) {
+  auto *Symbol = static_cast<MCSymbolGOFF *>(Sym);
+  switch (Attribute) {
+  case MCSA_Invalid:
+  case MCSA_Cold:
+  case MCSA_ELF_TypeFunction:
+  case MCSA_ELF_TypeIndFunction:
+  case MCSA_ELF_TypeObject:
+  case MCSA_ELF_TypeTLS:
+  case MCSA_ELF_TypeCommon:
+  case MCSA_ELF_TypeNoType:
+  case MCSA_ELF_TypeGnuUniqueObject:
+  case MCSA_LGlobal:
+  case MCSA_Extern:
+  case MCSA_Exported:
+  case MCSA_IndirectSymbol:
+  case MCSA_Internal:
+  case MCSA_LazyReference:
+  case MCSA_NoDeadStrip:
+  case MCSA_SymbolResolver:
+  case MCSA_AltEntry:
+  case MCSA_PrivateExtern:
+  case MCSA_Protected:
+  case MCSA_Reference:
+  case MCSA_WeakDefinition:
+  case MCSA_WeakDefAutoPrivate:
+  case MCSA_WeakAntiDep:
+  case MCSA_Memtag:
+    return false;
+
+  case MCSA_Global:
+    Symbol->setExternal(true);
+    break;
+  case MCSA_Local:
+    Symbol->setExternal(false);
+    break;
+  case MCSA_Weak:
+  case MCSA_WeakReference:
+    Symbol->setExternal(true);
+    Symbol->setWeak();
+    break;
+  case MCSA_Hidden:
+    Symbol->setHidden(true);
+    break;
+  }
+
+  return true;
+}
+
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
                                      std::unique_ptr<MCAsmBackend> &&MAB,
                                      std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
new file mode 100644
index 0000000000000..86de21b11bc0a
--- /dev/null
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -0,0 +1,39 @@
+//===- MCSymbolGOFF.cpp - GOFF Symbol 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/MCSymbolGOFF.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+void MCSymbolGOFF::initAttributes() {
+  if (hasLDAttributes())
+    return;
+
+  if (isDefined()) {
+    MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(getSection());
+    GOFF::ESDBindingScope BindingScope =
+        isExternal() ? (isExported() ? GOFF::ESD_BSC_ImportExport
+                                     : GOFF::ESD_BSC_Library)
+                     : GOFF::ESD_BSC_Section;
+    GOFF::ESDBindingStrength BindingStrength =
+        isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
+                 : GOFF::ESDBindingStrength::ESD_BST_Strong;
+    if (Section.isED()) {
+      setLDAttributes(GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, BindingStrength,
+                                   GOFF::ESD_LT_XPLink, GOFF::ESD_AMODE_64,
+                                   BindingScope});
+    } else if (Section.isPR()) {
+      // For data symbols, the attributes are already determind in TLOFI.
+      // TODO Does it make sense to it to here?
+    } else
+      llvm_unreachable("Unexpected section type for label");
+  }
+  // TODO Handle external symbol.
+}
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-1.ll b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
index b98584df54d5a..6caa8f4d607de 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
@@ -104,26 +104,34 @@ entry:
 ; CHECK-NEXT: 000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 000310 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
 
+; ESD record, type LD.
+; The name is me.
+; CHECK-NEXT: 000320 03 00 00 02 [[ME:00 00 00 09]] [[C_CODE64]] 00 00 00 00
+; CHECK-NEXT: 000330 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
+; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
+; CHECK-NEXT: 000360 00 04 20 00 00 00 00 02 94 85 00 00 00 00 00 00
+
 ; Text record for the code section C_CODE64.
 ; The regular expression matches the lower byte of the length.
-; CHECK-NEXT: 000320 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000330 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
+; CHECK-NEXT: 000370 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000380 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
 
 ; Text record for the section .&ppa2.
-; CHECK:      0003c0 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0003d0 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000410 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the ADA section test#S.
-; CHECK:      000410 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000460 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000470 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the section B_IDRL.
-; CHECK:      000460 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000470 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      0004b0 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; End record.
-; CHECK:      0004b0 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK:      000500 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

>From 194ba3a6efd669d3737efa033e767a45bd6f756e Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 29 Oct 2025 13:19:28 -0400
Subject: [PATCH 02/18] Add HLASM output and external references

Adds HLASM output and tests for it, per reviewer comment.
Also adds external references, because it fits very well
into the implementation.
---
 llvm/include/llvm/MC/MCDirectives.h           |   4 +
 llvm/include/llvm/MC/MCGOFFAttributes.h       |   8 +
 llvm/include/llvm/MC/MCGOFFStreamer.h         |   3 +
 llvm/include/llvm/MC/MCSymbolGOFF.h           |  28 +++-
 llvm/lib/MC/GOFFObjectWriter.cpp              |  21 +++
 llvm/lib/MC/MCAsmStreamer.cpp                 |   3 +
 llvm/lib/MC/MCELFStreamer.cpp                 |   2 +
 llvm/lib/MC/MCGOFFStreamer.cpp                |  19 +++
 llvm/lib/MC/MCMachOStreamer.cpp               |   2 +
 llvm/lib/MC/MCSymbolGOFF.cpp                  |  28 ++--
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 158 +++++++++++++++++-
 .../MCTargetDesc/SystemZHLASMAsmStreamer.h    |   7 +-
 .../MCTargetDesc/SystemZTargetStreamer.cpp    |  17 +-
 .../MCTargetDesc/SystemZTargetStreamer.h      |   7 +-
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp |  23 +++
 llvm/test/CodeGen/SystemZ/zos-no-eh-label.ll  |   2 +-
 llvm/test/CodeGen/SystemZ/zos-section-1.ll    |  52 ++++--
 llvm/test/CodeGen/SystemZ/zos-section-2.ll    |  34 ++--
 llvm/test/CodeGen/SystemZ/zos-symbol-1.ll     |  37 ++++
 19 files changed, 395 insertions(+), 60 deletions(-)
 create mode 100644 llvm/test/CodeGen/SystemZ/zos-symbol-1.ll

diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index f8b7e05b3719b..f69144367c8e7 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -48,6 +48,10 @@ enum MCSymbolAttr {
   MCSA_WeakDefAutoPrivate,      ///< .weak_def_can_be_hidden (MachO)
   MCSA_WeakAntiDep,             ///< .weak_anti_dep (COFF)
   MCSA_Memtag,                  ///< .memtag (ELF)
+
+  // Attributes specific for HLASM.
+  MCSA_Code,                    ///< symbol is code (GOFF)
+  MCSA_Data,                    ///< symbol is data (GOFF)
 };
 
 enum MCDataRegionType {
diff --git a/llvm/include/llvm/MC/MCGOFFAttributes.h b/llvm/include/llvm/MC/MCGOFFAttributes.h
index c996f0cae2c69..1631d59462935 100644
--- a/llvm/include/llvm/MC/MCGOFFAttributes.h
+++ b/llvm/include/llvm/MC/MCGOFFAttributes.h
@@ -80,6 +80,14 @@ struct PRAttr {
   uint32_t SortKey = 0;
 };
 
+// Attributes for ER symbols.
+struct ERAttr {
+  GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
+  GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
+  GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
+  GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
+};
+
 // Predefined GOFF class names.
 constexpr StringLiteral CLASS_CODE = "C_CODE64";
 constexpr StringLiteral CLASS_WSA = "C_WSA64";
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 6fa6e6481347f..3d13ddf216aa3 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -14,6 +14,7 @@
 
 namespace llvm {
 class GOFFObjectWriter;
+class MCSymbolGOFF;
 
 class MCGOFFStreamer : public MCObjectStreamer {
 
@@ -34,6 +35,8 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         Align ByteAlignment) override {}
+
+  void emitExterns();
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index b58b520cc5c49..58305a00ec235 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -23,13 +23,21 @@ namespace llvm {
 
 class MCSymbolGOFF : public MCSymbol {
   // Associated data area of the section. Needs to be emitted first.
-  MCSectionGOFF *ADA;
+  MCSectionGOFF *ADA = nullptr;
+
+  // Owner of the symbol if symbol is an external reference. External references
+  // need a section, too, but adding them to a section would make the symbol
+  // defined.
+  MCSectionGOFF *Owner = nullptr;
 
   GOFF::LDAttr LDAttributes;
+  GOFF::ERAttr ERAttributes;
+
+  GOFF::ESDExecutable CodeData = GOFF::ESDExecutable::ESD_EXE_Unspecified;
 
   enum SymbolFlags : uint16_t {
     SF_LD = 0x01,     // LD attributes are set.
-                      // Leave place for EX attributes.
+    SF_ER = 0x02,     // ER attributes are set.
     SF_Hidden = 0x04, // Symbol is hidden, aka not exported.
     SF_Weak = 0x08,   // Symbol is weak.
   };
@@ -46,12 +54,25 @@ class MCSymbolGOFF : public MCSymbol {
   GOFF::LDAttr &getLDAttributes() { return LDAttributes; }
   bool hasLDAttributes() const { return getFlags() & SF_LD; }
 
+  void setERAttributes(GOFF::ERAttr Attr) {
+    modifyFlags(SF_ER, SF_ER);
+    ERAttributes = Attr;
+  }
+  const GOFF::ERAttr &getERAttributes() const { return ERAttributes; }
+  GOFF::ERAttr &getERAttributes() { return ERAttributes; }
+  bool hasERAttributes() const { return getFlags() & SF_ER; }
+
   void setADA(MCSectionGOFF *AssociatedDataArea) {
     ADA = AssociatedDataArea;
     AssociatedDataArea->RequiresNonZeroLength = true;
   }
   MCSectionGOFF *getADA() const { return ADA; }
 
+  void setOwner(MCSectionGOFF *Owner) {
+    this->Owner = Owner;
+  }
+  MCSectionGOFF *getOwner() const { return Owner; }
+
   bool isExternal() const { return IsExternal; }
   void setExternal(bool Value) const { IsExternal = Value; }
 
@@ -64,6 +85,9 @@ class MCSymbolGOFF : public MCSymbol {
   void setWeak(bool Value = true) { modifyFlags(Value ? SF_Weak : 0, SF_Weak); }
   bool isWeak() const { return getFlags() & SF_Weak; }
 
+  void setCodeData(GOFF::ESDExecutable Value) { CodeData = Value; }
+  GOFF::ESDExecutable getCodeData() const { return CodeData; }
+
   void initAttributes();
 };
 } // end namespace llvm
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index b42ba148ef65b..51f95813eabc8 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -266,6 +266,17 @@ class GOFFSymbol {
     BehavAttrs.setBindingScope(Attr.BindingScope);
     BehavAttrs.setAlignment(EDAttr.Alignment);
   }
+
+  GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
+             const GOFF::ERAttr &Attr)
+      : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
+        SymbolType(GOFF::ESD_ST_ExternalReference),
+        NameSpace(GOFF::ESD_NS_NormalName) {
+    BehavAttrs.setExecutable(Attr.Executable);
+    BehavAttrs.setBindingStrength(Attr.BindingStrength);
+    BehavAttrs.setLinkageType(Attr.Linkage);
+    BehavAttrs.setBindingScope(Attr.BindingScope);
+  }
 };
 
 class GOFFWriter {
@@ -279,6 +290,7 @@ class GOFFWriter {
 
   void defineSectionSymbols(const MCSectionGOFF &Section);
   void defineLabel(const MCSymbolGOFF &Symbol);
+  void defineExtern(const MCSymbolGOFF &Symbol);
   void defineSymbols();
 
 public:
@@ -332,6 +344,12 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
   writeSymbol(LD);
 }
 
+void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
+  GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(),
+                Symbol.getOwner()->getOrdinal(), Symbol.getERAttributes());
+  writeSymbol(ER);
+}
+
 void GOFFWriter::defineSymbols() {
   unsigned Ordinal = 0;
   // Process all sections.
@@ -349,6 +367,9 @@ void GOFFWriter::defineSymbols() {
     if (Symbol.hasLDAttributes()) {
       Symbol.setIndex(++Ordinal);
       defineLabel(Symbol);
+    } else if (Symbol.hasERAttributes()) {
+      Symbol.setIndex(++Ordinal);
+      defineExtern(Symbol);
     }
   }
 }
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 885fa55b65d50..60e3757f60fed 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -774,6 +774,9 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
     // Assemblers currently do not support a .cold directive.
   case MCSA_Exported:
     // Non-AIX assemblers currently do not support exported visibility.
+  case MCSA_Code:
+  case MCSA_Data:
+    // Only for HLASM.
     return false;
   case MCSA_Memtag:
     OS << "\t.memtag\t";
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 1bc1b92610871..4d4148c506b4f 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -151,6 +151,8 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
   case MCSA_IndirectSymbol:
   case MCSA_Exported:
   case MCSA_WeakAntiDep:
+  case MCSA_Code:
+  case MCSA_Data:
     return false;
 
   case MCSA_NoDeadStrip:
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index c76e8cd1dc3c8..62a9117fe895f 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/MC/MCGOFFStreamer.h"
+#include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCCodeEmitter.h"
@@ -75,6 +76,12 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Memtag:
     return false;
 
+  case MCSA_Code:
+    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
+    break;
+  case MCSA_Data:
+    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
+    break;
   case MCSA_Global:
     Symbol->setExternal(true);
     break;
@@ -94,6 +101,18 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   return true;
 }
 
+void MCGOFFStreamer::emitExterns() {
+  for (auto &Symbol : getAssembler().symbols()) {
+    if (Symbol.isTemporary())
+      continue;
+    if (Symbol.isRegistered()) {
+      auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
+      Sym.setOwner(static_cast<MCSectionGOFF *>(getCurrentSection().first));
+      Sym.initAttributes();
+    }
+  }
+}
+
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
                                      std::unique_ptr<MCAsmBackend> &&MAB,
                                      std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 2b7a248e6d109..da148f81012f7 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -299,6 +299,8 @@ bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Exported:
   case MCSA_Memtag:
   case MCSA_WeakAntiDep:
+  case MCSA_Code:
+  case MCSA_Data:
     return false;
 
   case MCSA_Global:
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index 86de21b11bc0a..5e248dea033a4 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -13,20 +13,26 @@
 using namespace llvm;
 
 void MCSymbolGOFF::initAttributes() {
-  if (hasLDAttributes())
+  // Temporary labels are not emitted into the object file.
+  if (isTemporary())
     return;
 
+  // Do not initialize the attributes multiple times.
+  if (hasLDAttributes() || hasERAttributes())
+    return;
+
+  GOFF::ESDBindingScope BindingScope =
+      isExternal()
+          ? (isExported() ? GOFF::ESD_BSC_ImportExport : GOFF::ESD_BSC_Library)
+          : GOFF::ESD_BSC_Section;
+  GOFF::ESDBindingStrength BindingStrength =
+      isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
+               : GOFF::ESDBindingStrength::ESD_BST_Strong;
+
   if (isDefined()) {
     MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(getSection());
-    GOFF::ESDBindingScope BindingScope =
-        isExternal() ? (isExported() ? GOFF::ESD_BSC_ImportExport
-                                     : GOFF::ESD_BSC_Library)
-                     : GOFF::ESD_BSC_Section;
-    GOFF::ESDBindingStrength BindingStrength =
-        isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
-                 : GOFF::ESDBindingStrength::ESD_BST_Strong;
     if (Section.isED()) {
-      setLDAttributes(GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, BindingStrength,
+      setLDAttributes(GOFF::LDAttr{false, CodeData, BindingStrength,
                                    GOFF::ESD_LT_XPLink, GOFF::ESD_AMODE_64,
                                    BindingScope});
     } else if (Section.isPR()) {
@@ -34,6 +40,8 @@ void MCSymbolGOFF::initAttributes() {
       // TODO Does it make sense to it to here?
     } else
       llvm_unreachable("Unexpected section type for label");
+  } else {
+    setERAttributes(GOFF::ERAttr{CodeData, BindingStrength,
+                                 GOFF::ESD_LT_XPLink, BindingScope});
   }
-  // TODO Handle external symbol.
 }
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 72bb37265259e..8553f8bc14f56 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -8,12 +8,19 @@
 
 #include "SystemZHLASMAsmStreamer.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCGOFFAttributes.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Signals.h"
 #include <sstream>
 
 using namespace llvm;
 
+void SystemZHLASMAsmStreamer::visitUsedSymbol(const MCSymbol &Sym) {
+  Assembler->registerSymbol(Sym);
+}
+
 void SystemZHLASMAsmStreamer::EmitEOL() {
   // Comments are emitted on a new line before the instruction.
   if (IsVerboseAsm)
@@ -183,17 +190,132 @@ void SystemZHLASMAsmStreamer::emitInstruction(const MCInst &Inst,
   EmitEOL();
 }
 
+static void emitXATTR(raw_ostream &OS, StringRef Name,
+                      GOFF::ESDLinkageType Linkage,
+                      GOFF::ESDExecutable Executable,
+                      GOFF::ESDBindingScope BindingScope) {
+  llvm::ListSeparator Sep(",");
+  OS << Name << " XATTR ";
+  OS << Sep << "LINKAGE(" << (Linkage == GOFF::ESD_LT_OS ? "OS" : "XPLINK")
+     << ")";
+  if (Executable != GOFF::ESD_EXE_Unspecified)
+    OS << Sep << "REFERENCE("
+       << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA") << ")";
+  if (BindingScope != GOFF::ESD_BSC_Unspecified) {
+    OS << Sep << "SCOPE(";
+    switch (BindingScope) {
+    case GOFF::ESD_BSC_Section:
+      OS << "SECTION";
+      break;
+    case GOFF::ESD_BSC_Module:
+      OS << "MODULE";
+      break;
+    case GOFF::ESD_BSC_Library:
+      OS << "LIBRARY";
+      break;
+    case GOFF::ESD_BSC_ImportExport:
+      OS << "EXPORT";
+      break;
+    default:
+      break;
+    }
+    OS << ')';
+  }
+  OS << '\n';
+}
+
+static bool sameNameAsCSECT(MCSymbolGOFF *Sym) {
+  if (Sym->hasLDAttributes() && Sym->isInSection()) {
+    MCSectionGOFF &ED = static_cast<MCSectionGOFF &>(Sym->getSection());
+    return Sym->getName() == ED.getParent()->getName();
+  }
+  return false;
+}
+
 void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+  MCSymbolGOFF *Sym = static_cast<MCSymbolGOFF *>(Symbol);
+
+  MCStreamer::emitLabel(Sym, Loc);
+  Sym->initAttributes();
+
+  // Emit ENTRY statement only if not implied by CSECT.
+  bool EmitEntry = !sameNameAsCSECT(Sym);
+
+  if (!Sym->isTemporary() && Sym->hasLDAttributes()) {
+    GOFF::LDAttr &LD = Sym->getLDAttributes();
+    if (EmitEntry) {
+      OS << " ENTRY " << Sym->getName();
+      EmitEOL();
+    }
 
-  MCStreamer::emitLabel(Symbol, Loc);
+    emitXATTR(OS, Sym->getName(), LD.Linkage, LD.Executable, LD.BindingScope);
+    EmitEOL();
+  }
 
-  Symbol->print(OS, MAI);
   // TODO Need to adjust this based on Label type
-  OS << " DS 0H";
-  // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been
-  // moved to HLASM syntax.
-  // OS << MAI->getLabelSuffix();
-  EmitEOL();
+  if (EmitEntry) {
+    OS << Sym->getName() << " DS 0H";
+    // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been
+    // moved to HLASM syntax.
+    // OS << MAI->getLabelSuffix();
+    EmitEOL();
+  }
+}
+
+bool SystemZHLASMAsmStreamer::emitSymbolAttribute(MCSymbol *Sym,
+                                                  MCSymbolAttr Attribute) {
+  auto *Symbol = static_cast<MCSymbolGOFF *>(Sym);
+  switch (Attribute) {
+  case MCSA_Invalid:
+  case MCSA_Cold:
+  case MCSA_ELF_TypeFunction:
+  case MCSA_ELF_TypeIndFunction:
+  case MCSA_ELF_TypeObject:
+  case MCSA_ELF_TypeTLS:
+  case MCSA_ELF_TypeCommon:
+  case MCSA_ELF_TypeNoType:
+  case MCSA_ELF_TypeGnuUniqueObject:
+  case MCSA_LGlobal:
+  case MCSA_Extern:
+  case MCSA_Exported:
+  case MCSA_IndirectSymbol:
+  case MCSA_Internal:
+  case MCSA_LazyReference:
+  case MCSA_NoDeadStrip:
+  case MCSA_SymbolResolver:
+  case MCSA_AltEntry:
+  case MCSA_PrivateExtern:
+  case MCSA_Protected:
+  case MCSA_Reference:
+  case MCSA_WeakDefinition:
+  case MCSA_WeakDefAutoPrivate:
+  case MCSA_WeakAntiDep:
+  case MCSA_Memtag:
+    return false;
+
+  case MCSA_Code:
+    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
+    break;
+  case MCSA_Data:
+    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
+    break;
+  case MCSA_Global:
+    Symbol->setExternal(true);
+    break;
+  case MCSA_Local:
+    Symbol->setExternal(false);
+    break;
+  case MCSA_Weak:
+  case MCSA_WeakReference:
+    Symbol->setExternal(true);
+    Symbol->setWeak();
+    break;
+  case MCSA_Hidden:
+    Symbol->setHidden(true);
+    break;
+  }
+
+  return true;
 }
 
 void SystemZHLASMAsmStreamer::emitRawTextImpl(StringRef String) {
@@ -276,6 +398,7 @@ void SystemZHLASMAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
   assert(getCurrentSectionOnly() &&
          "Cannot emit contents before setting section!");
 
+  MCStreamer::emitValueImpl(Value, Size, Loc);
   OS << " DC ";
   emitHLASMValueImpl(Value, Size, true);
   EmitEOL();
@@ -285,3 +408,24 @@ void SystemZHLASMAsmStreamer::emitEnd() {
   OS << " END";
   EmitEOL();
 }
+
+void SystemZHLASMAsmStreamer::emitExterns() {
+  for (auto &Symbol : getAssembler().symbols()) {
+    if (Symbol.isTemporary())
+      continue;
+    if (Symbol.isRegistered()) {
+      auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
+      Sym.setOwner(static_cast<MCSectionGOFF *>(getCurrentSection().first));
+      Sym.initAttributes();
+      GOFF::ERAttr &ER = Sym.getERAttributes();
+      OS << " "
+         << (ER.BindingStrength == GOFF::ESDBindingStrength::ESD_BST_Weak
+                 ? "WXTRN"
+                 : "EXTRN")
+         << " " << Sym.getName();
+      EmitEOL();
+      emitXATTR(OS, Sym.getName(), ER.Linkage, ER.Executable, ER.BindingScope);
+      EmitEOL();
+    }
+  }
+}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
index 93b1ac4d901aa..81cfdad472244 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
@@ -28,6 +28,7 @@
 #include "llvm/Support/FormattedStream.h"
 
 namespace llvm {
+class MCSymbolGOFF;
 
 class SystemZHLASMAsmStreamer final : public MCStreamer {
   constexpr static size_t InstLimit = 80;
@@ -100,14 +101,13 @@ class SystemZHLASMAsmStreamer final : public MCStreamer {
 
   /// @name MCStreamer Interface
   /// @{
+  void visitUsedSymbol(const MCSymbol &Sym) override;
 
   void changeSection(MCSection *Section, uint32_t Subsection) override;
 
   void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
   void emitLabel(MCSymbol *Symbol, SMLoc Loc) override;
-  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
-    return false;
-  }
+  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
 
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         Align ByteAlignment) override {}
@@ -123,6 +123,7 @@ class SystemZHLASMAsmStreamer final : public MCStreamer {
   /// @}
 
   void emitEnd();
+  void emitExterns();
 };
 } // namespace llvm
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index 1a3e373f25374..d25c77e21d9f8 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -15,6 +15,7 @@
 #include "SystemZTargetStreamer.h"
 #include "SystemZHLASMAsmStreamer.h"
 #include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCGOFFStreamer.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 
 using namespace llvm;
@@ -38,12 +39,12 @@ SystemZHLASMAsmStreamer &SystemZTargetHLASMStreamer::getHLASMStreamer() {
   return static_cast<SystemZHLASMAsmStreamer &>(getStreamer());
 }
 
-void SystemZTargetHLASMStreamer::emitExtern(StringRef Sym) {
-  getStreamer().emitRawText(Twine(" EXTRN ") + Twine(Sym));
-}
-
 void SystemZTargetHLASMStreamer::emitEnd() { getHLASMStreamer().emitEnd(); }
 
+void SystemZTargetHLASMStreamer::emitExterns() {
+  getHLASMStreamer().emitExterns();
+}
+
 // HLASM statements can only perform a single operation at a time
 const MCExpr *SystemZTargetHLASMStreamer::createWordDiffExpr(
     MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) {
@@ -66,3 +67,11 @@ const MCExpr *SystemZTargetGOFFStreamer::createWordDiffExpr(
                               MCSymbolRefExpr::create(Lo, Ctx), Ctx),
       MCConstantExpr::create(1, Ctx), Ctx);
 }
+
+MCGOFFStreamer &SystemZTargetGOFFStreamer::getGOFFStreamer() {
+  return static_cast<MCGOFFStreamer &>(getStreamer());
+}
+
+void SystemZTargetGOFFStreamer::emitExterns() {
+  getGOFFStreamer().emitExterns();
+}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 3fc09bc8c683a..31433cc9739c6 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -20,6 +20,7 @@
 #include <utility>
 
 namespace llvm {
+class MCGOFFStreamer;
 class SystemZHLASMAsmStreamer;
 
 class SystemZTargetStreamer : public MCTargetStreamer {
@@ -57,8 +58,8 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 
   virtual void emitMachine(StringRef CPUOrCommand) {};
 
-  virtual void emitExtern(StringRef Str) {};
   virtual void emitEnd() {};
+  virtual void emitExterns() {};
 
   virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                            const MCSymbol *Lo) {
@@ -69,6 +70,8 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
 public:
   SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
+  MCGOFFStreamer &getGOFFStreamer();
+  void emitExterns() override;
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
 };
@@ -80,8 +83,8 @@ class SystemZTargetHLASMStreamer : public SystemZTargetStreamer {
   SystemZTargetHLASMStreamer(MCStreamer &S, formatted_raw_ostream &OS)
       : SystemZTargetStreamer(S), OS(OS) {}
   SystemZHLASMAsmStreamer &getHLASMStreamer();
-  void emitExtern(StringRef Sym) override;
   void emitEnd() override;
+  void emitExterns() override;
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
 };
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index e31d7c6a86476..87ff2f0353161 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInstBuilder.h"
 #include "llvm/MC/MCSectionELF.h"
@@ -1112,6 +1113,22 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
   if (TT.isOSzOS()) {
     emitADASection();
     emitIDRLSection(M);
+    // Emit EXTRN declarations.
+    OutStreamer->pushSection();
+    for (auto &GO : M.global_objects()) {
+      if (GO.isDeclaration()) {
+        MCSymbol *Sym = TM.getSymbol(&GO);
+        OutStreamer->emitSymbolAttribute(
+            Sym, GO.hasExternalWeakLinkage() ? MCSA_WeakReference : MCSA_Global);
+        OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO) ? MCSA_Code
+                                                                : MCSA_Data);
+      }
+    }
+    OutStreamer->switchSection(
+        static_cast<MCSectionGOFF *>(getObjFileLowering().getTextSection())
+            ->getParent());
+    getTargetStreamer()->emitExterns();
+    OutStreamer->popSection();
   }
   emitAttributes(M);
   // Emit the END instruction in case of HLASM output. This must be the last
@@ -1570,6 +1587,9 @@ void SystemZAsmPrinter::emitPPA2(Module &M) {
   // Make CELQSTRT symbol.
   const char *StartSymbolName = "CELQSTRT";
   MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
+  OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Code);
+  // TODO Mark as OS linkage.
+  OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
 
   // Create symbol and assign to class field for use in PPA1.
   PPA2Sym = OutContext.createTempSymbol("PPA2", false);
@@ -1734,6 +1754,9 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
     }
     OutStreamer->emitInt32(DSAAndFlags);
+
+    // Functions denote CODE.
+    OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_Code);
   }
 
   AsmPrinter::emitFunctionEntryLabel();
diff --git a/llvm/test/CodeGen/SystemZ/zos-no-eh-label.ll b/llvm/test/CodeGen/SystemZ/zos-no-eh-label.ll
index b28f0dd17599a..43ac737b29778 100644
--- a/llvm/test/CodeGen/SystemZ/zos-no-eh-label.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-no-eh-label.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple s390x-ibm-zos < %s | FileCheck %s
+; RUN: llc -mtriple s390x-ibm-zos -emit-gnuas-syntax-on-zos=false < %s | FileCheck %s
 
 define signext i32 @_Z9computeitv() personality ptr @__zos_cxx_personality_v2 {
   ret i32 0
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-1.ll b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
index 6caa8f4d607de..0e6619157261d 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
@@ -104,34 +104,50 @@ entry:
 ; CHECK-NEXT: 000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 000310 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
 
+; ESD record, type ER.
+; The name is CELQSTRT.
+; CHECK-NEXT: 000320 03 00 00 04 [[CELQSTRT:00 00 00 09]] [[ROOTSD]] 00 00 00 00
+; CHECK-NEXT: 000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
+; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+; CHECK-NEXT: 000360 00 04 20 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
+
 ; ESD record, type LD.
 ; The name is me.
-; CHECK-NEXT: 000320 03 00 00 02 [[ME:00 00 00 09]] [[C_CODE64]] 00 00 00 00
-; CHECK-NEXT: 000330 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
-; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
-; CHECK-NEXT: 000360 00 04 20 00 00 00 00 02 94 85 00 00 00 00 00 00
+; CHECK-NEXT: 000370 03 00 00 02 [[ME:00 00 00 0a]] [[C_CODE64]] 00 00 00 00
+; CHECK-NEXT: 000380 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000390 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
+; CHECK-NEXT: 0003a0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
+; CHECK-NEXT: 0003b0 00 04 20 00 00 00 00 02 94 85 00 00 00 00 00 00
+
+; ESD record, type ER.
+; The name is other.
+; CHECK-NEXT: 0003c0 03 00 00 04 [[OTHER:00 00 00 0b]] [[ROOTSD]] 00 00 00 00
+; CHECK-NEXT: 0003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0003e0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
+; CHECK-NEXT: 0003f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+; CHECK-NEXT: 000400 00 04 20 00 00 00 00 05 96 a3 88 85 99 00 00 00
 
 ; Text record for the code section C_CODE64.
 ; The regular expression matches the lower byte of the length.
-; CHECK-NEXT: 000370 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000380 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
+; CHECK-NEXT: 000410 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
 
 ; Text record for the section .&ppa2.
-; CHECK:      000410 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      0004b0 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the ADA section test#S.
-; CHECK:      000460 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000470 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000500 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000510 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the section B_IDRL.
-; CHECK:      0004b0 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000550 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000560 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; End record.
-; CHECK:      000500 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK:      0005a0 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0005b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0005c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0005d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0005e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-2.ll b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
index 0f608c1206b96..bf3fd8234eb33 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-2.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
@@ -147,29 +147,37 @@ source_filename = "test.ll"
 ; CHECK-NEXT: 0004e0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 0004f0 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
 
+; ESD record, type ER.
+; The name is CELQSTRT.
+; CHECK-NEXT: 000500 03 00 00 04 [[CELQSTRT:00 00 00 0f]] [[ROOTSD]] 00 00 00 00
+; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
+; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+; CHECK-NEXT: 000540 00 04 20 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
+
 ; Text record for the code section C_CODE64.
 ; The regular expression matches the lower byte of the length.
-; CHECK-NEXT: 000500 03 10 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000510 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK-NEXT: 000550 03 10 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000560 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the section .&ppa2.
-; CHECK:      000550 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000560 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      0005a0 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0005b0 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the section data.
 ; Length is 4, and the content is 0x2a = 42.
-; CHECK:      0005a0 03 10 00 00 [[DATA_PR]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0005b0 00 00 00 00 00 00 00 04 00 00 00 2a 00 00 00 00
+; CHECK:      0005f0 03 10 00 00 [[DATA_PR]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000600 00 00 00 00 00 00 00 04 00 00 00 2a 00 00 00 00
 
 ; There is no text record for section bss!
 
 ; Text record for the section B_IDRL.
-; CHECK:      0005f0 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000600 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000640 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000650 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; End record.
-; CHECK:      000640 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK:      000690 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0006a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0006b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0006c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0006d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll b/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
new file mode 100644
index 0000000000000..eaae1b7bbcfd2
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
@@ -0,0 +1,37 @@
+; RUN: llc <%s --mtriple s390x-ibm-zos -emit-gnuas-syntax-on-zos=false | FileCheck %s
+
+declare extern_weak void @other1(...)
+declare void @other2(...)
+
+define internal void @me1() {
+entry:
+  ret void
+}
+
+define hidden void @me2() {
+entry:
+  tail call void @other1()
+  ret void
+}
+
+define default void @me3() {
+entry:
+  tail call void @other2()
+  ret void
+}
+
+; CHECK:        ENTRY me1
+; CHECK-NEXT: me1 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(SECTION)
+
+; CHECK:       ENTRY me2
+; CHECK-NEXT: me2 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(LIBRARY)
+
+; CHECK:       ENTRY me3
+; CHECK-NEXT: me3 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
+
+; CHECK:       EXTRN CELQSTRT
+; CHECK-NEXT: CELQSTRT XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
+; CHECK-NEXT:  WXTRN other1
+; CHECK-NEXT: other1 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
+; CHECK-NEXT:  EXTRN other2
+; CHECK-NEXT: other2 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
\ No newline at end of file

>From c19957c59feabbcfb36107f019e915acb6787050 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 3 Nov 2025 17:36:29 -0500
Subject: [PATCH 03/18] Fix some formatting issues.

---
 llvm/include/llvm/MC/MCSymbolGOFF.h           | 4 +---
 llvm/lib/MC/MCSymbolGOFF.cpp                  | 4 ++--
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 5 +++--
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 58305a00ec235..301be80a8b575 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -68,9 +68,7 @@ class MCSymbolGOFF : public MCSymbol {
   }
   MCSectionGOFF *getADA() const { return ADA; }
 
-  void setOwner(MCSectionGOFF *Owner) {
-    this->Owner = Owner;
-  }
+  void setOwner(MCSectionGOFF *Owner) { this->Owner = Owner; }
   MCSectionGOFF *getOwner() const { return Owner; }
 
   bool isExternal() const { return IsExternal; }
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index 5e248dea033a4..33c7d658038bd 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -41,7 +41,7 @@ void MCSymbolGOFF::initAttributes() {
     } else
       llvm_unreachable("Unexpected section type for label");
   } else {
-    setERAttributes(GOFF::ERAttr{CodeData, BindingStrength,
-                                 GOFF::ESD_LT_XPLink, BindingScope});
+    setERAttributes(GOFF::ERAttr{CodeData, BindingStrength, GOFF::ESD_LT_XPLink,
+                                 BindingScope});
   }
 }
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 87ff2f0353161..0a02397ab100b 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1118,8 +1118,9 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
     for (auto &GO : M.global_objects()) {
       if (GO.isDeclaration()) {
         MCSymbol *Sym = TM.getSymbol(&GO);
-        OutStreamer->emitSymbolAttribute(
-            Sym, GO.hasExternalWeakLinkage() ? MCSA_WeakReference : MCSA_Global);
+        OutStreamer->emitSymbolAttribute(Sym, GO.hasExternalWeakLinkage()
+                                                  ? MCSA_WeakReference
+                                                  : MCSA_Global);
         OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO) ? MCSA_Code
                                                                 : MCSA_Data);
       }

>From 2fa73af9d9f9fc87c939e175f90343aa8738d638 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 7 Nov 2025 15:46:26 -0500
Subject: [PATCH 04/18] ER symbols also need to set AMODE

---
 llvm/include/llvm/MC/MCGOFFAttributes.h    | 1 +
 llvm/lib/MC/GOFFObjectWriter.cpp           | 1 +
 llvm/lib/MC/MCSymbolGOFF.cpp               | 2 +-
 llvm/test/CodeGen/SystemZ/zos-section-1.ll | 4 ++--
 llvm/test/CodeGen/SystemZ/zos-section-2.ll | 2 +-
 5 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFAttributes.h b/llvm/include/llvm/MC/MCGOFFAttributes.h
index 1631d59462935..e771f36f35346 100644
--- a/llvm/include/llvm/MC/MCGOFFAttributes.h
+++ b/llvm/include/llvm/MC/MCGOFFAttributes.h
@@ -85,6 +85,7 @@ struct ERAttr {
   GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
   GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
   GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
+  GOFF::ESDAmode Amode;
   GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
 };
 
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 51f95813eabc8..07aecf13bce37 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -275,6 +275,7 @@ class GOFFSymbol {
     BehavAttrs.setExecutable(Attr.Executable);
     BehavAttrs.setBindingStrength(Attr.BindingStrength);
     BehavAttrs.setLinkageType(Attr.Linkage);
+    BehavAttrs.setAmode(Attr.Amode);
     BehavAttrs.setBindingScope(Attr.BindingScope);
   }
 };
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index 33c7d658038bd..2d067155d45aa 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -42,6 +42,6 @@ void MCSymbolGOFF::initAttributes() {
       llvm_unreachable("Unexpected section type for label");
   } else {
     setERAttributes(GOFF::ERAttr{CodeData, BindingStrength, GOFF::ESD_LT_XPLink,
-                                 BindingScope});
+                                 GOFF::ESD_AMODE_64, BindingScope});
   }
 }
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-1.ll b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
index 0e6619157261d..728686127bacd 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
@@ -109,7 +109,7 @@ entry:
 ; CHECK-NEXT: 000320 03 00 00 04 [[CELQSTRT:00 00 00 09]] [[ROOTSD]] 00 00 00 00
 ; CHECK-NEXT: 000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
-; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 000360 00 04 20 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
 
 ; ESD record, type LD.
@@ -125,7 +125,7 @@ entry:
 ; CHECK-NEXT: 0003c0 03 00 00 04 [[OTHER:00 00 00 0b]] [[ROOTSD]] 00 00 00 00
 ; CHECK-NEXT: 0003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK-NEXT: 0003e0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
-; CHECK-NEXT: 0003f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+; CHECK-NEXT: 0003f0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 000400 00 04 20 00 00 00 00 05 96 a3 88 85 99 00 00 00
 
 ; Text record for the code section C_CODE64.
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-2.ll b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
index bf3fd8234eb33..d3a0d75acba88 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-2.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
@@ -152,7 +152,7 @@ source_filename = "test.ll"
 ; CHECK-NEXT: 000500 03 00 00 04 [[CELQSTRT:00 00 00 0f]] [[ROOTSD]] 00 00 00 00
 ; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
-; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 000540 00 04 20 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
 
 ; Text record for the code section C_CODE64.

>From 43dcc134f279af6836a635748c8db084f420a92f Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 7 Nov 2025 17:49:56 -0500
Subject: [PATCH 05/18] Add linkage attribute

---
 llvm/include/llvm/MC/MCDirectives.h           | 4 ++--
 llvm/include/llvm/MC/MCSymbolGOFF.h           | 4 ++++
 llvm/lib/MC/MCELFStreamer.cpp                 | 3 +++
 llvm/lib/MC/MCGOFFStreamer.cpp                | 6 ++++++
 llvm/lib/MC/MCMachOStreamer.cpp               | 2 ++
 llvm/lib/MC/MCSymbolGOFF.cpp                  | 7 +++----
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 2 +-
 llvm/test/CodeGen/SystemZ/zos-section-1.ll    | 2 +-
 llvm/test/CodeGen/SystemZ/zos-section-2.ll    | 2 +-
 9 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index f69144367c8e7..39ecadb9cd029 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -48,10 +48,10 @@ enum MCSymbolAttr {
   MCSA_WeakDefAutoPrivate,      ///< .weak_def_can_be_hidden (MachO)
   MCSA_WeakAntiDep,             ///< .weak_anti_dep (COFF)
   MCSA_Memtag,                  ///< .memtag (ELF)
-
-  // Attributes specific for HLASM.
   MCSA_Code,                    ///< symbol is code (GOFF)
   MCSA_Data,                    ///< symbol is data (GOFF)
+  MCSA_OSLinkage,               ///< symbol uses OS linkage (GOFF)
+  MCSA_XPLinkage,               ///< symbol uses XP linkage (GOFF)
 };
 
 enum MCDataRegionType {
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 301be80a8b575..f1397a6b3822c 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -34,6 +34,7 @@ class MCSymbolGOFF : public MCSymbol {
   GOFF::ERAttr ERAttributes;
 
   GOFF::ESDExecutable CodeData = GOFF::ESDExecutable::ESD_EXE_Unspecified;
+  GOFF::ESDLinkageType Linkage = GOFF::ESDLinkageType::ESD_LT_XPLink;
 
   enum SymbolFlags : uint16_t {
     SF_LD = 0x01,     // LD attributes are set.
@@ -86,6 +87,9 @@ class MCSymbolGOFF : public MCSymbol {
   void setCodeData(GOFF::ESDExecutable Value) { CodeData = Value; }
   GOFF::ESDExecutable getCodeData() const { return CodeData; }
 
+  void setLinkage(GOFF::ESDLinkageType Value) { Linkage = Value; }
+  GOFF::ESDLinkageType getLinkage() const { return Linkage; }
+
   void initAttributes();
 };
 } // end namespace llvm
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 4d4148c506b4f..a296977f7ae98 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -18,6 +18,7 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCELFObjectWriter.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCFixup.h"
@@ -153,6 +154,8 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
   case MCSA_WeakAntiDep:
   case MCSA_Code:
   case MCSA_Data:
+  case MCSA_OSLinkage:
+  case MCSA_XPLinkage:
     return false;
 
   case MCSA_NoDeadStrip:
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 62a9117fe895f..8450f7cfb5381 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -82,6 +82,12 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Data:
     Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
     break;
+  case MCSA_OSLinkage:
+    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_OS);
+    break;
+  case MCSA_XPLinkage:
+    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_XPLink);
+    break;
   case MCSA_Global:
     Symbol->setExternal(true);
     break;
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index da148f81012f7..3b0acd71e2057 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -301,6 +301,8 @@ bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_WeakAntiDep:
   case MCSA_Code:
   case MCSA_Data:
+  case MCSA_OSLinkage:
+  case MCSA_XPLinkage:
     return false;
 
   case MCSA_Global:
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index 2d067155d45aa..345572418ecd8 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -32,16 +32,15 @@ void MCSymbolGOFF::initAttributes() {
   if (isDefined()) {
     MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(getSection());
     if (Section.isED()) {
-      setLDAttributes(GOFF::LDAttr{false, CodeData, BindingStrength,
-                                   GOFF::ESD_LT_XPLink, GOFF::ESD_AMODE_64,
-                                   BindingScope});
+      setLDAttributes(GOFF::LDAttr{false, CodeData, BindingStrength, Linkage,
+                                   GOFF::ESD_AMODE_64, BindingScope});
     } else if (Section.isPR()) {
       // For data symbols, the attributes are already determind in TLOFI.
       // TODO Does it make sense to it to here?
     } else
       llvm_unreachable("Unexpected section type for label");
   } else {
-    setERAttributes(GOFF::ERAttr{CodeData, BindingStrength, GOFF::ESD_LT_XPLink,
+    setERAttributes(GOFF::ERAttr{CodeData, BindingStrength, Linkage,
                                  GOFF::ESD_AMODE_64, BindingScope});
   }
 }
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 0a02397ab100b..193e6ef6d1e64 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1589,7 +1589,7 @@ void SystemZAsmPrinter::emitPPA2(Module &M) {
   const char *StartSymbolName = "CELQSTRT";
   MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
   OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Code);
-  // TODO Mark as OS linkage.
+  OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
   OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
 
   // Create symbol and assign to class field for use in PPA1.
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-1.ll b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
index 728686127bacd..cae371b07d0eb 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
@@ -110,7 +110,7 @@ entry:
 ; CHECK-NEXT: 000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
 ; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
-; CHECK-NEXT: 000360 00 04 20 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
+; CHECK-NEXT: 000360 00 04 00 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
 
 ; ESD record, type LD.
 ; The name is me.
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-2.ll b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
index d3a0d75acba88..f59bace65ca73 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-2.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
@@ -153,7 +153,7 @@ source_filename = "test.ll"
 ; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
 ; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
-; CHECK-NEXT: 000540 00 04 20 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
+; CHECK-NEXT: 000540 00 04 00 00 00 00 00 08 c3 c5 d3 d8 e2 e3 d9 e3
 
 ; Text record for the code section C_CODE64.
 ; The regular expression matches the lower byte of the length.

>From ee1434b325d46403b98cb1c369b69be04db22a08 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 7 Nov 2025 18:02:27 -0500
Subject: [PATCH 06/18] Update the asm output for the linkage type

---
 llvm/lib/MC/MCAsmStreamer.cpp                               | 2 ++
 .../Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp | 6 ++++++
 llvm/test/CodeGen/SystemZ/zos-symbol-1.ll                   | 2 +-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 60e3757f60fed..18db8ef99c2cf 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -776,6 +776,8 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
     // Non-AIX assemblers currently do not support exported visibility.
   case MCSA_Code:
   case MCSA_Data:
+  case MCSA_OSLinkage:
+  case MCSA_XPLinkage:
     // Only for HLASM.
     return false;
   case MCSA_Memtag:
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 8553f8bc14f56..7294d0a12b7ce 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -299,6 +299,12 @@ bool SystemZHLASMAsmStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Data:
     Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
     break;
+  case MCSA_OSLinkage:
+    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_OS);
+    break;
+  case MCSA_XPLinkage:
+    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_XPLink);
+    break;
   case MCSA_Global:
     Symbol->setExternal(true);
     break;
diff --git a/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll b/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
index eaae1b7bbcfd2..bd4361aaafdcb 100644
--- a/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
@@ -30,7 +30,7 @@ entry:
 ; CHECK-NEXT: me3 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
 
 ; CHECK:       EXTRN CELQSTRT
-; CHECK-NEXT: CELQSTRT XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
+; CHECK-NEXT: CELQSTRT XATTR LINKAGE(OS),REFERENCE(CODE),SCOPE(EXPORT)
 ; CHECK-NEXT:  WXTRN other1
 ; CHECK-NEXT: other1 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
 ; CHECK-NEXT:  EXTRN other2

>From 214d716d483c6536c56fb45138bbca035b25c846 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 19 Nov 2025 13:37:36 -0500
Subject: [PATCH 07/18] Replace MCSA_Code/Data

Use MCSA_ELF_TypeFunction/TypeObject instead.
---
 llvm/include/llvm/MC/MCDirectives.h                      | 2 --
 llvm/lib/MC/MCAsmStreamer.cpp                            | 2 --
 llvm/lib/MC/MCELFStreamer.cpp                            | 2 --
 llvm/lib/MC/MCGOFFStreamer.cpp                           | 6 ++----
 llvm/lib/MC/MCMachOStreamer.cpp                          | 2 --
 .../SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp     | 6 ++----
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp            | 9 +++++----
 7 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index 39ecadb9cd029..3b9c4670399c9 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -48,8 +48,6 @@ enum MCSymbolAttr {
   MCSA_WeakDefAutoPrivate,      ///< .weak_def_can_be_hidden (MachO)
   MCSA_WeakAntiDep,             ///< .weak_anti_dep (COFF)
   MCSA_Memtag,                  ///< .memtag (ELF)
-  MCSA_Code,                    ///< symbol is code (GOFF)
-  MCSA_Data,                    ///< symbol is data (GOFF)
   MCSA_OSLinkage,               ///< symbol uses OS linkage (GOFF)
   MCSA_XPLinkage,               ///< symbol uses XP linkage (GOFF)
 };
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 18db8ef99c2cf..7ff570c7df402 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -774,8 +774,6 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
     // Assemblers currently do not support a .cold directive.
   case MCSA_Exported:
     // Non-AIX assemblers currently do not support exported visibility.
-  case MCSA_Code:
-  case MCSA_Data:
   case MCSA_OSLinkage:
   case MCSA_XPLinkage:
     // Only for HLASM.
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index a296977f7ae98..13a7f6d999e61 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -152,8 +152,6 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
   case MCSA_IndirectSymbol:
   case MCSA_Exported:
   case MCSA_WeakAntiDep:
-  case MCSA_Code:
-  case MCSA_Data:
   case MCSA_OSLinkage:
   case MCSA_XPLinkage:
     return false;
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 8450f7cfb5381..81472ba5e4de6 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -51,9 +51,7 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   switch (Attribute) {
   case MCSA_Invalid:
   case MCSA_Cold:
-  case MCSA_ELF_TypeFunction:
   case MCSA_ELF_TypeIndFunction:
-  case MCSA_ELF_TypeObject:
   case MCSA_ELF_TypeTLS:
   case MCSA_ELF_TypeCommon:
   case MCSA_ELF_TypeNoType:
@@ -76,10 +74,10 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Memtag:
     return false;
 
-  case MCSA_Code:
+  case MCSA_ELF_TypeFunction:
     Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
     break;
-  case MCSA_Data:
+  case MCSA_ELF_TypeObject:
     Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
     break;
   case MCSA_OSLinkage:
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 3b0acd71e2057..b8e7772f4e16f 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -299,8 +299,6 @@ bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Exported:
   case MCSA_Memtag:
   case MCSA_WeakAntiDep:
-  case MCSA_Code:
-  case MCSA_Data:
   case MCSA_OSLinkage:
   case MCSA_XPLinkage:
     return false;
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 7294d0a12b7ce..ac0dd84fe9941 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -268,9 +268,7 @@ bool SystemZHLASMAsmStreamer::emitSymbolAttribute(MCSymbol *Sym,
   switch (Attribute) {
   case MCSA_Invalid:
   case MCSA_Cold:
-  case MCSA_ELF_TypeFunction:
   case MCSA_ELF_TypeIndFunction:
-  case MCSA_ELF_TypeObject:
   case MCSA_ELF_TypeTLS:
   case MCSA_ELF_TypeCommon:
   case MCSA_ELF_TypeNoType:
@@ -293,10 +291,10 @@ bool SystemZHLASMAsmStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Memtag:
     return false;
 
-  case MCSA_Code:
+  case MCSA_ELF_TypeFunction:
     Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
     break;
-  case MCSA_Data:
+  case MCSA_ELF_TypeObject:
     Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
     break;
   case MCSA_OSLinkage:
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 193e6ef6d1e64..b895ae9546e5a 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1121,8 +1121,9 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
         OutStreamer->emitSymbolAttribute(Sym, GO.hasExternalWeakLinkage()
                                                   ? MCSA_WeakReference
                                                   : MCSA_Global);
-        OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO) ? MCSA_Code
-                                                                : MCSA_Data);
+        OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO)
+                                                  ? MCSA_ELF_TypeFunction
+                                                  : MCSA_ELF_TypeObject);
       }
     }
     OutStreamer->switchSection(
@@ -1588,7 +1589,7 @@ void SystemZAsmPrinter::emitPPA2(Module &M) {
   // Make CELQSTRT symbol.
   const char *StartSymbolName = "CELQSTRT";
   MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
-  OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Code);
+  OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_ELF_TypeFunction);
   OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
   OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
 
@@ -1757,7 +1758,7 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
     OutStreamer->emitInt32(DSAAndFlags);
 
     // Functions denote CODE.
-    OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_Code);
+    OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
   }
 
   AsmPrinter::emitFunctionEntryLabel();

>From 1f4399374acfb1b4cd5a7995af0ce9d4205c2230 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 19 Nov 2025 16:36:30 -0500
Subject: [PATCH 08/18] Remove owner from MCSymbolGOFF

It's only needed on the binary object path, pushing the section into the GOFFObjectWriter is enough.
---
 llvm/include/llvm/MC/MCGOFFObjectWriter.h     |  6 +++++
 llvm/include/llvm/MC/MCGOFFStreamer.h         |  2 ++
 llvm/include/llvm/MC/MCSymbolGOFF.h           |  8 -------
 llvm/lib/MC/GOFFObjectWriter.cpp              | 12 +++++-----
 llvm/lib/MC/MCGOFFStreamer.cpp                | 22 +++++++++++++------
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  |  1 -
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp |  4 ----
 7 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFObjectWriter.h b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
index ec07637dd2847..90887b296d46f 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -14,6 +14,7 @@
 
 namespace llvm {
 class MCObjectWriter;
+class MCSectionGOFF;
 class raw_pwrite_stream;
 
 class MCGOFFObjectTargetWriter : public MCObjectTargetWriter {
@@ -37,11 +38,16 @@ class GOFFObjectWriter : public MCObjectWriter {
   // The stream used to write the GOFF records.
   raw_pwrite_stream &OS;
 
+  // The RootSD section.
+  MCSectionGOFF *RootSD = nullptr;
+
 public:
   GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
                    raw_pwrite_stream &OS);
   ~GOFFObjectWriter() override;
 
+  void setRootSD(MCSectionGOFF *RootSD) { this->RootSD = RootSD; }
+
   // Implementation of the MCObjectWriter interface.
   void recordRelocation(const MCFragment &F, const MCFixup &Fixup,
                         MCValue Target, uint64_t &FixedValue) override {}
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 3d13ddf216aa3..622fca0c5e70f 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -25,6 +25,8 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   ~MCGOFFStreamer() override;
 
+  void finishImpl() override;
+
   void changeSection(MCSection *Section, uint32_t Subsection = 0) override;
 
   GOFFObjectWriter &getWriter();
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index f1397a6b3822c..61a5db3d83540 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -25,11 +25,6 @@ class MCSymbolGOFF : public MCSymbol {
   // Associated data area of the section. Needs to be emitted first.
   MCSectionGOFF *ADA = nullptr;
 
-  // Owner of the symbol if symbol is an external reference. External references
-  // need a section, too, but adding them to a section would make the symbol
-  // defined.
-  MCSectionGOFF *Owner = nullptr;
-
   GOFF::LDAttr LDAttributes;
   GOFF::ERAttr ERAttributes;
 
@@ -69,9 +64,6 @@ class MCSymbolGOFF : public MCSymbol {
   }
   MCSectionGOFF *getADA() const { return ADA; }
 
-  void setOwner(MCSectionGOFF *Owner) { this->Owner = Owner; }
-  MCSectionGOFF *getOwner() const { return Owner; }
-
   bool isExternal() const { return IsExternal; }
   void setExternal(bool Value) const { IsExternal = Value; }
 
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 07aecf13bce37..860d0a50ccb35 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -283,6 +283,7 @@ class GOFFSymbol {
 class GOFFWriter {
   GOFFOstream OS;
   MCAssembler &Asm;
+  MCSectionGOFF *RootSD;
 
   void writeHeader();
   void writeSymbol(const GOFFSymbol &Symbol);
@@ -295,13 +296,14 @@ class GOFFWriter {
   void defineSymbols();
 
 public:
-  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
+  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, MCSectionGOFF *RootSD);
   uint64_t writeObject();
 };
 } // namespace
 
-GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
-    : OS(OS), Asm(Asm) {}
+GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
+                       MCSectionGOFF *RootSD)
+    : OS(OS), Asm(Asm), RootSD(RootSD) {}
 
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
   if (Section.isSD()) {
@@ -347,7 +349,7 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
 
 void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
   GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(),
-                Symbol.getOwner()->getOrdinal(), Symbol.getERAttributes());
+                RootSD->getOrdinal(), Symbol.getERAttributes());
   writeSymbol(ER);
 }
 
@@ -546,7 +548,7 @@ GOFFObjectWriter::GOFFObjectWriter(
 GOFFObjectWriter::~GOFFObjectWriter() = default;
 
 uint64_t GOFFObjectWriter::writeObject() {
-  uint64_t Size = GOFFWriter(OS, *Asm).writeObject();
+  uint64_t Size = GOFFWriter(OS, *Asm, RootSD).writeObject();
   return Size;
 }
 
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 81472ba5e4de6..e462864b55054 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -18,13 +18,28 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
+#include "llvm/MC/MCObjectStreamer.h"
 #include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/MC/TargetRegistry.h"
 
 using namespace llvm;
 
+MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
+                               std::unique_ptr<MCAsmBackend> MAB,
+                               std::unique_ptr<MCObjectWriter> OW,
+                               std::unique_ptr<MCCodeEmitter> Emitter)
+    : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
+                       std::move(Emitter)) {}
+
 MCGOFFStreamer::~MCGOFFStreamer() = default;
 
+void MCGOFFStreamer::finishImpl() {
+  getWriter().setRootSD(static_cast<MCSectionGOFF *>(
+                            getContext().getObjectFileInfo()->getTextSection())
+                            ->getParent());
+  MCObjectStreamer::finishImpl();
+}
+
 GOFFObjectWriter &MCGOFFStreamer::getWriter() {
   return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
 }
@@ -111,7 +126,6 @@ void MCGOFFStreamer::emitExterns() {
       continue;
     if (Symbol.isRegistered()) {
       auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
-      Sym.setOwner(static_cast<MCSectionGOFF *>(getCurrentSection().first));
       Sym.initAttributes();
     }
   }
@@ -125,9 +139,3 @@ MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
       new MCGOFFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
   return S;
 }
-llvm::MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
-                                     std::unique_ptr<MCAsmBackend> MAB,
-                                     std::unique_ptr<MCObjectWriter> OW,
-                                     std::unique_ptr<MCCodeEmitter> Emitter)
-    : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
-                       std::move(Emitter)) {}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index ac0dd84fe9941..fe2470e374352 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -419,7 +419,6 @@ void SystemZHLASMAsmStreamer::emitExterns() {
       continue;
     if (Symbol.isRegistered()) {
       auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
-      Sym.setOwner(static_cast<MCSectionGOFF *>(getCurrentSection().first));
       Sym.initAttributes();
       GOFF::ERAttr &ER = Sym.getERAttributes();
       OS << " "
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index b895ae9546e5a..cddda67e91674 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1114,7 +1114,6 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
     emitADASection();
     emitIDRLSection(M);
     // Emit EXTRN declarations.
-    OutStreamer->pushSection();
     for (auto &GO : M.global_objects()) {
       if (GO.isDeclaration()) {
         MCSymbol *Sym = TM.getSymbol(&GO);
@@ -1126,9 +1125,6 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
                                                   : MCSA_ELF_TypeObject);
       }
     }
-    OutStreamer->switchSection(
-        static_cast<MCSectionGOFF *>(getObjFileLowering().getTextSection())
-            ->getParent());
     getTargetStreamer()->emitExterns();
     OutStreamer->popSection();
   }

>From 9c35da10f0e210ed7aac4ec6ef3e03bd4bc4c260 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 21 Nov 2025 18:15:07 -0500
Subject: [PATCH 09/18] Remove LDAttr/ERAttr and initAttributes.

---
 llvm/include/llvm/MC/MCSymbolGOFF.h           | 30 +++---------
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  |  7 +--
 llvm/lib/MC/MCGOFFStreamer.cpp                |  9 ----
 llvm/lib/MC/MCSymbolGOFF.cpp                  | 46 ++++++++++---------
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 25 +++++-----
 5 files changed, 48 insertions(+), 69 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 61a5db3d83540..7e9765330e1c3 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -25,38 +25,22 @@ class MCSymbolGOFF : public MCSymbol {
   // Associated data area of the section. Needs to be emitted first.
   MCSectionGOFF *ADA = nullptr;
 
-  GOFF::LDAttr LDAttributes;
-  GOFF::ERAttr ERAttributes;
-
   GOFF::ESDExecutable CodeData = GOFF::ESDExecutable::ESD_EXE_Unspecified;
   GOFF::ESDLinkageType Linkage = GOFF::ESDLinkageType::ESD_LT_XPLink;
 
   enum SymbolFlags : uint16_t {
-    SF_LD = 0x01,     // LD attributes are set.
-    SF_ER = 0x02,     // ER attributes are set.
-    SF_Hidden = 0x04, // Symbol is hidden, aka not exported.
-    SF_Weak = 0x08,   // Symbol is weak.
+    SF_Hidden = 0x01, // Symbol is hidden, aka not exported.
+    SF_Weak = 0x02,   // Symbol is weak.
   };
 
 public:
   MCSymbolGOFF(const MCSymbolTableEntry *Name, bool IsTemporary)
       : MCSymbol(Name, IsTemporary) {}
 
-  void setLDAttributes(GOFF::LDAttr Attr) {
-    modifyFlags(SF_LD, SF_LD);
-    LDAttributes = Attr;
-  }
-  const GOFF::LDAttr &getLDAttributes() const { return LDAttributes; }
-  GOFF::LDAttr &getLDAttributes() { return LDAttributes; }
-  bool hasLDAttributes() const { return getFlags() & SF_LD; }
-
-  void setERAttributes(GOFF::ERAttr Attr) {
-    modifyFlags(SF_ER, SF_ER);
-    ERAttributes = Attr;
-  }
-  const GOFF::ERAttr &getERAttributes() const { return ERAttributes; }
-  GOFF::ERAttr &getERAttributes() { return ERAttributes; }
-  bool hasERAttributes() const { return getFlags() & SF_ER; }
+  GOFF::LDAttr getLDAttributes() const;
+  bool hasLDAttributes() const;
+  GOFF::ERAttr getERAttributes() const;
+  bool hasERAttributes() const;
 
   void setADA(MCSectionGOFF *AssociatedDataArea) {
     ADA = AssociatedDataArea;
@@ -81,8 +65,6 @@ class MCSymbolGOFF : public MCSymbol {
 
   void setLinkage(GOFF::ESDLinkageType Value) { Linkage = Value; }
   GOFF::ESDLinkageType getLinkage() const { return Linkage; }
-
-  void initAttributes();
 };
 } // end namespace llvm
 
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index ae681b9aebdfb..5edbc4caf3fae 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2788,9 +2788,10 @@ void TargetLoweringObjectFileGOFF::getModuleMetadata(Module &M) {
   // 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_BST_Strong, GOFF::ESD_LT_XPLink,
-      GOFF::ESD_AMODE_64, GOFF::ESD_BSC_Section});
+  TextLD->setCodeData(GOFF::ESD_EXE_CODE);
+  TextLD->setLinkage(GOFF::ESD_LT_XPLink);
+  TextLD->setExternal(false);
+  TextLD->setWeak(false);
   TextLD->setADA(ADAPR);
   TextSection->setBeginSymbol(TextLD);
 }
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index e462864b55054..2fc50b0c3f11b 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -57,7 +57,6 @@ void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
 
 void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
   MCObjectStreamer::emitLabel(Symbol, Loc);
-  static_cast<MCSymbolGOFF *>(Symbol)->initAttributes();
 }
 
 bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
@@ -121,14 +120,6 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
 }
 
 void MCGOFFStreamer::emitExterns() {
-  for (auto &Symbol : getAssembler().symbols()) {
-    if (Symbol.isTemporary())
-      continue;
-    if (Symbol.isRegistered()) {
-      auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
-      Sym.initAttributes();
-    }
-  }
 }
 
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index 345572418ecd8..cd55c759614ef 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -12,14 +12,13 @@
 
 using namespace llvm;
 
-void MCSymbolGOFF::initAttributes() {
-  // Temporary labels are not emitted into the object file.
-  if (isTemporary())
-    return;
+bool MCSymbolGOFF::hasLDAttributes() const {
+  return !isTemporary() && isDefined() &&
+         static_cast<MCSectionGOFF &>(getSection()).isED();
+}
 
-  // Do not initialize the attributes multiple times.
-  if (hasLDAttributes() || hasERAttributes())
-    return;
+GOFF::LDAttr MCSymbolGOFF::getLDAttributes() const {
+  assert(hasLDAttributes() && "Symbol does not have LD attributes");
 
   GOFF::ESDBindingScope BindingScope =
       isExternal()
@@ -28,19 +27,24 @@ void MCSymbolGOFF::initAttributes() {
   GOFF::ESDBindingStrength BindingStrength =
       isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
                : GOFF::ESDBindingStrength::ESD_BST_Strong;
+  return GOFF::LDAttr{false,   CodeData,           BindingStrength,
+                      Linkage, GOFF::ESD_AMODE_64, BindingScope};
+}
+
+bool MCSymbolGOFF::hasERAttributes() const {
+  return !isTemporary() && !isDefined() && isExternal();
+}
+
+GOFF::ERAttr MCSymbolGOFF::getERAttributes() const {
+  assert(hasERAttributes() && "Symbol does not have ER attributes");
 
-  if (isDefined()) {
-    MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(getSection());
-    if (Section.isED()) {
-      setLDAttributes(GOFF::LDAttr{false, CodeData, BindingStrength, Linkage,
-                                   GOFF::ESD_AMODE_64, BindingScope});
-    } else if (Section.isPR()) {
-      // For data symbols, the attributes are already determind in TLOFI.
-      // TODO Does it make sense to it to here?
-    } else
-      llvm_unreachable("Unexpected section type for label");
-  } else {
-    setERAttributes(GOFF::ERAttr{CodeData, BindingStrength, Linkage,
-                                 GOFF::ESD_AMODE_64, BindingScope});
-  }
+  GOFF::ESDBindingScope BindingScope =
+      isExternal()
+          ? (isExported() ? GOFF::ESD_BSC_ImportExport : GOFF::ESD_BSC_Library)
+          : GOFF::ESD_BSC_Section;
+  GOFF::ESDBindingStrength BindingStrength =
+      isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
+               : GOFF::ESDBindingStrength::ESD_BST_Strong;
+  return GOFF::ERAttr{CodeData, BindingStrength, Linkage, GOFF::ESD_AMODE_64,
+                      BindingScope};
 }
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index fe2470e374352..b44cea33bd3ba 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -236,13 +236,12 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
   MCSymbolGOFF *Sym = static_cast<MCSymbolGOFF *>(Symbol);
 
   MCStreamer::emitLabel(Sym, Loc);
-  Sym->initAttributes();
 
   // Emit ENTRY statement only if not implied by CSECT.
   bool EmitEntry = !sameNameAsCSECT(Sym);
 
   if (!Sym->isTemporary() && Sym->hasLDAttributes()) {
-    GOFF::LDAttr &LD = Sym->getLDAttributes();
+    GOFF::LDAttr LD = Sym->getLDAttributes();
     if (EmitEntry) {
       OS << " ENTRY " << Sym->getName();
       EmitEOL();
@@ -419,16 +418,18 @@ void SystemZHLASMAsmStreamer::emitExterns() {
       continue;
     if (Symbol.isRegistered()) {
       auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
-      Sym.initAttributes();
-      GOFF::ERAttr &ER = Sym.getERAttributes();
-      OS << " "
-         << (ER.BindingStrength == GOFF::ESDBindingStrength::ESD_BST_Weak
-                 ? "WXTRN"
-                 : "EXTRN")
-         << " " << Sym.getName();
-      EmitEOL();
-      emitXATTR(OS, Sym.getName(), ER.Linkage, ER.Executable, ER.BindingScope);
-      EmitEOL();
+      if (Sym.hasERAttributes()) {
+        GOFF::ERAttr ER = Sym.getERAttributes();
+        OS << " "
+           << (ER.BindingStrength == GOFF::ESDBindingStrength::ESD_BST_Weak
+                   ? "WXTRN"
+                   : "EXTRN")
+           << " " << Sym.getName();
+        EmitEOL();
+        emitXATTR(OS, Sym.getName(), ER.Linkage, ER.Executable,
+                  ER.BindingScope);
+        EmitEOL();
+      }
     }
   }
 }

>From b75d2cb5b92cb59adc6b00b496adc218f40d0fdb Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 26 Nov 2025 13:42:03 -0500
Subject: [PATCH 10/18] Fix formatting

---
 llvm/lib/MC/GOFFObjectWriter.cpp | 4 ++--
 llvm/lib/MC/MCGOFFStreamer.cpp   | 3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 860d0a50ccb35..2e1bc49938dd6 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -348,8 +348,8 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
 }
 
 void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
-  GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(),
-                RootSD->getOrdinal(), Symbol.getERAttributes());
+  GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(), RootSD->getOrdinal(),
+                Symbol.getERAttributes());
   writeSymbol(ER);
 }
 
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 2fc50b0c3f11b..fddf553b28b5a 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -119,8 +119,7 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   return true;
 }
 
-void MCGOFFStreamer::emitExterns() {
-}
+void MCGOFFStreamer::emitExterns() {}
 
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
                                      std::unique_ptr<MCAsmBackend> &&MAB,

>From 28a99e3d2cb5dc255aeea282830e2602b742cdf4 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 28 Nov 2025 10:10:25 -0500
Subject: [PATCH 11/18] Centralize setting of symbol attributes

---
 llvm/include/llvm/MC/MCGOFFStreamer.h         |  4 +
 llvm/lib/MC/MCGOFFStreamer.cpp                | 83 ++++++++++---------
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 58 +------------
 3 files changed, 51 insertions(+), 94 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 622fca0c5e70f..348194eb14697 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -16,6 +16,10 @@ namespace llvm {
 class GOFFObjectWriter;
 class MCSymbolGOFF;
 
+namespace goff {
+bool setSymbolAttribute(MCSymbolGOFF *Symbol, MCSymbolAttr Attribute);
+}
+
 class MCGOFFStreamer : public MCObjectStreamer {
 
 public:
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index fddf553b28b5a..d77d252df8728 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -24,44 +24,9 @@
 
 using namespace llvm;
 
-MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
-                               std::unique_ptr<MCAsmBackend> MAB,
-                               std::unique_ptr<MCObjectWriter> OW,
-                               std::unique_ptr<MCCodeEmitter> Emitter)
-    : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
-                       std::move(Emitter)) {}
-
-MCGOFFStreamer::~MCGOFFStreamer() = default;
-
-void MCGOFFStreamer::finishImpl() {
-  getWriter().setRootSD(static_cast<MCSectionGOFF *>(
-                            getContext().getObjectFileInfo()->getTextSection())
-                            ->getParent());
-  MCObjectStreamer::finishImpl();
-}
-
-GOFFObjectWriter &MCGOFFStreamer::getWriter() {
-  return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
-}
-
-void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
-  // Make sure that all section are registered in the correct order.
-  SmallVector<MCSectionGOFF *> Sections;
-  for (auto *S = static_cast<MCSectionGOFF *>(Section); S; S = S->getParent())
-    Sections.push_back(S);
-  while (!Sections.empty()) {
-    auto *S = Sections.pop_back_val();
-    MCObjectStreamer::changeSection(S, Sections.empty() ? Subsection : 0);
-  }
-}
-
-void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
-  MCObjectStreamer::emitLabel(Symbol, Loc);
-}
-
-bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
-                                         MCSymbolAttr Attribute) {
-  auto *Symbol = static_cast<MCSymbolGOFF *>(Sym);
+namespace llvm {
+namespace goff {
+bool setSymbolAttribute(MCSymbolGOFF *Symbol, MCSymbolAttr Attribute) {
   switch (Attribute) {
   case MCSA_Invalid:
   case MCSA_Cold:
@@ -118,6 +83,48 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
 
   return true;
 }
+} // namespace goff
+} // namespace llvm
+
+MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
+                               std::unique_ptr<MCAsmBackend> MAB,
+                               std::unique_ptr<MCObjectWriter> OW,
+                               std::unique_ptr<MCCodeEmitter> Emitter)
+    : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
+                       std::move(Emitter)) {}
+
+MCGOFFStreamer::~MCGOFFStreamer() = default;
+
+void MCGOFFStreamer::finishImpl() {
+  getWriter().setRootSD(static_cast<MCSectionGOFF *>(
+                            getContext().getObjectFileInfo()->getTextSection())
+                            ->getParent());
+  MCObjectStreamer::finishImpl();
+}
+
+GOFFObjectWriter &MCGOFFStreamer::getWriter() {
+  return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
+}
+
+void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
+  // Make sure that all section are registered in the correct order.
+  SmallVector<MCSectionGOFF *> Sections;
+  for (auto *S = static_cast<MCSectionGOFF *>(Section); S; S = S->getParent())
+    Sections.push_back(S);
+  while (!Sections.empty()) {
+    auto *S = Sections.pop_back_val();
+    MCObjectStreamer::changeSection(S, Sections.empty() ? Subsection : 0);
+  }
+}
+
+void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+  MCObjectStreamer::emitLabel(Symbol, Loc);
+}
+
+bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
+                                         MCSymbolAttr Attribute) {
+  return goff::setSymbolAttribute(static_cast<MCSymbolGOFF *>(Sym), Attribute);
+}
 
 void MCGOFFStreamer::emitExterns() {}
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index b44cea33bd3ba..49a6bf6611798 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -10,6 +10,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCGOFFAttributes.h"
+#include "llvm/MC/MCGOFFStreamer.h"
 #include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Signals.h"
@@ -263,62 +264,7 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
 
 bool SystemZHLASMAsmStreamer::emitSymbolAttribute(MCSymbol *Sym,
                                                   MCSymbolAttr Attribute) {
-  auto *Symbol = static_cast<MCSymbolGOFF *>(Sym);
-  switch (Attribute) {
-  case MCSA_Invalid:
-  case MCSA_Cold:
-  case MCSA_ELF_TypeIndFunction:
-  case MCSA_ELF_TypeTLS:
-  case MCSA_ELF_TypeCommon:
-  case MCSA_ELF_TypeNoType:
-  case MCSA_ELF_TypeGnuUniqueObject:
-  case MCSA_LGlobal:
-  case MCSA_Extern:
-  case MCSA_Exported:
-  case MCSA_IndirectSymbol:
-  case MCSA_Internal:
-  case MCSA_LazyReference:
-  case MCSA_NoDeadStrip:
-  case MCSA_SymbolResolver:
-  case MCSA_AltEntry:
-  case MCSA_PrivateExtern:
-  case MCSA_Protected:
-  case MCSA_Reference:
-  case MCSA_WeakDefinition:
-  case MCSA_WeakDefAutoPrivate:
-  case MCSA_WeakAntiDep:
-  case MCSA_Memtag:
-    return false;
-
-  case MCSA_ELF_TypeFunction:
-    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
-    break;
-  case MCSA_ELF_TypeObject:
-    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
-    break;
-  case MCSA_OSLinkage:
-    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_OS);
-    break;
-  case MCSA_XPLinkage:
-    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_XPLink);
-    break;
-  case MCSA_Global:
-    Symbol->setExternal(true);
-    break;
-  case MCSA_Local:
-    Symbol->setExternal(false);
-    break;
-  case MCSA_Weak:
-  case MCSA_WeakReference:
-    Symbol->setExternal(true);
-    Symbol->setWeak();
-    break;
-  case MCSA_Hidden:
-    Symbol->setHidden(true);
-    break;
-  }
-
-  return true;
+  return goff::setSymbolAttribute(static_cast<MCSymbolGOFF *>(Sym), Attribute);
 }
 
 void SystemZHLASMAsmStreamer::emitRawTextImpl(StringRef String) {

>From 063b271b1a7611a37030e19c46d649b7965e6c36 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 28 Nov 2025 13:38:14 -0500
Subject: [PATCH 12/18] Remove unused emitExterns()

---
 llvm/include/llvm/MC/MCGOFFStreamer.h                         | 2 --
 llvm/lib/MC/MCGOFFStreamer.cpp                                | 2 --
 .../lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp | 4 ----
 llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h  | 1 -
 4 files changed, 9 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 348194eb14697..77a06de51f3f9 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -41,8 +41,6 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         Align ByteAlignment) override {}
-
-  void emitExterns();
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index d77d252df8728..880bbcc069f90 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -126,8 +126,6 @@ bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   return goff::setSymbolAttribute(static_cast<MCSymbolGOFF *>(Sym), Attribute);
 }
 
-void MCGOFFStreamer::emitExterns() {}
-
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
                                      std::unique_ptr<MCAsmBackend> &&MAB,
                                      std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index d25c77e21d9f8..52bae0d6fdfd1 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -71,7 +71,3 @@ const MCExpr *SystemZTargetGOFFStreamer::createWordDiffExpr(
 MCGOFFStreamer &SystemZTargetGOFFStreamer::getGOFFStreamer() {
   return static_cast<MCGOFFStreamer &>(getStreamer());
 }
-
-void SystemZTargetGOFFStreamer::emitExterns() {
-  getGOFFStreamer().emitExterns();
-}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 31433cc9739c6..529aabe57e3e6 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -71,7 +71,6 @@ class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
 public:
   SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
   MCGOFFStreamer &getGOFFStreamer();
-  void emitExterns() override;
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
 };

>From 7fa4651ce58774e52135d92fd296f0fb1af4d823 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 28 Nov 2025 14:26:32 -0500
Subject: [PATCH 13/18] Completely remove attributes from MCSymbolGOFF

---
 llvm/include/llvm/MC/MCSymbolGOFF.h           |  4 +--
 llvm/lib/MC/GOFFObjectWriter.cpp              | 15 ++++++--
 llvm/lib/MC/MCSymbolGOFF.cpp                  | 34 ++++---------------
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 15 +++-----
 4 files changed, 26 insertions(+), 42 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 7e9765330e1c3..de26d2f031987 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -37,9 +37,7 @@ class MCSymbolGOFF : public MCSymbol {
   MCSymbolGOFF(const MCSymbolTableEntry *Name, bool IsTemporary)
       : MCSymbol(Name, IsTemporary) {}
 
-  GOFF::LDAttr getLDAttributes() const;
   bool hasLDAttributes() const;
-  GOFF::ERAttr getERAttributes() const;
   bool hasERAttributes() const;
 
   void setADA(MCSectionGOFF *AssociatedDataArea) {
@@ -65,6 +63,8 @@ class MCSymbolGOFF : public MCSymbol {
 
   void setLinkage(GOFF::ESDLinkageType Value) { Linkage = Value; }
   GOFF::ESDLinkageType getLinkage() const { return Linkage; }
+
+  GOFF::ESDBindingScope getBindingScope() const;
 };
 } // end namespace llvm
 
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 2e1bc49938dd6..02e7666af1d1f 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -340,7 +340,13 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
 void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
   MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(Symbol.getSection());
   GOFFSymbol LD(Symbol.getName(), Symbol.getIndex(), Section.getOrdinal(),
-                Section.getEDAttributes().NameSpace, Symbol.getLDAttributes());
+                Section.getEDAttributes().NameSpace,
+                GOFF::LDAttr{false, Symbol.getCodeData(),
+                             Symbol.isWeak()
+                                 ? GOFF::ESDBindingStrength::ESD_BST_Weak
+                                 : GOFF::ESDBindingStrength::ESD_BST_Strong,
+                             Symbol.getLinkage(), GOFF::ESD_AMODE_64,
+                             Symbol.getBindingScope()});
   if (Symbol.getADA())
     LD.ADAEsdId = Symbol.getADA()->getOrdinal();
   LD.Offset = Asm.getSymbolOffset(Symbol);
@@ -349,7 +355,12 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
 
 void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
   GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(), RootSD->getOrdinal(),
-                Symbol.getERAttributes());
+                GOFF::ERAttr{Symbol.getCodeData(),
+                             Symbol.isWeak()
+                                 ? GOFF::ESDBindingStrength::ESD_BST_Weak
+                                 : GOFF::ESDBindingStrength::ESD_BST_Strong,
+                             Symbol.getLinkage(), GOFF::ESD_AMODE_64,
+                             Symbol.getBindingScope()});
   writeSymbol(ER);
 }
 
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index cd55c759614ef..9b69bb8f8e0a7 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -12,39 +12,17 @@
 
 using namespace llvm;
 
+GOFF::ESDBindingScope MCSymbolGOFF::getBindingScope() const {
+  return isExternal() ? (isExported() ? GOFF::ESD_BSC_ImportExport
+                                      : GOFF::ESD_BSC_Library)
+                      : GOFF::ESD_BSC_Section;
+}
+
 bool MCSymbolGOFF::hasLDAttributes() const {
   return !isTemporary() && isDefined() &&
          static_cast<MCSectionGOFF &>(getSection()).isED();
 }
 
-GOFF::LDAttr MCSymbolGOFF::getLDAttributes() const {
-  assert(hasLDAttributes() && "Symbol does not have LD attributes");
-
-  GOFF::ESDBindingScope BindingScope =
-      isExternal()
-          ? (isExported() ? GOFF::ESD_BSC_ImportExport : GOFF::ESD_BSC_Library)
-          : GOFF::ESD_BSC_Section;
-  GOFF::ESDBindingStrength BindingStrength =
-      isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
-               : GOFF::ESDBindingStrength::ESD_BST_Strong;
-  return GOFF::LDAttr{false,   CodeData,           BindingStrength,
-                      Linkage, GOFF::ESD_AMODE_64, BindingScope};
-}
-
 bool MCSymbolGOFF::hasERAttributes() const {
   return !isTemporary() && !isDefined() && isExternal();
 }
-
-GOFF::ERAttr MCSymbolGOFF::getERAttributes() const {
-  assert(hasERAttributes() && "Symbol does not have ER attributes");
-
-  GOFF::ESDBindingScope BindingScope =
-      isExternal()
-          ? (isExported() ? GOFF::ESD_BSC_ImportExport : GOFF::ESD_BSC_Library)
-          : GOFF::ESD_BSC_Section;
-  GOFF::ESDBindingStrength BindingStrength =
-      isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
-               : GOFF::ESDBindingStrength::ESD_BST_Strong;
-  return GOFF::ERAttr{CodeData, BindingStrength, Linkage, GOFF::ESD_AMODE_64,
-                      BindingScope};
-}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 49a6bf6611798..adb7d56a9f269 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -242,13 +242,13 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
   bool EmitEntry = !sameNameAsCSECT(Sym);
 
   if (!Sym->isTemporary() && Sym->hasLDAttributes()) {
-    GOFF::LDAttr LD = Sym->getLDAttributes();
     if (EmitEntry) {
       OS << " ENTRY " << Sym->getName();
       EmitEOL();
     }
 
-    emitXATTR(OS, Sym->getName(), LD.Linkage, LD.Executable, LD.BindingScope);
+    emitXATTR(OS, Sym->getName(), Sym->getLinkage(), Sym->getCodeData(),
+              Sym->getBindingScope());
     EmitEOL();
   }
 
@@ -365,15 +365,10 @@ void SystemZHLASMAsmStreamer::emitExterns() {
     if (Symbol.isRegistered()) {
       auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
       if (Sym.hasERAttributes()) {
-        GOFF::ERAttr ER = Sym.getERAttributes();
-        OS << " "
-           << (ER.BindingStrength == GOFF::ESDBindingStrength::ESD_BST_Weak
-                   ? "WXTRN"
-                   : "EXTRN")
-           << " " << Sym.getName();
+        OS << " " << (Sym.isWeak() ? "WXTRN" : "EXTRN") << " " << Sym.getName();
         EmitEOL();
-        emitXATTR(OS, Sym.getName(), ER.Linkage, ER.Executable,
-                  ER.BindingScope);
+        emitXATTR(OS, Sym.getName(), Sym.getLinkage(), Sym.getCodeData(),
+                  Sym.getBindingScope());
         EmitEOL();
       }
     }

>From 653783442d341d956f12dcd640db017621e86c4e Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 28 Nov 2025 14:45:18 -0500
Subject: [PATCH 14/18] Remove left-over popSection()

---
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index cddda67e91674..08cfa5acb414f 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1126,7 +1126,6 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
       }
     }
     getTargetStreamer()->emitExterns();
-    OutStreamer->popSection();
   }
   emitAttributes(M);
   // Emit the END instruction in case of HLASM output. This must be the last

>From f07556ac9320b6435b6e8bd3aa300ee4f8113be4 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 28 Nov 2025 15:19:07 -0500
Subject: [PATCH 15/18] Simplify the implementation by moving some code into
 finishImpl()

---
 .../SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 11 +++++------
 .../SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h    |  3 +--
 .../SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp    |  6 ------
 .../SystemZ/MCTargetDesc/SystemZTargetStreamer.h      |  5 -----
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp         |  4 ----
 llvm/test/CodeGen/SystemZ/zos-symbol-1.ll             |  3 ++-
 6 files changed, 8 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index adb7d56a9f269..349f7d777e9d3 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -353,12 +353,7 @@ void SystemZHLASMAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
   EmitEOL();
 }
 
-void SystemZHLASMAsmStreamer::emitEnd() {
-  OS << " END";
-  EmitEOL();
-}
-
-void SystemZHLASMAsmStreamer::emitExterns() {
+void SystemZHLASMAsmStreamer::finishImpl() {
   for (auto &Symbol : getAssembler().symbols()) {
     if (Symbol.isTemporary())
       continue;
@@ -373,4 +368,8 @@ void SystemZHLASMAsmStreamer::emitExterns() {
       }
     }
   }
+
+  // Finish the assembly output.
+  OS << " END";
+  EmitEOL();
 }
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
index 81cfdad472244..1eb358d45e0f4 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
@@ -122,8 +122,7 @@ class SystemZHLASMAsmStreamer final : public MCStreamer {
                           bool Parens = false);
   /// @}
 
-  void emitEnd();
-  void emitExterns();
+  void finishImpl() override;
 };
 } // namespace llvm
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index 52bae0d6fdfd1..2127b7aa24c21 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -39,12 +39,6 @@ SystemZHLASMAsmStreamer &SystemZTargetHLASMStreamer::getHLASMStreamer() {
   return static_cast<SystemZHLASMAsmStreamer &>(getStreamer());
 }
 
-void SystemZTargetHLASMStreamer::emitEnd() { getHLASMStreamer().emitEnd(); }
-
-void SystemZTargetHLASMStreamer::emitExterns() {
-  getHLASMStreamer().emitExterns();
-}
-
 // HLASM statements can only perform a single operation at a time
 const MCExpr *SystemZTargetHLASMStreamer::createWordDiffExpr(
     MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) {
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 529aabe57e3e6..fc2bcee17cf81 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -58,9 +58,6 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 
   virtual void emitMachine(StringRef CPUOrCommand) {};
 
-  virtual void emitEnd() {};
-  virtual void emitExterns() {};
-
   virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                            const MCSymbol *Lo) {
     return nullptr;
@@ -82,8 +79,6 @@ class SystemZTargetHLASMStreamer : public SystemZTargetStreamer {
   SystemZTargetHLASMStreamer(MCStreamer &S, formatted_raw_ostream &OS)
       : SystemZTargetStreamer(S), OS(OS) {}
   SystemZHLASMAsmStreamer &getHLASMStreamer();
-  void emitEnd() override;
-  void emitExterns() override;
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
 };
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 08cfa5acb414f..9469d6841d6aa 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1125,12 +1125,8 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
                                                   : MCSA_ELF_TypeObject);
       }
     }
-    getTargetStreamer()->emitExterns();
   }
   emitAttributes(M);
-  // Emit the END instruction in case of HLASM output. This must be the last
-  // instruction in the source file.
-  getTargetStreamer()->emitEnd();
 }
 
 void SystemZAsmPrinter::emitADASection() {
diff --git a/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll b/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
index bd4361aaafdcb..6768da0da7cfc 100644
--- a/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-symbol-1.ll
@@ -34,4 +34,5 @@ entry:
 ; CHECK-NEXT:  WXTRN other1
 ; CHECK-NEXT: other1 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
 ; CHECK-NEXT:  EXTRN other2
-; CHECK-NEXT: other2 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
\ No newline at end of file
+; CHECK-NEXT: other2 XATTR LINKAGE(XPLINK),REFERENCE(CODE),SCOPE(EXPORT)
+; CHECK-NEXT:  END

>From 126ad826f294ab1fac5c8a7f82debc4eedd4d97b Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 28 Nov 2025 15:43:23 -0500
Subject: [PATCH 16/18] Move loop to AsmPrinter

---
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    | 15 +++++++++++++++
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 12 ------------
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3aa245b7f3f1e..85f49d6953361 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2937,6 +2937,21 @@ bool AsmPrinter::doFinalization(Module &M) {
     }
   }
 
+  // Emit symbol attributes for declarations (GOFF only).
+  if (TM.getTargetTriple().isOSBinFormatGOFF()) {
+    for (auto &GO : M.global_objects()) {
+      if (GO.isDeclaration()) {
+        MCSymbol *Sym = TM.getSymbol(&GO);
+        OutStreamer->emitSymbolAttribute(Sym, GO.hasExternalWeakLinkage()
+                                                  ? MCSA_WeakReference
+                                                  : MCSA_Global);
+        OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO)
+                                                  ? MCSA_ELF_TypeFunction
+                                                  : MCSA_ELF_TypeObject);
+      }
+    }
+  }
+
   // Allow the target to emit any magic that it wants at the end of the file,
   // after everything else has gone out.
   emitEndOfAsmFile(M);
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 9469d6841d6aa..31c57a63e5c87 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1113,18 +1113,6 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
   if (TT.isOSzOS()) {
     emitADASection();
     emitIDRLSection(M);
-    // Emit EXTRN declarations.
-    for (auto &GO : M.global_objects()) {
-      if (GO.isDeclaration()) {
-        MCSymbol *Sym = TM.getSymbol(&GO);
-        OutStreamer->emitSymbolAttribute(Sym, GO.hasExternalWeakLinkage()
-                                                  ? MCSA_WeakReference
-                                                  : MCSA_Global);
-        OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO)
-                                                  ? MCSA_ELF_TypeFunction
-                                                  : MCSA_ELF_TypeObject);
-      }
-    }
   }
   emitAttributes(M);
 }

>From 9fd32acf391de1c7ee26ea21b46043fecb300778 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Wed, 3 Dec 2025 09:14:48 -0500
Subject: [PATCH 17/18] Address most review comments

---
 llvm/include/llvm/MC/MCGOFFStreamer.h         |  6 --
 llvm/include/llvm/MC/MCSymbolGOFF.h           | 14 +++-
 llvm/lib/MC/GOFFObjectWriter.cpp              | 12 +---
 llvm/lib/MC/MCGOFFStreamer.cpp                | 68 +------------------
 llvm/lib/MC/MCSymbolGOFF.cpp                  | 64 +++++++++++++++--
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  |  2 +-
 .../MCTargetDesc/SystemZTargetStreamer.cpp    |  4 --
 .../MCTargetDesc/SystemZTargetStreamer.h      |  1 -
 8 files changed, 76 insertions(+), 95 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 77a06de51f3f9..886efe10d45df 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -16,10 +16,6 @@ namespace llvm {
 class GOFFObjectWriter;
 class MCSymbolGOFF;
 
-namespace goff {
-bool setSymbolAttribute(MCSymbolGOFF *Symbol, MCSymbolAttr Attribute);
-}
-
 class MCGOFFStreamer : public MCObjectStreamer {
 
 public:
@@ -35,8 +31,6 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   GOFFObjectWriter &getWriter();
 
-  void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
-
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
 
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index de26d2f031987..0a39d04ad3c8d 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -14,6 +14,7 @@
 #define LLVM_MC_MCSYMBOLGOFF_H
 
 #include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCSymbol.h"
@@ -64,7 +65,18 @@ class MCSymbolGOFF : public MCSymbol {
   void setLinkage(GOFF::ESDLinkageType Value) { Linkage = Value; }
   GOFF::ESDLinkageType getLinkage() const { return Linkage; }
 
-  GOFF::ESDBindingScope getBindingScope() const;
+  GOFF::ESDBindingScope getBindingScope() const {
+    return isExternal() ? (isExported() ? GOFF::ESD_BSC_ImportExport
+                                        : GOFF::ESD_BSC_Library)
+                        : GOFF::ESD_BSC_Section;
+  }
+
+  GOFF::ESDBindingStrength getBindingStrength() const {
+    return isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
+                    : GOFF::ESDBindingStrength::ESD_BST_Strong;
+  }
+
+  bool setSymbolAttribute(MCSymbolAttr Attribute);
 };
 } // end namespace llvm
 
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 02e7666af1d1f..66e0cf5bc178a 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -342,11 +342,8 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
   GOFFSymbol LD(Symbol.getName(), Symbol.getIndex(), Section.getOrdinal(),
                 Section.getEDAttributes().NameSpace,
                 GOFF::LDAttr{false, Symbol.getCodeData(),
-                             Symbol.isWeak()
-                                 ? GOFF::ESDBindingStrength::ESD_BST_Weak
-                                 : GOFF::ESDBindingStrength::ESD_BST_Strong,
-                             Symbol.getLinkage(), GOFF::ESD_AMODE_64,
-                             Symbol.getBindingScope()});
+                             Symbol.getBindingStrength(), Symbol.getLinkage(),
+                             GOFF::ESD_AMODE_64, Symbol.getBindingScope()});
   if (Symbol.getADA())
     LD.ADAEsdId = Symbol.getADA()->getOrdinal();
   LD.Offset = Asm.getSymbolOffset(Symbol);
@@ -355,10 +352,7 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
 
 void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
   GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(), RootSD->getOrdinal(),
-                GOFF::ERAttr{Symbol.getCodeData(),
-                             Symbol.isWeak()
-                                 ? GOFF::ESDBindingStrength::ESD_BST_Weak
-                                 : GOFF::ESDBindingStrength::ESD_BST_Strong,
+                GOFF::ERAttr{Symbol.getCodeData(), Symbol.getBindingStrength(),
                              Symbol.getLinkage(), GOFF::ESD_AMODE_64,
                              Symbol.getBindingScope()});
   writeSymbol(ER);
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index 880bbcc069f90..51580e0063207 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -24,68 +24,6 @@
 
 using namespace llvm;
 
-namespace llvm {
-namespace goff {
-bool setSymbolAttribute(MCSymbolGOFF *Symbol, MCSymbolAttr Attribute) {
-  switch (Attribute) {
-  case MCSA_Invalid:
-  case MCSA_Cold:
-  case MCSA_ELF_TypeIndFunction:
-  case MCSA_ELF_TypeTLS:
-  case MCSA_ELF_TypeCommon:
-  case MCSA_ELF_TypeNoType:
-  case MCSA_ELF_TypeGnuUniqueObject:
-  case MCSA_LGlobal:
-  case MCSA_Extern:
-  case MCSA_Exported:
-  case MCSA_IndirectSymbol:
-  case MCSA_Internal:
-  case MCSA_LazyReference:
-  case MCSA_NoDeadStrip:
-  case MCSA_SymbolResolver:
-  case MCSA_AltEntry:
-  case MCSA_PrivateExtern:
-  case MCSA_Protected:
-  case MCSA_Reference:
-  case MCSA_WeakDefinition:
-  case MCSA_WeakDefAutoPrivate:
-  case MCSA_WeakAntiDep:
-  case MCSA_Memtag:
-    return false;
-
-  case MCSA_ELF_TypeFunction:
-    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
-    break;
-  case MCSA_ELF_TypeObject:
-    Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
-    break;
-  case MCSA_OSLinkage:
-    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_OS);
-    break;
-  case MCSA_XPLinkage:
-    Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_XPLink);
-    break;
-  case MCSA_Global:
-    Symbol->setExternal(true);
-    break;
-  case MCSA_Local:
-    Symbol->setExternal(false);
-    break;
-  case MCSA_Weak:
-  case MCSA_WeakReference:
-    Symbol->setExternal(true);
-    Symbol->setWeak();
-    break;
-  case MCSA_Hidden:
-    Symbol->setHidden(true);
-    break;
-  }
-
-  return true;
-}
-} // namespace goff
-} // namespace llvm
-
 MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
                                std::unique_ptr<MCAsmBackend> MAB,
                                std::unique_ptr<MCObjectWriter> OW,
@@ -117,13 +55,9 @@ void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
   }
 }
 
-void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
-  MCObjectStreamer::emitLabel(Symbol, Loc);
-}
-
 bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
                                          MCSymbolAttr Attribute) {
-  return goff::setSymbolAttribute(static_cast<MCSymbolGOFF *>(Sym), Attribute);
+  return static_cast<MCSymbolGOFF *>(Sym)->setSymbolAttribute(Attribute);
 }
 
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index 9b69bb8f8e0a7..c2622e1bf3667 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -12,12 +12,6 @@
 
 using namespace llvm;
 
-GOFF::ESDBindingScope MCSymbolGOFF::getBindingScope() const {
-  return isExternal() ? (isExported() ? GOFF::ESD_BSC_ImportExport
-                                      : GOFF::ESD_BSC_Library)
-                      : GOFF::ESD_BSC_Section;
-}
-
 bool MCSymbolGOFF::hasLDAttributes() const {
   return !isTemporary() && isDefined() &&
          static_cast<MCSectionGOFF &>(getSection()).isED();
@@ -26,3 +20,61 @@ bool MCSymbolGOFF::hasLDAttributes() const {
 bool MCSymbolGOFF::hasERAttributes() const {
   return !isTemporary() && !isDefined() && isExternal();
 }
+
+bool MCSymbolGOFF::setSymbolAttribute(MCSymbolAttr Attribute) {
+  switch (Attribute) {
+  case MCSA_Invalid:
+  case MCSA_Cold:
+  case MCSA_ELF_TypeIndFunction:
+  case MCSA_ELF_TypeTLS:
+  case MCSA_ELF_TypeCommon:
+  case MCSA_ELF_TypeNoType:
+  case MCSA_ELF_TypeGnuUniqueObject:
+  case MCSA_LGlobal:
+  case MCSA_Extern:
+  case MCSA_Exported:
+  case MCSA_IndirectSymbol:
+  case MCSA_Internal:
+  case MCSA_LazyReference:
+  case MCSA_NoDeadStrip:
+  case MCSA_SymbolResolver:
+  case MCSA_AltEntry:
+  case MCSA_PrivateExtern:
+  case MCSA_Protected:
+  case MCSA_Reference:
+  case MCSA_WeakDefinition:
+  case MCSA_WeakDefAutoPrivate:
+  case MCSA_WeakAntiDep:
+  case MCSA_Memtag:
+    return false;
+
+  case MCSA_ELF_TypeFunction:
+    setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
+    break;
+  case MCSA_ELF_TypeObject:
+    setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
+    break;
+  case MCSA_OSLinkage:
+    setLinkage(GOFF::ESDLinkageType::ESD_LT_OS);
+    break;
+  case MCSA_XPLinkage:
+    setLinkage(GOFF::ESDLinkageType::ESD_LT_XPLink);
+    break;
+  case MCSA_Global:
+    setExternal(true);
+    break;
+  case MCSA_Local:
+    setExternal(false);
+    break;
+  case MCSA_Weak:
+  case MCSA_WeakReference:
+    setExternal(true);
+    setWeak();
+    break;
+  case MCSA_Hidden:
+    setHidden(true);
+    break;
+  }
+
+  return true;
+}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 349f7d777e9d3..3f7228bbdcbbf 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -264,7 +264,7 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
 
 bool SystemZHLASMAsmStreamer::emitSymbolAttribute(MCSymbol *Sym,
                                                   MCSymbolAttr Attribute) {
-  return goff::setSymbolAttribute(static_cast<MCSymbolGOFF *>(Sym), Attribute);
+  return static_cast<MCSymbolGOFF *>(Sym)->setSymbolAttribute(Attribute);
 }
 
 void SystemZHLASMAsmStreamer::emitRawTextImpl(StringRef String) {
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index 2127b7aa24c21..eeaa7382ad761 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -61,7 +61,3 @@ const MCExpr *SystemZTargetGOFFStreamer::createWordDiffExpr(
                               MCSymbolRefExpr::create(Lo, Ctx), Ctx),
       MCConstantExpr::create(1, Ctx), Ctx);
 }
-
-MCGOFFStreamer &SystemZTargetGOFFStreamer::getGOFFStreamer() {
-  return static_cast<MCGOFFStreamer &>(getStreamer());
-}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index fc2bcee17cf81..4f9a4a0a97ed8 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -67,7 +67,6 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
 public:
   SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
-  MCGOFFStreamer &getGOFFStreamer();
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
 };

>From 8b710565e25b9c8989e48bf2727edc0cb5045e44 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Thu, 4 Dec 2025 14:55:10 -0500
Subject: [PATCH 18/18] Remove hasLDAttributes() and hasERAttributes()

Just inline and simplify the expressions.
---
 llvm/include/llvm/MC/MCSymbolGOFF.h           |  3 ---
 llvm/lib/MC/GOFFObjectWriter.cpp              |  6 ++++--
 llvm/lib/MC/MCSymbolGOFF.cpp                  |  9 --------
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 21 ++++++++++---------
 4 files changed, 15 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 0a39d04ad3c8d..7108f7ebd2b2d 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -38,9 +38,6 @@ class MCSymbolGOFF : public MCSymbol {
   MCSymbolGOFF(const MCSymbolTableEntry *Name, bool IsTemporary)
       : MCSymbol(Name, IsTemporary) {}
 
-  bool hasLDAttributes() const;
-  bool hasERAttributes() const;
-
   void setADA(MCSectionGOFF *AssociatedDataArea) {
     ADA = AssociatedDataArea;
     AssociatedDataArea->RequiresNonZeroLength = true;
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 66e0cf5bc178a..d966021475abb 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -372,10 +372,12 @@ void GOFFWriter::defineSymbols() {
     if (Sym.isTemporary())
       continue;
     auto &Symbol = static_cast<const MCSymbolGOFF &>(Sym);
-    if (Symbol.hasLDAttributes()) {
+    bool IsDefined = Symbol.isDefined();
+    if (IsDefined &&
+         static_cast<MCSectionGOFF &>(Symbol.getSection()).isED()) {
       Symbol.setIndex(++Ordinal);
       defineLabel(Symbol);
-    } else if (Symbol.hasERAttributes()) {
+    } else if (!IsDefined) {
       Symbol.setIndex(++Ordinal);
       defineExtern(Symbol);
     }
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index c2622e1bf3667..2ed15e3fc9c94 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -12,15 +12,6 @@
 
 using namespace llvm;
 
-bool MCSymbolGOFF::hasLDAttributes() const {
-  return !isTemporary() && isDefined() &&
-         static_cast<MCSectionGOFF &>(getSection()).isED();
-}
-
-bool MCSymbolGOFF::hasERAttributes() const {
-  return !isTemporary() && !isDefined() && isExternal();
-}
-
 bool MCSymbolGOFF::setSymbolAttribute(MCSymbolAttr Attribute) {
   switch (Attribute) {
   case MCSA_Invalid:
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 3f7228bbdcbbf..ddc897b0e8393 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -226,9 +226,9 @@ static void emitXATTR(raw_ostream &OS, StringRef Name,
 }
 
 static bool sameNameAsCSECT(MCSymbolGOFF *Sym) {
-  if (Sym->hasLDAttributes() && Sym->isInSection()) {
+  if (!Sym->isTemporary() && Sym->isDefined() && Sym->isInSection()) {
     MCSectionGOFF &ED = static_cast<MCSectionGOFF &>(Sym->getSection());
-    return Sym->getName() == ED.getParent()->getName();
+    return ED.isED() && Sym->getName() == ED.getParent()->getName();
   }
   return false;
 }
@@ -241,7 +241,8 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
   // Emit ENTRY statement only if not implied by CSECT.
   bool EmitEntry = !sameNameAsCSECT(Sym);
 
-  if (!Sym->isTemporary() && Sym->hasLDAttributes()) {
+  if (!Sym->isTemporary() && Sym->isDefined() &&
+      static_cast<MCSectionGOFF &>(Sym->getSection()).isED()) {
     if (EmitEntry) {
       OS << " ENTRY " << Sym->getName();
       EmitEOL();
@@ -358,14 +359,14 @@ void SystemZHLASMAsmStreamer::finishImpl() {
     if (Symbol.isTemporary())
       continue;
     if (Symbol.isRegistered()) {
+      if (Symbol.isDefined())
+        continue;
       auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
-      if (Sym.hasERAttributes()) {
-        OS << " " << (Sym.isWeak() ? "WXTRN" : "EXTRN") << " " << Sym.getName();
-        EmitEOL();
-        emitXATTR(OS, Sym.getName(), Sym.getLinkage(), Sym.getCodeData(),
-                  Sym.getBindingScope());
-        EmitEOL();
-      }
+      OS << " " << (Sym.isWeak() ? "WXTRN" : "EXTRN") << " " << Sym.getName();
+      EmitEOL();
+      emitXATTR(OS, Sym.getName(), Sym.getLinkage(), Sym.getCodeData(),
+                Sym.getBindingScope());
+      EmitEOL();
     }
   }
 



More information about the llvm-commits mailing list