https://github.com/pvelesko updated 
https://github.com/llvm/llvm-project/pull/206902

>From 2ef481e7f54affbc2ca8eb1499a938a66d1682b7 Mon Sep 17 00:00:00 2001
From: Paulius Velesko <[email protected]>
Date: Thu, 9 Jul 2026 16:00:53 +0300
Subject: [PATCH 1/3] [Darwin] Add regression test for HIP-SPIR-V offload
 version-init crash

HIP-SPIR-V offloading to a Darwin host lazily initializes the host
target from the triple (ensureTargetInitialized) before
AddDeploymentTarget() computes the authoritative deployment target; any
disagreement between the two trips setTarget()'s "Target already
initialized!" assertion and aborts the driver:

- the default macOS host triple carries the Darwin *kernel* version
  (darwin24.3.0), which mismatches the macOS *product* version (15.x)
  that AddDeploymentTarget() derives
- a deployment target from MACOSX_DEPLOYMENT_TARGET or
  -mmacosx-version-min mismatches any triple-recorded version
- an unversioned triple mismatches the version inferred from the SDK or
  the host

All four RUN lines abort (assert) on the current behavior and are fixed
by the following commits.
---
 .../test/Driver/darwin-hip-spirv-version.hip  | 33 +++++++++++++++++++
 1 file changed, 33 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..754c7a1d079d6
--- /dev/null
+++ b/clang/test/Driver/darwin-hip-spirv-version.hip
@@ -0,0 +1,33 @@
+// 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
+// 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.]+}}"

>From 1dd6e81f17941ad589f3d2a00df3cbb6db223be5 Mon Sep 17 00:00:00 2001
From: Paulius Velesko <[email protected]>
Date: Thu, 9 Jul 2026 16:01:57 +0300
Subject: [PATCH 2/3] [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()
derives the deployment target again -- for darwin-OS triples the
-target path bails out and the version comes from arch inference via
getInferredOSVersion(), which maps the triple's kernel version to the
product version -- and calls setTarget() with it. 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 derives from the
triple.
---
 clang/lib/Driver/ToolChains/Darwin.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 64bc96a900f30..934325a37bc0c 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1210,7 +1210,16 @@ void Darwin::ensureTargetInitialized() const {
   else if (getTriple().isMacCatalystEnvironment())
     Environment = MacCatalyst;
 
-  VersionTuple OsVer = getTriple().getOSVersion();
+  VersionTuple OsVer;
+  if (Platform == MacOS) {
+    // 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 {
+    OsVer = getTriple().getOSVersion();
+  }
   setTarget(Platform, Environment, OsVer.getMajor(),
             OsVer.getMinor().value_or(0), OsVer.getSubminor().value_or(0),
             VersionTuple());

>From 0a6411e89a0e38893a671ca868540d606a1b20cb Mon Sep 17 00:00:00 2001
From: Paulius Velesko <[email protected]>
Date: Thu, 9 Jul 2026 16:02:34 +0300
Subject: [PATCH 3/3] [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 ++++++++++++++--
 2 files changed, 18 insertions(+), 2 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;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to