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
