Skip to content

[SystemZ] Emit external aliases required for indirect symbol handling support - #183442

Merged
amy-kwan merged 3 commits into
mainfrom
users/amy-kwan/indirectsymbols-2
Feb 27, 2026
Merged

amy-kwan merged 3 commits into
mainfrom
users/amy-kwan/indirectsymbols-2

Conversation

@amy-kwan

Copy link
Copy Markdown
Member

This is the second of three patches aimed to support indirect symbol handling for the SystemZ backend. An external name is added for both MC sections and symbols and makes the relevant printers and writers utilize the external name when present. Furthermore, the ALIAS HLASM instruction is emitted after every XATTR instruction.

Depends on #183441.

@llvmbot

llvmbot commented Feb 26, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-mc

@llvm/pr-subscribers-backend-systemz

Author: Amy Kwan (amy-kwan)

Changes

This is the second of three patches aimed to support indirect symbol handling for the SystemZ backend. An external name is added for both MC sections and symbols and makes the relevant printers and writers utilize the external name when present. Furthermore, the ALIAS HLASM instruction is emitted after every XATTR instruction.

Depends on #183441.


Full diff: https://github.com/llvm/llvm-project/pull/183442.diff

6 Files Affected:

  • (modified) llvm/include/llvm/MC/MCSectionGOFF.h (+8)
  • (modified) llvm/include/llvm/MC/MCSymbolGOFF.h (+9)
  • (modified) llvm/lib/MC/GOFFObjectWriter.cpp (+19-15)
  • (modified) llvm/lib/MC/MCAsmInfoGOFF.cpp (+6)
  • (modified) llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp (+4)
  • (modified) llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h (+17)
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index 2136148368fbd..288f9038bb65e 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -27,6 +27,8 @@ namespace llvm {
 class MCExpr;
 
 class LLVM_ABI MCSectionGOFF final : public MCSection {
+  StringRef ExternalName; // Alternate external name.
+
   // Parent of this section. Implies that the parent is emitted first.
   MCSectionGOFF *Parent;
 
@@ -115,6 +117,12 @@ class LLVM_ABI MCSectionGOFF final : public MCSection {
   bool requiresNonZeroLength() const { return RequiresNonZeroLength; }
 
   void setName(StringRef SectionName) { Name = SectionName; }
+
+  bool hasExternalName() const { return !ExternalName.empty(); }
+  void setExternalName(StringRef Name) { ExternalName = Name; }
+  StringRef getExternalName() const {
+    return hasExternalName() ? ExternalName : getName();
+  }
 };
 } // end namespace llvm
 
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index 15193c8379d14..0e646b8babb6b 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -23,6 +23,9 @@
 namespace llvm {
 
 class MCSymbolGOFF : public MCSymbol {
+
+  StringRef ExternalName; // Alternate external name.
+
   // Associated data area of the section. Needs to be emitted first.
   MCSectionGOFF *ADA = nullptr;
 
@@ -48,6 +51,12 @@ class MCSymbolGOFF : public MCSymbol {
   bool isExternal() const { return IsExternal; }
   void setExternal(bool Value) const { IsExternal = Value; }
 
+  bool hasExternalName() const { return !ExternalName.empty(); }
+  void setExternalName(StringRef Name) { ExternalName = Name; }
+  StringRef getExternalName() const {
+    return hasExternalName() ? ExternalName : getName();
+  }
+
   void setHidden(bool Value = true) {
     modifyFlags(Value ? SF_Hidden : 0, SF_Hidden);
   }
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index a619328c09fa3..84e43e30636c8 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -315,13 +315,13 @@ GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
 
 void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
   if (Section.isSD()) {
-    GOFFSymbol SD(Section.getName(), Section.getOrdinal(),
+    GOFFSymbol SD(Section.getExternalName(), Section.getOrdinal(),
                   Section.getSDAttributes());
     writeSymbol(SD);
   }
 
   if (Section.isED()) {
-    GOFFSymbol ED(Section.getName(), Section.getOrdinal(),
+    GOFFSymbol ED(Section.getExternalName(), Section.getOrdinal(),
                   Section.getParent()->getOrdinal(), Section.getEDAttributes());
     ED.SectionLength = Asm.getSectionAddressSize(Section);
     writeSymbol(ED);
@@ -329,8 +329,9 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
 
   if (Section.isPR()) {
     MCSectionGOFF *Parent = Section.getParent();
-    GOFFSymbol PR(Section.getName(), Section.getOrdinal(), Parent->getOrdinal(),
-                  Parent->getEDAttributes(), Section.getPRAttributes());
+    GOFFSymbol PR(Section.getExternalName(), Section.getOrdinal(),
+                  Parent->getOrdinal(), Parent->getEDAttributes(),
+                  Section.getPRAttributes());
     PR.SectionLength = Asm.getSectionAddressSize(Section);
     if (Section.requiresNonZeroLength()) {
       // We cannot have a zero-length section for data.  If we do,
@@ -347,8 +348,8 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
 
 void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
   MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(Symbol.getSection());
-  GOFFSymbol LD(Symbol.getName(), Symbol.getIndex(), Section.getOrdinal(),
-                Section.getEDAttributes().NameSpace,
+  GOFFSymbol LD(Symbol.getExternalName(), Symbol.getIndex(),
+                Section.getOrdinal(), Section.getEDAttributes().NameSpace,
                 GOFF::LDAttr{false, Symbol.getCodeData(),
                              Symbol.getBindingStrength(), Symbol.getLinkage(),
                              GOFF::ESD_AMODE_64, Symbol.getBindingScope()});
@@ -359,7 +360,7 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
 }
 
 void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
-  GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(), RootSD->getOrdinal(),
+  GOFFSymbol ER(Symbol.getExternalName(), Symbol.getIndex(), RootSD->getOrdinal(),
                 GOFF::ERAttr{Symbol.isIndirect(), Symbol.getCodeData(),
                              Symbol.getBindingStrength(), Symbol.getLinkage(),
                              GOFF::ESD_AMODE_64, Symbol.getBindingScope()});
@@ -695,25 +696,26 @@ void GOFFObjectWriter::recordRelocation(const MCFragment &F,
       Asm->reportError(
           Fixup.getLoc(),
           Twine("symbol ")
-              .concat(A.getName())
+              .concat(A.getExternalName())
               .concat(" must be defined for a relative immediate relocation"));
       return;
     }
     if (&A.getSection() != PSection) {
+      MCSectionGOFF &GOFFSection = static_cast<MCSectionGOFF &>(A.getSection());
       Asm->reportError(Fixup.getLoc(),
                        Twine("relative immediate relocation section mismatch: ")
-                           .concat(A.getSection().getName())
+                           .concat(GOFFSection.getExternalName())
                            .concat(" of symbol ")
-                           .concat(A.getName())
+                           .concat(A.getExternalName())
                            .concat(" <-> ")
-                           .concat(PSection->getName()));
+                           .concat(PSection->getExternalName()));
       return;
     }
     if (B) {
       Asm->reportError(
           Fixup.getLoc(),
           Twine("subtractive symbol ")
-              .concat(B->getName())
+              .concat(B->getExternalName())
               .concat(" not supported for a relative immediate relocation"));
       return;
     }
@@ -767,9 +769,11 @@ void GOFFObjectWriter::recordRelocation(const MCFragment &F,
     default:
       Con = "(unknown)";
     }
-    dbgs() << "Reloc " << N << ": " << Con << " Rptr: " << Sym->getName()
-           << " Pptr: " << PSection->getName() << " Offset: " << FixupOffset
-           << " Fixed Imm: " << FixedValue << "\n";
+    dbgs() << "Reloc " << N << ": " << Con
+           << " Rptr: " << Sym->getExternalName()
+           << " Pptr: " << PSection->getExternalName()
+           << " Offset: " << FixupOffset << " Fixed Imm: " << FixedValue
+           << "\n";
   };
   (void)DumpReloc;
 
diff --git a/llvm/lib/MC/MCAsmInfoGOFF.cpp b/llvm/lib/MC/MCAsmInfoGOFF.cpp
index 4dc33943609db..721d62fab512d 100644
--- a/llvm/lib/MC/MCAsmInfoGOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoGOFF.cpp
@@ -124,6 +124,8 @@ void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section,
   case GOFF::ESD_ST_SectionDefinition: {
     OS << Sec.getName() << " CSECT\n";
     Sec.Emitted = true;
+    if (Sec.hasExternalName())
+      OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";
     break;
   }
   case GOFF::ESD_ST_ElementDefinition: {
@@ -134,6 +136,8 @@ void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section,
                 GOFF::ESD_EXE_Unspecified, Sec.EDAttributes.IsReadOnly, 0,
                 Sec.EDAttributes.FillByteValue, StringRef());
       Sec.Emitted = true;
+      if (Sec.hasExternalName())
+        OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";
     } else
       OS << Sec.getName() << " CATTR\n";
     break;
@@ -151,6 +155,8 @@ void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section,
                 Sec.PRAttributes.Executable, Sec.PRAttributes.BindingScope);
       ED->Emitted = true;
       Sec.Emitted = true;
+      if (Sec.hasExternalName())
+        OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";
     } else
       OS << ED->getName() << " CATTR PART(" << Sec.getName() << ")\n";
     break;
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index bb49ab85ad126..52e3e950cbb0c 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -263,6 +263,8 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
     emitXATTR(OS, Sym->getName(), Sym->isIndirect(), Sym->getLinkage(),
               Sym->getCodeData(), Sym->getBindingScope());
     EmitEOL();
+    if (Sym->hasExternalName())
+      OS << Sym->getName() << " ALIAS \"" << Sym->getExternalName() << "\"\n";
   }
 
   if (EmitLabelAndEntry) {
@@ -373,6 +375,8 @@ void SystemZHLASMAsmStreamer::finishImpl() {
     emitXATTR(OS, Sym.getName(), Sym.isIndirect(), Sym.getLinkage(),
               Sym.getCodeData(), Sym.getBindingScope());
     EmitEOL();
+    if (Sym.hasExternalName())
+      OS << Sym.getName() << " ALIAS \"" << Sym.getExternalName() << "\"\n";
   }
 
   // Finish the assembly output.
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 4f9a4a0a97ed8..878600a67edbc 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -13,8 +13,10 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/Support/FormattedStream.h"
 #include <map>
 #include <utility>
@@ -58,6 +60,9 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 
   virtual void emitMachine(StringRef CPUOrCommand) {};
 
+  virtual void emitExternalName(MCSymbol *Sym, StringRef Name) {}
+  virtual void emitExternalName(MCSection *Sec, StringRef Name) {}
+
   virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                            const MCSymbol *Lo) {
     return nullptr;
@@ -69,6 +74,12 @@ class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
   SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
+  virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override {
+    static_cast<MCSymbolGOFF *>(Sym)->setExternalName(Name);
+  }
+  virtual void emitExternalName(MCSection *Sec, StringRef Name) override {
+    static_cast<MCSectionGOFF *>(Sec)->setExternalName(Name);
+  }
 };
 
 class SystemZTargetHLASMStreamer : public SystemZTargetStreamer {
@@ -80,6 +91,12 @@ class SystemZTargetHLASMStreamer : public SystemZTargetStreamer {
   SystemZHLASMAsmStreamer &getHLASMStreamer();
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
+  virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override {
+    static_cast<MCSymbolGOFF *>(Sym)->setExternalName(Name);
+  }
+  virtual void emitExternalName(MCSection *Sec, StringRef Name) override {
+    static_cast<MCSectionGOFF *>(Sec)->setExternalName(Name);
+  }
 };
 
 class SystemZTargetELFStreamer : public SystemZTargetStreamer {

@github-actions

github-actions Bot commented Feb 26, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@amy-kwan
amy-kwan force-pushed the users/amy-kwan/indirectsymbols-1 branch from 69e9313 to ad410c6 Compare February 26, 2026 05:52
@amy-kwan
amy-kwan force-pushed the users/amy-kwan/indirectsymbols-2 branch from 8d3ab19 to ac321c2 Compare February 26, 2026 05:53

@uweigand uweigand left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@redstar redstar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct the syntax of ALIAS, otherwise LGTM.

Comment thread llvm/lib/MC/MCAsmInfoGOFF.cpp Outdated
OS << Sec.getName() << " CSECT\n";
Sec.Emitted = true;
if (Sec.hasExternalName())
OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The syntax of ALIAS is slightly different, see https://www.ibm.com/docs/en/hla-and-tf/1.6.0?topic=statements-alias-instruction:

Suggested change
OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";
OS << Sec.getName() << " ALIAS "C'" << Sec.getExternalName() << "'\n";

Comment thread llvm/lib/MC/MCAsmInfoGOFF.cpp Outdated
Sec.EDAttributes.FillByteValue, StringRef());
Sec.Emitted = true;
if (Sec.hasExternalName())
OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

Comment thread llvm/lib/MC/MCAsmInfoGOFF.cpp Outdated
Comment on lines +158 to +159
if (Sec.hasExternalName())
OS << Sec.getName() << " ALIAS \"" << Sec.getExternalName() << "\"\n";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.
Looks like using a lamba would avoid the repetition, e.g.

auto EmitExternalName = [&Sec]() {
  if (Sec.hasExternalName())
        OS << Sec.getName() << " ALIAS "C'" << Sec.getExternalName() << "'\n";
}

Sym->getCodeData(), Sym->getBindingScope());
EmitEOL();
if (Sym->hasExternalName())
OS << Sym->getName() << " ALIAS \"" << Sym->getExternalName() << "\"\n";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same syntax.

Sym.getCodeData(), Sym.getBindingScope());
EmitEOL();
if (Sym.hasExternalName())
OS << Sym.getName() << " ALIAS \"" << Sym.getExternalName() << "\"\n";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same syntax.

@amy-kwan
amy-kwan force-pushed the users/amy-kwan/indirectsymbols-2 branch from ac321c2 to 502aa43 Compare February 26, 2026 20:54
@amy-kwan
amy-kwan requested a review from redstar February 26, 2026 20:55
Base automatically changed from users/amy-kwan/indirectsymbols-1 to main February 27, 2026 16:12
… support

This is the second of three patches aimed to support indirect symbol handling for
the SystemZ backend. An external name is added for both MC sections and symbols
and makes the relevant printers and writers utilize the external name when present.
Furthermore, the ALIAS HLASM instruction is emitted after every XATTR instruction.
@amy-kwan
amy-kwan force-pushed the users/amy-kwan/indirectsymbols-2 branch from 4bec1b8 to acded03 Compare February 27, 2026 17:30
@amy-kwan
amy-kwan merged commit c3b3f41 into main Feb 27, 2026
9 of 10 checks passed
@amy-kwan
amy-kwan deleted the users/amy-kwan/indirectsymbols-2 branch February 27, 2026 18:07
amy-kwan added a commit that referenced this pull request Feb 27, 2026
…the ADA section (#183443)

This is the last of the three patches aimed to support indirect symbol
handling for the SystemZ backend.

An external alias is emitted for indirect function descriptors within
the ADA section, rather than a temporary alias, while also setting all
of the appropriate symbol attributes that are needed for the HLASM
streamer to emit the correct XATTR and ALIAS instructions for the
indirect symbols.

Moreover, this patch updates the
`CodeGen/SystemZ/zos-ada-relocations.ll` test as the ADA section is
currently the only user of indirect symbols on z/OS.

Depends on #183442.
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Feb 27, 2026
…riptors in the ADA section (#183443)

This is the last of the three patches aimed to support indirect symbol
handling for the SystemZ backend.

An external alias is emitted for indirect function descriptors within
the ADA section, rather than a temporary alias, while also setting all
of the appropriate symbol attributes that are needed for the HLASM
streamer to emit the correct XATTR and ALIAS instructions for the
indirect symbols.

Moreover, this patch updates the
`CodeGen/SystemZ/zos-ada-relocations.ll` test as the ADA section is
currently the only user of indirect symbols on z/OS.

Depends on llvm/llvm-project#183442.
sujianIBM pushed a commit to sujianIBM/llvm-project that referenced this pull request Mar 5, 2026
… support (llvm#183442)

This is the second of three patches aimed to support indirect symbol
handling for the SystemZ backend. An external name is added for both MC
sections and symbols and makes the relevant printers and writers utilize
the external name when present. Furthermore, the ALIAS HLASM instruction
is emitted after every XATTR instruction.

Depends on llvm#183441.
sujianIBM pushed a commit to sujianIBM/llvm-project that referenced this pull request Mar 5, 2026
…the ADA section (llvm#183443)

This is the last of the three patches aimed to support indirect symbol
handling for the SystemZ backend.

An external alias is emitted for indirect function descriptors within
the ADA section, rather than a temporary alias, while also setting all
of the appropriate symbol attributes that are needed for the HLASM
streamer to emit the correct XATTR and ALIAS instructions for the
indirect symbols.

Moreover, this patch updates the
`CodeGen/SystemZ/zos-ada-relocations.ll` test as the ADA section is
currently the only user of indirect symbols on z/OS.

Depends on llvm#183442.
markrvmurray pushed a commit to markrvmurray/llvm-mc6809 that referenced this pull request Jun 14, 2026
…the ADA section (#183443)

This is the last of the three patches aimed to support indirect symbol
handling for the SystemZ backend.

An external alias is emitted for indirect function descriptors within
the ADA section, rather than a temporary alias, while also setting all
of the appropriate symbol attributes that are needed for the HLASM
streamer to emit the correct XATTR and ALIAS instructions for the
indirect symbols.

Moreover, this patch updates the
`CodeGen/SystemZ/zos-ada-relocations.ll` test as the ADA section is
currently the only user of indirect symbols on z/OS.

Depends on llvm/llvm-project#183442.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:SystemZ llvm:mc Machine (object) code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants