olestrohm updated this revision to Diff 340796.
olestrohm added a comment.

Improved the description and example per the feedback.

The check for dependent type is needed. If it is not included the diagnostic 
will get triggered when the extension is disabled, but not when it's enabled.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101168/new/

https://reviews.llvm.org/D101168

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Misc/amdgcn.languageOptsOpenCL.cl
  clang/test/Misc/nvptx.languageOptsOpenCL.cl
  clang/test/Misc/r600.languageOptsOpenCL.cl
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===================================================================
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+#endif
 
 struct C {
   kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@
 kernel void int_p_r(__global int *__global &in);
 kernel void int_p_p_r(__global int *__global *__global &in);
 
-// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
 kernel void k_atomic_v(atomic_int in);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
 kernel void k_atomic_p(__global atomic_int *in);
 kernel void k_atomic_r(__global atomic_int &in);
 
@@ -56,7 +63,10 @@
   StandardLayout(int a, int b) : a(a), b(b) {}
 };
 
-kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
 kernel void standard_p(__global StandardLayout *in) {}
 kernel void standard_p_p(__global StandardLayout *__global *in) {}
 kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@
   int b;
 };
 
-kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif
Index: clang/test/Misc/r600.languageOptsOpenCL.cl
===================================================================
--- clang/test/Misc/r600.languageOptsOpenCL.cl
+++ clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -34,6 +34,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif
Index: clang/test/Misc/nvptx.languageOptsOpenCL.cl
===================================================================
--- clang/test/Misc/nvptx.languageOptsOpenCL.cl
+++ clang/test/Misc/nvptx.languageOptsOpenCL.cl
@@ -28,6 +28,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif
Index: clang/test/Misc/amdgcn.languageOptsOpenCL.cl
===================================================================
--- clang/test/Misc/amdgcn.languageOptsOpenCL.cl
+++ clang/test/Misc/amdgcn.languageOptsOpenCL.cl
@@ -24,6 +24,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifndef cl_khr_fp16
 #error "Missing cl_khr_fp16 define"
 #endif
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -8648,6 +8648,9 @@
 }
 
 static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
+  if (PT->isDependentType())
+    return InvalidKernelParam;
+
   if (PT->isPointerType() || PT->isReferenceType()) {
     QualType PointeeType = PT->getPointeeType();
     if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
@@ -8670,8 +8673,11 @@
     // Moreover the types used in parameters of the kernel functions must be:
     // Standard layout types for pointer parameters. The same applies to
     // reference if an implementation supports them in kernel parameters.
-    if (S.getLangOpts().OpenCLCPlusPlus && !PointeeType->isAtomicType() &&
-        !PointeeType->isVoidType() && !PointeeType->isStandardLayoutType())
+    if (S.getLangOpts().OpenCLCPlusPlus &&
+        !S.getOpenCLOptions().isAvailableOption(
+            "__cl_clang_non_portable_kernel_parameters", S.getLangOpts()) &&
+        !PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+        !PointeeType->isStandardLayoutType())
       return InvalidKernelParam;
 
     return PtrKernelParam;
@@ -8711,8 +8717,10 @@
   // Moreover the types used in parameters of the kernel functions must be:
   // Trivial and standard-layout types C++17 [basic.types] (plain old data
   // types) for parameters passed by value;
-  if (S.getLangOpts().OpenCLCPlusPlus && !PT->isOpenCLSpecificType() &&
-      !PT.isPODType(S.Context))
+  if (S.getLangOpts().OpenCLCPlusPlus &&
+      !S.getOpenCLOptions().isAvailableOption(
+          "__cl_clang_non_portable_kernel_parameters", S.getLangOpts()) &&
+      !PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
     return InvalidKernelParam;
 
   if (PT->isRecordType())
Index: clang/lib/Basic/Targets/NVPTX.h
===================================================================
--- clang/lib/Basic/Targets/NVPTX.h
+++ clang/lib/Basic/Targets/NVPTX.h
@@ -130,6 +130,7 @@
     Opts["cl_clang_storage_class_specifiers"] = true;
     Opts["__cl_clang_function_pointers"] = true;
     Opts["__cl_clang_variadic_functions"] = true;
+    Opts["__cl_clang_non_portable_kernel_parameters"] = true;
 
     Opts["cl_khr_fp64"] = true;
     Opts["cl_khr_byte_addressable_store"] = true;
Index: clang/lib/Basic/Targets/AMDGPU.h
===================================================================
--- clang/lib/Basic/Targets/AMDGPU.h
+++ clang/lib/Basic/Targets/AMDGPU.h
@@ -287,6 +287,7 @@
     Opts["cl_clang_storage_class_specifiers"] = true;
     Opts["__cl_clang_variadic_functions"] = true;
     Opts["__cl_clang_function_pointers"] = true;
+    Opts["__cl_clang_non_portable_kernel_parameters"] = true;
 
     bool IsAMDGCN = isAMDGCN(getTriple());
 
Index: clang/include/clang/Basic/OpenCLExtensions.def
===================================================================
--- clang/include/clang/Basic/OpenCLExtensions.def
+++ clang/include/clang/Basic/OpenCLExtensions.def
@@ -87,6 +87,7 @@
 OPENCL_EXTENSION(cl_clang_storage_class_specifiers, true, 100)
 OPENCL_EXTENSION(__cl_clang_function_pointers, true, 100)
 OPENCL_EXTENSION(__cl_clang_variadic_functions, true, 100)
+OPENCL_EXTENSION(__cl_clang_non_portable_kernel_parameters, true, 100)
 
 // AMD OpenCL extensions
 OPENCL_EXTENSION(cl_amd_media_ops, true, 100)
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -1801,6 +1801,50 @@
   #pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
   void bar(int a, ...); // error - variadic prototype is not allowed
 
+``__cl_clang_non_portable_kernel_parameters``
+---------------------------------------------
+
+With this extension it is possible to enable the use of some restricted types in kernel parameters.
+The restrictions can be relaxed using regular OpenCL extension pragma mechanism
+detailed in `the OpenCL Extension Specification, section 1.2
+<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+
+This is not a conformant behavior and it can only be used when the
+kernel arguments are not accessed on the host side or the data layout/size between the host and device is known to be compatible.
+
+**Example of Use**:
+
+.. code-block:: c++
+  // Is POD because it is Plain Old Data
+  struct Pod {
+    int a;
+    int b;
+  };
+
+  // Not POD because of the constructor
+  // Is standard layout because there is only one access control
+  struct OnlySL {
+    int a;
+    int b;
+    NotPod() : a(0), b(0) {}
+  };
+
+  // Not standard layout because of two different access control
+  struct NotSL {
+    int a;
+  private:
+    int b;
+  }
+
+  kernel void kernel_main(
+    Pod a,
+  #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+    OnlySL b,
+    global NotSL *c,
+  #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : disable
+    global OnlySL *d,
+  );
+
 Builtin Functions
 =================
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to