[llvm] [SystemZ][z/OS] Keep weak references weak (PR #226840)
MMS IT GmbH via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 02:53:36 PDT 2026
https://github.com/mms-it-ch updated https://github.com/llvm/llvm-project/pull/226840
>From c737d5b34ad701809446d4c22fc8bd7d01297fbd Mon Sep 17 00:00:00 2001
From: mms-it-ch <info at mms-it.ch>
Date: Sun, 27 Sep 2026 23:37:55 +0200
Subject: [PATCH] [SystemZ][z/OS] Keep weak references weak
An extern_weak reference must stay unresolved without an error when the
symbol does not exist. On z/OS two kinds of references were always
strong:
- Taking the address of an external function goes through the indirect
symbol <name>@indirect, which never got the weak attribute of the
function symbol. The attribute is already set when the ADA is emitted,
because AsmPrinter::doFinalization emits the weak references before
emitEndOfAsmFile.
- An external data reference is a part reference (PR). GOFF::PRAttr had
no binding strength, and the PR constructor did not set it.
Without this change the binder reports IEW2456E for such references.
Fixes #226835.
Assisted-by: Claude Code (Anthropic)
---
llvm/include/llvm/MC/MCGOFFAttributes.h | 1 +
llvm/lib/MC/GOFFObjectWriter.cpp | 5 ++-
.../SystemZ/SystemZXPLINKAsmPrinter.cpp | 4 ++
llvm/test/CodeGen/SystemZ/zos-extern-weak.ll | 37 +++++++++++++++++++
4 files changed, 45 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/SystemZ/zos-extern-weak.ll
diff --git a/llvm/include/llvm/MC/MCGOFFAttributes.h b/llvm/include/llvm/MC/MCGOFFAttributes.h
index 289d962e993b8..eb2abd4cf806b 100644
--- a/llvm/include/llvm/MC/MCGOFFAttributes.h
+++ b/llvm/include/llvm/MC/MCGOFFAttributes.h
@@ -77,6 +77,7 @@ struct PRAttr {
GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
uint32_t SortKey = 0;
+ GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
};
// Attributes for ER symbols.
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 36407759dbc50..435e144f828bd 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -265,6 +265,7 @@ class GOFFSymbol {
SymbolType(GOFF::ESD_ST_PartReference), NameSpace(EDAttr.NameSpace) {
SymbolFlags.setRenameable(Attr.IsRenamable);
BehavAttrs.setExecutable(Attr.Executable);
+ BehavAttrs.setBindingStrength(Attr.BindingStrength);
BehavAttrs.setLinkageType(Attr.Linkage);
BehavAttrs.setBindingScope(Attr.BindingScope);
BehavAttrs.setAlignment(Alignment);
@@ -401,8 +402,8 @@ void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
GOFFSymbol PR(Symbol.getExternalName(), Symbol.getIndex(), ED->getOrdinal(),
ED->getEDAttributes(), ED->getEDAlignment(),
GOFF::PRAttr{/*IsRenamable*/ false, Symbol.getCodeData(),
- Symbol.getLinkage(), Symbol.getBindingScope(),
- 0});
+ Symbol.getLinkage(), Symbol.getBindingScope(), 0,
+ Symbol.getBindingStrength()});
writeSymbol(PR);
} else {
GOFFSymbol ER(Symbol.getExternalName(), Symbol.getIndex(),
diff --git a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
index 3ab3dfc4a0bcb..166185fa0967d 100644
--- a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
@@ -341,6 +341,10 @@ void SystemZXPLINKAsmPrinter::emitADASection() {
OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern);
MCSymbolGOFF *GOFFSym =
static_cast<llvm::MCSymbolGOFF *>(const_cast<llvm::MCSymbol *>(Sym));
+ // A weak reference (extern_weak) stays weak through the indirect
+ // symbol, otherwise the binder fails on the unresolved reference.
+ if (GOFFSym->isWeak())
+ OutStreamer->emitSymbolAttribute(Alias, MCSA_WeakReference);
ZOS->emitExternalName(Alias, GOFFSym->getExternalName());
EMIT_COMMENT("pointer to function descriptor");
OutStreamer->emitValue(
diff --git a/llvm/test/CodeGen/SystemZ/zos-extern-weak.ll b/llvm/test/CodeGen/SystemZ/zos-extern-weak.ll
new file mode 100644
index 0000000000000..d8b1d1e9789f7
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/zos-extern-weak.ll
@@ -0,0 +1,37 @@
+; Weak references (extern_weak) must be weak in the object file: the indirect
+; symbol through which the address of a function is taken, and the part
+; reference for external data. Otherwise the binder fails when the symbol
+; does not exist.
+; RUN: llc < %s -mtriple=s390x-ibm-zos | FileCheck %s
+; RUN: llc < %s -mtriple=s390x-ibm-zos --filetype=obj | \
+; RUN: od -Ax -tx1 -v | FileCheck --check-prefix=CHECKOBJ --ignore-case %s
+
+; CHECK-DAG: WXTRN wf at indirect
+; CHECK-DAG: WXTRN wf{{ *$}}
+; CHECK-NOT: {{^ EXTRN wf}}
+
+; The last bytes of the ESD records: behavioral attributes 4-9 (binding
+; strength 1 = weak in byte 4), name length and name.
+; PR wv (external data):
+; CHECKOBJ: {{^[0-9a-f]+}} 01 04 24 00 00 00 00 02 a6 a5
+; ER wf at indirect (external name wf, indirect reference):
+; CHECKOBJ: {{^[0-9a-f]+}} 01 14 20 00 00 00 00 02 a6 86
+; ER wf:
+; CHECKOBJ: {{^[0-9a-f]+}} 01 04 20 00 00 00 00 02 a6 86
+
+ at wv = extern_weak global i32
+
+declare extern_weak void @wf()
+
+define ptr @getv() {
+ ret ptr @wv
+}
+
+define ptr @getf() {
+ ret ptr @wf
+}
+
+define void @callf() {
+ call void @wf()
+ ret void
+}
More information about the llvm-commits
mailing list