Index: clang/lib/Sema/OpenCLBuiltins.td =================================================================== --- clang/lib/Sema/OpenCLBuiltins.td +++ clang/lib/Sema/OpenCLBuiltins.td @@ -30,14 +30,14 @@ // Address spaces // Pointer types need to be assigned an address space. class AddressSpace { - string AddrSpace = _AS; + string Name = _AS; } -def default_as : AddressSpace<"clang::LangAS::Default">; -def private_as : AddressSpace<"clang::LangAS::opencl_private">; -def global_as : AddressSpace<"clang::LangAS::opencl_global">; -def constant_as : AddressSpace<"clang::LangAS::opencl_constant">; -def local_as : AddressSpace<"clang::LangAS::opencl_local">; -def generic_as : AddressSpace<"clang::LangAS::opencl_generic">; +def DefaultAS : AddressSpace<"clang::LangAS::Default">; +def PrivateAS : AddressSpace<"clang::LangAS::opencl_private">; +def GlobalAS : AddressSpace<"clang::LangAS::opencl_global">; +def ConstantAS : AddressSpace<"clang::LangAS::opencl_constant">; +def LocalAS : AddressSpace<"clang::LangAS::opencl_local">; +def GenericAS : AddressSpace<"clang::LangAS::opencl_generic">; // Qualified Type. Allow to retrieve an ASTContext QualType. @@ -66,32 +66,68 @@ // function arguments. // See the definition of the "read_imagef" function as example. class Type { - // Name of the Type + // Name of the Type. string Name = _Name; - // QualType associated with this type + // QualType associated with this type. QualType QTName = _QTName; - // Size of the vector (if applicable) + // Size of the vector (if applicable). int VecWidth = 0; - // Is pointer + // Is 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 associated. - 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 AddrSpace = _Ty.AddrSpace; + let AccessQualifier = _Ty.AccessQualifier; } -// OpenCL pointer types (e.g. int*, float*, ...) -class PointerType : +// OpenCL pointer types (e.g.: int*) +class PointerType : Type<_Ty.Name, _Ty.QTName> { - bit IsPointer = 1; - string AddrSpace = _AS.AddrSpace; + let AddrSpace = _AS.Name; + // Inherited fields + let IsPointer = 1; + let VecWidth = _Ty.VecWidth; + 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 AddrSpace = _Ty.AddrSpace; + let AccessQualifier = _Ty.AccessQualifier; +} + +// 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 AddrSpace = _Ty.AddrSpace; + let AccessQualifier = _Ty.AccessQualifier; +} // OpenCL image types (e.g. image2d_t, ...) class ImageType : Type<_Ty.Name, _QTName> { @@ -204,6 +240,11 @@ // Lists of int. def ListNNonZero : IntList<"ListNNonZero", [2, 3, 4, 8, 16]>; def ListN : IntList<"ListN", [0, 2, 3, 4, 8, 16]>; +// GenTypes lists. +def GL00 : TypeList<"GL00", [char_t, uchar_t, short_t, ushort_t, int_t, uint_t, long_t, ulong_t, float_t, double_t, half_t]>; +// All +def aGenTypeN : GenericType<"aGenTypeN", GL00, ListN>; +def aGenTypeNNonZero : GenericType<"aGenTypeNNonZero", GL00, ListNNonZero>; // Generate basic GenTypes. Names are like: genType_char_zeroList. foreach Type = [char_t, uchar_t, short_t, ushort_t, @@ -250,6 +291,28 @@ } + +//-------------------------------------------------------------------- +// OpenCL v2.0 s6.13.11 - Atomics Functions. +// Functions are using memory_order and cl_mem_fence_flags typedefs, +// which make them not declarable here. + +// OpenCL v1.0 s9.5, s9.6, s9.7 - Atomic Functions for 32-bit integers. +// --- Table 9.1 --- +foreach Type = [int_t, uint_t] 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_t]>; 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,17 @@ typedef __SIZE_TYPE__ size_t; #endif + +kernel void basic_atomic(volatile __global void* global_p) { + int i; + unsigned int ui; + + 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 @@ -288,10 +288,18 @@ // Store information about types. A function signature reference entries in a // table of this strucure. struct OpenCLTypeStruct { - // A type (e.g.: float, int, ...) + // A type (e.g.: float, int, ...). OpenCLTypeID ID; // Size of the vector (if applicable, 0 otherwise and for generic types). unsigned VectorWidth; + // 0 if the type is not a pointer. + bool IsPointer; + // 0 if the type is not const. + bool IsConst; + // 0 if the type is not volatile. + bool IsVolatile; + // Address space of the pointer (if applicable). + LangAS AS; }; // Store a type (i.e. int, float, int2, ...). The type is stored as an index of @@ -361,7 +369,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"; } @@ -546,6 +558,28 @@ } } + if (Ty.IsVolatile != 0) { + for(Index = 0; Index < QT.size(); Index++) { + QT[Index] = Context.getVolatileType(QT[Index]); + } + } + + if (Ty.IsConst != 0) { + for(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(Index = 0; Index < QT.size(); Index++) { + QT[Index] = Context.getAddrSpaceQualType(QT[Index], Ty.AS); + QT[Index] = Context.getPointerType(QT[Index]); + } + } + return QT; } // OCL2Qual