From eae70ccbf9756e1e5b2c32f08558cb11e0f05dbf Mon Sep 17 00:00:00 2001 From: Ayal Zaks Date: Tue, 14 Feb 2023 11:56:21 +0200 Subject: [PATCH] [Clang][OpenCL] Allow pointers in structs as kernel arguments from 2.0 Structs that contain global or local pointers can be passed as kernel arguments starting OpenCL v2.0 with the introduction of shared virtual memory. Differential Revision: https://reviews.llvm.org/D143849 --- clang/lib/Sema/SemaDecl.cpp | 23 ++++++++++++++-------- clang/test/SemaOpenCL/invalid-kernel-parameters.cl | 9 ++++++++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 09540e5..b9cea8b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9273,6 +9273,12 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { ParamKind == InvalidKernelParam) return ParamKind; + // OpenCL v3.0 s6.11.a: + // A restriction to pass pointers to pointers only applies to OpenCL C + // v1.2 or below. + if (S.getLangOpts().getOpenCLCompatibleVersion() > 120) + return ValidKernelParam; + return PtrPtrKernelParam; } @@ -9300,6 +9306,11 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { return InvalidKernelParam; } + // OpenCL v1.2 s6.9.p: + // A restriction to pass pointers only applies to OpenCL C v1.2 or below. + if (S.getLangOpts().getOpenCLCompatibleVersion() > 120) + return ValidKernelParam; + return PtrKernelParam; } @@ -9366,13 +9377,8 @@ static void checkIsValidOpenCLKernelParameter( // OpenCL v3.0 s6.11.a: // A kernel function argument cannot be declared as a pointer to a pointer // type. [...] This restriction only applies to OpenCL C 1.2 or below. - if (S.getLangOpts().getOpenCLCompatibleVersion() <= 120) { - S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param); - D.setInvalidType(); - return; - } - - ValidTypes.insert(PT.getTypePtr()); + S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param); + D.setInvalidType(); return; case InvalidAddrSpacePtrKernelParam: @@ -9490,7 +9496,8 @@ static void checkIsValidOpenCLKernelParameter( // OpenCL v1.2 s6.9.p: // Arguments to kernel functions that are declared to be a struct or union // do not allow OpenCL objects to be passed as elements of the struct or - // union. + // union. This restriction was lifted in OpenCL v2.0 with the introduction + // of SVM. if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam || ParamType == InvalidAddrSpacePtrKernelParam) { S.Diag(Param->getLocation(), diff --git a/clang/test/SemaOpenCL/invalid-kernel-parameters.cl b/clang/test/SemaOpenCL/invalid-kernel-parameters.cl index de06b38..f0f5651 100644 --- a/clang/test/SemaOpenCL/invalid-kernel-parameters.cl +++ b/clang/test/SemaOpenCL/invalid-kernel-parameters.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -triple spir-unknown-unknown +// RUN: %clang_cc1 -fsyntax-only -verify=expected,ocl12 %s -triple spir-unknown-unknown // RUN: %clang_cc1 -fsyntax-only -verify %s -triple spir-unknown-unknown -cl-std=CL2.0 kernel void half_arg(half x) { } // expected-error{{declaring function parameter of type '__private half' is not allowed; did you forget * ?}} @@ -104,6 +104,13 @@ typedef struct Foo // expected-note{{within field of type 'Foo' declared here}} kernel void pointer_in_struct_arg(Foo arg) { } // expected-error{{struct kernel parameters may not contain pointers}} +typedef struct FooGlobal // ocl12-note{{within field of type 'FooGlobal' declared here}} +{ + global int* ptrField; // ocl12-note{{field of illegal pointer type '__global int *' declared here}} +} FooGlobal; + +kernel void global_pointer_in_struct_arg(FooGlobal arg) { } // ocl12-error{{struct kernel parameters may not contain pointers}} + typedef union FooUnion // expected-note{{within field of type 'FooUnion' declared here}} { int* ptrField; // expected-note-re{{field of illegal pointer type '__{{private|generic}} int *' declared here}} -- 2.7.4