https://github.com/schittir updated https://github.com/llvm/llvm-project/pull/215620
>From e465e699bacb7e0be98902a68a7c53c04270f32f Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Tue, 11 Aug 2026 10:05:44 -0700 Subject: [PATCH 1/8] [clang] Diagnose host/device pointer width mismatches in offload compilations SPIR, physical SPIR-V, and NVPTX device targets take their pointer related types from the host target, so a host whose pointer width differs from the device's leaves size_t, ptrdiff_t, and intptr_t inconsistent with the device data layout. Such pairings were previously accepted and silently miscompiled. This patch diagnoses these invalid combinations by calling the diagnostic at: 1. Driver::CreateOffloadingDeviceToolChains(), covering --offload=, --offload-targets=, and -fsycl. 2. TargetInfo::CreateTargetInfo(), covering -cc1 -triple X -aux-triple Y and anything else that bypasses the driver. This is the follow-up to #208196, as discussed during review. --- clang/docs/ReleaseNotes.md | 6 +++ .../clang/Basic/DiagnosticCommonKinds.td | 3 ++ clang/lib/Basic/Targets.cpp | 24 +++++++++ clang/lib/Basic/Targets/SPIR.h | 50 +++++++++++-------- clang/lib/Driver/Driver.cpp | 16 ++++++ clang/test/CodeGenCUDA/anon-ns.cu | 4 +- clang/test/CodeGenCUDA/long-double.cu | 2 +- .../CodeGenCUDASPIRV/copy-aggregate-byval.cu | 4 +- .../test/CodeGenCUDASPIRV/kernel-argument.cu | 4 +- .../CodeGenSYCL/kernel-caller-entry-point.cpp | 9 ---- clang/test/Driver/cuda-device-triple.cu | 2 +- clang/test/Frontend/sycl-aux-triple.cpp | 4 +- clang/test/SemaCUDA/allow-int128.cu | 2 +- .../SemaCUDA/cuda-inherits-calling-conv.cu | 2 +- ...v-implicit-alloc-function-calling-conv.hip | 2 - 15 files changed, 91 insertions(+), 43 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 2f13ec59483ee4..d1651cdb925815 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -51,6 +51,12 @@ The previous behavior can be restored with `-Wno-error=unicode-whitespace`. Clang will stop accepting non-ascii whitespaces as token separators in a future version of Clang. +- Offload compilations that pair a SPIR, physical SPIR-V, or NVPTX device target + with a host of a different pointer width are now rejected, for example + `--offload=spirv32` with an `x86_64` host. These targets take `size_t`, + `ptrdiff_t`, and `intptr_t` from the host, so a mismatch disagreed with the + device data layout. Select a device target whose width matches the host's. + ### C++ Specific Potentially Breaking Changes ### ABI Changes in This Version diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 192fdf9299eb44..ece27b02f840ee 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -338,6 +338,9 @@ def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def note_valid_options : Note<"valid target CPU values are: %0">; def err_target_unsupported_cpu_for_micromips : Error< "micromips is not supported for target CPU '%0'">; +def err_target_unsupported_host_device_pointer_width : Error< + "device target '%0' with %1-bit pointers is incompatible with host target " + "'%2' with %3-bit pointers">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">; def err_target_unsupported_abi_for_triple : Error< diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 8c01cfca8ccb48..a939eb9b944707 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -835,6 +835,15 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, } // namespace clang using namespace clang::targets; + +/// Returns true if Triple names a target that takes its pointer related types +/// from a host target. Logical SPIR-V is excluded; it uses fixed values for +/// those types regardless of the host. +static bool adaptsToHostTarget(const llvm::Triple &Triple) { + return (Triple.isSPIROrSPIRV() && Triple.getArch() != llvm::Triple::spirv) || + Triple.isNVPTX(); +} + /// CreateTargetInfo - Return the target info object for the specified target /// options. TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, @@ -843,6 +852,21 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, llvm::Triple Triple(llvm::Triple::normalize(Opts->Triple)); + // Host and device pointer related type widths must match. Reject a mismatch + // before constructing the device target, which asserts on this. + if (adaptsToHostTarget(Triple) && !Opts->HostTriple.empty()) { + llvm::Triple HostTriple(llvm::Triple::normalize(Opts->HostTriple)); + if (!adaptsToHostTarget(HostTriple) && + HostTriple.getArch() != llvm::Triple::UnknownArch && + Triple.getArchPointerBitWidth() != + HostTriple.getArchPointerBitWidth()) { + Diags.Report(diag::err_target_unsupported_host_device_pointer_width) + << Triple.str() << Triple.getArchPointerBitWidth() << HostTriple.str() + << HostTriple.getArchPointerBitWidth(); + return nullptr; + } + } + // Construct the target std::unique_ptr<TargetInfo> Target = AllocateTarget(Triple, *Opts); if (!Target) { diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 20d8efdc832343..17f90e80dc5fdd 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -254,16 +254,18 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { : SPIRTargetInfo(Triple, Opts) { assert(Triple.getArch() == llvm::Triple::spir && "Invalid architecture for 32-bit SPIR."); - // FIXME: Assert that a present host target's pointer types match the ones - // set below, once the driver diagnoses unsupported host/device combinations - // (until then such an assert would fire on existing tests). PointerWidth = PointerAlign = 32; - const TargetInfo *HostTarget = getHostTarget(); - if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 32) { + if (!getHostTarget()) { SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; } + // Host and device pointer related type widths must match. + assert(PointerWidth == 32 && PointerAlign == 32 && + getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 && + getTypeWidth(IntPtrType) == 32 && + "Invalid pointer related types for SPIR32"); + // SPIR32 has support for atomic ops if atomic extension is enabled. // Take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); @@ -281,16 +283,18 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo { : SPIRTargetInfo(Triple, Opts) { assert(Triple.getArch() == llvm::Triple::spir64 && "Invalid architecture for 64-bit SPIR."); - // FIXME: Assert that a present host target's pointer types match the ones - // set below, once the driver diagnoses unsupported host/device combinations - // (until then such an assert would fire on existing tests). PointerWidth = PointerAlign = 64; - const TargetInfo *HostTarget = getHostTarget(); - if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 64) { + if (!getHostTarget()) { SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; } + // Host and device pointer related type widths must match. + assert(PointerWidth == 64 && PointerAlign == 64 && + getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 && + getTypeWidth(IntPtrType) == 64 && + "Invalid pointer related types for SPIR64"); + // SPIR64 has support for atomic ops if atomic extension is enabled. // Take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); @@ -379,15 +383,18 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo { "32-bit SPIR-V target must use unknown, chipstar, or vulkan OS"); assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && "32-bit SPIR-V target must use unknown environment type"); - // FIXME: Assert that a present host target's pointer types match the ones - // set below, once the driver diagnoses unsupported host/device combinations - // (until then such an assert would fire on existing tests). PointerWidth = PointerAlign = 32; - const TargetInfo *HostTarget = getHostTarget(); - if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 32) { + if (!getHostTarget()) { SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; } + + // Host and device pointer related type widths must match. + assert(PointerWidth == 32 && PointerAlign == 32 && + getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 && + getTypeWidth(IntPtrType) == 32 && + "Invalid pointer related types for SPIR-V 32"); + // SPIR-V has core support for atomic ops, and Int32 is always available; // we take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); @@ -410,15 +417,18 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo { "64-bit SPIR-V target must use unknown, chipstar, or vulkan OS"); assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && "64-bit SPIR-V target must use unknown environment type"); - // FIXME: Assert that a present host target's pointer types match the ones - // set below, once the driver diagnoses unsupported host/device combinations - // (until then such an assert would fire on existing tests). PointerWidth = PointerAlign = 64; - const TargetInfo *HostTarget = getHostTarget(); - if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 64) { + if (!getHostTarget()) { SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; } + + // Host and device pointer related type widths must match. + assert(PointerWidth == 64 && PointerAlign == 64 && + getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 && + getTypeWidth(IntPtrType) == 64 && + "Invalid pointer related types for SPIR-V 64"); + // SPIR-V has core support for atomic ops, and Int64 is always available; // we take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 3b5d0c0aad9819..cf7e49932a1a25 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1129,6 +1129,22 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, continue; } + const llvm::Triple &HostTriple = C.getDefaultToolChain().getTriple(); + // Logical SPIR-V is excluded; it overrides those types with fixed values. + auto AdaptsToHostTarget = [](const llvm::Triple &T) { + return (T.isSPIROrSPIRV() && T.getArch() != llvm::Triple::spirv) || + T.isNVPTX(); + }; + // Target and host pointer related type widths must match. + if (AdaptsToHostTarget(Target) && !AdaptsToHostTarget(HostTriple) && + Target.getArchPointerBitWidth() != + HostTriple.getArchPointerBitWidth()) { + Diag(diag::err_target_unsupported_host_device_pointer_width) + << Target.str() << Target.getArchPointerBitWidth() + << HostTriple.str() << HostTriple.getArchPointerBitWidth(); + continue; + } + std::string NormalizedName = Target.normalize(); auto [TripleIt, Inserted] = FoundNormalizedTriples.try_emplace(NormalizedName, Target.str()); diff --git a/clang/test/CodeGenCUDA/anon-ns.cu b/clang/test/CodeGenCUDA/anon-ns.cu index 651a20c653458c..e2b290bd21c3d5 100644 --- a/clang/test/CodeGenCUDA/anon-ns.cu +++ b/clang/test/CodeGenCUDA/anon-ns.cu @@ -11,12 +11,12 @@ // RUN: echo "GPU binary" > %t.fatbin -// RUN: %clang_cc1 -triple nvptx -fcuda-is-device -cuid=abc \ +// RUN: %clang_cc1 -triple nvptx64 -fcuda-is-device -cuid=abc \ // RUN: -aux-triple x86_64-unknown-linux-gnu -std=c++17 -fgpu-rdc \ // RUN: -emit-llvm -o - %s > %t.dev // RUN: %clang_cc1 -triple x86_64-gnu-linux -cuid=abc \ -// RUN: -aux-triple nvptx -std=c++17 -fgpu-rdc -fcuda-include-gpubinary %t.fatbin \ +// RUN: -aux-triple nvptx64 -std=c++17 -fgpu-rdc -fcuda-include-gpubinary %t.fatbin \ // RUN: -emit-llvm -o - %s > %t.host // RUN: cat %t.dev %t.host | FileCheck -check-prefixes=CUDA,COMMON %s diff --git a/clang/test/CodeGenCUDA/long-double.cu b/clang/test/CodeGenCUDA/long-double.cu index b4116c0b815944..0a06fbe5db6d07 100644 --- a/clang/test/CodeGenCUDA/long-double.cu +++ b/clang/test/CodeGenCUDA/long-double.cu @@ -6,7 +6,7 @@ // RUN: -aux-triple x86_64-unknown-gnu-linux -fcuda-is-device \ // RUN: -emit-llvm -o - -x hip %s 2>&1 | FileCheck %s -// RUN: %clang_cc1 -triple nvptx \ +// RUN: %clang_cc1 -triple nvptx64 \ // RUN: -aux-triple x86_64-unknown-gnu-linux -fcuda-is-device \ // RUN: -emit-llvm -o - %s 2>&1 | FileCheck %s diff --git a/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu b/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu index 2692ce4c92b288..fa6521b1fa5e3f 100644 --- a/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu +++ b/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu @@ -2,12 +2,12 @@ // destructor, copy constructor or move constructor defined by user. // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv32 \ -// RUN: -nocudalib -nocudainc %s -o %t.bc -c 2>&1 +// RUN: --target=i386-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc -c 2>&1 // RUN: llvm-dis %t.bc -o %t.ll // RUN: FileCheck %s --input-file=%t.ll // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv64 \ -// RUN: -nocudalib -nocudainc %s -o %t.bc -c 2>&1 +// RUN: --target=x86_64-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc -c 2>&1 // RUN: llvm-dis %t.bc -o %t.ll // RUN: FileCheck %s --input-file=%t.ll diff --git a/clang/test/CodeGenCUDASPIRV/kernel-argument.cu b/clang/test/CodeGenCUDASPIRV/kernel-argument.cu index ab885eb3d85c4a..8ec47949d0092f 100644 --- a/clang/test/CodeGenCUDASPIRV/kernel-argument.cu +++ b/clang/test/CodeGenCUDASPIRV/kernel-argument.cu @@ -2,12 +2,12 @@ // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv32 \ -// RUN: -nocudalib -nocudainc %s -o %t.bc -c 2>&1 +// RUN: --target=i386-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc -c 2>&1 // RUN: llvm-dis %t.bc -o %t.ll // RUN: FileCheck %s --input-file=%t.ll // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv64 \ -// RUN: -nocudalib -nocudainc %s -o %t.bc -c 2>&1 +// RUN: --target=x86_64-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc -c 2>&1 // RUN: llvm-dis %t.bc -o %t.ll // RUN: FileCheck %s --input-file=%t.ll diff --git a/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp b/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp index cc751cc683b594..bbbf4c037f7609 100644 --- a/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp +++ b/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp @@ -1,26 +1,17 @@ // RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64-unknown-linux-gnu -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-HOST,CHECK-HOST-LINUX %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple amdgpu-amd-amdhsa -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-AMDGCN %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple nvptx-nvidia-cuda -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple nvptx64-nvidia-cuda -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple spir-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple spir64-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple spirv32-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-unknown-linux-gnu -triple spirv64-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s // RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64-pc-windows-msvc -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-HOST,CHECK-HOST-WINDOWS %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple amdgpu-amd-amdhsa -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-AMDGCN %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple nvptx-nvidia-cuda -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple nvptx64-nvidia-cuda -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple spir-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple spir64-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple spirv32-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-pc-windows-msvc -triple spirv64-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s // RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64-uefi -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-HOST,CHECK-HOST-WINDOWS %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple amdgpu-amd-amdhsa -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-AMDGCN %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple nvptx-nvidia-cuda -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple nvptx64-nvidia-cuda -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple spir-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple spir64-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple spirv32-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple spirv64-unknown-unknown -std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s // Test code generation for functions declared with the sycl_kernel_entry_point diff --git a/clang/test/Driver/cuda-device-triple.cu b/clang/test/Driver/cuda-device-triple.cu index 8acd4585b8c828..5abdcbf2b7381a 100644 --- a/clang/test/Driver/cuda-device-triple.cu +++ b/clang/test/Driver/cuda-device-triple.cu @@ -1,4 +1,4 @@ -// RUN: %clang -### -emit-llvm --cuda-device-only \ +// RUN: %clang -### -emit-llvm --cuda-device-only --target=i386-unknown-linux-gnu \ // RUN: -nocudalib -nocudainc --offload=spirv32-unknown-unknown -c %s 2>&1 | FileCheck %s // Make sure there's no sm_* suffix on the output name diff --git a/clang/test/Frontend/sycl-aux-triple.cpp b/clang/test/Frontend/sycl-aux-triple.cpp index 38b6a24fb3ce99..2ab23fd1cf7e80 100644 --- a/clang/test/Frontend/sycl-aux-triple.cpp +++ b/clang/test/Frontend/sycl-aux-triple.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple spir -aux-triple x86_64-unknown-linux-gnu -E -dM | FileCheck %s -// RUN: %clang_cc1 %s -fsycl-is-device -triple spir -aux-triple x86_64-unknown-linux-gnu -E -dM | FileCheck --check-prefix=CHECK-SYCL %s +// RUN: %clang_cc1 %s -triple spir64 -aux-triple x86_64-unknown-linux-gnu -E -dM | FileCheck %s +// RUN: %clang_cc1 %s -fsycl-is-device -triple spir64 -aux-triple x86_64-unknown-linux-gnu -E -dM | FileCheck --check-prefix=CHECK-SYCL %s // CHECK-NOT:#define __x86_64__ 1 // CHECK-SYCL:#define __x86_64__ 1 diff --git a/clang/test/SemaCUDA/allow-int128.cu b/clang/test/SemaCUDA/allow-int128.cu index 44f8fefa3aa051..5d2f484bcd44d9 100644 --- a/clang/test/SemaCUDA/allow-int128.cu +++ b/clang/test/SemaCUDA/allow-int128.cu @@ -4,7 +4,7 @@ // RUN: %clang_cc1 -triple spirv64-amd-amdhsa \ // RUN: -aux-triple x86_64-unknown-linux-gnu \ // RUN: -fcuda-is-device -verify -fsyntax-only %s -// RUN: %clang_cc1 -triple nvptx \ +// RUN: %clang_cc1 -triple nvptx64 \ // RUN: -aux-triple x86_64-unknown-linux-gnu \ // RUN: -fcuda-is-device -verify -fsyntax-only %s diff --git a/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu b/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu index a6928e71f3ae09..a4a6292e012e44 100644 --- a/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu +++ b/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu @@ -5,7 +5,7 @@ // RUN: -aux-triple i386-windows-msvc -fsyntax-only \ // RUN: -fcuda-is-device -verify %s -// RUN: %clang_cc1 -std=c++11 -triple nvptx-nvidia-cuda \ +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda \ // RUN: -aux-triple x86_64-linux-gnu -fsyntax-only \ // RUN: -fcuda-is-device -verify -verify-ignore-unexpected=note \ // RUN: -DEXPECT_ERR %s diff --git a/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip b/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip index c3e7e1a5cd59ee..66bf9b359e65ad 100644 --- a/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip +++ b/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip @@ -1,10 +1,8 @@ // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa -verify -// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple x86_64-unknown-linux-gnu -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple x86_64-unknown-linux-gnu -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa -aux-triple x86_64-unknown-linux-gnu -verify -// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple x86_64-pc-windows-msvc -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple x86_64-pc-windows-msvc -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa -aux-triple x86_64-pc-windows-msvc -verify >From 306f69d8643631f04d935f9b3834f1031f61576a Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Fri, 28 Aug 2026 10:44:07 -0700 Subject: [PATCH 2/8] Diagnose other type and size mismatches in addition to pointer width --- clang/docs/ReleaseNotes.md | 9 ++- .../clang/Basic/DiagnosticCommonKinds.td | 7 +- clang/include/clang/Basic/TargetInfo.h | 30 +++++++ clang/lib/Basic/Targets.cpp | 79 ++++++++++++++----- clang/lib/Basic/Targets/SPIR.h | 32 +------- clang/lib/Driver/Driver.cpp | 18 ++--- clang/lib/Frontend/CompilerInstance.cpp | 8 +- clang/test/Driver/hip-autolink.hip | 6 +- clang/test/SemaCUDA/amdgpu-bf16.cu | 4 +- 9 files changed, 121 insertions(+), 72 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index d1651cdb925815..42f52a2fd1a835 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -51,11 +51,12 @@ The previous behavior can be restored with `-Wno-error=unicode-whitespace`. Clang will stop accepting non-ascii whitespaces as token separators in a future version of Clang. -- Offload compilations that pair a SPIR, physical SPIR-V, or NVPTX device target - with a host of a different pointer width are now rejected, for example - `--offload=spirv32` with an `x86_64` host. These targets take `size_t`, +- Offload compilations that pair a SPIR, physical SPIR-V, NVPTX, or AMDGPU device + target with an incompatible host target are now rejected, for example + `--offload=spirv32` with an `x86_64` host, or `--offload-arch=gfx906` with an + `i386` host. These targets take the pointer width and alignment, `size_t`, `ptrdiff_t`, and `intptr_t` from the host, so a mismatch disagreed with the - device data layout. Select a device target whose width matches the host's. + device data layout. Select a host and device target that agree on those types. ### C++ Specific Potentially Breaking Changes diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index ece27b02f840ee..bbf9882ffda069 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -338,9 +338,10 @@ def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def note_valid_options : Note<"valid target CPU values are: %0">; def err_target_unsupported_cpu_for_micromips : Error< "micromips is not supported for target CPU '%0'">; -def err_target_unsupported_host_device_pointer_width : Error< - "device target '%0' with %1-bit pointers is incompatible with host target " - "'%2' with %3-bit pointers">; +def err_target_unsupported_host_pointer_related_type : Error< + "device target '%0' takes %select{a pointer width|a pointer alignment|" + "a 'size_t' width|a 'ptrdiff_t' width|an 'intptr_t' width}2 of %3 bits from " + "host target '%1', but requires %4 bits">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">; def err_target_unsupported_abi_for_triple : Error< diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 6311b6b567a5e1..f0f5bf735ae953 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -327,6 +327,36 @@ class TargetInfo : public TransferrableTargetInfo, static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags, TargetOptions &Opts); + /// When a device target takes its pointer related types (the pointer width + /// and alignment, size_t, ptrdiff_t, and intptr_t) from a host target. + enum class HostAdaptation { + /// It keeps its own pointer related types. + None, + /// It adapts in its constructor, from TargetOptions::HostTriple. + Constructor, + SetAuxTarget, + }; + + /// Returns when the device target takes its pointer related types from the + /// host target, mirroring the conditions under which the TargetInfo + /// subclasses adapt. A device that declines a host keeps its own types, which + /// the driver's triple level check must not report as a mismatch. + static HostAdaptation getHostAdaptation(const llvm::Triple &DeviceTriple, + const llvm::Triple &HostTriple); + + static bool adaptsToHostTarget(const llvm::Triple &DeviceTriple, + const llvm::Triple &HostTriple) { + return getHostAdaptation(DeviceTriple, HostTriple) != HostAdaptation::None; + } + + /// Reports an error if this target adapts to the given host target at the + /// given stage and ended up with pointer related types that disagree with its + /// own data layout. Does nothing if it does not adapt at that stage. Returns + /// true if no error was reported. + bool checkHostPointerRelatedTypes(DiagnosticsEngine &Diags, + const llvm::Triple &HostTriple, + HostAdaptation Stage) const; + virtual ~TargetInfo(); /// Retrieve the target options. diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index a939eb9b944707..ed48400a947f96 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -836,12 +836,59 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, using namespace clang::targets; -/// Returns true if Triple names a target that takes its pointer related types -/// from a host target. Logical SPIR-V is excluded; it uses fixed values for -/// those types regardless of the host. -static bool adaptsToHostTarget(const llvm::Triple &Triple) { - return (Triple.isSPIROrSPIRV() && Triple.getArch() != llvm::Triple::spirv) || - Triple.isNVPTX(); +TargetInfo::HostAdaptation +TargetInfo::getHostAdaptation(const llvm::Triple &DeviceTriple, + const llvm::Triple &HostTriple) { + // No recognizable host triple, so nothing to adapt to. + if (HostTriple.getArch() == llvm::Triple::UnknownArch) + return HostAdaptation::None; + + // setAuxTarget() overwrites these, so constructor values are not yet final. + if (DeviceTriple.isAMDGPU() || + (DeviceTriple.getArch() == llvm::Triple::spirv64 && + DeviceTriple.getOS() == llvm::Triple::AMDHSA)) + return HostAdaptation::SetAuxTarget; + + // Logical SPIR-V sets these itself, with a 32-bit size_t by design. + if (DeviceTriple.isSPIRVLogical()) + return HostAdaptation::None; + + if (DeviceTriple.isSPIROrSPIRV()) + return HostTriple.isSPIROrSPIRV() ? HostAdaptation::None + : HostAdaptation::Constructor; + if (DeviceTriple.isNVPTX()) + return HostTriple.isNVPTX() ? HostAdaptation::None + : HostAdaptation::Constructor; + + return HostAdaptation::None; +} + +bool TargetInfo::checkHostPointerRelatedTypes(DiagnosticsEngine &Diags, + const llvm::Triple &HostTriple, + HostAdaptation Stage) const { + assert(Stage != HostAdaptation::None && "Nothing to check"); + if (getHostAdaptation(getTriple(), HostTriple) != Stage) + return true; + + // The device data layout fixes the width of every one of these types. + unsigned Required = getTriple().getArchPointerBitWidth(); + // The order matches the %select in the diagnostic below. + unsigned Widths[] = {getPointerWidth(LangAS::Default), + getPointerAlign(LangAS::Default), + getTypeWidth(getSizeType()), + getTypeWidth(getPtrDiffType(LangAS::Default)), + getTypeWidth(getIntPtrType())}; + + for (auto [Which, Width] : llvm::enumerate(Widths)) { + if (Width != Required) { + Diags.Report(diag::err_target_unsupported_host_pointer_related_type) + << getTriple().str() << HostTriple.str() + << static_cast<unsigned>(Which) << Width << Required; + return false; + } + } + + return true; } /// CreateTargetInfo - Return the target info object for the specified target @@ -852,21 +899,6 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, llvm::Triple Triple(llvm::Triple::normalize(Opts->Triple)); - // Host and device pointer related type widths must match. Reject a mismatch - // before constructing the device target, which asserts on this. - if (adaptsToHostTarget(Triple) && !Opts->HostTriple.empty()) { - llvm::Triple HostTriple(llvm::Triple::normalize(Opts->HostTriple)); - if (!adaptsToHostTarget(HostTriple) && - HostTriple.getArch() != llvm::Triple::UnknownArch && - Triple.getArchPointerBitWidth() != - HostTriple.getArchPointerBitWidth()) { - Diags.Report(diag::err_target_unsupported_host_device_pointer_width) - << Triple.str() << Triple.getArchPointerBitWidth() << HostTriple.str() - << HostTriple.getArchPointerBitWidth(); - return nullptr; - } - } - // Construct the target std::unique_ptr<TargetInfo> Target = AllocateTarget(Triple, *Opts); if (!Target) { @@ -875,6 +907,11 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, } Target->TargetOpts = Opts; + // Targets that adapt in their constructor have done so by now. + if (!Target->checkHostPointerRelatedTypes( + Diags, llvm::Triple(Opts->HostTriple), HostAdaptation::Constructor)) + return nullptr; + // Set the target CPU if specified. if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) { Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU; diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 17f90e80dc5fdd..b5400cddf575c6 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -254,18 +254,12 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { : SPIRTargetInfo(Triple, Opts) { assert(Triple.getArch() == llvm::Triple::spir && "Invalid architecture for 32-bit SPIR."); - PointerWidth = PointerAlign = 32; if (!getHostTarget()) { + PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; } - // Host and device pointer related type widths must match. - assert(PointerWidth == 32 && PointerAlign == 32 && - getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 && - getTypeWidth(IntPtrType) == 32 && - "Invalid pointer related types for SPIR32"); - // SPIR32 has support for atomic ops if atomic extension is enabled. // Take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); @@ -283,18 +277,12 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo { : SPIRTargetInfo(Triple, Opts) { assert(Triple.getArch() == llvm::Triple::spir64 && "Invalid architecture for 64-bit SPIR."); - PointerWidth = PointerAlign = 64; if (!getHostTarget()) { + PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; } - // Host and device pointer related type widths must match. - assert(PointerWidth == 64 && PointerAlign == 64 && - getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 && - getTypeWidth(IntPtrType) == 64 && - "Invalid pointer related types for SPIR64"); - // SPIR64 has support for atomic ops if atomic extension is enabled. // Take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); @@ -383,18 +371,12 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo { "32-bit SPIR-V target must use unknown, chipstar, or vulkan OS"); assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && "32-bit SPIR-V target must use unknown environment type"); - PointerWidth = PointerAlign = 32; if (!getHostTarget()) { + PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; } - // Host and device pointer related type widths must match. - assert(PointerWidth == 32 && PointerAlign == 32 && - getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 && - getTypeWidth(IntPtrType) == 32 && - "Invalid pointer related types for SPIR-V 32"); - // SPIR-V has core support for atomic ops, and Int32 is always available; // we take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); @@ -417,18 +399,12 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo { "64-bit SPIR-V target must use unknown, chipstar, or vulkan OS"); assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && "64-bit SPIR-V target must use unknown environment type"); - PointerWidth = PointerAlign = 64; if (!getHostTarget()) { + PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; } - // Host and device pointer related type widths must match. - assert(PointerWidth == 64 && PointerAlign == 64 && - getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 && - getTypeWidth(IntPtrType) == 64 && - "Invalid pointer related types for SPIR-V 64"); - // SPIR-V has core support for atomic ops, and Int64 is always available; // we take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index cf7e49932a1a25..f90c2804b805c4 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -55,6 +55,7 @@ #include "ToolChains/ZOS.h" #include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/TargetID.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -1129,19 +1130,16 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, continue; } + // A triple level approximation that catches the common cases early; the + // types are checked once the device adapts. const llvm::Triple &HostTriple = C.getDefaultToolChain().getTriple(); - // Logical SPIR-V is excluded; it overrides those types with fixed values. - auto AdaptsToHostTarget = [](const llvm::Triple &T) { - return (T.isSPIROrSPIRV() && T.getArch() != llvm::Triple::spirv) || - T.isNVPTX(); - }; - // Target and host pointer related type widths must match. - if (AdaptsToHostTarget(Target) && !AdaptsToHostTarget(HostTriple) && + if (TargetInfo::adaptsToHostTarget(Target, HostTriple) && Target.getArchPointerBitWidth() != HostTriple.getArchPointerBitWidth()) { - Diag(diag::err_target_unsupported_host_device_pointer_width) - << Target.str() << Target.getArchPointerBitWidth() - << HostTriple.str() << HostTriple.getArchPointerBitWidth(); + Diag(diag::err_target_unsupported_host_pointer_related_type) + << Target.str() << HostTriple.str() << /*pointer width*/ 0 + << HostTriple.getArchPointerBitWidth() + << Target.getArchPointerBitWidth(); continue; } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 66662a786e6fca..7a7373b82ebb9a 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -167,9 +167,15 @@ bool CompilerInstance::createTarget() { // created. This complexity should be lifted elsewhere. getTarget().adjust(getDiagnostics(), getLangOpts(), getAuxTarget()); - if (auto *Aux = getAuxTarget()) + if (auto *Aux = getAuxTarget()) { getTarget().setAuxTarget(Aux); + if (!getTarget().checkHostPointerRelatedTypes( + getDiagnostics(), Aux->getTriple(), + TargetInfo::HostAdaptation::SetAuxTarget)) + return false; + } + return true; } diff --git a/clang/test/Driver/hip-autolink.hip b/clang/test/Driver/hip-autolink.hip index cce3977375d2e0..e37c6e5d7e5029 100644 --- a/clang/test/Driver/hip-autolink.hip +++ b/clang/test/Driver/hip-autolink.hip @@ -1,10 +1,10 @@ -// RUN: %clang --target=i386-pc-windows-msvc --cuda-gpu-arch=gfx906 -nogpulib -nogpuinc \ +// RUN: %clang --target=x86_64-pc-windows-msvc --cuda-gpu-arch=gfx906 -nogpulib -nogpuinc \ // RUN: --cuda-device-only %s -### 2>&1 | FileCheck --check-prefix=DEV %s -// RUN: %clang --target=i386-pc-windows-msvc --cuda-gpu-arch=gfx906 -nogpulib -nogpuinc \ +// RUN: %clang --target=x86_64-pc-windows-msvc --cuda-gpu-arch=gfx906 -nogpulib -nogpuinc \ // RUN: --cuda-host-only %s -### 2>&1 | FileCheck --check-prefix=HOST %s // DEV: "-cc1" "-triple" "amdgcn-amd-amdhsa" // DEV-SAME: "-fno-autolink" -// HOST: "-cc1" "-triple" "i386-pc-windows-msvc{{.*}}" +// HOST: "-cc1" "-triple" "x86_64-pc-windows-msvc{{.*}}" // HOST-NOT: "-fno-autolink" diff --git a/clang/test/SemaCUDA/amdgpu-bf16.cu b/clang/test/SemaCUDA/amdgpu-bf16.cu index 0b5ce1a4f64cf5..b14a3dd608aeb2 100644 --- a/clang/test/SemaCUDA/amdgpu-bf16.cu +++ b/clang/test/SemaCUDA/amdgpu-bf16.cu @@ -1,8 +1,8 @@ // REQUIRES: amdgpu-registered-target // REQUIRES: x86-registered-target -// RUN: %clang_cc1 "-aux-triple" "x86_64-unknown-linux-gnu" "-triple" "r600-unknown-unknown"\ -// RUN: -fcuda-is-device "-aux-target-cpu" "x86-64" -fsyntax-only -verify=r600 %s +// RUN: %clang_cc1 "-aux-triple" "i386-unknown-linux-gnu" "-triple" "r600-unknown-unknown"\ +// RUN: -fcuda-is-device "-aux-target-cpu" "i686" -fsyntax-only -verify=r600 %s // AMDGCN has storage-only support for bf16. R600 does not support it should error out when // it's the main target. >From 8aa1d9a9082399bb2350654cc708b16a61884fe3 Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Fri, 28 Aug 2026 12:43:03 -0700 Subject: [PATCH 3/8] Static cast to unsigned. --- clang/lib/Basic/Targets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index ed48400a947f96..a328f175b5afc4 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -873,8 +873,8 @@ bool TargetInfo::checkHostPointerRelatedTypes(DiagnosticsEngine &Diags, // The device data layout fixes the width of every one of these types. unsigned Required = getTriple().getArchPointerBitWidth(); // The order matches the %select in the diagnostic below. - unsigned Widths[] = {getPointerWidth(LangAS::Default), - getPointerAlign(LangAS::Default), + unsigned Widths[] = {static_cast<unsigned>(getPointerWidth(LangAS::Default)), + static_cast<unsigned>(getPointerAlign(LangAS::Default)), getTypeWidth(getSizeType()), getTypeWidth(getPtrDiffType(LangAS::Default)), getTypeWidth(getIntPtrType())}; >From 67dfe736a64ab5cb021b69a45b85b831b9924cc1 Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Mon, 31 Aug 2026 19:35:26 -0700 Subject: [PATCH 4/8] [clang] Add tests for the host/device pointer related type diagnostic Add the driver and frontend tests for the diagnostic, and adapt two existing tests that pair a 64-bit device target with a 32-bit host: Preprocessor/init-amdgpu.c and SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip --- .../Driver/offload-pointer-width-mismatch.c | 31 +++++++ .../offload-pointer-width-mismatch.cpp | 93 +++++++++++++++++++ clang/test/Preprocessor/init-amdgpu.c | 2 +- ...mdgcnspirv-host-cconv-in-abstract-type.hip | 1 - 4 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 clang/test/Driver/offload-pointer-width-mismatch.c create mode 100644 clang/test/Frontend/offload-pointer-width-mismatch.cpp diff --git a/clang/test/Driver/offload-pointer-width-mismatch.c b/clang/test/Driver/offload-pointer-width-mismatch.c new file mode 100644 index 00000000000000..98fd079d5edae8 --- /dev/null +++ b/clang/test/Driver/offload-pointer-width-mismatch.c @@ -0,0 +1,31 @@ +// Offload targets that take their pointer related types from the host target +// are rejected early, before any compilation job is built. + +// RUN: not %clang -### --target=i386-unknown-linux-gnu -x hip --offload-arch=gfx906 \ +// RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s +// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda --offload=nvptx64-nvidia-cuda \ +// RUN: --offload-arch=sm_60 -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=NVPTX %s +// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -x cuda --cuda-device-only \ +// RUN: -nogpulib -nogpuinc --offload=spirv32-unknown-unknown -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=SPIRV32 %s +// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda \ +// RUN: --offload-targets=nvptx64-nvidia-cuda --offload-arch=sm_60 -nogpulib -nogpuinc \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=NVPTX %s + +// OpenMP offloading reaches the same check. + +// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp \ +// RUN: -fopenmp-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=NVPTX %s +// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp --offload-arch=gfx906 \ +// RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s + +// AMDGPU: error: device target 'amdgpu-amd-amdhsa' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits +// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits +// SPIRV32: error: device target 'spirv32-unknown-unknown' takes a pointer width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits + +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -x hip --offload-arch=gfx906 \ +// RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=OK %s + +// OK-NOT: error: +// OK: "-cc1" "-triple" "amdgpu9.06-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu" diff --git a/clang/test/Frontend/offload-pointer-width-mismatch.cpp b/clang/test/Frontend/offload-pointer-width-mismatch.cpp new file mode 100644 index 00000000000000..4d1107079253cf --- /dev/null +++ b/clang/test/Frontend/offload-pointer-width-mismatch.cpp @@ -0,0 +1,93 @@ +// REQUIRES: amdgpu-registered-target, nvptx-registered-target +// REQUIRES: spirv-registered-target, x86-registered-target + +// RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple i386-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=AMDGCN %s +// RUN: not %clang_cc1 -triple r600-unknown-unknown -aux-triple x86_64-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=R600 %s +// RUN: not %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple i386-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x cuda %s 2>&1 | FileCheck --check-prefix=NVPTX %s +// RUN: not %clang_cc1 -triple spir-unknown-unknown -aux-triple x86_64-unknown-linux-gnu \ +// RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=SPIR %s +// RUN: not %clang_cc1 -triple spirv64-unknown-unknown -aux-triple i386-unknown-linux-gnu \ +// RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=SPIRV %s + +// AMDGCN: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits +// R600: error: device target 'r600-unknown-unknown' takes a pointer width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits +// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits +// SPIR: error: device target 'spir-unknown-unknown' takes a pointer width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits +// SPIRV: error: device target 'spirv64-unknown-unknown' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits + +// OpenMP device compilation adapts at both stages too. + +// RUN: not %clang_cc1 -fopenmp -fopenmp-is-target-device -triple amdgcn-amd-amdhsa \ +// RUN: -aux-triple i386-unknown-linux-gnu -fsyntax-only %s 2>&1 \ +// RUN: | FileCheck --check-prefix=AMDGCN %s +// RUN: not %clang_cc1 -fopenmp -fopenmp-is-target-device -triple nvptx64-nvidia-cuda \ +// RUN: -aux-triple i386-unknown-linux-gnu -fsyntax-only %s 2>&1 \ +// RUN: | FileCheck --check-prefix=NVPTX %s + +// A host target that is itself a device target is no exception. + +// RUN: not %clang_cc1 -triple spirv64-unknown-unknown -aux-triple nvptx-nvidia-cuda \ +// RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=SPIRV-NVPTX %s +// RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple r600-unknown-unknown \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=AMDGCN-R600 %s +// RUN: not %clang_cc1 -triple spirv64-amd-amdhsa -aux-triple spir-unknown-unknown \ +// RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=AMDHSA-SPIR %s + +// SPIRV-NVPTX: error: device target 'spirv64-unknown-unknown' takes a pointer width of 32 bits from host target 'nvptx-nvidia-cuda', but requires 64 bits +// AMDGCN-R600: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 32 bits from host target 'r600-unknown-unknown', but requires 64 bits +// AMDHSA-SPIR: error: device target 'spirv64-amd-amdhsa' takes a pointer width of 32 bits from host target 'spir-unknown-unknown', but requires 64 bits + +// The host pointer width is taken from the host target rather than from its +// triple, so an ABI that narrows pointers is caught too. + +// RUN: not %clang_cc1 -triple spir64-unknown-unknown -aux-triple x86_64-unknown-linux-gnux32 \ +// RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=SPIR64-X32 %s +// RUN: not %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple x86_64-unknown-linux-gnux32 \ +// RUN: -fcuda-is-device -fsyntax-only -x cuda %s 2>&1 | FileCheck --check-prefix=NVPTX64-X32 %s +// RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-linux-gnux32 \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=AMDGCN-X32 %s + +// SPIR64-X32: error: device target 'spir64-unknown-unknown' takes a pointer width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits +// NVPTX64-X32: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits +// AMDGCN-X32: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits + +// NVPTX and AMDGPU take the pointer alignment from the host too, so a host that +// under aligns pointers is a mismatch even where the widths agree. + +// RUN: not %clang_cc1 -triple nvptx-nvidia-cuda -aux-triple m68k-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x cuda %s 2>&1 | FileCheck --check-prefix=NVPTX-M68K %s +// RUN: not %clang_cc1 -triple r600-unknown-unknown -aux-triple m68k-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=R600-M68K %s + +// NVPTX-M68K: error: device target 'nvptx-nvidia-cuda' takes a pointer alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 bits +// R600-M68K: error: device target 'r600-unknown-unknown' takes a pointer alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 bits + +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s +// RUN: %clang_cc1 -triple r600-unknown-unknown -aux-triple i386-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x hip %s +// RUN: %clang_cc1 -triple nvptx-nvidia-cuda -aux-triple i386-unknown-linux-gnu \ +// RUN: -fcuda-is-device -fsyntax-only -x cuda %s +// RUN: %clang_cc1 -triple spir64-unknown-unknown -aux-triple x86_64-unknown-linux-gnu \ +// RUN: -fsycl-is-device -fsyntax-only %s +// RUN: %clang_cc1 -triple spir64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \ +// RUN: -fsycl-is-device -fsyntax-only %s +// RUN: %clang_cc1 -fopenmp -fopenmp-is-target-device -triple amdgcn-amd-amdhsa \ +// RUN: -aux-triple x86_64-unknown-linux-gnu -fsyntax-only %s + +// SPIR and SPIR-V align pointers to their own width rather than to the host +// alignment, so an under aligning host is not a mismatch there. + +// RUN: %clang_cc1 -triple spir-unknown-unknown -aux-triple m68k-unknown-linux-gnu \ +// RUN: -fsycl-is-device -fsyntax-only %s + +// SPIR, SPIR-V, and NVPTX keep their own pointer related types when the host is +// of their own family, so a differing width is not a mismatch there. + +// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple spir-unknown-unknown \ +// RUN: -fsycl-is-device -fsyntax-only %s +// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple nvptx-nvidia-cuda \ +// RUN: -fcuda-is-device -fsyntax-only -x cuda %s diff --git a/clang/test/Preprocessor/init-amdgpu.c b/clang/test/Preprocessor/init-amdgpu.c index 9e938ab4502a51..5a88de5b9a71f5 100644 --- a/clang/test/Preprocessor/init-amdgpu.c +++ b/clang/test/Preprocessor/init-amdgpu.c @@ -32,7 +32,7 @@ // RUN: -aux-triple x86_64-pc-windows-msvc < /dev/null \ // RUN: | FileCheck -match-full-lines -check-prefix=LLP64 %s // RUN: %clang_cc1 -x hip -fcuda-is-device -E -dM -triple=amdgpu12.50-amd-amdhsa \ -// RUN: -aux-triple i386-unknown-linux-gnu < /dev/null \ +// RUN: -aux-triple x86_64-pc-windows-msvc < /dev/null \ // RUN: | FileCheck -match-full-lines -check-prefix=LLP64 %s // RUN: %clang_cc1 -fopenmp -fopenmp-is-target-device -E -dM \ // RUN: -triple=amdgpu9.0a-amd-amdhsa -aux-triple x86_64-pc-windows-msvc < /dev/null \ diff --git a/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip b/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip index f6b4ed3d6c33e0..95c1154a68f5fe 100644 --- a/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip +++ b/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip @@ -1,4 +1,3 @@ -// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple x86_64-pc-windows-msvc -fms-extensions -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fms-extensions -verify // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa -aux-triple x86_64-pc-windows-msvc -fms-extensions -verify >From 06b60e4757e11fb6f91c0f5622122e63967c895b Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Tue, 1 Sep 2026 09:18:15 -0700 Subject: [PATCH 5/8] [clang] Report host/device target incompatibility with notes per type --- .../clang/Basic/DiagnosticCommonKinds.td | 9 +-- clang/include/clang/Basic/TargetInfo.h | 14 ++--- clang/lib/Basic/Targets.cpp | 59 ++++++++++++------- clang/lib/Driver/Driver.cpp | 9 +-- clang/lib/Frontend/CompilerInstance.cpp | 2 +- .../Driver/offload-pointer-width-mismatch.c | 11 +++- .../offload-pointer-width-mismatch.cpp | 50 ++++++++++++---- 7 files changed, 100 insertions(+), 54 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index bbf9882ffda069..7415a2768050c2 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -338,10 +338,11 @@ def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def note_valid_options : Note<"valid target CPU values are: %0">; def err_target_unsupported_cpu_for_micromips : Error< "micromips is not supported for target CPU '%0'">; -def err_target_unsupported_host_pointer_related_type : Error< - "device target '%0' takes %select{a pointer width|a pointer alignment|" - "a 'size_t' width|a 'ptrdiff_t' width|an 'intptr_t' width}2 of %3 bits from " - "host target '%1', but requires %4 bits">; +def err_incompatible_host_and_device_targets : Error< + "device target '%0' is not compatible with host target '%1'">; +def note_incompatible_host_and_device_type : Note< + "%select{alignment|size}0 of type '%1' for the host target (%2 bytes) does " + "not match the %select{alignment|size}0 for the device target (%3 bytes)">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">; def err_target_unsupported_abi_for_triple : Error< diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 52c2f40b85aed2..741b0cc3852c08 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -348,13 +348,13 @@ class TargetInfo : public TransferrableTargetInfo, return getHostAdaptation(DeviceTriple, HostTriple) != HostAdaptation::None; } - /// Reports an error if this target adapts to the given host target at the - /// given stage and ended up with pointer related types that disagree with its - /// own data layout. Does nothing if it does not adapt at that stage. Returns - /// true if no error was reported. - bool checkHostPointerRelatedTypes(DiagnosticsEngine &Diags, - const llvm::Triple &HostTriple, - HostAdaptation Stage) const; + /// Reports an error, and a note per offending type, if this target adapts to + /// the given host target at the given stage and ended up with pointer related + /// types that disagree with its own data layout. Does nothing if it does not + /// adapt at that stage. Returns true if no error was reported. + bool checkHostCompatibility(DiagnosticsEngine &Diags, + const llvm::Triple &HostTriple, + HostAdaptation Stage) const; virtual ~TargetInfo(); diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index a328f175b5afc4..81608ef3d06263 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -863,32 +863,47 @@ TargetInfo::getHostAdaptation(const llvm::Triple &DeviceTriple, return HostAdaptation::None; } -bool TargetInfo::checkHostPointerRelatedTypes(DiagnosticsEngine &Diags, - const llvm::Triple &HostTriple, - HostAdaptation Stage) const { +bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags, + const llvm::Triple &HostTriple, + HostAdaptation Stage) const { assert(Stage != HostAdaptation::None && "Nothing to check"); if (getHostAdaptation(getTriple(), HostTriple) != Stage) return true; - // The device data layout fixes the width of every one of these types. + // The device data layout fixes the size and the alignment of a pointer, and + // with them the width of every integer type that has to hold one. unsigned Required = getTriple().getArchPointerBitWidth(); - // The order matches the %select in the diagnostic below. - unsigned Widths[] = {static_cast<unsigned>(getPointerWidth(LangAS::Default)), - static_cast<unsigned>(getPointerAlign(LangAS::Default)), - getTypeWidth(getSizeType()), - getTypeWidth(getPtrDiffType(LangAS::Default)), - getTypeWidth(getIntPtrType())}; - - for (auto [Which, Width] : llvm::enumerate(Widths)) { - if (Width != Required) { - Diags.Report(diag::err_target_unsupported_host_pointer_related_type) - << getTriple().str() << HostTriple.str() - << static_cast<unsigned>(Which) << Width << Required; - return false; - } - } + struct Mismatch { + unsigned Which; + const char *TypeName; + unsigned HostBits; + }; + // The order matches the %select in note_incompatible_host_and_device_type. + enum { Alignment, Size }; + + SmallVector<Mismatch, 5> Mismatches; + auto Check = [&](unsigned Which, const char *TypeName, uint64_t HostBits) { + if (HostBits != Required) + Mismatches.push_back({Which, TypeName, static_cast<unsigned>(HostBits)}); + }; + + Check(Size, "void *", getPointerWidth(LangAS::Default)); + Check(Alignment, "void *", getPointerAlign(LangAS::Default)); + Check(Size, "size_t", getTypeWidth(getSizeType())); + Check(Size, "ptrdiff_t", getTypeWidth(getPtrDiffType(LangAS::Default))); + Check(Size, "intptr_t", getTypeWidth(getIntPtrType())); + + if (Mismatches.empty()) + return true; + + Diags.Report(diag::err_incompatible_host_and_device_targets) + << getTriple().str() << HostTriple.str(); + for (const Mismatch &M : Mismatches) + Diags.Report(diag::note_incompatible_host_and_device_type) + << M.Which << M.TypeName << M.HostBits / getCharWidth() + << Required / getCharWidth(); - return true; + return false; } /// CreateTargetInfo - Return the target info object for the specified target @@ -908,8 +923,8 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, Target->TargetOpts = Opts; // Targets that adapt in their constructor have done so by now. - if (!Target->checkHostPointerRelatedTypes( - Diags, llvm::Triple(Opts->HostTriple), HostAdaptation::Constructor)) + if (!Target->checkHostCompatibility(Diags, llvm::Triple(Opts->HostTriple), + HostAdaptation::Constructor)) return nullptr; // Set the target CPU if specified. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 54ca09f1b793a6..ac075e9de5f96f 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1168,10 +1168,11 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, if (TargetInfo::adaptsToHostTarget(Target, HostTriple) && Target.getArchPointerBitWidth() != HostTriple.getArchPointerBitWidth()) { - Diag(diag::err_target_unsupported_host_pointer_related_type) - << Target.str() << HostTriple.str() << /*pointer width*/ 0 - << HostTriple.getArchPointerBitWidth() - << Target.getArchPointerBitWidth(); + Diag(diag::err_incompatible_host_and_device_targets) + << Target.str() << HostTriple.str(); + Diag(diag::note_incompatible_host_and_device_type) + << /*size*/ 1 << "void *" << HostTriple.getArchPointerBitWidth() / 8 + << Target.getArchPointerBitWidth() / 8; continue; } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 6ed32d91f4f247..cad0215ae32340 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -170,7 +170,7 @@ bool CompilerInstance::createTarget() { if (auto *Aux = getAuxTarget()) { getTarget().setAuxTarget(Aux); - if (!getTarget().checkHostPointerRelatedTypes( + if (!getTarget().checkHostCompatibility( getDiagnostics(), Aux->getTriple(), TargetInfo::HostAdaptation::SetAuxTarget)) return false; diff --git a/clang/test/Driver/offload-pointer-width-mismatch.c b/clang/test/Driver/offload-pointer-width-mismatch.c index 98fd079d5edae8..9fefa4df9f17b1 100644 --- a/clang/test/Driver/offload-pointer-width-mismatch.c +++ b/clang/test/Driver/offload-pointer-width-mismatch.c @@ -20,9 +20,14 @@ // RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp --offload-arch=gfx906 \ // RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s -// AMDGPU: error: device target 'amdgpu-amd-amdhsa' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits -// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits -// SPIRV32: error: device target 'spirv32-unknown-unknown' takes a pointer width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits +// The driver only knows the triples, so it notes the pointer size alone. + +// AMDGPU: error: device target 'amdgpu-amd-amdhsa' is not compatible with host target 'i386-unknown-linux-gnu' +// AMDGPU-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// NVPTX: error: device target 'nvptx64-nvidia-cuda' is not compatible with host target 'i386-unknown-linux-gnu' +// NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// SPIRV32: error: device target 'spirv32-unknown-unknown' is not compatible with host target 'x86_64-unknown-linux-gnu' +// SPIRV32-NEXT: note: size of type 'void *' for the host target (8 bytes) does not match the size for the device target (4 bytes) // RUN: %clang -### --target=x86_64-unknown-linux-gnu -x hip --offload-arch=gfx906 \ // RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=OK %s diff --git a/clang/test/Frontend/offload-pointer-width-mismatch.cpp b/clang/test/Frontend/offload-pointer-width-mismatch.cpp index 4d1107079253cf..9ad94417a115f9 100644 --- a/clang/test/Frontend/offload-pointer-width-mismatch.cpp +++ b/clang/test/Frontend/offload-pointer-width-mismatch.cpp @@ -12,11 +12,23 @@ // RUN: not %clang_cc1 -triple spirv64-unknown-unknown -aux-triple i386-unknown-linux-gnu \ // RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=SPIRV %s -// AMDGCN: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits -// R600: error: device target 'r600-unknown-unknown' takes a pointer width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits -// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits -// SPIR: error: device target 'spir-unknown-unknown' takes a pointer width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits -// SPIRV: error: device target 'spirv64-unknown-unknown' takes a pointer width of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits +// Every type that disagrees with the device data layout is noted. + +// AMDGCN: error: device target 'amdgcn-amd-amdhsa' is not compatible with host target 'i386-unknown-linux-gnu' +// AMDGCN-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// AMDGCN-NEXT: note: alignment of type 'void *' for the host target (4 bytes) does not match the alignment for the device target (8 bytes) +// AMDGCN-NEXT: note: size of type 'size_t' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// AMDGCN-NEXT: note: size of type 'ptrdiff_t' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// AMDGCN-NEXT: note: size of type 'intptr_t' for the host target (4 bytes) does not match the size for the device target (8 bytes) + +// R600: error: device target 'r600-unknown-unknown' is not compatible with host target 'x86_64-unknown-linux-gnu' +// R600-NEXT: note: size of type 'void *' for the host target (8 bytes) does not match the size for the device target (4 bytes) +// NVPTX: error: device target 'nvptx64-nvidia-cuda' is not compatible with host target 'i386-unknown-linux-gnu' +// NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// SPIR: error: device target 'spir-unknown-unknown' is not compatible with host target 'x86_64-unknown-linux-gnu' +// SPIR-NEXT: note: size of type 'void *' for the host target (8 bytes) does not match the size for the device target (4 bytes) +// SPIRV: error: device target 'spirv64-unknown-unknown' is not compatible with host target 'i386-unknown-linux-gnu' +// SPIRV-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) // OpenMP device compilation adapts at both stages too. @@ -36,9 +48,12 @@ // RUN: not %clang_cc1 -triple spirv64-amd-amdhsa -aux-triple spir-unknown-unknown \ // RUN: -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck --check-prefix=AMDHSA-SPIR %s -// SPIRV-NVPTX: error: device target 'spirv64-unknown-unknown' takes a pointer width of 32 bits from host target 'nvptx-nvidia-cuda', but requires 64 bits -// AMDGCN-R600: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 32 bits from host target 'r600-unknown-unknown', but requires 64 bits -// AMDHSA-SPIR: error: device target 'spirv64-amd-amdhsa' takes a pointer width of 32 bits from host target 'spir-unknown-unknown', but requires 64 bits +// SPIRV-NVPTX: error: device target 'spirv64-unknown-unknown' is not compatible with host target 'nvptx-nvidia-cuda' +// SPIRV-NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// AMDGCN-R600: error: device target 'amdgcn-amd-amdhsa' is not compatible with host target 'r600-unknown-unknown' +// AMDGCN-R600-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// AMDHSA-SPIR: error: device target 'spirv64-amd-amdhsa' is not compatible with host target 'spir-unknown-unknown' +// AMDHSA-SPIR-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) // The host pointer width is taken from the host target rather than from its // triple, so an ABI that narrows pointers is caught too. @@ -50,9 +65,12 @@ // RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-linux-gnux32 \ // RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=AMDGCN-X32 %s -// SPIR64-X32: error: device target 'spir64-unknown-unknown' takes a pointer width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits -// NVPTX64-X32: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits -// AMDGCN-X32: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits +// SPIR64-X32: error: device target 'spir64-unknown-unknown' is not compatible with host target 'x86_64-unknown-linux-gnux32' +// SPIR64-X32-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// NVPTX64-X32: error: device target 'nvptx64-nvidia-cuda' is not compatible with host target 'x86_64-unknown-linux-gnux32' +// NVPTX64-X32-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) +// AMDGCN-X32: error: device target 'amdgcn-amd-amdhsa' is not compatible with host target 'x86_64-unknown-linux-gnux32' +// AMDGCN-X32-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) // NVPTX and AMDGPU take the pointer alignment from the host too, so a host that // under aligns pointers is a mismatch even where the widths agree. @@ -62,8 +80,14 @@ // RUN: not %clang_cc1 -triple r600-unknown-unknown -aux-triple m68k-unknown-linux-gnu \ // RUN: -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck --check-prefix=R600-M68K %s -// NVPTX-M68K: error: device target 'nvptx-nvidia-cuda' takes a pointer alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 bits -// R600-M68K: error: device target 'r600-unknown-unknown' takes a pointer alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 bits +// The alignment is then the only type detail noted. + +// NVPTX-M68K: error: device target 'nvptx-nvidia-cuda' is not compatible with host target 'm68k-unknown-linux-gnu' +// NVPTX-M68K-NEXT: note: alignment of type 'void *' for the host target (2 bytes) does not match the alignment for the device target (4 bytes) +// NVPTX-M68K-NOT: note: +// R600-M68K: error: device target 'r600-unknown-unknown' is not compatible with host target 'm68k-unknown-linux-gnu' +// R600-M68K-NEXT: note: alignment of type 'void *' for the host target (2 bytes) does not match the alignment for the device target (4 bytes) +// R600-M68K-NOT: note: // RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-linux-gnu \ // RUN: -fcuda-is-device -fsyntax-only -x hip %s >From d3cd49ebde2cadbb69777622e3c7d69f63dedf0f Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Tue, 1 Sep 2026 10:40:29 -0700 Subject: [PATCH 6/8] [clang] Check the built device target instead of tracking adaptation --- clang/include/clang/Basic/TargetInfo.h | 35 +++------------ clang/lib/Basic/Targets.cpp | 44 +++---------------- clang/lib/Driver/Driver.cpp | 15 ------- clang/lib/Frontend/CompilerInstance.cpp | 6 +-- .../Driver/offload-pointer-width-mismatch.c | 44 +++++++------------ 5 files changed, 33 insertions(+), 111 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 741b0cc3852c08..d3a98eb1018bde 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -326,35 +326,14 @@ class TargetInfo : public TransferrableTargetInfo, static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags, TargetOptions &Opts); - /// When a device target takes its pointer related types (the pointer width - /// and alignment, size_t, ptrdiff_t, and intptr_t) from a host target. - enum class HostAdaptation { - /// It keeps its own pointer related types. - None, - /// It adapts in its constructor, from TargetOptions::HostTriple. - Constructor, - SetAuxTarget, - }; - - /// Returns when the device target takes its pointer related types from the - /// host target, mirroring the conditions under which the TargetInfo - /// subclasses adapt. A device that declines a host keeps its own types, which - /// the driver's triple level check must not report as a mismatch. - static HostAdaptation getHostAdaptation(const llvm::Triple &DeviceTriple, - const llvm::Triple &HostTriple); - - static bool adaptsToHostTarget(const llvm::Triple &DeviceTriple, - const llvm::Triple &HostTriple) { - return getHostAdaptation(DeviceTriple, HostTriple) != HostAdaptation::None; - } - - /// Reports an error, and a note per offending type, if this target adapts to - /// the given host target at the given stage and ended up with pointer related - /// types that disagree with its own data layout. Does nothing if it does not - /// adapt at that stage. Returns true if no error was reported. + /// Reports an error, and a note per offending type, if a pointer related type + /// (the pointer size and alignment, size_t, ptrdiff_t, and intptr_t) that + /// this device target took from the given host target disagrees with its own + /// data layout. Returns true if no error was reported. Call this once the + /// target has taken whatever it takes from the host target, that is, after + /// setAuxTarget(). bool checkHostCompatibility(DiagnosticsEngine &Diags, - const llvm::Triple &HostTriple, - HostAdaptation Stage) const; + const llvm::Triple &HostTriple) const; virtual ~TargetInfo(); diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 81608ef3d06263..eccd91d14778bf 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -836,42 +836,15 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, using namespace clang::targets; -TargetInfo::HostAdaptation -TargetInfo::getHostAdaptation(const llvm::Triple &DeviceTriple, - const llvm::Triple &HostTriple) { - // No recognizable host triple, so nothing to adapt to. - if (HostTriple.getArch() == llvm::Triple::UnknownArch) - return HostAdaptation::None; - - // setAuxTarget() overwrites these, so constructor values are not yet final. - if (DeviceTriple.isAMDGPU() || - (DeviceTriple.getArch() == llvm::Triple::spirv64 && - DeviceTriple.getOS() == llvm::Triple::AMDHSA)) - return HostAdaptation::SetAuxTarget; - - // Logical SPIR-V sets these itself, with a 32-bit size_t by design. - if (DeviceTriple.isSPIRVLogical()) - return HostAdaptation::None; - - if (DeviceTriple.isSPIROrSPIRV()) - return HostTriple.isSPIROrSPIRV() ? HostAdaptation::None - : HostAdaptation::Constructor; - if (DeviceTriple.isNVPTX()) - return HostTriple.isNVPTX() ? HostAdaptation::None - : HostAdaptation::Constructor; - - return HostAdaptation::None; -} - bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags, - const llvm::Triple &HostTriple, - HostAdaptation Stage) const { - assert(Stage != HostAdaptation::None && "Nothing to check"); - if (getHostAdaptation(getTriple(), HostTriple) != Stage) + const llvm::Triple &HostTriple) const { + // Logical SPIR-V has no pointer size to require. + if (getTriple().isSPIRVLogical()) return true; - // The device data layout fixes the size and the alignment of a pointer, and - // with them the width of every integer type that has to hold one. + // Whatever this target took from the host target, it has to hold a pointer, + // whose size and alignment its own data layout fixes. A target that took + // nothing agrees with itself and is reported here in no case. unsigned Required = getTriple().getArchPointerBitWidth(); struct Mismatch { unsigned Which; @@ -922,11 +895,6 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, } Target->TargetOpts = Opts; - // Targets that adapt in their constructor have done so by now. - if (!Target->checkHostCompatibility(Diags, llvm::Triple(Opts->HostTriple), - HostAdaptation::Constructor)) - return nullptr; - // Set the target CPU if specified. if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) { Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index ac075e9de5f96f..f06f1c5a75ff81 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -55,7 +55,6 @@ #include "ToolChains/ZOS.h" #include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/TargetID.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -1162,20 +1161,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, continue; } - // A triple level approximation that catches the common cases early; the - // types are checked once the device adapts. - const llvm::Triple &HostTriple = C.getDefaultToolChain().getTriple(); - if (TargetInfo::adaptsToHostTarget(Target, HostTriple) && - Target.getArchPointerBitWidth() != - HostTriple.getArchPointerBitWidth()) { - Diag(diag::err_incompatible_host_and_device_targets) - << Target.str() << HostTriple.str(); - Diag(diag::note_incompatible_host_and_device_type) - << /*size*/ 1 << "void *" << HostTriple.getArchPointerBitWidth() / 8 - << Target.getArchPointerBitWidth() / 8; - continue; - } - std::string NormalizedName = Target.normalize(); auto [TripleIt, Inserted] = FoundNormalizedTriples.try_emplace(NormalizedName, Target.str()); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index cad0215ae32340..b3eef5301e41af 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -170,9 +170,9 @@ bool CompilerInstance::createTarget() { if (auto *Aux = getAuxTarget()) { getTarget().setAuxTarget(Aux); - if (!getTarget().checkHostCompatibility( - getDiagnostics(), Aux->getTriple(), - TargetInfo::HostAdaptation::SetAuxTarget)) + // The target has taken everything it takes from the host target by now. + if (getLangOpts().isTargetDevice() && + !getTarget().checkHostCompatibility(getDiagnostics(), Aux->getTriple())) return false; } diff --git a/clang/test/Driver/offload-pointer-width-mismatch.c b/clang/test/Driver/offload-pointer-width-mismatch.c index 9fefa4df9f17b1..d443c80613efe7 100644 --- a/clang/test/Driver/offload-pointer-width-mismatch.c +++ b/clang/test/Driver/offload-pointer-width-mismatch.c @@ -1,36 +1,26 @@ -// Offload targets that take their pointer related types from the host target -// are rejected early, before any compilation job is built. +// An offload compilation whose device target takes its pointer related types +// from an incompatible host target fails when the device compilation runs. -// RUN: not %clang -### --target=i386-unknown-linux-gnu -x hip --offload-arch=gfx906 \ -// RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s -// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda --offload=nvptx64-nvidia-cuda \ -// RUN: --offload-arch=sm_60 -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=NVPTX %s -// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -x cuda --cuda-device-only \ -// RUN: -nogpulib -nogpuinc --offload=spirv32-unknown-unknown -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=SPIRV32 %s -// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda \ -// RUN: --offload-targets=nvptx64-nvidia-cuda --offload-arch=sm_60 -nogpulib -nogpuinc \ -// RUN: -c %s 2>&1 | FileCheck --check-prefix=NVPTX %s +// REQUIRES: amdgpu-registered-target, nvptx-registered-target -// OpenMP offloading reaches the same check. - -// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp \ -// RUN: -fopenmp-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -c %s 2>&1 \ +// RUN: not %clang --target=i386-unknown-linux-gnu -x hip --offload-arch=gfx906 \ +// RUN: -nogpulib -nogpuinc -fsyntax-only %s 2>&1 | FileCheck --check-prefix=AMDGPU %s +// RUN: not %clang --target=i386-unknown-linux-gnu -x cuda --offload=nvptx64-nvidia-cuda \ +// RUN: --offload-arch=sm_60 -nogpulib -nogpuinc -fsyntax-only %s 2>&1 \ // RUN: | FileCheck --check-prefix=NVPTX %s -// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp --offload-arch=gfx906 \ -// RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s - -// The driver only knows the triples, so it notes the pointer size alone. +// RUN: not %clang --target=i386-unknown-linux-gnu -fopenmp \ +// RUN: -fopenmp-targets=nvptx64-nvidia-cuda --offload-arch=sm_60 -nogpulib -nogpuinc \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck --check-prefix=NVPTX %s -// AMDGPU: error: device target 'amdgpu-amd-amdhsa' is not compatible with host target 'i386-unknown-linux-gnu' +// AMDGPU: error: device target 'amdgpu9.06-amd-amdhsa' is not compatible with host target 'i386-unknown-linux-gnu' // AMDGPU-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) // NVPTX: error: device target 'nvptx64-nvidia-cuda' is not compatible with host target 'i386-unknown-linux-gnu' // NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does not match the size for the device target (8 bytes) -// SPIRV32: error: device target 'spirv32-unknown-unknown' is not compatible with host target 'x86_64-unknown-linux-gnu' -// SPIRV32-NEXT: note: size of type 'void *' for the host target (8 bytes) does not match the size for the device target (4 bytes) -// RUN: %clang -### --target=x86_64-unknown-linux-gnu -x hip --offload-arch=gfx906 \ -// RUN: -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=OK %s +// A host target of a matching pointer width is accepted, and so is the 32-bit +// device target that a 32-bit host selects by default. -// OK-NOT: error: -// OK: "-cc1" "-triple" "amdgpu9.06-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu" +// RUN: %clang --target=x86_64-unknown-linux-gnu -x hip --offload-arch=gfx906 \ +// RUN: -nogpulib -nogpuinc -fsyntax-only %s +// RUN: %clang --target=i386-unknown-linux-gnu -x cuda --offload-arch=sm_60 \ +// RUN: -nogpulib -nogpuinc -fsyntax-only %s >From 1ceb1fb76a28c00b7c02b120e940a9fd712c723b Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Tue, 1 Sep 2026 12:12:47 -0700 Subject: [PATCH 7/8] [clang] Take the auxiliary target compatibility check to its own interface --- clang/include/clang/Basic/TargetInfo.h | 12 ++++-------- clang/lib/Basic/Targets.cpp | 17 +++++++++++------ clang/lib/Frontend/CompilerInstance.cpp | 6 +++--- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index d3a98eb1018bde..b2c0d870324a22 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -326,14 +326,10 @@ class TargetInfo : public TransferrableTargetInfo, static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags, TargetOptions &Opts); - /// Reports an error, and a note per offending type, if a pointer related type - /// (the pointer size and alignment, size_t, ptrdiff_t, and intptr_t) that - /// this device target took from the given host target disagrees with its own - /// data layout. Returns true if no error was reported. Call this once the - /// target has taken whatever it takes from the host target, that is, after - /// setAuxTarget(). - bool checkHostCompatibility(DiagnosticsEngine &Diags, - const llvm::Triple &HostTriple) const; + /// Diagnoses the pointer related types that this target took from its + /// auxiliary target if they disagree with its own data layout. Returns true + /// if no error was reported. Call after setAuxTarget(). + bool checkAuxTargetCompatibility(DiagnosticsEngine &Diags) const; virtual ~TargetInfo(); diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index eccd91d14778bf..fe46d979152aad 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -836,15 +836,20 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, using namespace clang::targets; -bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags, - const llvm::Triple &HostTriple) const { +bool TargetInfo::checkAuxTargetCompatibility(DiagnosticsEngine &Diags) const { + // Only a device target takes its pointer related types from another target, + // and only such a target is given the triple of the target it takes them + // from. + StringRef HostTriple = getTargetOpts().HostTriple; + if (HostTriple.empty()) + return true; + // Logical SPIR-V has no pointer size to require. if (getTriple().isSPIRVLogical()) return true; - // Whatever this target took from the host target, it has to hold a pointer, - // whose size and alignment its own data layout fixes. A target that took - // nothing agrees with itself and is reported here in no case. + // These getters return what the target took from the host, so a disagreement + // with the width its own data layout fixes is a host/device mismatch. unsigned Required = getTriple().getArchPointerBitWidth(); struct Mismatch { unsigned Which; @@ -870,7 +875,7 @@ bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags, return true; Diags.Report(diag::err_incompatible_host_and_device_targets) - << getTriple().str() << HostTriple.str(); + << getTriple().str() << HostTriple; for (const Mismatch &M : Mismatches) Diags.Report(diag::note_incompatible_host_and_device_type) << M.Which << M.TypeName << M.HostBits / getCharWidth() diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index b3eef5301e41af..a1784bdd1cd937 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -170,9 +170,9 @@ bool CompilerInstance::createTarget() { if (auto *Aux = getAuxTarget()) { getTarget().setAuxTarget(Aux); - // The target has taken everything it takes from the host target by now. - if (getLangOpts().isTargetDevice() && - !getTarget().checkHostCompatibility(getDiagnostics(), Aux->getTriple())) + // The target has taken everything it takes from the auxiliary target by + // now, which TargetInfo::adjust() above is too early for. + if (!getTarget().checkAuxTargetCompatibility(getDiagnostics())) return false; } >From 747dccfa0e2efdac53446430697781ada012e0a4 Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Wed, 2 Sep 2026 07:24:14 -0700 Subject: [PATCH 8/8] [clang] Add asserts on SPIR and SPIR-V target pointer types/sizes --- clang/lib/Basic/Targets/SPIR.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 7c36ac5e0ef36d..73ff5030320782 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -253,6 +253,12 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; + + assert(PointerWidth == 32); + assert(PointerAlign == 32); + assert(getTypeWidth(SizeType) == 32); + assert(getTypeWidth(PtrDiffType) == 32); + assert(getTypeWidth(IntPtrType) == 32); } // SPIR32 has support for atomic ops if atomic extension is enabled. @@ -276,6 +282,11 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo { PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; + assert(PointerWidth == 64); + assert(PointerAlign == 64); + assert(getTypeWidth(SizeType) == 64); + assert(getTypeWidth(PtrDiffType) == 64); + assert(getTypeWidth(IntPtrType) == 64); } // SPIR64 has support for atomic ops if atomic extension is enabled. @@ -370,6 +381,11 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo { PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; + assert(PointerWidth == 32); + assert(PointerAlign == 32); + assert(getTypeWidth(SizeType) == 32); + assert(getTypeWidth(PtrDiffType) == 32); + assert(getTypeWidth(IntPtrType) == 32); } // SPIR-V has core support for atomic ops, and Int32 is always available; @@ -398,6 +414,11 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo { PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; + assert(PointerWidth == 64); + assert(PointerAlign == 64); + assert(getTypeWidth(SizeType) == 64); + assert(getTypeWidth(PtrDiffType) == 64); + assert(getTypeWidth(IntPtrType) == 64); } // SPIR-V has core support for atomic ops, and Int64 is always available; @@ -445,6 +466,17 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; + + // With a host target the widths above are the host's until setAuxTarget() + // replaces them, so only what this target sets itself is asserted. + if (!getHostTarget()) { + assert(PointerWidth == 64); + assert(PointerAlign == 64); + assert(getTypeWidth(SizeType) == 64); + assert(getTypeWidth(PtrDiffType) == 64); + assert(getTypeWidth(IntPtrType) == 64); + } + AddrSpaceMap = &SPIRDefIsGenMap; resetDataLayout(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
