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. @@ -60,8 +60,9 @@ // OpenCL C classes for types //===----------------------------------------------------------------------===// // OpenCL C types (int, float, ...). -// Its Child classes are VectorType, PointerType, ImageType and GenericType. I -// Instances of these child classes should be declared "on the fly". +// Its Child classes are VectorType, PointerType, VolatileType, ConstType, +// ImageType and GenericType. Instances of these child classes should be +// declared "on the fly". // See the definition of the "read_imagef" function as example. class Type { // Name of the Type @@ -72,24 +73,60 @@ int VecWidth = 0; // 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> { @@ -201,6 +238,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, @@ -247,6 +289,28 @@ } + +//-------------------------------------------------------------------- +// OpenCL v2.0/2.2 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 @@ -35,7 +35,6 @@ #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/TableGenBackend.h" -#include using namespace llvm; @@ -239,6 +238,14 @@ enum OpenCLTypeID ID; // Size of the vector (if applicable, 0 otherwise) 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 @@ -284,19 +291,19 @@ } auto Signature = B->getValueAsListOfDefs("Signature"); - auto it = std::find_if( + auto It = std::find_if( SignaturesList.begin(), SignaturesList.end(), [&](const std::pair, unsigned> &a) { return a.first == Signature; }); unsigned SignIndex; - if (it == SignaturesList.end()) { + if (It == SignaturesList.end()) { SignaturesList.push_back(std::make_pair(Signature, CumulativeSignIndex)); SignIndex = CumulativeSignIndex; CumulativeSignIndex += Signature.size(); } else { - SignIndex = it->second; + SignIndex = It->second; } FctOverloadMap[BName].push_back(std::make_pair(B, SignIndex)); } @@ -308,7 +315,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"; } @@ -437,8 +448,7 @@ if (TypesSeen.find(T->getValueAsString("Name")) != TypesSeen.end()) continue; TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true)); - - // Check the Type does not have an "abstract" QualType + // Check the Type doesn't have an "abstract" QualType auto QT = T->getValueAsDef("QTName"); if (QT->getValueAsBit("IsAbstract") == 1) continue; @@ -479,6 +489,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; }