Index: clang/lib/Sema/OpenCLBuiltins.td =================================================================== --- clang/lib/Sema/OpenCLBuiltins.td +++ clang/lib/Sema/OpenCLBuiltins.td @@ -20,12 +20,13 @@ //===----------------------------------------------------------------------===// // Versions of OpenCL class Version { - int Version = _Version; + int ID = _Version; } -def CL10: Version<100>; -def CL11: Version<110>; -def CL12: Version<120>; -def CL20: Version<200>; +def CLAll : Version< 0>; +def CL10 : Version<100>; +def CL11 : Version<110>; +def CL12 : Version<120>; +def CL20 : Version<200>; // Address spaces // Pointer types need to be assigned an address space. @@ -197,8 +198,13 @@ list Signature = _Signature; // OpenCL Extension to which the function belongs (cl_khr_subgroups, ...) string Extension = ""; - // OpenCL Version to which the function belongs (CL10, ...) - Version Version = CL10; + // Version of OpenCL from which the function is available (e.g.: CL10). + // MinVersion is inclusive. + Version MinVersion = CL10; + // Version of OpenCL from which the function is not supported anymore. + // MaxVersion is exclusive. + // CLAll makes the function available for all versions. + Version MaxVersion = CLAll; } //===----------------------------------------------------------------------===// @@ -318,6 +324,137 @@ } } +//-------------------------------------------------------------------- +// OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0 s6.13.1 - Work-item Functions +// --- Table 7 --- +def : Builtin<"get_work_dim", [UInt]>; +foreach name = ["get_global_size", "get_global_id", "get_local_size", + "get_local_id", "get_num_groups", "get_group_id", + "get_global_offset"] in { + def : Builtin; +} + +let MinVersion = CL20 in { + def : Builtin<"get_enqueued_local_size", [Size, UInt]>; + foreach name = ["get_global_linear_id", "get_local_linear_id"] in { + def : Builtin; + } +} + +//-------------------------------------------------------------------- +// OpenCL v1.1 s6.11.7, v1.2 s6.12.7, v2.0 s6.13.7 - Vector Data Load and Store Functions +// OpenCL Extension v1.1 s9.3.6 and s9.6.6, v1.2 s9.5.6, v2.0 s9.4.6, v2.0 s5.1.6 and 6.1.6 - Vector Data Load and Store Functions +// --- Table 15 --- +// Variants for OpenCL versions below 2.0, using pointers to the global, local +// and private address spaces. +let MaxVersion = CL20 in { + foreach AS = [GlobalAS, LocalAS, PrivateAS] in { + foreach VSize = [2, 3, 4, 8, 16] in { + foreach name = ["vload" # VSize] in { + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + } + foreach name = ["vstore" # VSize] in { + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + def : Builtin, Size, PointerType, AS>]>; + } + foreach name = ["vloada_half" # VSize] in { + def : Builtin, Size, PointerType, AS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half" # VSize # rnd] in { + def : Builtin, Size, PointerType]>; + def : Builtin, Size, PointerType]>; + } + } + } + } +} +// Variants for OpenCL versions above 2.0, using pointers to the generic +// address space. +let MinVersion = CL20 in { + foreach VSize = [2, 3, 4, 8, 16] in { + foreach name = ["vload" # VSize] in { + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + } + foreach name = ["vstore" # VSize] in { + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + def : Builtin, Size, PointerType, GenericAS>]>; + } + foreach name = ["vloada_half" # VSize] in { + def : Builtin, Size, PointerType, GenericAS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half" # VSize # rnd] in { + def : Builtin, Size, PointerType]>; + def : Builtin, Size, PointerType]>; + } + } + } +} +// Variants using pointers to the constant address space. +foreach VSize = [2, 3, 4, 8, 16] in { + foreach name = ["vload" # VSize] in { + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + def : Builtin, Size, PointerType, ConstantAS>]>; + } + foreach name = ["vloada_half" # VSize] in { + def : Builtin, Size, PointerType, ConstantAS>]>; + } + foreach rnd = ["", "_rte", "_rtz", "_rtp", "_rtn"] in { + foreach name = ["vstorea_half" # VSize # rnd] in { + def : Builtin, Size, PointerType]>; + def : Builtin, Size, PointerType]>; + } + } +} + //-------------------------------------------------------------------- // OpenCL v1.1 s6.11.10, v1.2 s6.12.10, v2.0 s6.13.10: Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch // OpenCL Extension v2.0 s5.1.7 and s6.1.7: Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch @@ -356,14 +493,6 @@ } } -// OpenCL v1.2 s6.12.1: Work-Item Functions -def get_work_dim : Builtin<"get_work_dim", [UInt]>; -foreach name = ["get_global_size", "get_global_id", "get_local_size", - "get_local_id", "get_num_groups", "get_group_id", - "get_global_offset"] in { - def : Builtin; -} - // OpenCL v1.2 s6.12.2: Math Functions foreach name = ["acos", "acosh", "acospi", "asin", "asinh", "asinpi", @@ -517,7 +646,7 @@ // OpenCL v2.0 s9.17.3: Additions to section 6.13.1: Work-Item Functions -let Version = CL20 in { +let MinVersion = CL20 in { let Extension = "cl_khr_subgroups" in { def get_sub_group_size : Builtin<"get_sub_group_size", [UInt]>; def get_max_sub_group_size : Builtin<"get_max_sub_group_size", [UInt]>; Index: clang/lib/Sema/SemaLookup.cpp =================================================================== --- clang/lib/Sema/SemaLookup.cpp +++ clang/lib/Sema/SemaLookup.cpp @@ -764,6 +764,13 @@ BuiltinTable[FctIndex + SignatureIndex]; ASTContext &Context = S.Context; + // Ignore this BIF if its version does not match the language options. + if (Context.getLangOpts().OpenCLVersion < OpenCLBuiltin.MinVersion) + continue; + if ((OpenCLBuiltin.MaxVersion != 0) && + (Context.getLangOpts().OpenCLVersion >= OpenCLBuiltin.MaxVersion)) + continue; + SmallVector RetTypes; SmallVector, 5> ArgTypes; Index: clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl =================================================================== --- clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -1,10 +1,20 @@ +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL -fdeclare-opencl-builtins -DNO_HEADER +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL -fdeclare-opencl-builtins -finclude-default-header +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL1.2 -fdeclare-opencl-builtins -DNO_HEADER +// RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL1.2 -fdeclare-opencl-builtins -finclude-default-header // RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -DNO_HEADER // RUN: %clang_cc1 %s -triple spir -verify -pedantic -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header + +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 // expected-no-diagnostics +#endif // Test the -fdeclare-opencl-builtins option. #pragma OPENCL EXTENSION cl_khr_fp16 : enable +#if __OPENCL_C_VERSION__ < CL_VERSION_1_2 +#pragma OPENCL EXTENSION cl_khr_fp64 : enable +#endif // Provide typedefs when invoking clang without -finclude-default-header. #ifdef NO_HEADER @@ -15,7 +25,10 @@ typedef int int2 __attribute__((ext_vector_type(2))); typedef int int4 __attribute__((ext_vector_type(4))); typedef long long2 __attribute__((ext_vector_type(2))); +typedef unsigned char uchar; typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; typedef __SIZE_TYPE__ size_t; #endif @@ -60,12 +73,14 @@ res = read_imageh(image_read_only_image2d, sampler, i2); } +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 kernel void basic_image_readwrite(read_write image3d_t image_read_write_image3d) { half4 h4; int4 i4; write_imageh(image_read_write_image3d, i4, h4); } +#endif // __OPENCL_C_VERSION__ >= CL_VERSION_2_0 kernel void basic_image_writeonly(write_only image1d_buffer_t image_write_only_image1d_buffer) { half4 h4; @@ -78,4 +93,39 @@ kernel void basic_subgroup(global uint *out) { out[0] = get_sub_group_size(); +#if __OPENCL_C_VERSION__ < CL_VERSION_2_0 +// expected-error@-2{{implicit declaration of function 'get_sub_group_size' is invalid in OpenCL}} +#endif +} + +kernel void basic_vector_data() { +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 + generic void *generic_p; +#endif + constant void *constant_p; + local void *local_p; + global void *global_p; + private void *private_p; + size_t s; + + vload4(s, (const __constant ulong *) constant_p); + vload16(s, (const __constant short *) constant_p); + +#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 + vload3(s, (const __generic ushort *) generic_p); + vload16(s, (const __generic uchar *) generic_p); +#endif + + vload8(s, (const __global long *) global_p); + vload2(s, (const __local uint *) local_p); + vload16(s, (const __private float *) private_p); +} + +kernel void basic_work_item() { + uint ui; + + get_enqueued_local_size(ui); +#if __OPENCL_C_VERSION__ < CL_VERSION_2_0 +// expected-error@-2{{implicit declaration of function 'get_enqueued_local_size' is invalid in OpenCL}} +#endif } Index: clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -121,11 +121,13 @@ // Emit the BuiltinTable table. This table contains all the overloads of // each function, and is a struct OpenCLBuiltinDecl. // E.g.: - // // convert_float2_rtn - // { 58, 2 }, + // // 891 convert_float2_rtn + // { 58, 2, 100, 0 }, // This means that the signature of this convert_float2_rtn overload has // 1 argument (+1 for the return type), stored at index 58 in - // the SignatureTable. + // the SignatureTable. The last two values represent the minimum (1.0) and + // maximum (0, meaning no max version) OpenCL version in which this overload + // is supported. void EmitBuiltinTable(); // Emit a StringMatcher function to check whether a function name is an @@ -268,6 +270,10 @@ // the SignatureTable represent the complete signature. The first type at // index SigTableIndex is the return type. const unsigned NumTypes; + // First OpenCL version in which this overload was introduced (e.g. CL20). + const unsigned short MinVersion; + // First OpenCL version in which this overload was removed (e.g. CL20). + const unsigned short MaxVersion; }; )"; @@ -400,11 +406,13 @@ OS << " // " << (Index + 1) << ": " << FOM.first << "\n"; for (const auto &Overload : FOM.second) { - OS << " { " - << Overload.second << ", " - << Overload.first->getValueAsListOfDefs("Signature").size() + OS << " { " << Overload.second << ", " + << Overload.first->getValueAsListOfDefs("Signature").size() << ", " + << Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID") + << ", " + << Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID") << " },\n"; - Index++; + Index++; } } OS << "};\n\n";