[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