[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