[clang] 23d65aa - [OpenCL] Support enum and typedef args in TableGen BIFs

Sven van Haastregt via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 17 06:17:55 PST 2021


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 at -1 0+{{candidate function not viable}}
+  // expected-error at -2 0+{{argument type 'void' is incomplete}}
+  // expected-error at -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 at -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.


        


More information about the cfe-commits mailing list