https://github.com/yserrr created https://github.com/llvm/llvm-project/pull/208375
64-bit integer support is core in the OpenCL C full profile but optional in the embedded profile: `cles_khr_int64` in OpenCL C 1.x, and the `__opencl_c_int64` feature in OpenCL C 3.0. Clang currently declares `cles_khr_int64` in `OpenCLExtensions.def`, but nothing in the tree ever reads it, and `__opencl_c_int64` is defined unconditionally (`InitPreprocessor.cpp`: "Assume compiling for FULL profile"). As a result, there is no way to make Clang reject 64-bit integer types for an embedded-profile target without int64 support. Kernels using `long` compile silently and then fail much later in the backend. Concretely: Mesa's rusticl on the Raspberry Pi's v3d GPU (an embedded-profile device without int64) aborts inside the backend compiler on such kernels, and Mesa already works around the unconditional macro (`clc_helpers.cpp`: "clang defines this unconditionally, we need to fix that"). `half`/`cl_khr_fp16` and `double`/`cl_khr_fp64` both already handle exactly this shape of problem. This patch follows the `double` approach: - Register `__opencl_c_int64` in `OpenCLExtensions.def`. It is available as an option (and macro) from OpenCL C 1.0 on - like `cl_khr_fp64` - since the embedded profile predates OpenCL C 3.0 features. - Default the option to enabled in `CreateTargetInfo`, preserving the current full-profile assumption, including for targets with explicit support lists (AMDGPU, NVPTX). The unconditional macro definition is dropped: the macro now simply tracks the option, so `-cl-ext=-all` / `-cl-ext=-__opencl_c_int64` disable it. - Diagnose declarations using `long`/`ulong` (`ConvertDeclSpecToType`) and 64-bit integer literals (`ActOnNumericConstant`) with `err_opencl_requires_extension` when *neither* `cles_khr_int64` nor `__opencl_c_int64` is supported. Unlike `half` (where pointers remain legal without `cl_khr_fp16`), the embedded profile without int64 has no 64-bit integer types, so declarations are rejected outright, like `double` without `cl_khr_fp64`. - Guard the `ulong` and `long`/`ulong` vector typedefs in `opencl-c-base.h`, like the `cl_khr_fp16` vector typedefs. - Attach a `TypeExtension` to `long`/`ulong` in `OpenCLBuiltins.td` so `-fdeclare-opencl-builtins` stops offering 64-bit overloads when the feature is disabled, like `double`. - Treat `cles_khr_int64` as implying `__opencl_c_int64` in `setDependentOpenCLOpts`, so a driver that only knows the 1.x spelling keeps the conditional typedefs and builtin overloads. Behavior is unchanged in default configurations: both options stay enabled unless a driver explicitly disables them. The one visible change is that `__opencl_c_int64` is no longer defined once `-cl-ext=-all` (or `-...int64`) is given - which is the point of the patch - and `SemaOpenCL/features.cl` / `SemaOpenCL/amd-media-ops.cl` are updated accordingly, with new coverage in `SemaOpenCL/int64.cl`. With this, an embedded-profile driver (e.g. Mesa's `clc_helpers.cpp`, which already passes `-cl-ext=-all` plus per-feature enables, including `+cles_khr_int64,+__opencl_c_int64` when the device does support int64) gets a clean compile-time diagnostic instead of a backend crash, with no changes needed on the Mesa side. Known limitation: the full `opencl-c.h` header declares 64-bit builtins unconditionally, so `-finclude-default-header` (without `-fdeclare-opencl-builtins`) with int64 disabled diagnoses inside the header. Guarding those declarations is a large mechanical change (compare the ~260 `cl_khr_fp16` guards) left for a follow-up; the `-fdeclare-opencl-builtins` path is covered by the new tests in `SemaOpenCL/int64.cl`. A second known limitation: non-standard extensions can still form 64-bit integer types past these diagnostics - `_BitInt(64)` and `__attribute__((mode(DI)))` are accepted with int64 disabled. The existing `cl_khr_fp64` gate shares the same gap (`mode(DF)` passes with fp64 disabled), so a proper fix would cover both gates together in a follow-up. The standard OpenCL C paths (declarations, literals, header typedefs, `-fdeclare-opencl-builtins` overloads) are covered by the added tests. >From eb5a93a794c539c48f3a0c72d9a5fbc722487824 Mon Sep 17 00:00:00 2001 From: JaeHoon Lee <[email protected]> Date: Wed, 8 Jul 2026 15:14:04 +0900 Subject: [PATCH] [OpenCL] Require cles_khr_int64 or __opencl_c_int64 for 64-bit integers 64-bit integers are core in the OpenCL C full profile but optional in the embedded profile: cles_khr_int64 in OpenCL C 1.x, the __opencl_c_int64 feature in OpenCL C 3.0. Clang registers cles_khr_int64 but never reads it and defines __opencl_c_int64 unconditionally, so kernels using 'long' on a device without int64 support compile silently and only fail deep in the backend compiler (e.g. Mesa's rusticl on the Raspberry Pi v3d GPU, which already carries a workaround comment for the unconditional macro). Follow the approach used for double/cl_khr_fp64: - Register __opencl_c_int64 in OpenCLExtensions.def, available from OpenCL C 1.0 (the embedded profile predates the 3.0 features) and enabled by default, including for targets with explicit support lists (AMDGPU, NVPTX). The predefined macro now tracks the option, so -cl-ext=-all or -cl-ext=-__opencl_c_int64 disables it. - Diagnose declarations (ConvertDeclSpecToType) and 64-bit literals (ActOnNumericConstant) when neither option is supported. Unlike half without cl_khr_fp16, where pointers stay legal, a target without int64 has no 64-bit integer types, so uses are rejected outright like double without cl_khr_fp64. - Make the ulong/long vector typedefs in opencl-c-base.h and the OpenCLBuiltins.td overloads conditional on the options, and treat cles_khr_int64 as implying __opencl_c_int64 (setDependentOpenCLOpts) so the 1.x spelling alone also keeps them available. Defaults are unchanged; only compilations that explicitly disable both options (e.g. Mesa's -cl-ext=-all) are affected. Guarding the unconditional 64-bit declarations in the full opencl-c.h header is left for a follow-up; the -fdeclare-opencl-builtins path is covered by the new tests in SemaOpenCL/int64.cl. Assisted-by: Claude Code (Claude Fable 5) --- clang/docs/ReleaseNotes.md | 8 +++ .../include/clang/Basic/OpenCLExtensions.def | 1 + clang/lib/Basic/TargetInfo.cpp | 5 ++ clang/lib/Basic/Targets.cpp | 4 ++ clang/lib/Frontend/InitPreprocessor.cpp | 3 - clang/lib/Headers/opencl-c-base.h | 4 ++ clang/lib/Sema/OpenCLBuiltins.td | 8 ++- clang/lib/Sema/SemaExpr.cpp | 11 ++++ clang/lib/Sema/SemaType.cpp | 18 ++++++ clang/test/SemaOpenCL/amd-media-ops.cl | 12 ++-- clang/test/SemaOpenCL/features.cl | 22 +++---- clang/test/SemaOpenCL/int64.cl | 59 +++++++++++++++++++ 12 files changed, 134 insertions(+), 21 deletions(-) create mode 100644 clang/test/SemaOpenCL/int64.cl diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index e12ae0b2eeed4..fc39af50e2df1 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -236,6 +236,11 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the section 6.11.d states that "Variable length arrays and structures with flexible (or unsized) arrays are not supported." +- The `__opencl_c_int64` feature macro is no longer unconditionally defined: + it tracks a default-enabled feature option, so `-cl-ext=-all` (or + `-cl-ext=-__opencl_c_int64`) now disables it. When neither it nor + `cles_khr_int64` is supported, 64-bit integer types are diagnosed as errors. + {#what-s-new-in-clang-release} ## What's New in Clang {{env.config.release}}? @@ -927,6 +932,9 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the ### OpenCL Specific Changes - Added support for OpenCL C 3.1 language version (`-cl-std=CL3.1`). +- 64-bit integer types now require the `cles_khr_int64` extension or the + `__opencl_c_int64` feature (both enabled by default), following the same + approach as `double` with `cl_khr_fp64`. ### Target Specific Changes diff --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def index 08ac5f692616a..924a9bf1ea4d4 100644 --- a/clang/include/clang/Basic/OpenCLExtensions.def +++ b/clang/include/clang/Basic/OpenCLExtensions.def @@ -154,6 +154,7 @@ OPENCL_EXTENSION(cl_intel_device_side_avc_motion_estimation, true, 100) // OpenCL C 3.0 features (6.2.1. Features) OPENCL_OPTIONALCOREFEATURE(__opencl_c_3d_image_writes, false, 300, OCL_C_30) OPENCL_OPTIONALCOREFEATURE(__opencl_c_fp64, false, 300, OCL_C_30) +OPENCL_OPTIONALCOREFEATURE(__opencl_c_int64, false, 100, OCL_C_30) OPENCL_OPTIONALCOREFEATURE(__opencl_c_subgroups, false, 300, OCL_C_30) #undef OPENCL_OPTIONALCOREFEATURE diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 9a25384347073..3d74b2d35c978 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -660,6 +660,11 @@ void TargetInfo::setDependentOpenCLOpts() { setFeatureEnabled(Opts, "__opencl_c_ext_fp64_global_atomic_min_max", false); setFeatureEnabled(Opts, "__opencl_c_ext_fp64_local_atomic_min_max", false); } + + // cles_khr_int64 (OpenCL C 1.x embedded profile) means the device has + // 64-bit integers, so it implies the __opencl_c_int64 feature. + if (hasFeatureEnabled(Opts, "cles_khr_int64")) + setFeatureEnabled(Opts, "__opencl_c_int64", true); } LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const { diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index ed88ae7173bad..d4dcc558e2f92 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -909,6 +909,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, return nullptr; Target->setSupportedOpenCLOpts(); + // 64-bit integers are optional in the OpenCL C embedded profile. Assume + // the full profile unless the target or the command line says otherwise. + Target->getTargetOpts().OpenCLFeaturesMap.try_emplace("__opencl_c_int64", + true); Target->setCommandLineOpenCLOpts(); Target->setDependentOpenCLOpts(); Target->setMaxAtomicWidth(); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 7752ab5131aae..e36edb5c9e0fb 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -781,9 +781,6 @@ void InitializeOpenCLFeatureTestMacros(const TargetInfo &TI, #define OPENCL_GENERIC_EXTENSION(Ext, ...) \ defineOpenCLExtMacro(#Ext, __VA_ARGS__); #include "clang/Basic/OpenCLExtensions.def" - - // Assume compiling for FULL profile - Builder.defineMacro("__opencl_c_int64"); } llvm::SmallString<32> ConstructFixedPointLiteral(llvm::APFixedPoint Val, diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index 5e24aa60b8d7f..22d64ce388932 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -44,10 +44,12 @@ typedef unsigned short ushort; */ typedef unsigned int uint; +#if defined(__opencl_c_int64) || defined(cles_khr_int64) /** * An unsigned 64-bit integer. */ typedef unsigned long ulong; +#endif // defined(__opencl_c_int64) || defined(cles_khr_int64) /** * The unsigned integer type of the result of the sizeof operator. This @@ -110,6 +112,7 @@ typedef uint uint3 __attribute__((ext_vector_type(3))); typedef uint uint4 __attribute__((ext_vector_type(4))); typedef uint uint8 __attribute__((ext_vector_type(8))); typedef uint uint16 __attribute__((ext_vector_type(16))); +#if defined(__opencl_c_int64) || defined(cles_khr_int64) typedef long long2 __attribute__((ext_vector_type(2))); typedef long long3 __attribute__((ext_vector_type(3))); typedef long long4 __attribute__((ext_vector_type(4))); @@ -120,6 +123,7 @@ typedef ulong ulong3 __attribute__((ext_vector_type(3))); typedef ulong ulong4 __attribute__((ext_vector_type(4))); typedef ulong ulong8 __attribute__((ext_vector_type(8))); typedef ulong ulong16 __attribute__((ext_vector_type(16))); +#endif // defined(__opencl_c_int64) || defined(cles_khr_int64) typedef float float2 __attribute__((ext_vector_type(2))); typedef float float3 __attribute__((ext_vector_type(3))); typedef float float4 __attribute__((ext_vector_type(4))); diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td index 761c9771b0891..7668bc3d5e4d5 100644 --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -78,6 +78,7 @@ class concatExtension<FunctionExtension Base, string NewExts> { def NoTypeExt : TypeExtension<"">; def Fp16TypeExt : TypeExtension<"cl_khr_fp16">; def Fp64TypeExt : TypeExtension<"cl_khr_fp64">; +def Int64TypeExt : TypeExtension<"__opencl_c_int64">; def Atomic64TypeExt : TypeExtension<"cl_khr_int64_base_atomics cl_khr_int64_extended_atomics">; def AtomicFp64TypeExt : TypeExtension<"cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_fp64">; @@ -351,8 +352,11 @@ def Short : Type<"short", QualType<"Context.ShortTy">>; def UShort : Type<"ushort", QualType<"Context.UnsignedShortTy">>; def Int : Type<"int", QualType<"Context.IntTy">>; def UInt : Type<"uint", QualType<"Context.UnsignedIntTy">>; -def Long : Type<"long", QualType<"Context.LongTy">>; -def ULong : Type<"ulong", QualType<"Context.UnsignedLongTy">>; +// 64-bit integer types, optional in the embedded profile (__opencl_c_int64). +let Extension = Int64TypeExt in { + def Long : Type<"long", QualType<"Context.LongTy">>; + def ULong : Type<"ulong", QualType<"Context.UnsignedLongTy">>; +} def Float : Type<"float", QualType<"Context.FloatTy">>; let Extension = Fp64TypeExt in { def Double : Type<"double", QualType<"Context.DoubleTy">>; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 274973c78da81..31ed1018c1553 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4248,6 +4248,17 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { if (ResultVal.getBitWidth() != Width) ResultVal = ResultVal.trunc(Width); + + // OpenCL C v3.0 s6.2.1: 64-bit integer types are optional. A literal + // can produce one without any 'long' declaration, so check here too. + if (getLangOpts().OpenCL && Width == 64 && + !getOpenCLOptions().isSupported("cles_khr_int64", getLangOpts()) && + !getOpenCLOptions().isSupported("__opencl_c_int64", getLangOpts())) + Diag(Tok.getLocation(), diag::err_opencl_requires_extension) + << 0 << Ty + << (getLangOpts().getOpenCLCompatibleVersion() >= 300 + ? "__opencl_c_int64" + : "cles_khr_int64"); } Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation()); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 1378c7baca92e..c4d1ddf958e3d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1084,6 +1084,24 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; } } + + // OpenCL C v3.0 s6.2.1: 64-bit integer types require the + // __opencl_c_int64 feature (cles_khr_int64 in the 1.x embedded profile). + if (S.getLangOpts().OpenCL && + (Result == Context.LongTy || Result == Context.UnsignedLongTy || + Result == Context.LongLongTy || + Result == Context.UnsignedLongLongTy) && + !S.getOpenCLOptions().isSupported("cles_khr_int64", + S.getLangOpts()) && + !S.getOpenCLOptions().isSupported("__opencl_c_int64", + S.getLangOpts())) + // Note: 'long' alone has TST_unspecified, so the type specifier + // location can be invalid; the width specifier is always present. + S.Diag(DS.getTypeSpecWidthLoc(), diag::err_opencl_requires_extension) + << 0 << Result + << (S.getLangOpts().getOpenCLCompatibleVersion() >= 300 + ? "__opencl_c_int64" + : "cles_khr_int64"); break; } case DeclSpec::TST_bitint: { diff --git a/clang/test/SemaOpenCL/amd-media-ops.cl b/clang/test/SemaOpenCL/amd-media-ops.cl index 9b9b9f54ecf8b..762abfad43dbb 100644 --- a/clang/test/SemaOpenCL/amd-media-ops.cl +++ b/clang/test/SemaOpenCL/amd-media-ops.cl @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+cl_amd_media_ops,+cl_amd_media_ops2 -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+cl_amd_media_ops,+cl_amd_media_ops2 -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+__opencl_c_int64,+cl_amd_media_ops,+cl_amd_media_ops2 -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+__opencl_c_int64,+cl_amd_media_ops,+cl_amd_media_ops2 -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins // expected-no-diagnostics -// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+cl_amd_media_ops2 -verify=ops -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+cl_amd_media_ops -verify=ops2 -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+cl_amd_media_ops2 -verify=ops -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins -// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+cl_amd_media_ops -verify=ops2 -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+__opencl_c_int64,+cl_amd_media_ops2 -verify=ops -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+__opencl_c_int64,+cl_amd_media_ops -verify=ops2 -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+__opencl_c_int64,+cl_amd_media_ops2 -verify=ops -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -cl-ext=-all,+__opencl_c_int64,+cl_amd_media_ops -verify=ops2 -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins #define TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ ret test_ ## builtin ## _ ## ret ## _## type (type a) { \ diff --git a/clang/test/SemaOpenCL/features.cl b/clang/test/SemaOpenCL/features.cl index e95f94d56c8d9..adf48a11284f1 100644 --- a/clang/test/SemaOpenCL/features.cl +++ b/clang/test/SemaOpenCL/features.cl @@ -1,26 +1,26 @@ // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL3.0 -cl-ext=-all \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// RUN: | FileCheck -match-full-lines %s --check-prefixes=NO-FEATURES,NO-INT64 // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL3.0 -cl-ext=+all \ // RUN: | FileCheck -match-full-lines %s --check-prefix=FEATURES // RUN: %clang_cc1 -triple r600-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL3.0 \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// RUN: | FileCheck -match-full-lines %s --check-prefixes=NO-FEATURES,INT64 // RUN: %clang_cc1 -triple r600-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL3.0 -cl-ext=+all \ // RUN: | FileCheck -match-full-lines %s --check-prefix=FEATURES // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=clc++2021 -cl-ext=-all \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// RUN: | FileCheck -match-full-lines %s --check-prefixes=NO-FEATURES,NO-INT64 // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=clc++2021 -cl-ext=+all \ // RUN: | FileCheck -match-full-lines %s --check-prefix=FEATURES // RUN: %clang_cc1 -triple r600-unknown-unknown %s -E -dM -o - -x cl -cl-std=clc++2021 \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// RUN: | FileCheck -match-full-lines %s --check-prefixes=NO-FEATURES,INT64 // RUN: %clang_cc1 -triple r600-unknown-unknown %s -E -dM -o - -x cl -cl-std=clc++2021 -cl-ext=+all \ // RUN: | FileCheck -match-full-lines %s --check-prefix=FEATURES // For OpenCL C 2.0 feature macros, test that CL2.0 define them but earlier OpenCL // versions don't define feature macros accidentally. // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL1.1 \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// RUN: | FileCheck -match-full-lines %s --check-prefixes=NO-FEATURES,INT64 // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL1.2 \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=NO-FEATURES +// RUN: | FileCheck -match-full-lines %s --check-prefixes=NO-FEATURES,INT64 // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=CL2.0 \ // RUN: | FileCheck -match-full-lines %s --check-prefix=FEATURES-CL20 // RUN: %clang_cc1 -triple spir-unknown-unknown %s -E -dM -o - -x cl -cl-std=clc++1.0 \ @@ -39,8 +39,10 @@ // RUN: -cl-ext=-__opencl_c_read_write_images \ // RUN: | FileCheck %s --check-prefix=DISABLE-FEATURES -// Note that __opencl_c_int64 is always defined assuming -// always compiling for FULL OpenCL profile +// Note that __opencl_c_int64 is defined by default for every OpenCL version +// (the full profile is assumed), but unlike before it now tracks the feature +// option, so it can be disabled with -cl-ext (e.g. for an embedded profile +// target without 64-bit integer support). // FEATURES: #define __opencl_c_3d_image_writes 1 // FEATURES: #define __opencl_c_atomic_order_acq_rel 1 @@ -78,7 +80,8 @@ // FEATURES-CL20: #define __opencl_c_read_write_images 1 // FEATURES-CL20: #define __opencl_c_work_group_collective_functions 1 -// NO-FEATURES: #define __opencl_c_int64 1 +// INT64: #define __opencl_c_int64 1 +// NO-INT64-NOT: #define __opencl_c_int64 1 // NO-FEATURES-NOT: #define __opencl_c_3d_image_writes 1 // NO-FEATURES-NOT: #define __opencl_c_atomic_order_acq_rel 1 // NO-FEATURES-NOT: #define __opencl_c_atomic_order_seq_cst 1 @@ -90,7 +93,6 @@ // NO-FEATURES-NOT: #define __opencl_c_fp64 1 // NO-FEATURES-NOT: #define __opencl_c_generic_address_space 1 // NO-FEATURES-NOT: #define __opencl_c_images 1 -// NO-FEATURES-NOT: #define __opencl_c_int64 1 // NO-FEATURES-NOT: #define __opencl_c_integer_dot_product_input_4x8bit 1 // NO-FEATURES-NOT: #define __opencl_c_integer_dot_product_input_4x8bit_packed 1 // NO-FEATURES-NOT: #define __opencl_c_kernel_clock_scope_device 1 diff --git a/clang/test/SemaOpenCL/int64.cl b/clang/test/SemaOpenCL/int64.cl new file mode 100644 index 0000000000000..bd64ce82bf9a6 --- /dev/null +++ b/clang/test/SemaOpenCL/int64.cl @@ -0,0 +1,59 @@ +// Test that 64-bit integer types require cles_khr_int64 (OpenCL C 1.x, +// embedded profile) or the __opencl_c_int64 feature (OpenCL C 3.0). + +// 64-bit integers are available by default: the full profile is assumed. +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=good -fsyntax-only -cl-std=CL1.2 +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=good -fsyntax-only -cl-std=CL3.0 + +// Either option restores 64-bit integers after -cl-ext=-all. +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=good -fsyntax-only -cl-std=CL1.2 -cl-ext=-all,+cles_khr_int64 +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=good -fsyntax-only -cl-std=CL3.0 -cl-ext=-all,+__opencl_c_int64 + +// With both options disabled, 64-bit integer types and literals are rejected. +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=err12 -fsyntax-only -cl-std=CL1.2 -cl-ext=-cles_khr_int64,-__opencl_c_int64 +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=err30 -fsyntax-only -cl-std=CL3.0 -cl-ext=-all + +// The -fdeclare-opencl-builtins overloads follow the same two options. +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=good -fsyntax-only -cl-std=CL3.0 -fdeclare-opencl-builtins -DBUILTINS +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=good -fsyntax-only -cl-std=CL1.2 -cl-ext=-all,+cles_khr_int64 -fdeclare-opencl-builtins -DBUILTINS +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify=err30,errb -fsyntax-only -cl-std=CL3.0 -cl-ext=-all -fdeclare-opencl-builtins -DBUILTINS + +// good-no-diagnostics + +typedef long long_vec2 __attribute__((ext_vector_type(2))); +// err12-error@-1{{use of type 'long' requires cles_khr_int64 support}} +// err30-error@-2{{use of type 'long' requires __opencl_c_int64 support}} + +kernel void test_int64(void) { + long l; + // err12-error@-1{{use of type 'long' requires cles_khr_int64 support}} + // err30-error@-2{{use of type 'long' requires __opencl_c_int64 support}} + + unsigned long ul; + // err12-error@-1{{use of type 'unsigned long' requires cles_khr_int64 support}} + // err30-error@-2{{use of type 'unsigned long' requires __opencl_c_int64 support}} + + // Pointers to 64-bit integers are rejected as well: without the extension + // the types do not exist at all (unlike half with cl_khr_fp16). + private long *p; + // err12-error@-1{{use of type 'long' requires cles_khr_int64 support}} + // err30-error@-2{{use of type 'long' requires __opencl_c_int64 support}} + + // A literal that does not fit in 32 bits gets a 64-bit type without any + // 'long' declaration, so it is diagnosed too. + (void)5000000000; + // err12-error@-1{{use of type 'long' requires cles_khr_int64 support}} + // err30-error@-2{{use of type 'long' requires __opencl_c_int64 support}} + + // 32-bit literals are fine. + (void)2147483647; +} + +#ifdef BUILTINS +kernel void test_int64_builtins(int i) { + long l = convert_long(i); + // err30-error@-1{{use of type 'long' requires __opencl_c_int64 support}} + // errb-error@-2{{use of undeclared identifier 'convert_long'}} + (void)l; +} +#endif _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
