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. @@ -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 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 AccessQualifier = _Ty.AccessQualifier; + let AddrSpace = _Ty.AddrSpace; } -// OpenCL pointer types (e.g.: int*, float*, ...). -class PointerType : +// OpenCL pointer types (e.g.: int*, float*, ...) +class PointerType : Type<_Ty.Name, _Ty.QTName> { - bit IsPointer = 1; - string AddrSpace = _AS.AddrSpace; + 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, ...) @@ -208,10 +245,16 @@ def ListN : IntList<"ListN", [1, 2, 3, 4, 8, 16]>; def ListNNoScalar : IntList<"ListNNoScalar", [2, 3, 4, 8, 16]>; // Lists of types. -def TL00 : TypeList<"TL00", [Float, Double, Half]>; +def TL00 : TypeList<"TL10", [Char, UChar, Short, UShort, Int, UInt, Long, ULong, Float, Double, Half]>; +def TL10 : TypeList<"TL00", [Float, Double, Half]>; // GenTypes definitions. -def FGenTypeN : GenericType<"FGenTypeN", TL00, ListN>; +// All +def AGenTypeN : GenericType<"AGenTypeN", TL00, ListN>; +def AGenTypeNNoScalar : GenericType<"AGenTypeNNoScalar", TL00, ListNNoScalar>; +// Float +def FGenTypeN : GenericType<"FGenTypeN", TL10, ListN>; + // Generate basic GenTypes. Names are like: GenTypeFloatListN. foreach Type = [Char, UChar, Short, UShort, Int, UInt, Long, ULong, @@ -252,6 +295,26 @@ } +//-------------------------------------------------------------------- +// 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, 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,15 @@ 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 @@ -40,7 +40,10 @@ // }; // // static const OpenCLTypeStruct TypeTable[] = { -// {OCLT_Double, 2}, // This represents the double2 type. +// { OCLT_double, 2, 0, 0, 0, clang::LangAS::Default}, +// // This represents the double type, with a vector width of 2, +// // which is not a pointer (0), not a const (0), not a volatile (0). +// // The address space is not relevant since this is not a pointer. // ... // Other types with their vector size. // }; // @@ -169,7 +172,7 @@ // have several attributes (e.g. the size of the vector (if applicable), // if this is a pointer type, a const type, ...). // E.g.: - // {OCLT_Double, 2}, + // { OCLT_Double, 2, 0, 0, 0, clang::LangAS::Default}, // is describing the type "Double", being a vector of 2 elements. See the // struct OpenCLTypeStruct for more information. void EmitTypeTable(); @@ -325,10 +328,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, ...). const OpenCLTypeID ID; // Size of the vector (if applicable, 0 otherwise and for 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; }; // Store one overload of an OpenCL builtin function. Multiple entries of a @@ -390,7 +401,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"; } @@ -420,7 +435,7 @@ OS << "static const OpenCLBuiltinStruct BuiltinTable[] = {\n"; for (const auto &FOM : FctOverloadMap) { - OS << "// " << Index << " "; + OS << "// " << Index << " " << FOM.first << "\n"; for (const auto &Overload : FOM.second) { OS << " { " @@ -494,6 +509,28 @@ QT[Index] = Context.getExtVectorType(QT[Index], Ty.VectorWidth); } } + + 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]); + } + } )"; }