https://github.com/pvelesko updated https://github.com/llvm/llvm-project/pull/206902
>From 3973d6b66a239d6d5bee5f751dcb3fe1d3a0e3db Mon Sep 17 00:00:00 2001 From: Paulius Velesko <[email protected]> Date: Tue, 30 Jun 2026 12:59:25 +0300 Subject: [PATCH 1/4] [Darwin] Add regression test for HIP-SPIR-V offload version-init crash HIP-SPIR-V offloading to a Darwin host whose triple carries a Darwin kernel version (e.g. `--target=arm64-apple-darwin24.3.0`) crashes the driver: ensureTargetInitialized() records the kernel version (24.x) via setTarget(), then AddDeploymentTarget() calls setTarget() again with the macOS product version (15.x); the version mismatch trips the "Target already initialized!" assertion. This test fails (clang aborts) on the current behavior and is fixed by the following commit. --- .../test/Driver/darwin-hip-spirv-version.hip | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 clang/test/Driver/darwin-hip-spirv-version.hip diff --git a/clang/test/Driver/darwin-hip-spirv-version.hip b/clang/test/Driver/darwin-hip-spirv-version.hip new file mode 100644 index 0000000000000..7e1ff20e7d662 --- /dev/null +++ b/clang/test/Driver/darwin-hip-spirv-version.hip @@ -0,0 +1,21 @@ +// Regression test: HIP-SPIR-V offloading to a Darwin host whose triple carries +// a Darwin *kernel* version (e.g. darwin24.3.0) must not crash the driver. +// +// The HIP-SPIR-V offload path calls Darwin::ensureTargetInitialized() early. +// It records the deployment version via setTarget(); the later host job calls +// setTarget() again from AddDeploymentTarget(). setTarget()'s reinit guard only +// short-circuits when the two versions match. ensureTargetInitialized() must +// therefore record the converted macOS *product* version (15.x) rather than the +// raw Darwin *kernel* version (24.x); otherwise the second call mismatches and +// trips the "Target already initialized!" assertion. + +// REQUIRES: spirv-registered-target +// UNSUPPORTED: system-windows, system-cygwin + +// RUN: %clang -### -x hip --offload=spirv64 --target=arm64-apple-darwin24.3.0 \ +// RUN: -nogpulib -nogpuinc %s 2>&1 | FileCheck %s + +// The Darwin host -cc1 job uses the converted macOS product version, and the +// driver does not assert/crash. +// CHECK: "-triple" "arm64-apple-macosx{{[0-9.]+}}" +// CHECK-NOT: "-triple" "arm64-apple-darwin >From 56fc4ab25aedb8b5085b2ea5887d3b9900f5f2f8 Mon Sep 17 00:00:00 2001 From: Paulius Velesko <[email protected]> Date: Wed, 1 Jul 2026 12:02:44 +0300 Subject: [PATCH 2/4] [Darwin] Use macOS product version in ensureTargetInitialized Darwin::ensureTargetInitialized() (the lazy target-init helper used by the HIP-SPIR-V offload toolchain) passed setTarget() the raw triple OS version from getOSVersion(). On macOS that is the Darwin *kernel* version (e.g. 24.3.0), not the macOS *product* version (e.g. 15.0.0). When clang later builds the offload host job, AddDeploymentTarget() calls setTarget() again with the product version. setTarget()'s reinit guard only short-circuits when the versions match; 24.3.0 != 15.0.0, so it falls through to assert(!TargetInitialized) and clang aborts on every '-x hip --offload=spirv64* --target=arm64-apple-darwin' compile. Convert macOS kernel versions via getMacOSXVersion() so the lazy init records the same version AddDeploymentTarget() later uses. --- clang/lib/Driver/ToolChains/Darwin.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 64bc96a900f30..de62a7c8ee9c2 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1210,7 +1210,18 @@ void Darwin::ensureTargetInitialized() const { else if (getTriple().isMacCatalystEnvironment()) Environment = MacCatalyst; - VersionTuple OsVer = getTriple().getOSVersion(); + VersionTuple OsVer; + if (Platform == MacOS) { + // Convert a Darwin kernel version (e.g. darwin24.3.0) to the macOS product + // version (e.g. 15.0.0). The raw getOSVersion() returns the kernel version, + // which mismatches the macOS version that AddDeploymentTarget() later + // passes to setTarget(), tripping its "Target already initialized!" + // assertion on the HIP-SPIR-V offload path. + if (!getTriple().getMacOSXVersion(OsVer)) + return; + } else { + OsVer = getTriple().getOSVersion(); + } setTarget(Platform, Environment, OsVer.getMajor(), OsVer.getMinor().value_or(0), OsVer.getSubminor().value_or(0), VersionTuple()); >From a61ef01d8f114e2ec34baf280ebd97c6a615f259 Mon Sep 17 00:00:00 2001 From: Paulius Velesko <[email protected]> Date: Thu, 9 Jul 2026 15:03:31 +0300 Subject: [PATCH 3/4] [Darwin] Tighten ensureTargetInitialized comment and version test Reword the version-conversion comment to state the invariant rather than the bug history, and pin the expected product version (macosx15) in the regression test so it verifies the darwin24->macosx15 mapping, not just the triple spelling. --- clang/lib/Driver/ToolChains/Darwin.cpp | 8 +++----- clang/test/Driver/darwin-hip-spirv-version.hip | 14 ++++---------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index de62a7c8ee9c2..934325a37bc0c 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1212,11 +1212,9 @@ void Darwin::ensureTargetInitialized() const { VersionTuple OsVer; if (Platform == MacOS) { - // Convert a Darwin kernel version (e.g. darwin24.3.0) to the macOS product - // version (e.g. 15.0.0). The raw getOSVersion() returns the kernel version, - // which mismatches the macOS version that AddDeploymentTarget() later - // passes to setTarget(), tripping its "Target already initialized!" - // assertion on the HIP-SPIR-V offload path. + // Record the macOS product version (e.g. macosx15), not the Darwin kernel + // version (e.g. darwin24.3): version checks against the lazily-recorded + // target must behave as if AddDeploymentTarget() had computed it. if (!getTriple().getMacOSXVersion(OsVer)) return; } else { diff --git a/clang/test/Driver/darwin-hip-spirv-version.hip b/clang/test/Driver/darwin-hip-spirv-version.hip index 7e1ff20e7d662..299fff5d08083 100644 --- a/clang/test/Driver/darwin-hip-spirv-version.hip +++ b/clang/test/Driver/darwin-hip-spirv-version.hip @@ -1,13 +1,7 @@ // Regression test: HIP-SPIR-V offloading to a Darwin host whose triple carries -// a Darwin *kernel* version (e.g. darwin24.3.0) must not crash the driver. -// -// The HIP-SPIR-V offload path calls Darwin::ensureTargetInitialized() early. -// It records the deployment version via setTarget(); the later host job calls -// setTarget() again from AddDeploymentTarget(). setTarget()'s reinit guard only -// short-circuits when the two versions match. ensureTargetInitialized() must -// therefore record the converted macOS *product* version (15.x) rather than the -// raw Darwin *kernel* version (24.x); otherwise the second call mismatches and -// trips the "Target already initialized!" assertion. +// a Darwin *kernel* version (e.g. darwin24.3.0) must not crash the driver: +// ensureTargetInitialized() must record the macOS *product* version that +// AddDeploymentTarget() later derives, or setTarget()'s reinit guard asserts. // REQUIRES: spirv-registered-target // UNSUPPORTED: system-windows, system-cygwin @@ -17,5 +11,5 @@ // The Darwin host -cc1 job uses the converted macOS product version, and the // driver does not assert/crash. -// CHECK: "-triple" "arm64-apple-macosx{{[0-9.]+}}" +// CHECK: "-triple" "arm64-apple-macosx15{{[0-9.]*}}" // CHECK-NOT: "-triple" "arm64-apple-darwin >From a0faa08eb7ebd76f77c334dc9c718352d000d0b1 Mon Sep 17 00:00:00 2001 From: Paulius Velesko <[email protected]> Date: Thu, 9 Jul 2026 15:03:45 +0300 Subject: [PATCH 4/4] [Darwin] Let AddDeploymentTarget overwrite a lazily-initialized target ensureTargetInitialized() can only guess the deployment target from the triple, but AddDeploymentTarget() may derive a different version from -mmacosx-version-min, MACOSX_DEPLOYMENT_TARGET, the SDK, or the host system. Any such difference still tripped setTarget()'s "Target already initialized!" assertion on the offload path. Track lazy initialization and let the authoritative setTarget() call overwrite it. --- clang/lib/Driver/ToolChains/Darwin.cpp | 4 +++ clang/lib/Driver/ToolChains/Darwin.h | 16 ++++++++-- .../test/Driver/darwin-hip-spirv-version.hip | 32 +++++++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 934325a37bc0c..0f5635827b84f 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1223,6 +1223,10 @@ void Darwin::ensureTargetInitialized() const { setTarget(Platform, Environment, OsVer.getMajor(), OsVer.getMinor().value_or(0), OsVer.getSubminor().value_or(0), VersionTuple()); + // The version above is a guess from the triple alone; AddDeploymentTarget() + // may later derive a different deployment target from flags, environment + // variables, or the SDK, and overwrite this initialization. + TargetInitializedLazily = true; } AppleMachO::~AppleMachO() {} diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index 97520a89d8042..c41bb6c2eead5 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -355,6 +355,11 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO { // the argument translation business. mutable bool TargetInitialized; + /// Whether the target was lazily initialized from the triple by + /// ensureTargetInitialized() rather than by AddDeploymentTarget(). Such a + /// target is a best-effort guess that setTarget() may overwrite. + mutable bool TargetInitializedLazily = false; + // TODO: Are these useful? Can we use Triple::OSType/EnvironmentType instead? enum DarwinPlatformKind { MacOS, @@ -447,10 +452,17 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO { if (TargetInitialized && TargetPlatform == Platform && TargetEnvironment == Environment && (Environment == MacCatalyst ? OSTargetVersion : TargetVersion) == - VersionTuple(Major, Minor, Micro)) + VersionTuple(Major, Minor, Micro)) { + TargetInitializedLazily = false; return; + } - assert(!TargetInitialized && "Target already initialized!"); + // A lazily-initialized target (see ensureTargetInitialized()) is a + // best-effort guess from the triple alone; the authoritative + // initialization from AddDeploymentTarget() may overwrite it. + assert((!TargetInitialized || TargetInitializedLazily) && + "Target already initialized!"); + TargetInitializedLazily = false; TargetInitialized = true; TargetPlatform = Platform; TargetEnvironment = Environment; diff --git a/clang/test/Driver/darwin-hip-spirv-version.hip b/clang/test/Driver/darwin-hip-spirv-version.hip index 299fff5d08083..754c7a1d079d6 100644 --- a/clang/test/Driver/darwin-hip-spirv-version.hip +++ b/clang/test/Driver/darwin-hip-spirv-version.hip @@ -1,15 +1,33 @@ -// Regression test: HIP-SPIR-V offloading to a Darwin host whose triple carries -// a Darwin *kernel* version (e.g. darwin24.3.0) must not crash the driver: -// ensureTargetInitialized() must record the macOS *product* version that -// AddDeploymentTarget() later derives, or setTarget()'s reinit guard asserts. +// The HIP-SPIR-V offload path lazily initializes the Darwin host target from +// the triple (ensureTargetInitialized) before AddDeploymentTarget() computes +// the authoritative deployment target; a disagreement between the two used to +// trip setTarget()'s "Target already initialized!" assertion. // REQUIRES: spirv-registered-target // UNSUPPORTED: system-windows, system-cygwin +// A Darwin *kernel* version in the triple (darwin24.3.0) is recorded as the +// macOS *product* version (macosx15) and the driver does not crash. // RUN: %clang -### -x hip --offload=spirv64 --target=arm64-apple-darwin24.3.0 \ // RUN: -nogpulib -nogpuinc %s 2>&1 | FileCheck %s - -// The Darwin host -cc1 job uses the converted macOS product version, and the -// driver does not assert/crash. // CHECK: "-triple" "arm64-apple-macosx15{{[0-9.]*}}" // CHECK-NOT: "-triple" "arm64-apple-darwin + +// A deployment target from the environment overrides the lazily-recorded +// triple version instead of asserting. +// RUN: env MACOSX_DEPLOYMENT_TARGET=14.0 %clang -### -x hip \ +// RUN: --offload=spirv64 --target=arm64-apple-darwin24.3.0 \ +// RUN: -nogpulib -nogpuinc %s 2>&1 | FileCheck --check-prefix=DEPLOY %s +// DEPLOY: "-triple" "arm64-apple-macosx14.0.0" + +// Same for -mmacosx-version-min. +// RUN: %clang -### -x hip --offload=spirv64 --target=arm64-apple-darwin24.3.0 \ +// RUN: -mmacosx-version-min=14.0 -nogpulib -nogpuinc %s 2>&1 \ +// RUN: | FileCheck --check-prefix=VERMIN %s +// VERMIN: "-triple" "arm64-apple-macosx14.0.0" + +// An unversioned triple must not crash either; the version is inferred (and +// on a macOS host may differ from the lazily-recorded default). +// RUN: %clang -### -x hip --offload=spirv64 --target=arm64-apple-darwin \ +// RUN: -nogpulib -nogpuinc %s 2>&1 | FileCheck --check-prefix=NOVER %s +// NOVER: "-triple" "arm64-apple-macosx{{[0-9.]+}}" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
