From ad410c6a9c15b5a30fdd43caf87d1befd5cb370e Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Thu, 19 Feb 2026 09:32:32 -0500 Subject: [PATCH 1/2] [SystemZ] Add indirect reference bit XATTR REFERENCE(INDIRECT) for indirect symbol handling support This is the first of three patches aimed to support indirect symbol handling for the SystemZ backend. This PR introduces a `GOFF:ERAttr` to represent indirect references, handles indirect symbols within `setSymbolAttribute()` by setting the indirect reference bit, and also updates the HLASM streamer to emit `XATTR REFERENCE(INDIRECT)` and various other combinations. --- llvm/include/llvm/MC/MCGOFFAttributes.h | 1 + llvm/include/llvm/MC/MCSymbolGOFF.h | 10 ++++-- llvm/lib/MC/GOFFObjectWriter.cpp | 7 ++-- llvm/lib/MC/MCSymbolGOFF.cpp | 4 ++- .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp | 33 ++++++++++++++----- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/MC/MCGOFFAttributes.h b/llvm/include/llvm/MC/MCGOFFAttributes.h index b1c6d73e41f9f..9787ef4c916a9 100644 --- a/llvm/include/llvm/MC/MCGOFFAttributes.h +++ b/llvm/include/llvm/MC/MCGOFFAttributes.h @@ -82,6 +82,7 @@ struct PRAttr { // Attributes for ER symbols. struct ERAttr { + bool IsIndirectReference = false; GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified; GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong; GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink; diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h index 310cc4db9a7e2..449307217d531 100644 --- a/llvm/include/llvm/MC/MCSymbolGOFF.h +++ b/llvm/include/llvm/MC/MCSymbolGOFF.h @@ -30,8 +30,9 @@ class MCSymbolGOFF : public MCSymbol { GOFF::ESDLinkageType Linkage = GOFF::ESDLinkageType::ESD_LT_XPLink; enum SymbolFlags : uint16_t { - SF_Hidden = 0x01, // Symbol is hidden, aka not exported. - SF_Weak = 0x02, // Symbol is weak. + SF_Hidden = 0x01, // Symbol is hidden, aka not exported. + SF_Weak = 0x02, // Symbol is weak. + SF_Indirect = 0x4, // Symbol referenced indirectly. }; public: @@ -53,6 +54,11 @@ class MCSymbolGOFF : public MCSymbol { bool isHidden() const { return getFlags() & SF_Hidden; } bool isExported() const { return !isHidden(); } + void setIndirect(bool Value = true) { + modifyFlags(Value ? SF_Indirect : 0, SF_Indirect); + } + bool isIndirect() const { return getFlags() & SF_Indirect; } + void setWeak(bool Value = true) { modifyFlags(Value ? SF_Weak : 0, SF_Weak); } bool isWeak() const { return getFlags() & SF_Weak; } diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp index cbe9c7eb2fac1..a619328c09fa3 100644 --- a/llvm/lib/MC/GOFFObjectWriter.cpp +++ b/llvm/lib/MC/GOFFObjectWriter.cpp @@ -278,6 +278,7 @@ class GOFFSymbol { BehavAttrs.setLinkageType(Attr.Linkage); BehavAttrs.setAmode(Attr.Amode); BehavAttrs.setBindingScope(Attr.BindingScope); + BehavAttrs.setIndirectReference(Attr.IsIndirectReference); } }; @@ -359,9 +360,9 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) { void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) { GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(), RootSD->getOrdinal(), - GOFF::ERAttr{Symbol.getCodeData(), Symbol.getBindingStrength(), - Symbol.getLinkage(), GOFF::ESD_AMODE_64, - Symbol.getBindingScope()}); + GOFF::ERAttr{Symbol.isIndirect(), Symbol.getCodeData(), + Symbol.getBindingStrength(), Symbol.getLinkage(), + GOFF::ESD_AMODE_64, Symbol.getBindingScope()}); writeSymbol(ER); } diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp index 00479d22232ff..b6a25c3a24d94 100644 --- a/llvm/lib/MC/MCSymbolGOFF.cpp +++ b/llvm/lib/MC/MCSymbolGOFF.cpp @@ -24,7 +24,6 @@ bool MCSymbolGOFF::setSymbolAttribute(MCSymbolAttr Attribute) { case MCSA_LGlobal: case MCSA_Extern: case MCSA_Exported: - case MCSA_IndirectSymbol: case MCSA_Internal: case MCSA_LazyReference: case MCSA_Local: @@ -40,6 +39,9 @@ bool MCSymbolGOFF::setSymbolAttribute(MCSymbolAttr Attribute) { case MCSA_Memtag: return false; + case MCSA_IndirectSymbol: + setIndirect(true); + break; case MCSA_ELF_TypeFunction: setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE); break; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp index 8a559e1ab261b..bb49ab85ad126 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp @@ -193,7 +193,7 @@ void SystemZHLASMAsmStreamer::emitInstruction(const MCInst &Inst, EmitEOL(); } -static void emitXATTR(raw_ostream &OS, StringRef Name, +static void emitXATTR(raw_ostream &OS, StringRef Name, bool IsIndirectReference, GOFF::ESDLinkageType Linkage, GOFF::ESDExecutable Executable, GOFF::ESDBindingScope BindingScope) { @@ -201,9 +201,25 @@ static void emitXATTR(raw_ostream &OS, StringRef Name, OS << Name << " XATTR "; OS << Sep << "LINKAGE(" << (Linkage == GOFF::ESD_LT_OS ? "OS" : "XPLINK") << ")"; - if (Executable != GOFF::ESD_EXE_Unspecified) - OS << Sep << "REFERENCE(" - << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA") << ")"; + + const bool NotUnspecified = (Executable != GOFF::ESD_EXE_Unspecified); + if (NotUnspecified || IsIndirectReference) { + OS << Sep << "REFERENCE("; + bool RequiresComma = false; + + if (NotUnspecified) { + OS << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA"); + RequiresComma = true; + } + + if (IsIndirectReference) { + if (RequiresComma) + OS << ","; + OS << "INDIRECT"; + } + + OS << ")"; + } if (BindingScope != GOFF::ESD_BSC_Unspecified) { OS << Sep << "SCOPE("; switch (BindingScope) { @@ -224,7 +240,6 @@ static void emitXATTR(raw_ostream &OS, StringRef Name, } OS << ')'; } - OS << '\n'; } void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { @@ -245,8 +260,8 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { EmitEOL(); } - emitXATTR(OS, Sym->getName(), Sym->getLinkage(), Sym->getCodeData(), - Sym->getBindingScope()); + emitXATTR(OS, Sym->getName(), Sym->isIndirect(), Sym->getLinkage(), + Sym->getCodeData(), Sym->getBindingScope()); EmitEOL(); } @@ -355,8 +370,8 @@ void SystemZHLASMAsmStreamer::finishImpl() { auto &Sym = static_cast(const_cast(Symbol)); OS << " " << (Sym.isWeak() ? "WXTRN" : "EXTRN") << " " << Sym.getName(); EmitEOL(); - emitXATTR(OS, Sym.getName(), Sym.getLinkage(), Sym.getCodeData(), - Sym.getBindingScope()); + emitXATTR(OS, Sym.getName(), Sym.isIndirect(), Sym.getLinkage(), + Sym.getCodeData(), Sym.getBindingScope()); EmitEOL(); } From ab94de9b869bf4adc612c0f0ef40386c33fae5ba Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Thu, 26 Feb 2026 13:40:59 -0500 Subject: [PATCH 2/2] Use ListSeparator to encapsulate boolean logic for ',' character in HLASM streamer. --- .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp index bb49ab85ad126..d425b6520a200 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp @@ -205,18 +205,13 @@ static void emitXATTR(raw_ostream &OS, StringRef Name, bool IsIndirectReference, const bool NotUnspecified = (Executable != GOFF::ESD_EXE_Unspecified); if (NotUnspecified || IsIndirectReference) { OS << Sep << "REFERENCE("; - bool RequiresComma = false; + llvm::ListSeparator SepRef(","); - if (NotUnspecified) { - OS << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA"); - RequiresComma = true; - } + if (NotUnspecified) + OS << SepRef << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA"); - if (IsIndirectReference) { - if (RequiresComma) - OS << ","; - OS << "INDIRECT"; - } + if (IsIndirectReference) + OS << SepRef << "INDIRECT"; OS << ")"; }