Author: Sven van Haastregt Date: 2021-02-17T14:17:43Z New Revision: 23d65aa446312402a0b4615122f0a18d4467ed60
URL: https://github.com/llvm/llvm-project/commit/23d65aa446312402a0b4615122f0a18d4467ed60 DIFF: https://github.com/llvm/llvm-project/commit/23d65aa446312402a0b4615122f0a18d4467ed60.diff LOG: [OpenCL] Support enum and typedef args in TableGen BIFs Add enum and typedef argument support to `-fdeclare-opencl-builtins`, which was the last major missing feature. Adding the remaining missing builtins is left as future work. Differential Revision: https://reviews.llvm.org/D96051 Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/OpenCLBuiltins.td clang/lib/Sema/SemaLookup.cpp clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f69ef3286975..a7a6b250b5a8 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9893,6 +9893,8 @@ def err_opencl_pointer_to_type : Error< "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< + "%0 type %1 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<IgnoredAttributes>; diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td index 7f32be6cc8e8..7f0e0c1e8297 100644 --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -178,6 +178,16 @@ class ImageType<Type _Ty, string _AccessQualifier> : let AddrSpace = _Ty.AddrSpace; } +// OpenCL enum type (e.g. memory_scope). +class EnumType<string _Name> : + Type<_Name, QualType<"getOpenCLEnumType(S, \"" # _Name # "\")", 0>> { +} + +// OpenCL typedef type (e.g. cl_mem_fence_flags). +class TypedefType<string _Name> : + Type<_Name, QualType<"getOpenCLTypedefType(S, \"" # _Name # "\")", 0>> { +} + // List of Types. class TypeList<list<Type> _Type> { list<Type> List = _Type; @@ -299,6 +309,7 @@ def ClkEvent : Type<"clk_event_t", QualType<"Context.OCLClkEventTy" 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)">>; @@ -312,6 +323,9 @@ def AtomicUIntPtr : Type<"atomic_uintptr_t", QualType<"Context.getAtomic def AtomicSize : Type<"atomic_size_t", QualType<"Context.getAtomicType(Context.getSizeType())">>; def AtomicPtrDiff : Type<"atomic_ptr diff _t", QualType<"Context.getAtomicType(Context.getPointerDiffType())">>; +def MemoryOrder : EnumType<"memory_order">; +def MemoryScope : EnumType<"memory_scope">; + //===----------------------------------------------------------------------===// // Definitions of OpenCL gentype variants //===----------------------------------------------------------------------===// @@ -897,6 +911,9 @@ foreach AS = [ConstantAS] in { } } +// 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 @@ -1028,6 +1045,12 @@ let MinVersion = CL20 in { def : Builtin<"atomic_compare_exchange_" # Variant, [Bool, PointerType<VolatileType<TypePair[0]>, GenericAS>, PointerType<TypePair[1], GenericAS>, TypePair[1]]>; + def : Builtin<"atomic_compare_exchange_" # Variant # "_explicit", + [Bool, PointerType<VolatileType<TypePair[0]>, GenericAS>, + PointerType<TypePair[1], GenericAS>, TypePair[1], MemoryOrder, MemoryOrder]>; + def : Builtin<"atomic_compare_exchange_" # Variant # "_explicit", + [Bool, PointerType<VolatileType<TypePair[0]>, GenericAS>, + PointerType<TypePair[1], GenericAS>, TypePair[1], MemoryOrder, MemoryOrder, MemoryScope]>; } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 3556f07b1fe5..404f24d8ce0a 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -677,9 +677,43 @@ LLVM_DUMP_METHOD void LookupResult::dump() { D->dump(); } +/// Diagnose a missing builtin type. +static QualType diagOpenCLBuiltinTypeError(Sema &S, llvm::StringRef TypeClass, + llvm::StringRef Name) { + S.Diag(SourceLocation(), diag::err_opencl_type_not_found) + << TypeClass << Name; + return S.Context.VoidTy; +} + +/// 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()) + return diagOpenCLBuiltinTypeError(S, "enum", Name); + EnumDecl *Decl = Result.getAsSingle<EnumDecl>(); + if (!Decl) + return diagOpenCLBuiltinTypeError(S, "enum", Name); + return S.Context.getEnumType(Decl); +} + +/// 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()) + return diagOpenCLBuiltinTypeError(S, "typedef", Name); + TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>(); + if (!Decl) + return diagOpenCLBuiltinTypeError(S, "typedef", Name); + return S.Context.getTypedefType(Decl); +} + /// 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 +723,20 @@ LLVM_DUMP_METHOD void LookupResult::dump() { /// argument, ArgTypes contains QualTypes for the Cartesian product /// of (vector sizes) x (types) . static void GetQualTypesForOpenCLBuiltin( - ASTContext &Context, const OpenCLBuiltinStruct &OpenCLBuiltin, - unsigned &GenTypeMaxCnt, SmallVector<QualType, 1> &RetTypes, + Sema &S, const OpenCLBuiltinStruct &OpenCLBuiltin, unsigned &GenTypeMaxCnt, + SmallVector<QualType, 1> &RetTypes, SmallVector<SmallVector<QualType, 1>, 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<QualType, 1> 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 +823,8 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, SmallVector<SmallVector<QualType, 1>, 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 index 6fa428125ce1..5614c097f5e6 100644 --- a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -17,6 +17,17 @@ #pragma OPENCL EXTENSION cl_khr_fp64 : enable #endif +// First, test that Clang gracefully handles missing types. +#ifdef NO_HEADER +void test_without_header() { + barrier(0); + // expected-note@-1 0+{{candidate function not viable}} + // expected-error@-2 0+{{argument type 'void' is incomplete}} + // expected-error@-3 0+{{no matching function for call to 'barrier'}} + // expected-error@* {{typedef type cl_mem_fence_flags not found; include the base header with -finclude-default-header}} +} +#endif + // Provide typedefs when invoking clang without -finclude-default-header. #ifdef NO_HEADER typedef unsigned char uchar; @@ -34,6 +45,9 @@ typedef int int4 __attribute__((ext_vector_type(4))); 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_extended_types 1 @@ -53,6 +67,18 @@ kernel void test_pointers(volatile global void *global_p, global const int4 *a) 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; @@ -184,6 +210,8 @@ kernel void basic_vector_data() { 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 index fa45e6b630f5..2288e2711e6a 100644 --- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -48,7 +48,7 @@ // Find out whether a string matches an existing OpenCL builtin function // name and return an index into BuiltinTable and the number of overloads. // -// * void OCL2Qual(ASTContext&, OpenCLTypeStruct, std::vector<QualType>&) +// * void OCL2Qual(Sema&, OpenCLTypeStruct, std::vector<QualType>&) // Convert an OpenCLTypeStruct type to a list of QualType instances. // One OpenCLTypeStruct can represent multiple types, primarily when using // GenTypes. @@ -628,6 +628,9 @@ static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name) { void BuiltinNameEmitter::EmitQualTypeFinder() { OS << R"( +static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name); +static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name); + // 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: @@ -636,8 +639,9 @@ void BuiltinNameEmitter::EmitQualTypeFinder() { // 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<QualType> &QT) { + ASTContext &Context = S.Context; // Number of scalar types in the GenType. unsigned GenTypeNumTypes; // Pointer to the list of vector sizes for the GenType. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits