diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9886,6 +9886,8 @@ "pointer to type %0 is invalid in OpenCL">; def err_opencl_type_can_only_be_used_as_function_parameter : Error < "type %0 can only be used as a function parameter in OpenCL">; +def err_opencl_type_not_found : Error< + "type %0 not found; include the base header with -finclude-default-header">; def warn_opencl_attr_deprecated_ignored : Warning < "%0 attribute is deprecated and ignored in OpenCL version %1">, InGroup; diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -177,6 +177,16 @@ let AddrSpace = _Ty.AddrSpace; } +// OpenCL enum type (e.g. memory_scope). +class EnumType : + Type<_Name, QualType<"getOpenCLEnumType(S, \"" # _Name # "\")", 0>> { +} + +// OpenCL typedef type (e.g. cl_mem_fence_flags). +class TypedefType : + Type<_Name, QualType<"getOpenCLTypedefType(S, \"" # _Name # "\")", 0>> { +} + // List of Types. class TypeList _Type> { list List = _Type; @@ -298,6 +308,7 @@ def Event : Type<"event_t", QualType<"Context.OCLEventTy">>; def Queue : Type<"queue_t", QualType<"Context.OCLQueueTy">>; def ReserveId : Type<"reserve_id_t", QualType<"Context.OCLReserveIDTy">>; +def MemFenceFlags : TypedefType<"cl_mem_fence_flags">; // OpenCL v2.0 s6.13.11: Atomic integer and floating-point types. def AtomicInt : Type<"atomic_int", QualType<"Context.getAtomicType(Context.IntTy)">>; @@ -311,6 +322,9 @@ def AtomicSize : Type<"atomic_size_t", QualType<"Context.getAtomicType(Context.getSizeType())">>; def AtomicPtrDiff : Type<"atomic_ptrdiff_t", QualType<"Context.getAtomicType(Context.getPointerDiffType())">>; +def MemoryOrder : EnumType<"memory_order">; +def MemoryScope : EnumType<"memory_scope">; + //===----------------------------------------------------------------------===// // Definitions of OpenCL gentype variants //===----------------------------------------------------------------------===// @@ -893,6 +907,9 @@ } } +// OpenCL v3.0 s6.15.8 - Synchronization Functions. +def : Builtin<"barrier", [Void, MemFenceFlags], Attr.Convergent>; + //-------------------------------------------------------------------- // 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 @@ -1024,6 +1041,12 @@ def : Builtin<"atomic_compare_exchange_" # Variant, [Bool, PointerType, GenericAS>, PointerType, TypePair[1]]>; + def : Builtin<"atomic_compare_exchange_" # Variant # "_explicit", + [Bool, PointerType, GenericAS>, + PointerType, TypePair[1], MemoryOrder, MemoryOrder]>; + def : Builtin<"atomic_compare_exchange_" # Variant # "_explicit", + [Bool, PointerType, GenericAS>, + PointerType, TypePair[1], MemoryOrder, MemoryOrder, MemoryScope]>; } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -679,7 +679,7 @@ /// Get the QualType instances of the return type and arguments for an OpenCL /// builtin function signature. -/// \param Context (in) The Context instance. +/// \param S (in) The Sema instance. /// \param OpenCLBuiltin (in) The signature currently handled. /// \param GenTypeMaxCnt (out) Maximum number of types contained in a generic /// type used as return type or as argument. @@ -689,20 +689,20 @@ /// argument, ArgTypes contains QualTypes for the Cartesian product /// of (vector sizes) x (types) . static void GetQualTypesForOpenCLBuiltin( - ASTContext &Context, const OpenCLBuiltinStruct &OpenCLBuiltin, - unsigned &GenTypeMaxCnt, SmallVector &RetTypes, + Sema &S, const OpenCLBuiltinStruct &OpenCLBuiltin, unsigned &GenTypeMaxCnt, + SmallVector &RetTypes, SmallVector, 5> &ArgTypes) { // Get the QualType instances of the return types. unsigned Sig = SignatureTable[OpenCLBuiltin.SigTableIndex]; - OCL2Qual(Context, TypeTable[Sig], RetTypes); + OCL2Qual(S, TypeTable[Sig], RetTypes); GenTypeMaxCnt = RetTypes.size(); // Get the QualType instances of the arguments. // First type is the return type, skip it. for (unsigned Index = 1; Index < OpenCLBuiltin.NumTypes; Index++) { SmallVector Ty; - OCL2Qual(Context, - TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]], Ty); + OCL2Qual(S, TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]], + Ty); GenTypeMaxCnt = (Ty.size() > GenTypeMaxCnt) ? Ty.size() : GenTypeMaxCnt; ArgTypes.push_back(std::move(Ty)); } @@ -789,8 +789,8 @@ SmallVector, 5> ArgTypes; // Obtain QualType lists for the function signature. - GetQualTypesForOpenCLBuiltin(Context, OpenCLBuiltin, GenTypeMaxCnt, - RetTypes, ArgTypes); + GetQualTypesForOpenCLBuiltin(S, OpenCLBuiltin, GenTypeMaxCnt, RetTypes, + ArgTypes); if (GenTypeMaxCnt > 1) { HasGenType = true; } diff --git a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl --- a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -34,6 +34,9 @@ typedef uint uint4 __attribute__((ext_vector_type(4))); typedef long long2 __attribute__((ext_vector_type(2))); +typedef uint cl_mem_fence_flags; +#define CLK_GLOBAL_MEM_FENCE 0x02 + // Enable extensions that are enabled in opencl-c-base.h. #if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #define cl_khr_subgroup_ballot 1 @@ -52,6 +55,18 @@ atom_cmpxchg((volatile __global unsigned int *)global_p, ui, ui); } +// Only test enum arguments when the base header is included, because we need +// the enum declarations. +#if !defined(NO_HEADER) && (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) +kernel void test_enum_args(volatile global atomic_int *global_p, global int* expected) { + int desired; + atomic_compare_exchange_strong_explicit(global_p, expected, desired, + memory_order_acq_rel, + memory_order_relaxed, + memory_scope_work_group); +} +#endif + kernel void basic_conversion() { double d; float f; @@ -180,6 +195,8 @@ kernel void basic_work_item() { uint ui; + barrier(CLK_GLOBAL_MEM_FENCE); + get_enqueued_local_size(ui); #if !defined(__OPENCL_CPP_VERSION__) && __OPENCL_C_VERSION__ < CL_VERSION_2_0 // expected-error@-2{{implicit declaration of function 'get_enqueued_local_size' is invalid in OpenCL}} diff --git a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp --- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -715,6 +715,30 @@ void BuiltinNameEmitter::EmitQualTypeFinder() { OS << R"( +// Lookup an OpenCL enum type. +static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name) { + LookupResult Result(S, &S.Context.Idents.get(Name), SourceLocation(), + Sema::LookupTagName); + S.LookupName(Result, S.TUScope); + if (Result.empty()) { + S.Diag(SourceLocation(), diag::err_opencl_type_not_found) << Name; + return S.Context.VoidTy; + } + return S.Context.getEnumType(Result.getAsSingle()); +} + +// Lookup an OpenCL typedef type. +static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name) { + LookupResult Result(S, &S.Context.Idents.get(Name), SourceLocation(), + Sema::LookupOrdinaryName); + S.LookupName(Result, S.TUScope); + if (Result.empty()) { + S.Diag(SourceLocation(), diag::err_opencl_type_not_found) << Name; + return S.Context.VoidTy; + } + return S.Context.getTypedefType(Result.getAsSingle()); +} + // Convert an OpenCLTypeStruct type to a list of QualTypes. // Generic types represent multiple types and vector sizes, thus a vector // is returned. The conversion is done in two steps: @@ -723,8 +747,9 @@ // or a single scalar type for non generic types. // Step 2: Qualifiers and other type properties such as vector size are // applied. -static void OCL2Qual(ASTContext &Context, const OpenCLTypeStruct &Ty, +static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty, llvm::SmallVectorImpl &QT) { + ASTContext &Context = S.Context; // Number of scalar types in the GenType. unsigned GenTypeNumTypes; // Pointer to the list of vector sizes for the GenType.