[llvm-branch-commits] [clang] [llvm] [GOFF] Implement lowerConstant/emitGlobalVariables/emitGlobalAlias (PR #169362)
Tony Tao via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Nov 24 08:44:03 PST 2025
https://github.com/tltao created https://github.com/llvm/llvm-project/pull/169362
Add additional functionality required on z/OS for `lowerConstant`, `emitGlobalVariable`, and `emitGlobalAlias`. The main addition is to properly apply the attribute to the various `MCSymbols` and also emit the correct `MCExpr`.
>From d565c7d8c772cf1c66d57bd1db0387ad90bb1d9b Mon Sep 17 00:00:00 2001
From: Tony Tao <tonytao at ca.ibm.com>
Date: Wed, 19 Nov 2025 19:55:35 +0000
Subject: [PATCH 1/4] Implement emitGlobalVariable and lowerConstant
---
clang/lib/Lex/HeaderMap.cpp | 1 +
llvm/lib/Support/VirtualOutputBackends.cpp | 23 +++++---
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 56 +++++++++++++++++++
llvm/lib/Target/SystemZ/SystemZAsmPrinter.h | 2 +
4 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/clang/lib/Lex/HeaderMap.cpp b/clang/lib/Lex/HeaderMap.cpp
index a7b670f00ac6e..588b32ee9ca8e 100644
--- a/clang/lib/Lex/HeaderMap.cpp
+++ b/clang/lib/Lex/HeaderMap.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SystemZ/zOSSupport.h"
#include <cstring>
#include <memory>
#include <optional>
diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp
index de59b8ab63a53..33a56c7f5f607 100644
--- a/llvm/lib/Support/VirtualOutputBackends.cpp
+++ b/llvm/lib/Support/VirtualOutputBackends.cpp
@@ -254,6 +254,18 @@ static Error createDirectoriesOnDemand(StringRef OutputPath,
});
}
+static sys::fs::OpenFlags generateFlagsFromConfig(OutputConfig Config) {
+ sys::fs::OpenFlags OF = sys::fs::OF_None;
+ if (Config.getTextWithCRLF())
+ OF |= sys::fs::OF_TextWithCRLF;
+ else if (Config.getText())
+ OF |= sys::fs::OF_Text;
+ if (Config.getAppend())
+ OF |= sys::fs::OF_Append;
+
+ return OF;
+}
+
Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
// Create a temporary file.
// Insert -%%%%%%%% before the extension (if any), and because some tools
@@ -268,9 +280,10 @@ Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
int NewFD;
+ sys::fs::OpenFlags OF = generateFlagsFromConfig(Config);
SmallString<128> UniquePath;
if (std::error_code EC =
- sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath))
+ sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath, OF))
return make_error<TempFileOutputError>(ModelPath, OutputPath, EC);
if (Config.getDiscardOnSignal())
@@ -312,13 +325,7 @@ Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
// Not using a temporary file. Open the final output file.
return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
int NewFD;
- sys::fs::OpenFlags OF = sys::fs::OF_None;
- if (Config.getTextWithCRLF())
- OF |= sys::fs::OF_TextWithCRLF;
- else if (Config.getText())
- OF |= sys::fs::OF_Text;
- if (Config.getAppend())
- OF |= sys::fs::OF_Append;
+ sys::fs::OpenFlags OF = generateFlagsFromConfig(Config);
if (std::error_code EC = sys::fs::openFileForWrite(
OutputPath, NewFD, sys::fs::CD_CreateAlways, OF))
return convertToOutputError(OutputPath, EC);
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 193e6ef6d1e64..151b59334cab1 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1123,6 +1123,7 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
: MCSA_Global);
OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO) ? MCSA_Code
: MCSA_Data);
+ llvm::dbgs() << "TONY emitting " << Sym->getName() << "\n";
}
}
OutStreamer->switchSection(
@@ -1699,6 +1700,61 @@ void SystemZAsmPrinter::emitPPA2(Module &M) {
OutStreamer->popSection();
}
+void SystemZAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
+ if (TM.getTargetTriple().isOSzOS()) {
+ auto *Sym = getSymbol(GV);
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_Data);
+ }
+
+ AsmPrinter::emitGlobalVariable(GV);
+}
+
+const MCExpr *SystemZAsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
+ const Triple &TargetTriple = TM.getTargetTriple();
+
+ if (TargetTriple.isOSzOS()) {
+ const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV);
+ const GlobalVariable *GV = dyn_cast<GlobalVariable>(CV);
+ const Function *FV = dyn_cast<Function>(CV);
+ bool IsFunc = !GV && (FV || (GA && isa<Function>(GA->getAliaseeObject())));
+
+ MCSymbol *Sym = NULL;
+
+ if (GA)
+ Sym = getSymbol(GA);
+ else if (IsFunc)
+ Sym = getSymbol(FV);
+ else if (GV)
+ Sym = getSymbol(GV);
+
+ if (IsFunc) {
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_Code);
+ if (FV->hasExternalLinkage()) {
+ return MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
+ SystemZ::S_VCon, OutContext);
+ }
+ // Trigger creation of function descriptor in ADA for internal
+ // functions.
+ unsigned Disp = ADATable.insert(Sym, SystemZII::MO_ADA_DIRECT_FUNC_DESC);
+ return MCBinaryExpr::createAdd(
+ MCSpecifierExpr::create(
+ MCSymbolRefExpr::create(
+ getObjFileLowering().getADASection()->getBeginSymbol(),
+ OutContext),
+ SystemZ::S_None, OutContext),
+ MCConstantExpr::create(Disp, OutContext), OutContext);
+ }
+ if (Sym) {
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_Data);
+ return MCSymbolRefExpr::create(Sym, OutContext);
+ }
+ }
+
+ return AsmPrinter::lowerConstant(CV);
+}
+
void SystemZAsmPrinter::emitFunctionEntryLabel() {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index cb101e472824f..5c7658dd3055b 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -130,6 +130,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
void emitFunctionEntryLabel() override;
void emitFunctionBodyEnd() override;
void emitStartOfAsmFile(Module &M) override;
+ void emitGlobalVariable(const GlobalVariable *GV) override;
+ const MCExpr *lowerConstant(const Constant *CV, const Constant *BaseCV = nullptr, uint64_t Offset = 0) override;
private:
void emitCallInformation(CallType CT);
>From 7e735024caf847edbf916e22097c3470ecc7543f Mon Sep 17 00:00:00 2001
From: Tony Tao <tonytao at ca.ibm.com>
Date: Wed, 19 Nov 2025 19:57:30 +0000
Subject: [PATCH 2/4] undo accdiental commit
---
llvm/lib/Support/VirtualOutputBackends.cpp | 23 ++++++++--------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp
index 33a56c7f5f607..de59b8ab63a53 100644
--- a/llvm/lib/Support/VirtualOutputBackends.cpp
+++ b/llvm/lib/Support/VirtualOutputBackends.cpp
@@ -254,18 +254,6 @@ static Error createDirectoriesOnDemand(StringRef OutputPath,
});
}
-static sys::fs::OpenFlags generateFlagsFromConfig(OutputConfig Config) {
- sys::fs::OpenFlags OF = sys::fs::OF_None;
- if (Config.getTextWithCRLF())
- OF |= sys::fs::OF_TextWithCRLF;
- else if (Config.getText())
- OF |= sys::fs::OF_Text;
- if (Config.getAppend())
- OF |= sys::fs::OF_Append;
-
- return OF;
-}
-
Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
// Create a temporary file.
// Insert -%%%%%%%% before the extension (if any), and because some tools
@@ -280,10 +268,9 @@ Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
int NewFD;
- sys::fs::OpenFlags OF = generateFlagsFromConfig(Config);
SmallString<128> UniquePath;
if (std::error_code EC =
- sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath, OF))
+ sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath))
return make_error<TempFileOutputError>(ModelPath, OutputPath, EC);
if (Config.getDiscardOnSignal())
@@ -325,7 +312,13 @@ Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
// Not using a temporary file. Open the final output file.
return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
int NewFD;
- sys::fs::OpenFlags OF = generateFlagsFromConfig(Config);
+ sys::fs::OpenFlags OF = sys::fs::OF_None;
+ if (Config.getTextWithCRLF())
+ OF |= sys::fs::OF_TextWithCRLF;
+ else if (Config.getText())
+ OF |= sys::fs::OF_Text;
+ if (Config.getAppend())
+ OF |= sys::fs::OF_Append;
if (std::error_code EC = sys::fs::openFileForWrite(
OutputPath, NewFD, sys::fs::CD_CreateAlways, OF))
return convertToOutputError(OutputPath, EC);
>From 3ba320b859221fbc6e44d1dfecfa559a2479db58 Mon Sep 17 00:00:00 2001
From: Tony Tao <tony.le.tao at gmail.com>
Date: Fri, 14 Nov 2025 13:19:26 -0500
Subject: [PATCH 3/4] [Support] Prevent loss of file type flags when creating
temporary (#167939)
Non-binary output files from the compiler need the `OF_Text` flag set
for encoding conversion to be performed correctly on z/OS.
---------
Co-authored-by: Tony Tao <tonytao at ca.ibm.com>
---
clang/test/CodeGen/SystemZ/encoding.c | 9 ++++++++
llvm/lib/Support/VirtualOutputBackends.cpp | 25 +++++++++++++++-------
2 files changed, 26 insertions(+), 8 deletions(-)
create mode 100644 clang/test/CodeGen/SystemZ/encoding.c
diff --git a/clang/test/CodeGen/SystemZ/encoding.c b/clang/test/CodeGen/SystemZ/encoding.c
new file mode 100644
index 0000000000000..d018a9c37852a
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/encoding.c
@@ -0,0 +1,9 @@
+// Checks encoding of output file
+// This is only required for z/OS.
+//
+// REQUIRES: system-zos, systemz-registered-target
+// RUN: %clang_cc1 -triple s390x-ibm-zos -S %s -o %t.s
+// RUN: ls -T %t.s | FileCheck %s
+
+// CHECK: t IBM-1047 T=on
+void foo() { return; }
diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp
index de59b8ab63a53..f9c8f1302e6c5 100644
--- a/llvm/lib/Support/VirtualOutputBackends.cpp
+++ b/llvm/lib/Support/VirtualOutputBackends.cpp
@@ -254,6 +254,20 @@ static Error createDirectoriesOnDemand(StringRef OutputPath,
});
}
+static sys::fs::OpenFlags generateFlagsFromConfig(OutputConfig Config) {
+ sys::fs::OpenFlags OF = sys::fs::OF_None;
+ if (Config.getTextWithCRLF())
+ OF |= sys::fs::OF_TextWithCRLF;
+ else if (Config.getText())
+ OF |= sys::fs::OF_Text;
+ // Don't pass OF_Append if writting to temporary since OF_Append is
+ // not Atomic Append
+ if (Config.getAppend() && !Config.getAtomicWrite())
+ OF |= sys::fs::OF_Append;
+
+ return OF;
+}
+
Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
// Create a temporary file.
// Insert -%%%%%%%% before the extension (if any), and because some tools
@@ -269,8 +283,9 @@ Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
int NewFD;
SmallString<128> UniquePath;
+ sys::fs::OpenFlags OF = generateFlagsFromConfig(Config);
if (std::error_code EC =
- sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath))
+ sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath, OF))
return make_error<TempFileOutputError>(ModelPath, OutputPath, EC);
if (Config.getDiscardOnSignal())
@@ -312,13 +327,7 @@ Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
// Not using a temporary file. Open the final output file.
return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
int NewFD;
- sys::fs::OpenFlags OF = sys::fs::OF_None;
- if (Config.getTextWithCRLF())
- OF |= sys::fs::OF_TextWithCRLF;
- else if (Config.getText())
- OF |= sys::fs::OF_Text;
- if (Config.getAppend())
- OF |= sys::fs::OF_Append;
+ sys::fs::OpenFlags OF = generateFlagsFromConfig(Config);
if (std::error_code EC = sys::fs::openFileForWrite(
OutputPath, NewFD, sys::fs::CD_CreateAlways, OF))
return convertToOutputError(OutputPath, EC);
>From 903ea3977745b15ff8bcae99af61ddc2a8a9cfc3 Mon Sep 17 00:00:00 2001
From: Tony Tao <tonytao at ca.ibm.com>
Date: Fri, 21 Nov 2025 13:58:15 -0500
Subject: [PATCH 4/4] implement more features
---
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 36 ++++++++++++++++++-
llvm/lib/Target/SystemZ/SystemZAsmPrinter.h | 1 +
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 151b59334cab1..17e71ec760095 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -347,7 +347,7 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
case SystemZ::ADA_ENTRY: {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
- uint32_t Disp = ADATable.insert(MI->getOperand(1));
+ uint32_t Disp = ADATable.insert(MI->getOperand(1));
Register TargetReg = MI->getOperand(0).getReg();
Register ADAReg = MI->getOperand(2).getReg();
@@ -373,6 +373,8 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
Disp = 0;
Op = Op0;
}
+ OutStreamer->AddComment(Twine("Loading from ADA at offset ")
+ .concat(utostr(Disp)));
EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
.addReg(TargetReg)
.addReg(ADAReg)
@@ -1755,6 +1757,38 @@ const MCExpr *SystemZAsmPrinter::lowerConstant(const Constant *CV,
return AsmPrinter::lowerConstant(CV);
}
+void SystemZAsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {
+ if (!TM.getTargetTriple().isOSzOS()) {
+ AsmPrinter::emitGlobalAlias(M, GA);
+ return;
+ }
+
+ MCSymbol *Name = getSymbol(&GA);
+ bool IsFunc = isa<Function>(GA.getAliasee()->stripPointerCasts());
+
+ if (GA.hasExternalLinkage() || !MAI->getWeakRefDirective())
+ OutStreamer->emitSymbolAttribute(Name, MCSA_Global);
+ else if (GA.hasWeakLinkage() || GA.hasLinkOnceLinkage())
+ OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference);
+ else
+ assert(GA.hasLocalLinkage() && "Invalid alias linkage");
+
+ emitVisibility(Name, GA.getVisibility());
+
+ const MCExpr *Expr;
+
+ // For XPLINK, create a VCON relocation in case of a function, and
+ // a direct reference else.
+ MCSymbol *Sym = getSymbol(GA.getAliaseeObject());
+ if (IsFunc)
+ Expr = MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
+ SystemZ::S_VCon, OutContext);
+ else
+ Expr = MCSymbolRefExpr::create(Sym, OutContext);
+
+ OutStreamer->emitAssignment(Name, Expr);
+}
+
void SystemZAsmPrinter::emitFunctionEntryLabel() {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index 5c7658dd3055b..003e9af7c2ca8 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -131,6 +131,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
void emitFunctionBodyEnd() override;
void emitStartOfAsmFile(Module &M) override;
void emitGlobalVariable(const GlobalVariable *GV) override;
+ void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override;
const MCExpr *lowerConstant(const Constant *CV, const Constant *BaseCV = nullptr, uint64_t Offset = 0) override;
private:
More information about the llvm-branch-commits
mailing list