[clang] [z/OS] Add option to target older versions of LE on z/OS (PR #123399)
Sean Perry via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 31 11:58:40 PST 2025
https://github.com/perry-ca updated https://github.com/llvm/llvm-project/pull/123399
>From 9f5763faa81691f540af42721147daf50042e549 Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Wed, 27 Nov 2024 18:33:09 -0600
Subject: [PATCH 1/3] Add -mzos-target
---
.../clang/Basic/DiagnosticDriverKinds.td | 5 ++
clang/include/clang/Driver/Options.td | 1 +
clang/lib/Basic/Targets/SystemZ.cpp | 15 ++++
clang/lib/Driver/Driver.cpp | 72 +++++++++++++++++++
clang/lib/Driver/ToolChain.cpp | 15 ++++
clang/test/Preprocessor/zos-target.c | 18 +++++
6 files changed, 126 insertions(+)
create mode 100644 clang/test/Preprocessor/zos-target.c
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 5155b23d151c04..140bc52af12b25 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -277,6 +277,11 @@ def err_cpu_unsupported_isa
def err_arch_unsupported_isa
: Error<"architecture '%0' does not support '%1' execution mode">;
+def err_zos_target_release_discontinued
+ : Error<"z/OS target level \"%0\" is discontinued. Unexpected behavior might occur if an out-of-support target level is specified. Use z/OS target level \"zOSv2r4\", or later instead">;
+def err_zos_target_unrecognized_release
+ : Error<"\"%0\" is not recognized as a valid z/OS target level. The z/OS target level must be \"current\", or of the form \"zosvVrR\", where \"V\" is the version and \"R\" is the release, or given as a \"0x\"-prefixed eight digit hexadecimal value">;
+
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 40fd48761928b3..ddbd857414e714 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4734,6 +4734,7 @@ def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=
def march_EQ : Joined<["-"], "march=">, Group<m_Group>,
Flags<[TargetSpecific]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"For a list of available architectures for the target use '-mcpu=help'">;
+def mzos_target_EQ : Joined<["-"], "mzos-target=">, Group<m_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Set the z/OS release of the runtime environment">;
def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Visibility<[ClangOption, FlangOption]>;
def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index 06f08db2eadd47..2c749c0ba76937 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -168,6 +168,21 @@ void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__VX__");
if (Opts.ZVector)
Builder.defineMacro("__VEC__", "10304");
+
+ /* Set __TARGET_LIB__ only if a value was given. If no value was given */
+ /* we rely on the LE headers to define __TARGET_LIB__. */
+ if (!getTriple().getOSVersion().empty()) {
+ llvm::VersionTuple V = getTriple().getOSVersion();
+ // Create string with form: 0xPVRRMMMM, where P=4
+ std::string Str("0x");
+ unsigned int Librel = 0x40000000;
+ Librel |= V.getMajor() << 24;
+ Librel |= (V.getMinor() ? V.getMinor().value() : 1) << 16;
+ Librel |= V.getSubminor() ? V.getSubminor().value() : 0;
+ Str += llvm::utohexstr(Librel);
+
+ Builder.defineMacro("__TARGET_LIB__", Str.c_str());
+ }
}
ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ad14b5c9b6dc80..eebe60648ed22b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -517,6 +517,72 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
return DAL;
}
+static void setZosTargetVersion(const Driver &D, llvm::Triple &Target,
+ StringRef ArgTarget) {
+
+ static bool BeSilent = false;
+ auto IsTooOldToBeSupported = [](int v, int r) -> bool {
+ return ((v < 2) || ((v == 2) && (r < 4)));
+ };
+
+ /* expect CURRENT, zOSV2R[45], or 0xnnnnnnnn */
+ if (ArgTarget.equals_insensitive("CURRENT")) {
+ /* If the user gives CURRENT, then we rely on the LE to set */
+ /* __TARGET_LIB__. There's nothing more we need to do. */
+ } else {
+ unsigned int Version = 0;
+ unsigned int Release = 0;
+ unsigned int Modification = 0;
+ bool IsOk = true;
+ llvm::Regex ZOsvRegex("[zZ][oO][sS][vV]([0-9])[rR]([0-9])");
+ llvm::Regex HexRegex(
+ "0x4" /* product */
+ "([0-9a-fA-F])" /* version */
+ "([0-9a-fA-F][0-9a-fA-F])" /* release */
+ "([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])" /* modification */);
+ SmallVector<StringRef> Matches;
+
+ if (ZOsvRegex.match(ArgTarget, &Matches)) {
+ Matches[1].getAsInteger(10, Version);
+ Matches[2].getAsInteger(10, Release);
+ Modification = 0;
+ if (IsTooOldToBeSupported(Version, Release)) {
+ if (!BeSilent)
+ D.Diag(diag::err_zos_target_release_discontinued) << ArgTarget;
+ IsOk = false;
+ }
+ } else if (HexRegex.match(ArgTarget, &Matches)) {
+ Matches[1].getAsInteger(16, Version);
+ Matches[2].getAsInteger(16, Release);
+ Matches[3].getAsInteger(16, Modification);
+ if (IsTooOldToBeSupported(Version, Release)) {
+ if (!BeSilent)
+ D.Diag(diag::err_zos_target_release_discontinued) << ArgTarget;
+ IsOk = false;
+ }
+ } else {
+ /* something else: need to report an error */
+ if (!BeSilent)
+ D.Diag(diag::err_zos_target_unrecognized_release) << ArgTarget;
+ IsOk = false;
+ }
+
+ if (IsOk) {
+ llvm::VersionTuple V(Version, Release, Modification);
+ llvm::VersionTuple TV = Target.getOSVersion();
+ // The goal is to pick the minimally supported version of
+ // the OS. Pick the lesser as the target.
+ if (TV.empty() || V < TV) {
+ SmallString<16> Str;
+ Str = llvm::Triple::getOSTypeName(Target.getOS());
+ Str += V.getAsString();
+ Target.setOSName(Str);
+ }
+ }
+ }
+ BeSilent = true;
+}
+
/// Compute target triple from args.
///
/// This routine provides the logic to compute a target triple from various
@@ -638,6 +704,12 @@ static llvm::Triple computeTargetTriple(const Driver &D,
}
}
+ if (Target.isOSzOS()) {
+ if ((A = Args.getLastArg(options::OPT_mzos_target_EQ))) {
+ setZosTargetVersion(D, Target, A->getValue());
+ }
+ }
+
// Handle -miamcu flag.
if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
if (Target.get32BitArchVariant().getArch() != llvm::Triple::x86)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 0d426a467e9a3b..24f8ba447052c1 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -846,6 +846,21 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
if (auto Path = getPathForTriple(getTriple()))
return *Path;
+ if (T.isOSzOS() &&
+ (!T.getOSVersion().empty() || !T.getEnvironmentVersion().empty())) {
+ // Build the triple without version information
+ const llvm::Triple &TripleWithoutVersion =
+ (T.hasEnvironment()
+ ? llvm::Triple(
+ T.getArchName(), T.getVendorName(),
+ llvm::Triple::getOSTypeName(T.getOS()),
+ llvm::Triple::getEnvironmentTypeName(T.getEnvironment()))
+ : llvm::Triple(T.getArchName(), T.getVendorName(),
+ llvm::Triple::getOSTypeName(T.getOS())));
+ if (auto Path = getPathForTriple(TripleWithoutVersion))
+ return *Path;
+ }
+
// When building with per target runtime directories, various ways of naming
// the Arm architecture may have been normalised to simply "arm".
// For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".
diff --git a/clang/test/Preprocessor/zos-target.c b/clang/test/Preprocessor/zos-target.c
new file mode 100644
index 00000000000000..9768812948bfc1
--- /dev/null
+++ b/clang/test/Preprocessor/zos-target.c
@@ -0,0 +1,18 @@
+// REQUIRES: target={{s390x-ibm-zos}}
+
+// In this case we expect __TARGET_LIB__ not to be defined because we don't
+// include any files here, and in particular, any from the LE.
+// RUN: %clang -mzos-target=current -dM -E %s | FileCheck --check-prefix=CURRENT %s
+// CURRENT-NOT: #define __TARGET_LIB__
+
+// RUN: %clang -mzos-target=zosv2r5 -dM -E %s | FileCheck --check-prefix=ZOSVR %s
+// ZOSVR: #define __TARGET_LIB__ 0x42050000
+
+// RUN: %clang -mzos-target=0x4204001f -dM -E %s | FileCheck --check-prefix=HEX %s
+// HEX: #define __TARGET_LIB__ 0x4204001F
+
+// RUN: not %clang -mzos-target=0x42010000 -dM -E %s 2>&1 | FileCheck --check-prefix=ERR-DISCONTINUED %s
+// ERR-DISCONTINUED: z/OS target level "0x42010000" is discontinued. Unexpected behavior might occur if an out-of-support target level is specified. Use z/OS target level "zosv2r4", or later instead
+
+// RUN: not %clang -mzos-target=Rubbish -dM -E %s 2>&1 | FileCheck --check-prefix=ERR-INVALID-ARG %s
+// ERR-INVALID-ARG: "Rubbish" is not recognized as a valid z/OS target level. The z/OS target level must be "current", or of the form "zosvVrR", where "V" is the version and "R" is the release, or given as a "0x"-prefixed eight digit hexadecimal value
>From 5bd29a0c12926e136cf15f18837f37bbdb9bbe0c Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Fri, 17 Jan 2025 15:01:02 -0500
Subject: [PATCH 2/3] build on latest source
---
clang/lib/Basic/Targets/SystemZ.cpp | 1 +
clang/lib/Driver/ToolChain.cpp | 9 +++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index 2c749c0ba76937..2731cb596fd27a 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 9a2f438cc45d22..0da0de2e254948 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -855,7 +855,8 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
return {};
};
- if (auto Path = getPathForTriple(getTriple()))
+ const llvm::Triple &T = getTriple();
+ if (auto Path = getPathForTriple(T))
return *Path;
if (T.isOSzOS() &&
@@ -888,14 +889,14 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
//
// M profile Arm is bare metal and we know they will not be using the per
// target runtime directory layout.
- if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) {
- llvm::Triple ArmTriple = getTriple();
+ if (T.getArch() == Triple::arm && !T.isArmMClass()) {
+ llvm::Triple ArmTriple = T;
ArmTriple.setArch(Triple::arm);
if (auto Path = getPathForTriple(ArmTriple))
return *Path;
}
- if (getTriple().isAndroid())
+ if (T.isAndroid())
return getFallbackAndroidTargetPath(BaseDir);
return {};
>From d532181334436832f74257478d1b7e3610134085 Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Fri, 31 Jan 2025 14:58:06 -0500
Subject: [PATCH 3/3] Simplify & shorten the wording of the messages
---
clang/include/clang/Basic/DiagnosticDriverKinds.td | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 1b679302197a2a..4020861e0d9a01 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -278,9 +278,9 @@ def err_arch_unsupported_isa
: Error<"architecture '%0' does not support '%1' execution mode">;
def err_zos_target_release_discontinued
- : Error<"z/OS target level \"%0\" is discontinued. Unexpected behavior might occur if an out-of-support target level is specified. Use z/OS target level \"zOSv2r4\", or later instead">;
+ : Error<"z/OS target level \"%0\" is discontinued">;
def err_zos_target_unrecognized_release
- : Error<"\"%0\" is not recognized as a valid z/OS target level. The z/OS target level must be \"current\", or of the form \"zosvVrR\", where \"V\" is the version and \"R\" is the release, or given as a \"0x\"-prefixed eight digit hexadecimal value">;
+ : Error<"z/OS target level \"%0\" is invalid">;
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
More information about the cfe-commits
mailing list