[clang] e2b3b89 - [OpenCL] Do not add builtins with unavailable types
Sven van Haastregt via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 21 04:00:16 PDT 2021
Author: Sven van Haastregt
Date: 2021-04-21T11:59:29+01:00
New Revision: e2b3b89bf1ce74bf889897e0353a3e3fa93e4452
URL: https://github.com/llvm/llvm-project/commit/e2b3b89bf1ce74bf889897e0353a3e3fa93e4452
DIFF: https://github.com/llvm/llvm-project/commit/e2b3b89bf1ce74bf889897e0353a3e3fa93e4452.diff
LOG: [OpenCL] Do not add builtins with unavailable types
Add functionality to assign extensions to types in OpenCLBuiltins.td
and use that information to filter candidates that should not be
exposed if a type is not available.
Differential Revision: https://reviews.llvm.org/D100209
Added:
Modified:
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/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td
index 1f9a7390cd148..5a9d9822dbfe3 100644
--- a/clang/lib/Sema/OpenCLBuiltins.td
+++ b/clang/lib/Sema/OpenCLBuiltins.td
@@ -50,6 +50,18 @@ class AbstractExtension<string _Ext> {
// Extension associated to a builtin function.
class FunctionExtension<string _Ext> : AbstractExtension<_Ext>;
+// Extension associated to a type. This enables implicit conditionalization of
+// builtin function overloads containing a type that depends on an extension.
+// During overload resolution, when a builtin function overload contains a type
+// with a TypeExtension, those overloads are skipped when the extension is
+// disabled.
+class TypeExtension<string _Ext> : AbstractExtension<_Ext>;
+
+// TypeExtension definitions.
+def NoTypeExt : TypeExtension<"">;
+def Fp16TypeExt : TypeExtension<"cl_khr_fp16">;
+def Fp64TypeExt : TypeExtension<"cl_khr_fp64">;
+
// FunctionExtension definitions.
def FuncExtNone : FunctionExtension<"">;
def FuncExtKhrSubgroups : FunctionExtension<"cl_khr_subgroups">;
@@ -119,6 +131,8 @@ class Type<string _Name, QualType _QTExpr> {
string AccessQualifier = "";
// Address space.
string AddrSpace = DefaultAS.Name;
+ // Extension that needs to be enabled to expose a builtin that uses this type.
+ TypeExtension Extension = NoTypeExt;
}
// OpenCL vector types (e.g. int2, int3, int16, float8, ...).
@@ -130,6 +144,7 @@ class VectorType<Type _Ty, int _VecWidth> : Type<_Ty.Name, _Ty.QTExpr> {
let IsConst = _Ty.IsConst;
let IsVolatile = _Ty.IsVolatile;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL pointer types (e.g. int*, float*, ...).
@@ -142,6 +157,7 @@ class PointerType<Type _Ty, AddressSpace _AS = DefaultAS> :
let IsConst = _Ty.IsConst;
let IsVolatile = _Ty.IsVolatile;
let AccessQualifier = _Ty.AccessQualifier;
+ let Extension = _Ty.Extension;
}
// OpenCL const types (e.g. const int).
@@ -153,6 +169,7 @@ class ConstType<Type _Ty> : Type<_Ty.Name, _Ty.QTExpr> {
let IsVolatile = _Ty.IsVolatile;
let AccessQualifier = _Ty.AccessQualifier;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL volatile types (e.g. volatile int).
@@ -164,6 +181,7 @@ class VolatileType<Type _Ty> : Type<_Ty.Name, _Ty.QTExpr> {
let IsConst = _Ty.IsConst;
let AccessQualifier = _Ty.AccessQualifier;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL image types (e.g. image2d).
@@ -176,6 +194,7 @@ class ImageType<Type _Ty, string _AccessQualifier> :
let IsConst = _Ty.IsConst;
let IsVolatile = _Ty.IsVolatile;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL enum type (e.g. memory_scope).
@@ -277,8 +296,12 @@ def UInt : Type<"uint", QualType<"Context.UnsignedIntTy">>;
def Long : Type<"long", QualType<"Context.LongTy">>;
def ULong : Type<"ulong", QualType<"Context.UnsignedLongTy">>;
def Float : Type<"float", QualType<"Context.FloatTy">>;
-def Double : Type<"double", QualType<"Context.DoubleTy">>;
-def Half : Type<"half", QualType<"Context.HalfTy">>;
+let Extension = Fp64TypeExt in {
+ def Double : Type<"double", QualType<"Context.DoubleTy">>;
+}
+let Extension = Fp16TypeExt in {
+ def Half : Type<"half", QualType<"Context.HalfTy">>;
+}
def Size : Type<"size_t", QualType<"Context.getSizeType()">>;
def PtrDiff : Type<"ptr
diff _t", QualType<"Context.getPointerDiffType()">>;
def IntPtr : Type<"intptr_t", QualType<"Context.getIntPtrType()">>;
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 9eba3e812bbf1..db6a01543d76a 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -759,11 +759,20 @@ static void GetOpenCLBuiltinFctOverloads(
Context.getDefaultCallingConvention(false, false, true));
PI.Variadic = false;
+ // Do not attempt to create any FunctionTypes if there are no return types,
+ // which happens when a type belongs to a disabled extension.
+ if (RetTypes.size() == 0)
+ return;
+
// Create FunctionTypes for each (gen)type.
for (unsigned IGenType = 0; IGenType < GenTypeMaxCnt; IGenType++) {
SmallVector<QualType, 5> ArgList;
for (unsigned A = 0; A < ArgTypes.size(); A++) {
+ // Bail out if there is an argument that has no available types.
+ if (ArgTypes[A].size() == 0)
+ return;
+
// Builtins such as "max" have an "sgentype" argument that represents
// the corresponding scalar type of a gentype. The number of gentypes
// must be a multiple of the number of sgentypes.
diff --git a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
index 103d1d8b262b5..36bdcffbeca48 100644
--- a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
+++ b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
@@ -6,6 +6,7 @@
// RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header
// RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CLC++ -fdeclare-opencl-builtins -DNO_HEADER
// RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CLC++ -fdeclare-opencl-builtins -finclude-default-header
+// RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header -cl-ext=-cl_khr_fp64 -DNO_FP64
// Test the -fdeclare-opencl-builtins option. This is not a completeness
// test, so it should not test for all builtins defined by OpenCL. Instead
@@ -122,15 +123,19 @@ void test_atomic_fetch(volatile __generic atomic_int *a_int,
#endif
kernel void basic_conversion() {
- double d;
float f;
char2 c2;
long2 l2;
float4 f4;
int4 i4;
+#ifdef NO_FP64
+ (void)convert_double_rtp(f);
+ // expected-error at -1{{implicit declaration of function 'convert_double_rtp' is invalid in OpenCL}}
+#else
+ double d;
f = convert_float(d);
- d = convert_double_rtp(f);
+#endif
l2 = convert_long2_rtz(c2);
i4 = convert_int4_sat(f4);
}
@@ -271,3 +276,13 @@ kernel void basic_work_item() {
// expected-error at -2{{implicit declaration of function 'get_enqueued_local_size' is invalid in OpenCL}}
#endif
}
+
+#ifdef NO_FP64
+void test_extension_types(char2 c2) {
+ // We should see 6 candidates for float and half types, and none for double types.
+ int i = isnan(c2);
+ // expected-error at -1{{no matching function for call to 'isnan'}}
+ // expected-note at -2 6 {{candidate function not viable: no known conversion from '__private char2' (vector of 2 'char' values) to 'float}}
+ // expected-note at -3 6 {{candidate function not viable: no known conversion from '__private char2' (vector of 2 'char' values) to 'half}}
+}
+#endif
diff --git a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
index aa22eea2ba95a..1e274389b119b 100644
--- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -727,34 +727,45 @@ static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty,
// Switch cases for generic types.
for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) {
- OS << " case OCLT_" << GenType->getValueAsString("Name") << ":\n";
- OS << " QT.append({";
+ OS << " case OCLT_" << GenType->getValueAsString("Name") << ": {\n";
// Build the Cartesian product of (vector sizes) x (types). Only insert
// the plain scalar types for now; other type information such as vector
// size and type qualifiers will be added after the switch statement.
- for (unsigned I = 0; I < GenType->getValueAsDef("VectorList")
- ->getValueAsListOfInts("List")
- .size();
- I++) {
- for (const auto *T :
- GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List")) {
- OS << T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ", ";
+ std::vector<Record *> BaseTypes =
+ GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List");
+
+ // Collect all QualTypes for a single vector size into TypeList.
+ OS << " SmallVector<QualType, " << BaseTypes.size() << "> TypeList;\n";
+ for (const auto *T : BaseTypes) {
+ StringRef Ext =
+ T->getValueAsDef("Extension")->getValueAsString("ExtName");
+ if (!Ext.empty()) {
+ OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext
+ << "\")) {\n ";
+ }
+ OS << " TypeList.push_back("
+ << T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ");\n";
+ if (!Ext.empty()) {
+ OS << " }\n";
}
}
- OS << "});\n";
- // GenTypeNumTypes is the number of types in the GenType
- // (e.g. float/double/half).
- OS << " GenTypeNumTypes = "
- << GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List")
- .size()
- << ";\n";
+ OS << " GenTypeNumTypes = TypeList.size();\n";
+
+ // Duplicate the TypeList for every vector size.
+ std::vector<int64_t> VectorList =
+ GenType->getValueAsDef("VectorList")->getValueAsListOfInts("List");
+ OS << " QT.reserve(" << VectorList.size() * BaseTypes.size() << ");\n"
+ << " for (unsigned I = 0; I < " << VectorList.size() << "; I++) {\n"
+ << " QT.append(TypeList);\n"
+ << " }\n";
+
// GenVectorSizes is the list of vector sizes for this GenType.
- // QT contains GenTypeNumTypes * #GenVectorSizes elements.
OS << " GenVectorSizes = List"
<< GenType->getValueAsDef("VectorList")->getValueAsString("Name")
- << ";\n";
- OS << " break;\n";
+ << ";\n"
+ << " break;\n"
+ << " }\n";
}
// Switch cases for non generic, non image types (int, int4, float, ...).
@@ -777,9 +788,20 @@ static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty,
if (QT->getValueAsBit("IsAbstract") == 1)
continue;
// Emit the cases for non generic, non image types.
- OS << " case OCLT_" << T->getValueAsString("Name") << ":\n"
- << " QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n"
- << " break;\n";
+ OS << " case OCLT_" << T->getValueAsString("Name") << ":\n";
+
+ StringRef Ext = T->getValueAsDef("Extension")->getValueAsString("ExtName");
+ // If this type depends on an extension, ensure the extension macro is
+ // defined.
+ if (!Ext.empty()) {
+ OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext
+ << "\")) {\n ";
+ }
+ OS << " QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n";
+ if (!Ext.empty()) {
+ OS << " }\n";
+ }
+ OS << " break;\n";
}
// End of switch statement.
More information about the cfe-commits
mailing list