Index: clang/lib/Sema/OpenCLBuiltins.td =================================================================== --- clang/lib/Sema/OpenCLBuiltins.td +++ clang/lib/Sema/OpenCLBuiltins.td @@ -77,10 +77,10 @@ bit IsConst = 0; // "volatile" qualifier bit IsVolatile = 0; - // Access qualifier. Must be one of ("RO", "WO", "RW"). - string AccessQualifier = ""; // Address space associated string AddrSpace = DefaultAS.Name; + // Access qualifier. Must be one of ("RO", "WO", "RW"). + string AccessQualifier = ""; } // OpenCL vector types (e.g.: int2, int3, int16, float8, ...) @@ -127,10 +127,17 @@ let AddrSpace = _Ty.AddrSpace; let AccessQualifier = _Ty.AccessQualifier; } -// OpenCL image types (e.g. image2d_t, ...) -class ImageType : - Type<_Ty.Name, _QTName> { + +// OpenCL image types (e.g.: image2d_t) +class ImageType : + Type<_Ty.Name, QualType<_Ty.QTName.Name#_AccessQualifier#"Ty", 0>> { let AccessQualifier = _AccessQualifier; + // Inherited fields + let VecWidth = _Ty.VecWidth; + let IsPointer = _Ty.IsPointer; + let IsConst = _Ty.IsConst; + let IsVolatile = _Ty.IsVolatile; + let AddrSpace = _Ty.AddrSpace; } // Store a list of Types. @@ -199,38 +206,22 @@ // this file as example. -// OpenCL v1.2 s6.1.3: Other Built-in Data Types -// These definitions with a "null" name are "abstract". They should not -// be used in definitions of Builtin functions. -def image2d_t : Type<"image2d_t", QualType<"null", 1>>; -def image3d_t : Type<"image3d_t", QualType<"null", 1>>; -def image2d_array_t : Type<"image2d_array_t", QualType<"null", 1>>; -def image1d_t : Type<"image1d_t", QualType<"null", 1>>; -def image1d_buffer_t : Type<"image1d_buffer_t", QualType<"null", 1>>; -def image1d_array_t : Type<"image1d_array_t", QualType<"null", 1>>; -// Unlike the few functions above, the following definitions can be used -// in definitions of Builtin functions (they have a QualType with a name). -foreach v = ["RO", "WO", "RW"] in { - def image2d_#v#_t : ImageType, - v>; - def image3d_#v#_t : ImageType, - v>; - def image2d_array#v#_t : ImageType, - v>; - def image1d_#v#_t : ImageType, - v>; - def image1d_buffer#v#_t : ImageType, - v>; - def image1d_array#v#_t : ImageType, - v>; -} - +// OpenCL v1.0/1.2/2.0/2.2 : 6.1.3 : Other Built-in Data Types +// These definitions are "abstract". They should not be used as such. +// They need an access qualifier specified (RO/WO/RW). +// See the OpenCL extension v2.2 s5.1.9 of this file as example. +def image2d_t : Type<"image2d_t", QualType<"OCLImage2d", 1>>; +def image3d_t : Type<"image3d_t", QualType<"OCLImage3d", 1>>; +def image2d_array_t : Type<"image2d_array_t", QualType<"OCLImage2dArray", 1>>; +def image1d_t : Type<"image1d_t", QualType<"OCLImage1d", 1>>; +def image1d_buffer_t : Type<"image1d_buffer_t", QualType<"OCLImage1dBuffer", 1>>; +def image1d_array_t : Type<"image1d_array_t", QualType<"OCLImage1dArray", 1>>; +def image2d_depth_t : Type<"image2d_depth_t", QualType<"OCLImage2dDepth", 1>>; +def image2d_array_depth_t : Type<"image2d_array_depth_t", QualType<"OCLImage2dArrayDepth", 1>>; +def image2d_msaa_t : Type<"image2d_msaa_t", QualType<"OCLImage2dMSAA", 1>>; +def image2d_array_msaa_t : Type<"image2d_array_msaa_t", QualType<"OCLImage2dArrayMSAA", 1>>; +def image2d_msaa_depth_t : Type<"image2d_msaa_depth_t", QualType<"OCLImage2dMSAADepth", 1>>; +def image2d_array_msaa_depth_t : Type<"image2d_array_msaa_depth_t", QualType<"OCLImage2dArrayMSAADepth", 1>>; def sampler_t : Type<"sampler_t", QualType<"OCLSamplerTy">>; def event_t : Type<"event_t", QualType<"OCLEventTy">>; @@ -337,14 +328,52 @@ def : Builtin; } -// OpenCL v1.2 s6.12.14: Built-in Image Read Functions -def read_imagef : Builtin<"read_imagef", - [VectorType, image2d_RO_t, VectorType]>; -def write_imagef : Builtin<"write_imagef", - [void_t, - image2d_WO_t, - VectorType, - VectorType]>; + +// OpenCL extension v2.2 s5.1.9 : Built-in Image Read Functions +// --- Table 8 --- +foreach aQual = ["RO"] in { + foreach name = ["read_imageh"] in { + foreach Type1 = [int_t, float_t] in { + foreach Type2 = [image2d_t, image1d_array_t] in { + def : Builtin, ImageType, sampler_t, VectorType]>; + } + foreach Type2 = [image3d_t, image2d_array_t] in { + def : Builtin, ImageType, sampler_t, VectorType]>; + } + foreach Type2 = [image1d_t] in { + def : Builtin, ImageType, sampler_t, Type1]>; + } + } + } +} +// OpenCL extension v2.2 s5.1.10 : Built-in Image Sampler-less Read Functions +// --- Table 9 --- +foreach aQual = ["RO", "RW"] in { + foreach name = ["read_imageh"] in { + foreach Type1 = [image2d_t, image1d_array_t] in { + def : Builtin, ImageType, VectorType]>; + } + foreach Type1 = [image3d_t, image2d_array_t] in { + def : Builtin, ImageType, VectorType]>; + } + foreach Type1 = [image1d_t, image1d_buffer_t] in { + def : Builtin, ImageType, int_t]>; + } + } +} +// OpenCL extension v2.2 s5.1.11 : Built-in Image Write Functions +// --- Table 10 --- +foreach aQual = ["WO", "RW"] in { + foreach name = ["write_imageh"] in { + def : Builtin, VectorType, VectorType]>; + def : Builtin, VectorType, VectorType]>; + def : Builtin, int_t, VectorType]>; + def : Builtin, int_t, VectorType]>; + def : Builtin, VectorType, VectorType]>; + def : Builtin, VectorType, VectorType]>; + } +} + // OpenCL v2.0 s9.17.3: Additions to section 6.13.1: Work-Item Functions Index: clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl =================================================================== --- clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -4,10 +4,13 @@ // Test the -fdeclare-opencl-builtins option. +#pragma OPENCL EXTENSION cl_khr_fp16 : enable + // Provide typedefs when invoking clang without -finclude-default-header. #ifdef NO_HEADER typedef char char2 __attribute__((ext_vector_type(2))); typedef float float4 __attribute__((ext_vector_type(4))); +typedef half half4 __attribute__((ext_vector_type(4))); typedef int int2 __attribute__((ext_vector_type(2))); typedef int int4 __attribute__((ext_vector_type(4))); typedef long long2 __attribute__((ext_vector_type(2))); @@ -40,8 +43,26 @@ i4 = convert_int4_sat(f4); } -kernel void basic_readonly_image_type(__read_only image2d_t img, int2 coord, global float4 *out) { - out[0] = read_imagef(img, coord); +kernel void basic_readonly_image_type(read_only image2d_t image_read_only_image2d) { + int2 i2; + sampler_t sampler; + + read_imageh(image_read_only_image2d, i2); + read_imageh(image_read_only_image2d, sampler, i2); +} + +kernel void basic_writeonly_image_type(write_only image1d_buffer_t image_write_only_image1d_buffer) { + half4 h4; + int i; + + write_imageh(image_write_only_image1d_buffer, i, h4); +} + +kernel void basic_readwrite_image_type(read_write image3d_t image_read_write_image3d) { + half4 h4; + int4 i4; + + write_imageh(image_read_write_image3d, i4, h4); } kernel void basic_subgroup(global uint *out) { Index: clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -244,6 +244,8 @@ bool IsConst; // 0 if the type is not volatile bool IsVolatile; + // 0:default, 1:read_only, 2:write_only, 3:read_write + unsigned AccessQualifier; // Address space of the pointer (if applicable) LangAS AS; }; @@ -311,14 +313,40 @@ void BuiltinNameEmitter::EmitTypeTable() { + // Access Qualifier + unsigned AQ; + std::string AQName; + OS << "static const OpenCLTypeStruct TypeTable[] = {\n"; for (const auto &T : TypeMap) { + AQ = 0; + AQName = T.first->getValueAsString("AccessQualifier"); + switch (AQName[0]) { + case 'R': + switch (AQName[1]) { + case 'O': // RO + AQ = 1; + break; + case 'W': // RW + AQ = 3; + break; + } + break; + case 'W': // WO + AQ = 2; + break; + default: // default + AQ = 0; + break; + } + OS << "// " << T.second << "\n"; OS << "{ OCLT_" << T.first->getValueAsString("Name") << ", " << T.first->getValueAsInt("VecWidth") << ", " << T.first->getValueAsBit("IsPointer") << ", " << T.first->getValueAsBit("IsConst") << ", " << T.first->getValueAsBit("IsVolatile") << ", " + << AQ << ", " // AccessQualifier << T.first->getValueAsString("AddrSpace") << "},\n"; } OS << "};\n\n"; @@ -415,6 +443,51 @@ OS << "\n\n switch (Ty.ID) {\n"; + // Switch cases for image types (image2d, image3d, ...) + std::vector ImageTypes = + Records.getAllDerivedDefinitions("ImageType"); + // Map an image type name to its records + std::map> ImageTypesMap; + for (auto *IT : ImageTypes) { + std::map>::iterator Entry = + ImageTypesMap.find(IT->getValueAsString("Name")); + if (Entry == ImageTypesMap.end()) { + SmallVector ImageList; + ImageList.push_back(IT); + ImageTypesMap.insert(std::make_pair(IT->getValueAsString("Name"), + ImageList)); + } else { + Entry->second.push_back(IT); + } + } + // Emit the cases for the image types + for (const auto &ITE : ImageTypesMap) { + OS << " case OCLT_" << ITE.first.str() << ":\n"; + OS << " switch (Ty.AccessQualifier) {\n"; + for (const auto &Image : ITE.second) { + switch (Image->getValueAsString("AccessQualifier").str()[0]) { + case 'R': + switch (Image->getValueAsString("AccessQualifier").str()[1]) { + case 'O': + OS << " case 1: // RO\n"; + break; + case 'W': + OS << " case 3: // RW\n"; + break; + } + break; + case 'W': + OS << " case 2: // WO\n"; + break; + } + OS << " QT.push_back(Context." + << Image->getValueAsDef("QTName")->getValueAsString("Name") << ");\n" + << " break;\n"; + } + OS << " }\n"; + OS << " break;\n"; + } + // Switch case for generic types for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) { OS << " case OCLT_" << GenType->getValueAsString("Name") << ":\n"; @@ -444,7 +517,10 @@ StringMap TypesSeen; for (const auto *T : Types) { - // Check we have not seen this Type + // Check this is not an image type + if (ImageTypesMap.find(T->getValueAsString("Name")) != ImageTypesMap.end()) + continue; + // Check we haven't seen this Type if (TypesSeen.find(T->getValueAsString("Name")) != TypesSeen.end()) continue; TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));