Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -1813,6 +1813,54 @@ #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 specified in `C++ for OpenCL v1.0 s2.4 +`_. +The restrictions can be relaxed using regular OpenCL extension pragma mechanism +detailed in `the OpenCL Extension Specification, section 1.2 +`_. + +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++ + + // Plain Old Data type. + struct Pod { + int a; + int b; + }; + + // Not POD type because of the constructor. + // Standard layout type because there is only one access control. + struct OnlySL { + int a; + int b; + NotPod() : a(0), b(0) {} + }; + + // Not standard layout type because of two different access controls. + 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, + ); + Legacy 1.x atomics with generic address space --------------------------------------------- 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/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/lib/Basic/Targets/NVPTX.h =================================================================== --- clang/lib/Basic/Targets/NVPTX.h +++ clang/lib/Basic/Targets/NVPTX.h @@ -133,6 +133,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/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -8649,6 +8649,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 || @@ -8671,8 +8674,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; @@ -8712,8 +8718,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/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/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/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/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