Index: clang/lib/Sema/OpenCLBuiltins.td =================================================================== --- clang/lib/Sema/OpenCLBuiltins.td +++ clang/lib/Sema/OpenCLBuiltins.td @@ -75,22 +75,59 @@ int VecWidth = 1; // Is a pointer. bit IsPointer = 0; + // "const" qualifier. + bit IsConst = 0; + // "volatile" qualifier. + bit IsVolatile = 0; // Access qualifier. Must be one of ("RO", "WO", "RW"). string AccessQualifier = ""; // Address space. - string AddrSpace = "clang::LangAS::Default"; + string AddrSpace = DefaultAS.Name; } -// OpenCL vector types (e.g. int2, int3, int16, float8, ...) +// OpenCL vector types (e.g. int2, int3, int16, float8, ...). class VectorType : Type<_Ty.Name, _Ty.QTName> { - int VecWidth = _VecWidth; + let VecWidth = _VecWidth; + // Inherited fields + let IsPointer = _Ty.IsPointer; + let IsConst = _Ty.IsConst; + let IsVolatile = _Ty.IsVolatile; + let AccessQualifier = _Ty.AccessQualifier; + let AddrSpace = _Ty.AddrSpace; } // OpenCL pointer types (e.g. int*, float*, ...). -class PointerType : +class PointerType : Type<_Ty.Name, _Ty.QTName> { - bit IsPointer = 1; - string AddrSpace = _AS.Name; + let AddrSpace = _AS.Name; + // Inherited fields + let VecWidth = _Ty.VecWidth; + let IsPointer = 1; + let IsConst = _Ty.IsConst; + let IsVolatile = _Ty.IsVolatile; + let AccessQualifier = _Ty.AccessQualifier; +} + +// OpenCL const types (e.g. const int). +class ConstType : Type<_Ty.Name, _Ty.QTName> { + let IsConst = 1; + // Inherited fields + let VecWidth = _Ty.VecWidth; + let IsPointer = _Ty.IsPointer; + let IsVolatile = _Ty.IsVolatile; + let AccessQualifier = _Ty.AccessQualifier; + let AddrSpace = _Ty.AddrSpace; +} + +// OpenCL volatile types (e.g. volatile int). +class VolatileType : Type<_Ty.Name, _Ty.QTName> { + let IsVolatile = 1; + // Inherited fields + let VecWidth = _Ty.VecWidth; + let IsPointer = _Ty.IsPointer; + let IsConst = _Ty.IsConst; + let AccessQualifier = _Ty.AccessQualifier; + let AddrSpace = _Ty.AddrSpace; } // OpenCL image types (e.g. image2d_t, ...) @@ -216,10 +253,15 @@ def VecNoScalar : IntList<"VecNoScalar", [2, 3, 4, 8, 16]>; // Type lists. +def TLAll : TypeList<"TLAll", [Char, UChar, Short, UShort, Int, UInt, Long, ULong, Float, Double, Half]>; def TLFloat : TypeList<"TLFloat", [Float, Double, Half]>; // GenType definitions. +// All +def AGenTypeN : GenericType<"AGenTypeN", TLAll, VecAndScalar>; +def AGenTypeNNoScalar : GenericType<"AGenTypeNNoScalar", TLAll, VecNoScalar>; def FGenTypeN : GenericType<"FGenTypeN", TLFloat, VecAndScalar>; + // Generate basic GenTypes. Names are like: GenTypeFloatVecAndScalar. foreach Type = [Char, UChar, Short, UShort, Int, UInt, Long, ULong, @@ -258,6 +300,44 @@ } } +//-------------------------------------------------------------------- +// 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 +// --- Table 18 --- +foreach name = ["async_work_group_copy"] in { + def : Builtin, PointerType, GlobalAS>, Size, Event]>; + def : Builtin, PointerType, LocalAS>, Size, Event]>; +} +foreach name = ["async_work_group_strided_copy"] in { + def : Builtin, PointerType, GlobalAS>, Size, Size, Event]>; + def : Builtin, PointerType, LocalAS>, Size, Size, Event]>; +} +foreach name = ["wait_group_events"] in { + def : Builtin]>; +} +foreach name = ["prefetch"] in { + def : Builtin, GlobalAS>, Size]>; +} + +//-------------------------------------------------------------------- +// OpenCL v2.0 s6.13.11 - Atomics Functions. +// Functions that use memory_order and cl_mem_fence_flags enums are not +// declared here as the TableGen backend does not handle enums. + +// OpenCL v1.0 s9.5, s9.6, s9.7 - Atomic Functions for 32-bit integers. +// --- Table 9.1 --- +foreach Type = [Int, UInt] in { + foreach name = ["atom_add", "atom_sub", "atom_xchg"] in { + def : Builtin, GlobalAS>, Type]>; + } + foreach name = ["atom_inc", "atom_dec"] in { + def : Builtin, GlobalAS>]>; + } + foreach name = ["atom_cmpxchg"] in { + def : Builtin, GlobalAS>, Type, Type]>; + } +} + // 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", Index: clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl =================================================================== --- clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -15,6 +15,16 @@ typedef __SIZE_TYPE__ size_t; #endif +kernel void test_pointers(volatile global void *global_p, global const int4 *a) { + int i; + unsigned int ui; + + prefetch(a, 2); + + atom_add((volatile __global int *)global_p, i); + atom_cmpxchg((volatile __global unsigned int *)global_p, ui, ui); +} + kernel void basic_conversion() { double d; float f; Index: clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -239,10 +239,18 @@ // Represents a return type or argument type. struct OpenCLTypeStruct { - // A type (e.g. float, int, ...) + // A type (e.g. float, int, ...). const OpenCLTypeID ID; // Vector size (if applicable; 0 for scalars and generic types). const unsigned VectorWidth; + // 0 if the type is not a pointer. + const bool IsPointer; + // 0 if the type is not const. + const bool IsConst; + // 0 if the type is not volatile. + const bool IsVolatile; + // Address space of the pointer (if applicable). + const LangAS AS; }; // One overload of an OpenCL builtin function. @@ -299,7 +307,11 @@ for (const auto &T : TypeMap) { OS << " // " << T.second << "\n"; OS << " { OCLT_" << T.first->getValueAsString("Name") << ", " - << T.first->getValueAsInt("VecWidth") << "},\n"; + << T.first->getValueAsInt("VecWidth") << ", " + << T.first->getValueAsBit("IsPointer") << ", " + << T.first->getValueAsBit("IsConst") << ", " + << T.first->getValueAsBit("IsVolatile") << ", " + << T.first->getValueAsString("AddrSpace") << "},\n"; } OS << "};\n\n"; } @@ -477,6 +489,28 @@ QT[Index] = Context.getExtVectorType(QT[Index], Ty.VectorWidth); } } + + if (Ty.IsVolatile != 0) { + for (unsigned Index = 0; Index < QT.size(); Index++) { + QT[Index] = Context.getVolatileType(QT[Index]); + } + } + + if (Ty.IsConst != 0) { + for (unsigned Index = 0; Index < QT.size(); Index++) { + QT[Index] = Context.getConstType(QT[Index]); + } + } + + // Transform the type to a pointer as the last step, if necessary. + // Builtin functions only have pointers on [const|volatile], no + // [const|volatile] pointers, so this is ok to do it as a last step. + if (Ty.IsPointer != 0) { + for (unsigned Index = 0; Index < QT.size(); Index++) { + QT[Index] = Context.getAddrSpaceQualType(QT[Index], Ty.AS); + QT[Index] = Context.getPointerType(QT[Index]); + } + } )"; // End of the "OCL2Qual" function.