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

>From 0d1109a022dfaeab8022870c248fe35a2398ddae Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Fri, 7 Nov 2025 11:13:49 -0500
Subject: [PATCH 1/7] [GOFF] Write out relocations in the GOFF writer

Add support for writing relocations. Since the symbol numbering is only
available after the symbols are written, the relocations are collected
in a vector. At write time, the relocations are converted using the
symbols ids, compressed and written out. A relocation data record is
limited to 32K-1 bytes, which requires making sure that larger relocation
data is written into multiple records.
---
 llvm/include/llvm/BinaryFormat/GOFF.h         |  26 ++
 llvm/include/llvm/MC/MCGOFFObjectWriter.h     |  36 ++-
 llvm/lib/MC/GOFFObjectWriter.cpp              | 266 +++++++++++++++++-
 .../MCTargetDesc/SystemZGOFFObjectWriter.cpp  |  24 ++
 .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.h   |   1 +
 llvm/test/CodeGen/SystemZ/zos-section-1.ll    |  23 +-
 llvm/test/CodeGen/SystemZ/zos-section-2.ll    |  16 +-
 7 files changed, 377 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h 
b/llvm/include/llvm/BinaryFormat/GOFF.h
index 49d2809cb6524..08bdb5d624fca 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -157,6 +157,32 @@ enum ESDAlignment : uint8_t {
   ESD_ALIGN_4Kpage = 12,
 };
 
+enum RLDReferenceType : uint8_t {
+  RLD_RT_RAddress = 0,
+  RLD_RT_ROffset = 1,
+  RLD_RT_RLength = 2,
+  RLD_RT_RRelativeImmediate = 6,
+  RLD_RT_RTypeConstant = 7,
+  RLD_RT_RLongDisplacement = 9,
+};
+
+enum RLDReferentType : uint8_t {
+  RLD_RO_Label = 0,
+  RLD_RO_Element = 1,
+  RLD_RO_Class = 2,
+  RLD_RO_Part = 3,
+};
+
+enum RLDAction : uint8_t {
+  RLD_ACT_Add = 0,
+  RLD_ACT_Subtract = 1,
+};
+
+enum RLDFetchStore : uint8_t {
+  RLD_FS_Fetch = 0,
+  RLD_FS_Store = 1
+};
+
 enum ENDEntryPointRequest : uint8_t {
   END_EPR_None = 0,
   END_EPR_EsdidOffset = 1,
diff --git a/llvm/include/llvm/MC/MCGOFFObjectWriter.h 
b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
index 90887b296d46f..4e23353536adf 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -11,10 +11,13 @@
 
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCValue.h"
+#include <memory>
+#include <vector>
 
 namespace llvm {
 class MCObjectWriter;
 class MCSectionGOFF;
+class MCSymbolGOFF;
 class raw_pwrite_stream;
 
 class MCGOFFObjectTargetWriter : public MCObjectTargetWriter {
@@ -22,8 +25,19 @@ class MCGOFFObjectTargetWriter : public MCObjectTargetWriter 
{
   MCGOFFObjectTargetWriter() = default;
 
 public:
+  enum RLDRelocationType {
+    Reloc_Type_ACon = 0x1,   // General address.
+    Reloc_Type_RelImm = 0x2, // Relative-immediate address.
+    Reloc_Type_QCon = 0x3,   // Offset of symbol in class.
+    Reloc_Type_VCon = 0x4,   // Address of external symbol.
+    Reloc_Type_RCon = 0x5,   // PSECT of symbol.
+  };
+
   ~MCGOFFObjectTargetWriter() override = default;
 
+  virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
+                                bool IsPCRel) const = 0;
+
   Triple::ObjectFormatType getFormat() const override { return Triple::GOFF; }
 
   static bool classof(const MCObjectTargetWriter *W) {
@@ -31,6 +45,23 @@ class MCGOFFObjectTargetWriter : public MCObjectTargetWriter 
{
   }
 };
 
+struct GOFFSavedRelocationEntry {
+  const MCSectionGOFF *Section;
+  const MCSymbolGOFF *SymA;
+  const MCSymbolGOFF *SymB;
+  unsigned RelocType;
+  uint64_t FixupOffset;
+  uint32_t Length;
+  uint64_t FixedValue; // Info only.
+
+  GOFFSavedRelocationEntry(const MCSectionGOFF *Section,
+                           const MCSymbolGOFF *SymA, const MCSymbolGOFF *SymB,
+                           unsigned RelocType, uint64_t FixupOffset,
+                           uint32_t Length, uint64_t FixedValue)
+      : Section(Section), SymA(SymA), SymB(SymB), RelocType(RelocType),
+        FixupOffset(FixupOffset), Length(Length), FixedValue(FixedValue) {}
+};
+
 class GOFFObjectWriter : public MCObjectWriter {
   // The target specific GOFF writer instance.
   std::unique_ptr<MCGOFFObjectTargetWriter> TargetObjectWriter;
@@ -41,6 +72,9 @@ class GOFFObjectWriter : public MCObjectWriter {
   // The RootSD section.
   MCSectionGOFF *RootSD = nullptr;
 
+  // Saved relocation data.
+  std::vector<GOFFSavedRelocationEntry> SavedRelocs;
+
 public:
   GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
                    raw_pwrite_stream &OS);
@@ -50,7 +84,7 @@ class GOFFObjectWriter : public MCObjectWriter {
 
   // Implementation of the MCObjectWriter interface.
   void recordRelocation(const MCFragment &F, const MCFixup &Fixup,
-                        MCValue Target, uint64_t &FixedValue) override {}
+                        MCValue Target, uint64_t &FixedValue) override;
 
   uint64_t writeObject() override;
 };
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 02e7666af1d1f..c3c34301ed3f4 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -10,7 +10,9 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
@@ -280,14 +282,43 @@ class GOFFSymbol {
   }
 };
 
+// A GOFFRelocationEntry describes a single relocation.
+struct GOFFRelocationEntry {
+  uint32_t REsdId;  // The R pointer.
+  uint32_t PEsdId;  // The P pointer.
+  uint64_t POffset; // The offset within the element described by the P 
pointer.
+
+  uint32_t TargetLength; // The byte length of the target field.
+
+  // Details of the relocation.
+  GOFF::RLDReferenceType ReferenceType : 4;
+  GOFF::RLDReferentType ReferentType : 2;
+  GOFF::RLDAction Action : 1;
+  GOFF::RLDFetchStore FetchStore : 1;
+
+  GOFFRelocationEntry() = default;
+  GOFFRelocationEntry(uint32_t REsdId, uint32_t PEsdId, uint64_t POffset,
+                      GOFF::RLDReferenceType ReferenceType,
+                      GOFF::RLDReferentType ReferentType,
+                      GOFF::RLDAction Action, GOFF::RLDFetchStore FetchStore,
+                      uint32_t TargetLength)
+      : REsdId(REsdId), PEsdId(PEsdId), POffset(POffset),
+        TargetLength(TargetLength), ReferenceType(ReferenceType),
+        ReferentType(ReferentType), Action(Action), FetchStore(FetchStore) {}
+};
+
 class GOFFWriter {
   GOFFOstream OS;
   MCAssembler &Asm;
   MCSectionGOFF *RootSD;
 
+  /// Saved relocation data collected in recordRelocations().
+  const std::vector<GOFFSavedRelocationEntry> &SavedRelocs;
+
   void writeHeader();
   void writeSymbol(const GOFFSymbol &Symbol);
   void writeText(const MCSectionGOFF *MC);
+  void writeRelocations();
   void writeEnd();
 
   void defineSectionSymbols(const MCSectionGOFF &Section);
@@ -296,14 +327,16 @@ class GOFFWriter {
   void defineSymbols();
 
 public:
-  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, MCSectionGOFF *RootSD);
+  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, MCSectionGOFF *RootSD,
+             const std::vector<GOFFSavedRelocationEntry> &SavedRelocs);
   uint64_t writeObject();
 };
 } // namespace
 
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
-                       MCSectionGOFF *RootSD)
-    : OS(OS), Asm(Asm), RootSD(RootSD) {}
+                       MCSectionGOFF *RootSD,
+                       const std::vector<GOFFSavedRelocationEntry> 
&SavedRelocs)
+    : OS(OS), Asm(Asm), RootSD(RootSD), SavedRelocs(SavedRelocs) {}
 
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
   if (Section.isSD()) {
@@ -515,6 +548,169 @@ void GOFFWriter::writeText(const MCSectionGOFF *Section) {
   Asm.writeSectionData(S, Section);
 }
 
+namespace {
+// RelocDataItemBuffer provides a static buffer for relocation data items.
+class RelocDataItemBuffer {
+  char Buffer[GOFF::MaxDataLength];
+  char *Ptr;
+
+public:
+  RelocDataItemBuffer() : Ptr(Buffer) {}
+  const char *data() { return Buffer; }
+  size_t size() { return Ptr - Buffer; }
+  void reset() { Ptr = Buffer; }
+  bool fits(size_t S) { return size() + S < GOFF::MaxDataLength; }
+  template <typename T> void writebe(T Val) {
+    assert(fits(sizeof(T)) && "Out-of-bounds write");
+    support::endian::write<T, llvm::endianness::big>(Ptr, Val);
+    Ptr += sizeof(T);
+  }
+};
+} // namespace
+
+void GOFFWriter::writeRelocations() {
+  // Transform a GOFFSavedRelocationEntry to 1 or 2 GOFFRelocationEntry
+  // instances. An expression like SymA - SymB + Const is implemented by 
storing
+  // Const in the memory (aka the FixedValue), and then having a relocation to
+  // add SymA, and another relocation to subtract SymB.
+  std::vector<GOFFRelocationEntry> Relocations;
+  for (auto &RelocEntry : SavedRelocs) {
+    auto *PSection = RelocEntry.Section;
+    auto RelocType = RelocEntry.RelocType;
+    auto *A = RelocEntry.SymA;
+    auto *B = RelocEntry.SymB;
+    auto FixupOffset = RelocEntry.FixupOffset;
+    auto Length = RelocEntry.Length;
+
+    auto GetRptr = [](const MCSymbolGOFF *Sym) -> uint32_t {
+      if (Sym->isTemporary())
+        return static_cast<MCSectionGOFF &>(Sym->getSection())
+            .getBeginSymbol()
+            ->getIndex();
+      return Sym->getIndex();
+    };
+
+    const uint32_t Pptr = PSection->getOrdinal();
+    uint32_t RptrA = GetRptr(A);
+    uint32_t RptrB = B ? GetRptr(B) : 0;
+
+    // UseQCon causes class offsets versus absolute addresses to be used. This
+    // is analogous to using QCONs in older OBJ object file format.
+    bool UseQCon = RelocType == MCGOFFObjectTargetWriter::Reloc_Type_QCon;
+
+    GOFF::RLDFetchStore FetchStore =
+        (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RCon ||
+         RelocType == MCGOFFObjectTargetWriter::Reloc_Type_VCon)
+            ? GOFF::RLDFetchStore::RLD_FS_Store
+            : GOFF::RLDFetchStore::RLD_FS_Fetch;
+    assert(FetchStore == GOFF::RLDFetchStore::RLD_FS_Fetch ||
+           RptrB == 0 && "No dependent relocations expected");
+
+    enum GOFF::RLDReferenceType ReferenceType = GOFF::RLD_RT_RAddress;
+    enum GOFF::RLDReferentType ReferentType = GOFF::RLD_RO_Label;
+    if (UseQCon) {
+      ReferenceType = GOFF::RLD_RT_ROffset;
+      ReferentType = GOFF::RLD_RO_Class;
+    }
+    if (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RCon)
+      ReferenceType = GOFF::RLD_RT_RTypeConstant;
+
+    if (RptrA) {
+      LLVM_DEBUG(dbgs() << "Reloc A: " << (UseQCon ? "QCon" : "ACon")
+                        << " Rptr: " << RptrA << " Pptr: " << Pptr
+                        << " Offset: " << FixupOffset
+                        << " Fixed Imm: " << RelocEntry.FixedValue << "\n");
+      Relocations.emplace_back(RptrA, Pptr, FixupOffset, ReferenceType,
+                               ReferentType, GOFF::RLD_ACT_Add, FetchStore,
+                               Length);
+    }
+    if (RptrB) {
+      LLVM_DEBUG(dbgs() << "Reloc B: " << (UseQCon ? "QCon" : "ACon")
+                        << " Rptr: " << RptrA << " Pptr: " << Pptr
+                        << " Offset: " << FixupOffset
+                        << " Fixed Imm: " << RelocEntry.FixedValue << "\n");
+      Relocations.emplace_back(RptrB, Pptr, FixupOffset, ReferenceType,
+                               ReferentType, GOFF::RLD_ACT_Subtract,
+                               GOFF::RLDFetchStore::RLD_FS_Fetch, Length);
+    }
+  }
+
+  // Sort relocation data items by the P pointer to save space.
+  std::sort(
+      Relocations.begin(), Relocations.end(),
+      [](const GOFFRelocationEntry &Left, const GOFFRelocationEntry &Right) {
+        return std::tie(Left.PEsdId, Left.REsdId, Left.POffset) <
+               std::tie(Right.PEsdId, Right.REsdId, Right.POffset);
+      });
+
+  // Construct the compressed relocation data items, and write them out.
+  RelocDataItemBuffer Buffer;
+  for (auto I = Relocations.begin(), E = Relocations.end(); I != E;) {
+    Buffer.reset();
+
+    uint32_t PrevResdId = -1;
+    uint32_t PrevPesdId = -1;
+    uint64_t PrevPOffset = -1;
+    for (; I != E; ++I) {
+      const GOFFRelocationEntry &Rel = *I;
+
+      bool SameREsdId = (Rel.REsdId == PrevResdId);
+      bool SamePEsdId = (Rel.PEsdId == PrevPesdId);
+      bool SamePOffset = (Rel.POffset == PrevPOffset);
+      bool EightByteOffset = ((Rel.POffset >> 32) & 0xffffffff);
+
+      // Calculate size of relocation data item, and check if it still fits 
into
+      // the record.
+      size_t ItemSize = 8; // Smallest size of a relocation data item.
+      if (!SameREsdId)
+        ItemSize += 4;
+      if (!SamePEsdId)
+        ItemSize += 4;
+      if (!SamePOffset)
+        ItemSize += (EightByteOffset ? 8 : 4);
+      if (!Buffer.fits(ItemSize))
+        break;
+
+      GOFF::Flags RelocFlags[6];
+      RelocFlags[0].set(0, 1, SameREsdId);
+      RelocFlags[0].set(1, 1, SamePEsdId);
+      RelocFlags[0].set(2, 1, SamePOffset);
+      RelocFlags[0].set(6, 1, EightByteOffset);
+
+      RelocFlags[1].set(0, 4, Rel.ReferenceType);
+      RelocFlags[1].set(4, 4, Rel.ReferentType);
+
+      RelocFlags[2].set(0, 7, Rel.Action);
+      RelocFlags[2].set(7, 1, Rel.FetchStore);
+
+      RelocFlags[4].set(0, 8, Rel.TargetLength);
+
+      for (auto F : RelocFlags)
+        Buffer.writebe<uint8_t>(F);
+      Buffer.writebe<uint16_t>(0); // Reserved.
+      if (!SameREsdId)
+        Buffer.writebe<uint32_t>(Rel.REsdId);
+      if (!SamePEsdId)
+        Buffer.writebe<uint32_t>(Rel.PEsdId);
+      if (!SamePOffset) {
+        if (EightByteOffset)
+          Buffer.writebe<uint64_t>(Rel.POffset);
+        else
+          Buffer.writebe<uint32_t>(Rel.POffset);
+      }
+
+      PrevResdId = Rel.REsdId;
+      PrevPesdId = Rel.PEsdId;
+      PrevPOffset = Rel.POffset;
+    }
+
+    OS.newRecord(GOFF::RT_RLD);
+    OS.writebe<uint8_t>(0);                 // Reserved.
+    OS.writebe<uint16_t>(Buffer.size());    // Length (of the relocation data).
+    OS.write(Buffer.data(), Buffer.size()); // Relocation Directory Data Items.
+  }
+}
+
 void GOFFWriter::writeEnd() {
   uint8_t F = GOFF::END_EPR_None;
   uint8_t AMODE = 0;
@@ -541,6 +737,8 @@ uint64_t GOFFWriter::writeObject() {
   for (const MCSection &Section : Asm)
     writeText(static_cast<const MCSectionGOFF *>(&Section));
 
+  writeRelocations();
+
   writeEnd();
 
   // Make sure all records are written.
@@ -558,8 +756,68 @@ GOFFObjectWriter::GOFFObjectWriter(
 
 GOFFObjectWriter::~GOFFObjectWriter() = default;
 
+void GOFFObjectWriter::recordRelocation(const MCFragment &F,
+                                        const MCFixup &Fixup, MCValue Target,
+                                        uint64_t &FixedValue) {
+  const MCFixupKindInfo &FKI =
+      Asm->getBackend().getFixupKindInfo(Fixup.getKind());
+  const uint32_t Length = FKI.TargetSize / 8;
+  assert(FKI.TargetSize % 8 == 0 && "Target Size not multiple of 8");
+  const uint64_t FixupOffset = Asm->getFragmentOffset(F) + Fixup.getOffset();
+  bool IsPCRel = Fixup.isPCRel();
+
+  unsigned RelocType = TargetObjectWriter->getRelocType(Target, Fixup, 
IsPCRel);
+
+  const MCSectionGOFF *PSection = static_cast<MCSectionGOFF *>(F.getParent());
+  const auto &A = *static_cast<const MCSymbolGOFF *>(Target.getAddSym());
+  const MCSymbolGOFF *B = static_cast<const MCSymbolGOFF 
*>(Target.getSubSym());
+  if (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RelImm) {
+    if (A.isUndefined()) {
+      Asm->reportError(
+          Fixup.getLoc(),
+          Twine("symbol ")
+              .concat(A.getName())
+              .concat(" must be defined for a relative immediate relocation"));
+      return;
+    }
+    if (&A.getSection() != PSection) {
+      Asm->reportError(Fixup.getLoc(),
+                       Twine("relative immediate relocation section mismatch: 
")
+                           .concat(A.getSection().getName())
+                           .concat(" of symbol ")
+                           .concat(A.getName())
+                           .concat(" <-> ")
+                           .concat(PSection->getName()));
+      return;
+    }
+    if (B) {
+      Asm->reportError(
+          Fixup.getLoc(),
+          Twine("subtractive symbol ")
+              .concat(B->getName())
+              .concat(" not supported for a relative immediate relocation"));
+      return;
+    }
+    FixedValue = Asm->getSymbolOffset(A) - FixupOffset + Target.getConstant();
+    return;
+  }
+  FixedValue = Target.getConstant();
+
+  // The symbol only has a section-relative offset if it is a temporary symbol.
+  FixedValue += A.isTemporary() ? Asm->getSymbolOffset(A) : 0;
+  A.setUsedInReloc();
+  if (B) {
+    FixedValue -= B->isTemporary() ? Asm->getSymbolOffset(*B) : 0;
+    B->setUsedInReloc();
+  }
+
+  // Save relocation data for later writing.
+  SavedRelocs.emplace_back(PSection, &A, B, RelocType, FixupOffset, Length,
+                           FixedValue);
+}
+
 uint64_t GOFFObjectWriter::writeObject() {
-  uint64_t Size = GOFFWriter(OS, *Asm, RootSD).writeObject();
+  uint64_t Size = GOFFWriter(OS, *Asm, RootSD, SavedRelocs).writeObject();
   return Size;
 }
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
index 205066814fbd0..8c042d1dbb014 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "MCTargetDesc/SystemZMCTargetDesc.h"
+#include "SystemZMCAsmInfo.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
 #include <memory>
 
@@ -16,12 +17,35 @@ namespace {
 class SystemZGOFFObjectWriter : public MCGOFFObjectTargetWriter {
 public:
   SystemZGOFFObjectWriter();
+
+  unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
+                        bool IsPCRel) const override;
 };
 } // end anonymous namespace
 
 SystemZGOFFObjectWriter::SystemZGOFFObjectWriter()
     : MCGOFFObjectTargetWriter() {}
 
+unsigned SystemZGOFFObjectWriter::getRelocType(const MCValue &Target,
+                                               const MCFixup &Fixup,
+                                               bool IsPCRel) const {
+  switch (Target.getSpecifier()) {
+  case SystemZ::S_PLT:  // TODO This doen't make sense.
+    return Reloc_Type_RelImm;
+  case SystemZ::S_RCon:
+    return Reloc_Type_RCon;
+  case SystemZ::S_VCon:
+    return Reloc_Type_VCon;
+  case SystemZ::S_QCon:
+    return Reloc_Type_QCon;
+  case SystemZ::S_None:
+    if (IsPCRel)
+      return Reloc_Type_RelImm;
+    return Reloc_Type_ACon;
+  }
+  llvm_unreachable("Modifier not supported");
+}
+
 std::unique_ptr<MCObjectTargetWriter> llvm::createSystemZGOFFObjectWriter() {
   return std::make_unique<SystemZGOFFObjectWriter>();
 }
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
index 11c2833b8ada8..668158b896856 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
@@ -51,6 +51,7 @@ enum {
   // https://www.ibm.com/docs/en/hla-and-tf/1.6?topic=value-address-constants
   S_RCon, // Address of ADA of symbol.
   S_VCon, // Address of external function symbol.
+  S_QCon, // Class-based offset.
 };
 } // namespace SystemZ
 
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-1.ll 
b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
index cae371b07d0eb..f4e245addc2c3 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
@@ -145,9 +145,22 @@ entry:
 ; 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 {{..}} {{.*}}
 
+; The relocation data directory.
+; CHECK:      0005a0 03 21 00 00 00 5c 00 00 02 00 04 00 00 00 00 00
+; CHECK-NEXT: 0005b0 00 08 00 00 00 02 00 00 00 5a 60 00 00 00 04 00
+; CHECK-NEXT: 0005c0 00 00 00 00 00 09 00 00 00 00 08 00 00 00 00 00
+; CHECK-NEXT: 0005d0 00 08 00 00 00 04 00 00 00 00 60 00 02 00 08 00
+; CHECK-NEXT: 0005e0 00 00 00 00 00 09 20 70 01 00 08 00 00 00 00 00
+; Continuation of the relocation data directory.
+; CHECK-NEXT: 0005f0 03 22 00 00 0b 00 00 00 06 c0 00 01 00 08 00 00
+; CHECK-NEXT: 000600 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
 ; End record.
-; 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
+; 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
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-2.ll 
b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
index f59bace65ca73..d3eb6d9505340 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-2.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-2.ll
@@ -175,9 +175,15 @@ source_filename = "test.ll"
 ; 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 {{..}} {{.*}}
 
+; The relocation data directory
+; CHECK:      000690 03 20 00 00 00 40 00 00 02 00 04 00 00 00 00 00
+; CHECK-NEXT: 0006a0 00 0e 00 00 00 02 00 00 00 04 60 00 00 00 04 00
+; CHECK-NEXT: 0006b0 00 00 00 00 00 0f 00 00 00 00 08 00 00 00 00 00
+; CHECK-NEXT: 0006c0 00 0e 00 00 00 04 00 00 00 00 60 00 02 00 08 00
+; CHECK-NEXT: 0006d0 00 00 00 00 00 0f 00 00 00 00 00 00 00 00 00 00
+
 ; End record.
-; 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
+; CHECK:      0006e0 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0006f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000710 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

>From 511ce34a5334ca12813465f116f8e2c1562766d3 Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Mon, 17 Nov 2025 11:16:45 -0500
Subject: [PATCH 2/7] Remove `IsPCRel` parameter

Information can be retrieved from `Fixup`.
---
 llvm/include/llvm/MC/MCGOFFObjectWriter.h             |  4 ++--
 llvm/lib/MC/GOFFObjectWriter.cpp                      |  3 +--
 .../SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp  | 11 +++++------
 3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFObjectWriter.h 
b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
index 4e23353536adf..3bffffc5fbdec 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -35,8 +35,8 @@ class MCGOFFObjectTargetWriter : public MCObjectTargetWriter {
 
   ~MCGOFFObjectTargetWriter() override = default;
 
-  virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
-                                bool IsPCRel) const = 0;
+  virtual unsigned getRelocType(const MCValue &Target,
+                                const MCFixup &Fixup) const = 0;
 
   Triple::ObjectFormatType getFormat() const override { return Triple::GOFF; }
 
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index c3c34301ed3f4..3fa0e8350b0a8 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -764,9 +764,8 @@ void GOFFObjectWriter::recordRelocation(const MCFragment &F,
   const uint32_t Length = FKI.TargetSize / 8;
   assert(FKI.TargetSize % 8 == 0 && "Target Size not multiple of 8");
   const uint64_t FixupOffset = Asm->getFragmentOffset(F) + Fixup.getOffset();
-  bool IsPCRel = Fixup.isPCRel();
 
-  unsigned RelocType = TargetObjectWriter->getRelocType(Target, Fixup, 
IsPCRel);
+  unsigned RelocType = TargetObjectWriter->getRelocType(Target, Fixup);
 
   const MCSectionGOFF *PSection = static_cast<MCSectionGOFF *>(F.getParent());
   const auto &A = *static_cast<const MCSymbolGOFF *>(Target.getAddSym());
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
index 8c042d1dbb014..cfbdd5d4780ab 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
@@ -18,8 +18,8 @@ class SystemZGOFFObjectWriter : public 
MCGOFFObjectTargetWriter {
 public:
   SystemZGOFFObjectWriter();
 
-  unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
-                        bool IsPCRel) const override;
+  unsigned getRelocType(const MCValue &Target,
+                        const MCFixup &Fixup) const override;
 };
 } // end anonymous namespace
 
@@ -27,10 +27,9 @@ SystemZGOFFObjectWriter::SystemZGOFFObjectWriter()
     : MCGOFFObjectTargetWriter() {}
 
 unsigned SystemZGOFFObjectWriter::getRelocType(const MCValue &Target,
-                                               const MCFixup &Fixup,
-                                               bool IsPCRel) const {
+                                               const MCFixup &Fixup) const {
   switch (Target.getSpecifier()) {
-  case SystemZ::S_PLT:  // TODO This doen't make sense.
+  case SystemZ::S_PLT: // TODO This doen't make sense.
     return Reloc_Type_RelImm;
   case SystemZ::S_RCon:
     return Reloc_Type_RCon;
@@ -39,7 +38,7 @@ unsigned SystemZGOFFObjectWriter::getRelocType(const MCValue 
&Target,
   case SystemZ::S_QCon:
     return Reloc_Type_QCon;
   case SystemZ::S_None:
-    if (IsPCRel)
+    if (Fixup.isPCRel())
       return Reloc_Type_RelImm;
     return Reloc_Type_ACon;
   }

>From 87dd5fa9975b6049c7498a78241b0216a9049a67 Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Mon, 17 Nov 2025 16:38:02 -0500
Subject: [PATCH 3/7] Use only one vector to store the relocations.

---
 llvm/include/llvm/MC/MCGOFFObjectWriter.h |  43 ++++---
 llvm/lib/MC/GOFFObjectWriter.cpp          | 150 +++++++++-------------
 2 files changed, 88 insertions(+), 105 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFObjectWriter.h 
b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
index 3bffffc5fbdec..1079009e8b13c 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_MC_MCGOFFOBJECTWRITER_H
 #define LLVM_MC_MCGOFFOBJECTWRITER_H
 
+#include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCValue.h"
 #include <memory>
@@ -45,21 +46,31 @@ class MCGOFFObjectTargetWriter : public 
MCObjectTargetWriter {
   }
 };
 
-struct GOFFSavedRelocationEntry {
-  const MCSectionGOFF *Section;
-  const MCSymbolGOFF *SymA;
-  const MCSymbolGOFF *SymB;
-  unsigned RelocType;
-  uint64_t FixupOffset;
-  uint32_t Length;
-  uint64_t FixedValue; // Info only.
-
-  GOFFSavedRelocationEntry(const MCSectionGOFF *Section,
-                           const MCSymbolGOFF *SymA, const MCSymbolGOFF *SymB,
-                           unsigned RelocType, uint64_t FixupOffset,
-                           uint32_t Length, uint64_t FixedValue)
-      : Section(Section), SymA(SymA), SymB(SymB), RelocType(RelocType),
-        FixupOffset(FixupOffset), Length(Length), FixedValue(FixedValue) {}
+// A GOFFRelocationEntry describes a single relocation.
+// For the naming, see
+// 
https://www.ibm.com/docs/en/zos/3.1.0?topic=record-relocation-directory-data-item.
+struct GOFFRelocationEntry {
+  const MCSymbolGOFF *Rptr;  // The R pointer.
+  const MCSectionGOFF *Pptr; // The P pointer.
+  uint32_t REsdId = 0;       // The R pointer id.
+  uint32_t PEsdId = 0;       // The P pointer id.
+  uint64_t POffset; // The offset within the element described by the P 
pointer.
+  uint32_t TargetLength; // The byte length of the target field.
+
+  // Details of the relocation.
+  GOFF::RLDReferenceType ReferenceType : 4;
+  GOFF::RLDReferentType ReferentType : 2;
+  GOFF::RLDAction Action : 1;
+  GOFF::RLDFetchStore FetchStore : 1;
+
+  GOFFRelocationEntry(const MCSectionGOFF *Pptr, const MCSymbolGOFF *Rptr,
+                      GOFF::RLDReferenceType ReferenceType,
+                      GOFF::RLDReferentType ReferentType,
+                      GOFF::RLDAction Action, GOFF::RLDFetchStore FetchStore,
+                      uint64_t POffset, uint32_t TargetLength)
+      : Rptr(Rptr), Pptr(Pptr), POffset(POffset), TargetLength(TargetLength),
+        ReferenceType(ReferenceType), ReferentType(ReferentType),
+        Action(Action), FetchStore(FetchStore) {}
 };
 
 class GOFFObjectWriter : public MCObjectWriter {
@@ -73,7 +84,7 @@ class GOFFObjectWriter : public MCObjectWriter {
   MCSectionGOFF *RootSD = nullptr;
 
   // Saved relocation data.
-  std::vector<GOFFSavedRelocationEntry> SavedRelocs;
+  std::vector<GOFFRelocationEntry> Relocations;
 
 public:
   GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 3fa0e8350b0a8..f13504c486cb2 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -10,7 +10,6 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/SmallVector.h"
 #include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAssembler.h"
@@ -282,38 +281,13 @@ class GOFFSymbol {
   }
 };
 
-// A GOFFRelocationEntry describes a single relocation.
-struct GOFFRelocationEntry {
-  uint32_t REsdId;  // The R pointer.
-  uint32_t PEsdId;  // The P pointer.
-  uint64_t POffset; // The offset within the element described by the P 
pointer.
-
-  uint32_t TargetLength; // The byte length of the target field.
-
-  // Details of the relocation.
-  GOFF::RLDReferenceType ReferenceType : 4;
-  GOFF::RLDReferentType ReferentType : 2;
-  GOFF::RLDAction Action : 1;
-  GOFF::RLDFetchStore FetchStore : 1;
-
-  GOFFRelocationEntry() = default;
-  GOFFRelocationEntry(uint32_t REsdId, uint32_t PEsdId, uint64_t POffset,
-                      GOFF::RLDReferenceType ReferenceType,
-                      GOFF::RLDReferentType ReferentType,
-                      GOFF::RLDAction Action, GOFF::RLDFetchStore FetchStore,
-                      uint32_t TargetLength)
-      : REsdId(REsdId), PEsdId(PEsdId), POffset(POffset),
-        TargetLength(TargetLength), ReferenceType(ReferenceType),
-        ReferentType(ReferentType), Action(Action), FetchStore(FetchStore) {}
-};
-
 class GOFFWriter {
   GOFFOstream OS;
   MCAssembler &Asm;
   MCSectionGOFF *RootSD;
 
   /// Saved relocation data collected in recordRelocations().
-  const std::vector<GOFFSavedRelocationEntry> &SavedRelocs;
+  std::vector<GOFFRelocationEntry> &Relocations;
 
   void writeHeader();
   void writeSymbol(const GOFFSymbol &Symbol);
@@ -328,15 +302,15 @@ class GOFFWriter {
 
 public:
   GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, MCSectionGOFF *RootSD,
-             const std::vector<GOFFSavedRelocationEntry> &SavedRelocs);
+             std::vector<GOFFRelocationEntry> &Relocations);
   uint64_t writeObject();
 };
 } // namespace
 
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
                        MCSectionGOFF *RootSD,
-                       const std::vector<GOFFSavedRelocationEntry> 
&SavedRelocs)
-    : OS(OS), Asm(Asm), RootSD(RootSD), SavedRelocs(SavedRelocs) {}
+                       std::vector<GOFFRelocationEntry> &Relocations)
+    : OS(OS), Asm(Asm), RootSD(RootSD), Relocations(Relocations) {}
 
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
   if (Section.isSD()) {
@@ -569,19 +543,8 @@ class RelocDataItemBuffer {
 } // namespace
 
 void GOFFWriter::writeRelocations() {
-  // Transform a GOFFSavedRelocationEntry to 1 or 2 GOFFRelocationEntry
-  // instances. An expression like SymA - SymB + Const is implemented by 
storing
-  // Const in the memory (aka the FixedValue), and then having a relocation to
-  // add SymA, and another relocation to subtract SymB.
-  std::vector<GOFFRelocationEntry> Relocations;
-  for (auto &RelocEntry : SavedRelocs) {
-    auto *PSection = RelocEntry.Section;
-    auto RelocType = RelocEntry.RelocType;
-    auto *A = RelocEntry.SymA;
-    auto *B = RelocEntry.SymB;
-    auto FixupOffset = RelocEntry.FixupOffset;
-    auto Length = RelocEntry.Length;
-
+  // Set the IDs in the relocation entries.
+  for (auto &RelocEntry : Relocations) {
     auto GetRptr = [](const MCSymbolGOFF *Sym) -> uint32_t {
       if (Sym->isTemporary())
         return static_cast<MCSectionGOFF &>(Sym->getSection())
@@ -590,49 +553,8 @@ void GOFFWriter::writeRelocations() {
       return Sym->getIndex();
     };
 
-    const uint32_t Pptr = PSection->getOrdinal();
-    uint32_t RptrA = GetRptr(A);
-    uint32_t RptrB = B ? GetRptr(B) : 0;
-
-    // UseQCon causes class offsets versus absolute addresses to be used. This
-    // is analogous to using QCONs in older OBJ object file format.
-    bool UseQCon = RelocType == MCGOFFObjectTargetWriter::Reloc_Type_QCon;
-
-    GOFF::RLDFetchStore FetchStore =
-        (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RCon ||
-         RelocType == MCGOFFObjectTargetWriter::Reloc_Type_VCon)
-            ? GOFF::RLDFetchStore::RLD_FS_Store
-            : GOFF::RLDFetchStore::RLD_FS_Fetch;
-    assert(FetchStore == GOFF::RLDFetchStore::RLD_FS_Fetch ||
-           RptrB == 0 && "No dependent relocations expected");
-
-    enum GOFF::RLDReferenceType ReferenceType = GOFF::RLD_RT_RAddress;
-    enum GOFF::RLDReferentType ReferentType = GOFF::RLD_RO_Label;
-    if (UseQCon) {
-      ReferenceType = GOFF::RLD_RT_ROffset;
-      ReferentType = GOFF::RLD_RO_Class;
-    }
-    if (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RCon)
-      ReferenceType = GOFF::RLD_RT_RTypeConstant;
-
-    if (RptrA) {
-      LLVM_DEBUG(dbgs() << "Reloc A: " << (UseQCon ? "QCon" : "ACon")
-                        << " Rptr: " << RptrA << " Pptr: " << Pptr
-                        << " Offset: " << FixupOffset
-                        << " Fixed Imm: " << RelocEntry.FixedValue << "\n");
-      Relocations.emplace_back(RptrA, Pptr, FixupOffset, ReferenceType,
-                               ReferentType, GOFF::RLD_ACT_Add, FetchStore,
-                               Length);
-    }
-    if (RptrB) {
-      LLVM_DEBUG(dbgs() << "Reloc B: " << (UseQCon ? "QCon" : "ACon")
-                        << " Rptr: " << RptrA << " Pptr: " << Pptr
-                        << " Offset: " << FixupOffset
-                        << " Fixed Imm: " << RelocEntry.FixedValue << "\n");
-      Relocations.emplace_back(RptrB, Pptr, FixupOffset, ReferenceType,
-                               ReferentType, GOFF::RLD_ACT_Subtract,
-                               GOFF::RLDFetchStore::RLD_FS_Fetch, Length);
-    }
+    RelocEntry.PEsdId = RelocEntry.Pptr->getOrdinal();
+    RelocEntry.REsdId = GetRptr(RelocEntry.Rptr);
   }
 
   // Sort relocation data items by the P pointer to save space.
@@ -810,13 +732,63 @@ void GOFFObjectWriter::recordRelocation(const MCFragment 
&F,
     B->setUsedInReloc();
   }
 
+  // UseQCon causes class offsets versus absolute addresses to be used. This
+  // is analogous to using QCONs in older OBJ object file format.
+  bool UseQCon = RelocType == MCGOFFObjectTargetWriter::Reloc_Type_QCon;
+
+  GOFF::RLDFetchStore FetchStore =
+      (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RCon ||
+       RelocType == MCGOFFObjectTargetWriter::Reloc_Type_VCon)
+          ? GOFF::RLDFetchStore::RLD_FS_Store
+          : GOFF::RLDFetchStore::RLD_FS_Fetch;
+  assert(FetchStore == GOFF::RLDFetchStore::RLD_FS_Fetch ||
+         B == nullptr && "No dependent relocations expected");
+
+  enum GOFF::RLDReferenceType ReferenceType = GOFF::RLD_RT_RAddress;
+  enum GOFF::RLDReferentType ReferentType = GOFF::RLD_RO_Label;
+  if (UseQCon) {
+    ReferenceType = GOFF::RLD_RT_ROffset;
+    ReferentType = GOFF::RLD_RO_Class;
+  }
+  if (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RCon)
+    ReferenceType = GOFF::RLD_RT_RTypeConstant;
+
+  auto DumpReloc = [&PSection, &ReferenceType, &FixupOffset,
+                    &FixedValue](const char *N, const MCSymbolGOFF *Sym) {
+    const char *Con;
+    switch (ReferenceType) {
+    case GOFF::RLDReferenceType::RLD_RT_RAddress:
+      Con = "ACon";
+      break;
+    case GOFF::RLDReferenceType::RLD_RT_ROffset:
+      Con = "QCon";
+      break;
+    case GOFF::RLDReferenceType::RLD_RT_RTypeConstant:
+      Con = "VCon";
+      break;
+    default:
+      Con = "(unknown)";
+    }
+    dbgs() << "Reloc " << N << ": " << Con << " Rptr: " << Sym->getName()
+           << " Pptr: " << PSection->getName() << " Offset: " << FixupOffset
+           << " Fixed Imm: " << FixedValue << "\n";
+  };
+  (void)DumpReloc;
+
   // Save relocation data for later writing.
-  SavedRelocs.emplace_back(PSection, &A, B, RelocType, FixupOffset, Length,
-                           FixedValue);
+  LLVM_DEBUG(DumpReloc("A", &A));
+  Relocations.emplace_back(PSection, &A, ReferenceType, ReferentType,
+                           GOFF::RLD_ACT_Add, FetchStore, FixupOffset, Length);
+  if (B) {
+    LLVM_DEBUG(DumpReloc("B", B));
+    Relocations.emplace_back(
+        PSection, B, ReferenceType, ReferentType, GOFF::RLD_ACT_Subtract,
+        GOFF::RLDFetchStore::RLD_FS_Fetch, FixupOffset, Length);
+  }
 }
 
 uint64_t GOFFObjectWriter::writeObject() {
-  uint64_t Size = GOFFWriter(OS, *Asm, RootSD, SavedRelocs).writeObject();
+  uint64_t Size = GOFFWriter(OS, *Asm, RootSD, Relocations).writeObject();
   return Size;
 }
 

>From 6e9cf9606020344e8e6fbec1e2f40a15594d66d5 Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Mon, 17 Nov 2025 16:59:45 -0500
Subject: [PATCH 4/7] Fix formatting.

---
 llvm/include/llvm/BinaryFormat/GOFF.h | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h 
b/llvm/include/llvm/BinaryFormat/GOFF.h
index 08bdb5d624fca..f54d8cd19c86b 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -178,10 +178,7 @@ enum RLDAction : uint8_t {
   RLD_ACT_Subtract = 1,
 };
 
-enum RLDFetchStore : uint8_t {
-  RLD_FS_Fetch = 0,
-  RLD_FS_Store = 1
-};
+enum RLDFetchStore : uint8_t { RLD_FS_Fetch = 0, RLD_FS_Store = 1 };
 
 enum ENDEntryPointRequest : uint8_t {
   END_EPR_None = 0,

>From 4e12b6c4900d9eaa116f442d422c72d9e69309f7 Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Wed, 19 Nov 2025 10:25:06 -0500
Subject: [PATCH 5/7] Remove use of S_PLT

---
 llvm/include/llvm/MC/MCGOFFObjectWriter.h              | 10 +++++-----
 llvm/lib/MC/GOFFObjectWriter.cpp                       |  2 +-
 .../SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp   |  4 +---
 .../Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp   |  3 +++
 .../lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h |  6 +++---
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp          |  2 +-
 llvm/test/CodeGen/SystemZ/call-zos-02.ll               |  4 ++--
 llvm/test/CodeGen/SystemZ/zos-ada.ll                   |  2 +-
 8 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFObjectWriter.h 
b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
index 1079009e8b13c..57e152f6a61dc 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -27,11 +27,11 @@ class MCGOFFObjectTargetWriter : public 
MCObjectTargetWriter {
 
 public:
   enum RLDRelocationType {
-    Reloc_Type_ACon = 0x1,   // General address.
-    Reloc_Type_RelImm = 0x2, // Relative-immediate address.
-    Reloc_Type_QCon = 0x3,   // Offset of symbol in class.
-    Reloc_Type_VCon = 0x4,   // Address of external symbol.
-    Reloc_Type_RCon = 0x5,   // PSECT of symbol.
+    Reloc_Type_ACon = 0x1,  // General address.
+    Reloc_Type_RICon = 0x2, // Relative-immediate address.
+    Reloc_Type_QCon = 0x3,  // Offset of symbol in class.
+    Reloc_Type_VCon = 0x4,  // Address of external symbol.
+    Reloc_Type_RCon = 0x5,  // PSECT of symbol.
   };
 
   ~MCGOFFObjectTargetWriter() override = default;
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index f13504c486cb2..68dee92c4ec9b 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -692,7 +692,7 @@ void GOFFObjectWriter::recordRelocation(const MCFragment &F,
   const MCSectionGOFF *PSection = static_cast<MCSectionGOFF *>(F.getParent());
   const auto &A = *static_cast<const MCSymbolGOFF *>(Target.getAddSym());
   const MCSymbolGOFF *B = static_cast<const MCSymbolGOFF 
*>(Target.getSubSym());
-  if (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RelImm) {
+  if (RelocType == MCGOFFObjectTargetWriter::Reloc_Type_RICon) {
     if (A.isUndefined()) {
       Asm->reportError(
           Fixup.getLoc(),
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
index cfbdd5d4780ab..43e06e2cbafeb 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZGOFFObjectWriter.cpp
@@ -29,8 +29,6 @@ SystemZGOFFObjectWriter::SystemZGOFFObjectWriter()
 unsigned SystemZGOFFObjectWriter::getRelocType(const MCValue &Target,
                                                const MCFixup &Fixup) const {
   switch (Target.getSpecifier()) {
-  case SystemZ::S_PLT: // TODO This doen't make sense.
-    return Reloc_Type_RelImm;
   case SystemZ::S_RCon:
     return Reloc_Type_RCon;
   case SystemZ::S_VCon:
@@ -39,7 +37,7 @@ unsigned SystemZGOFFObjectWriter::getRelocType(const MCValue 
&Target,
     return Reloc_Type_QCon;
   case SystemZ::S_None:
     if (Fixup.isPCRel())
-      return Reloc_Type_RelImm;
+      return Reloc_Type_RICon;
     return Reloc_Type_ACon;
   }
   llvm_unreachable("Modifier not supported");
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
index 2933b4becba05..887531f3e2299 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
@@ -65,6 +65,9 @@ void SystemZMCAsmInfoGOFF::printSpecifierExpr(
   case SystemZ::S_None:
     OS << "A";
     break;
+  case SystemZ::S_QCon:
+    OS << "Q";
+    break;
   case SystemZ::S_RCon:
     OS << "R";
     break;
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
index 668158b896856..36bbf2f19a674 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
@@ -49,9 +49,9 @@ enum {
 
   // HLASM docs for address constants:
   // https://www.ibm.com/docs/en/hla-and-tf/1.6?topic=value-address-constants
-  S_RCon, // Address of ADA of symbol.
-  S_VCon, // Address of external function symbol.
-  S_QCon, // Class-based offset.
+  S_RCon,  // Address of ADA of symbol.
+  S_VCon,  // Address of external function symbol.
+  S_QCon,  // Class-based offset.
 };
 } // namespace SystemZ
 
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp 
b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 31c57a63e5c87..414d68e2678ed 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -325,7 +325,7 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr 
*MI) {
     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
                                      .addReg(SystemZ::R7D)
                                      .addExpr(Lower.getExpr(MI->getOperand(0),
-                                                            SystemZ::S_PLT)));
+                                                            SystemZ::S_None)));
     emitCallInformation(CallType::BRASL7);
     return;
 
diff --git a/llvm/test/CodeGen/SystemZ/call-zos-02.ll 
b/llvm/test/CodeGen/SystemZ/call-zos-02.ll
index 444972fa8765e..a7f600ae99db0 100644
--- a/llvm/test/CodeGen/SystemZ/call-zos-02.ll
+++ b/llvm/test/CodeGen/SystemZ/call-zos-02.ll
@@ -9,8 +9,8 @@ entry:
 define hidden signext i32 @caller2() {
 entry:
 ; CHECK-LABEL:   caller2:
-; CHECK:         brasl 7,caller@PLT   * encoding: [0xc0,0x75,A,A,A,A]
-; CHECK-NEXT:    * fixup A - offset: 2, value: caller@PLT+2, kind: 
FK_390_PC32DBL
+; CHECK:         brasl 7,caller       * encoding: [0xc0,0x75,A,A,A,A]
+; CHECK-NEXT:    * fixup A - offset: 2, value: caller+2, kind: FK_390_PC32DBL
 ; CHECK-NEXT:    bcr     0,3          * encoding: [0x07,0x03]
   %call = call signext i32 @caller()
   ret i32 %call
diff --git a/llvm/test/CodeGen/SystemZ/zos-ada.ll 
b/llvm/test/CodeGen/SystemZ/zos-ada.ll
index bb2bd1c7672ea..8f00f32c1b805 100644
--- a/llvm/test/CodeGen/SystemZ/zos-ada.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-ada.ll
@@ -6,7 +6,7 @@
 ; CHECK:         stmg 6,8,1872(4)
 ; CHECK-NEXT:    aghi 4,-192
 ; CHECK-NEXT:    lgr 8,5
-; CHECK-NEXT:    brasl 7,callee_internal@PLT
+; CHECK-NEXT:    brasl 7,callee_internal
 ; CHECK-NEXT:    bcr 0,3
 ; CHECK-NEXT:    lg 6,8(8)
 ; CHECK-NEXT:    lg 5,0(8)

>From a112e7b8a4810bf902084e61debf656ad4206a7c Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Fri, 28 Nov 2025 17:54:12 -0500
Subject: [PATCH 6/7] Also test relocations

---
 .../SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp      | 3 +++
 llvm/test/CodeGen/SystemZ/zos-hlasm-out.ll                | 8 ++++++++
 2 files changed, 11 insertions(+)

diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 349f7d777e9d3..6e39bd84919f1 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -9,6 +9,7 @@
 #include "SystemZHLASMAsmStreamer.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCGOFFAttributes.h"
 #include "llvm/MC/MCGOFFStreamer.h"
 #include "llvm/MC/MCSymbolGOFF.h"
@@ -80,6 +81,7 @@ void SystemZHLASMAsmStreamer::changeSection(MCSection 
*Section,
   MAI->printSwitchToSection(*Section, Subsection,
                             getContext().getTargetTriple(), OS);
   MCStreamer::changeSection(Section, Subsection);
+  EmitEOL();
 }
 
 void SystemZHLASMAsmStreamer::emitAlignmentDS(uint64_t ByteAlignment,
@@ -332,6 +334,7 @@ void SystemZHLASMAsmStreamer::emitHLASMValueImpl(const 
MCExpr *Value,
     MAI->printExpr(OS, *Value);
     return;
   default:
+    Parens &= isa<MCSymbolRefExpr>(Value);
     if (Parens)
       OS << "A(";
     MAI->printExpr(OS, *Value);
diff --git a/llvm/test/CodeGen/SystemZ/zos-hlasm-out.ll 
b/llvm/test/CodeGen/SystemZ/zos-hlasm-out.ll
index a29646b8bcc61..cbfac001c9e2e 100644
--- a/llvm/test/CodeGen/SystemZ/zos-hlasm-out.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-hlasm-out.ll
@@ -42,6 +42,14 @@ define void @foo() {
 ; CHECK: DS 0B
 ; CHECK-LABEL: L#.str.1 DS 0H
 ; CHECK: DC XL6'576F726C6400'
+; CHECK: C_WSA64 CATTR 
ALIGN(4),FILL(0),DEFLOAD,NOTEXECUTABLE,RMODE(64),PART(stdi
+; CHECK:                in#S)
+; CHECK: stdin#S XATTR LINKAGE(XPLINK),REFERENCE(DATA),SCOPE(SECTION)
+; CHECK: * Offset 0 pointer to data symbol Greeting
+; CHECK:  DC A(Greeting)
+; CHECK: * Offset 8 function descriptor of outs
+; CHECK:  DC R(outs)
+; CHECK:  DC V(outs)
 ; CHECK: END
 entry:
   %0 = load ptr, ptr @Greeting, align 8

>From b634514b5d1028ee829ab027a62978c79421aecb Mon Sep 17 00:00:00 2001
From: Kai Nacke <[email protected]>
Date: Fri, 28 Nov 2025 17:57:56 -0500
Subject: [PATCH 7/7] Fix formatting.

---
 llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h 
b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
index 36bbf2f19a674..668158b896856 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h
@@ -49,9 +49,9 @@ enum {
 
   // HLASM docs for address constants:
   // https://www.ibm.com/docs/en/hla-and-tf/1.6?topic=value-address-constants
-  S_RCon,  // Address of ADA of symbol.
-  S_VCon,  // Address of external function symbol.
-  S_QCon,  // Class-based offset.
+  S_RCon, // Address of ADA of symbol.
+  S_VCon, // Address of external function symbol.
+  S_QCon, // Class-based offset.
 };
 } // namespace SystemZ
 

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to