[llvm-branch-commits] [llvm] [GOFF] Write out relocations in the GOFF writer (PR #167054)
Kai Nacke via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Nov 17 08:17:27 PST 2025
https://github.com/redstar updated https://github.com/llvm/llvm-project/pull/167054
>From 1f9bfbbd5e893bcab320dc26c71e49779ef7d04d Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Fri, 7 Nov 2025 11:13:49 -0500
Subject: [PATCH 1/2] [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 | 37 ++-
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, 378 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 ec07637dd2847..408d432a8f54f 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -11,9 +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 {
@@ -21,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) {
@@ -30,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;
@@ -37,6 +69,9 @@ class GOFFObjectWriter : public MCObjectWriter {
// The stream used to write the GOFF records.
raw_pwrite_stream &OS;
+ // Saved relocation data.
+ std::vector<GOFFSavedRelocationEntry> SavedRelocs;
+
public:
GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
@@ -44,7 +79,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 07aecf13bce37..b4640ed7871f0 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,13 +282,42 @@ 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;
+ /// 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);
@@ -295,13 +326,15 @@ class GOFFWriter {
void defineSymbols();
public:
- GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
+ GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
+ const std::vector<GOFFSavedRelocationEntry> &SavedRelocs);
uint64_t writeObject();
};
} // namespace
-GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
- : OS(OS), Asm(Asm) {}
+GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
+ const std::vector<GOFFSavedRelocationEntry> &SavedRelocs)
+ : OS(OS), Asm(Asm), SavedRelocs(SavedRelocs) {}
void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
if (Section.isSD()) {
@@ -502,6 +535,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;
@@ -528,6 +724,8 @@ uint64_t GOFFWriter::writeObject() {
for (const MCSection &Section : Asm)
writeText(static_cast<const MCSectionGOFF *>(&Section));
+ writeRelocations();
+
writeEnd();
// Make sure all records are written.
@@ -545,8 +743,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).writeObject();
+ uint64_t Size = GOFFWriter(OS, *Asm, 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 32fc1b7d949408bcd4717f7a033e9f40dd005820 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 17 Nov 2025 11:16:45 -0500
Subject: [PATCH 2/2] 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 408d432a8f54f..e8a81fc61330a 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 b4640ed7871f0..6b9543fdc1a62 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -751,9 +751,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;
}
More information about the llvm-branch-commits
mailing list