diff --git a/clang/include/clang/Basic/OpenCLOptions.h b/clang/include/clang/Basic/OpenCLOptions.h --- a/clang/include/clang/Basic/OpenCLOptions.h +++ b/clang/include/clang/Basic/OpenCLOptions.h @@ -67,7 +67,23 @@ /// OpenCL supported extensions and optional core features class OpenCLOptions { + public: + // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the + // __constant address space. + // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static + // variables inside a function can also be declared in the global + // address space. + // OpenCL C v3.0 s6.7.1 - Variables at program scope or static or extern + // variables inside functions can be declared in global address space if + // the __opencl_c_program_scope_global_variables feature is supported + // C++ for OpenCL inherits rule from OpenCL C v2.0. + bool areProgramScopeVariablesSupported(const LangOptions &Opts) const { + return Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200 || + (Opts.OpenCLVersion == 300 && + isSupported("__opencl_c_program_scope_global_variables", Opts)); + } + struct OpenCLOptionInfo { // Does this option have pragma. bool WithPragma = false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6424,7 +6424,11 @@ if (Type->isSamplerT() || Type->isVoidType()) return; LangAS ImplAS = LangAS::opencl_private; - if ((getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) && + // OpenCL C v3.0 s6.7.8 - For OpenCL C 2.0 or with the + // __opencl_c_program_scope_global_variables feature, the address space + // for a variable at program scope or a static or extern variable inside + // a function are inferred to be __global. + if (getOpenCLOptions().areProgramScopeVariablesSupported(getLangOpts()) && Var->hasGlobalStorage()) ImplAS = LangAS::opencl_global; // If the original type from a decayed type is an array type and that array @@ -8018,23 +8022,16 @@ } } - // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the - // __constant address space. - // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static - // variables inside a function can also be declared in the global - // address space. - // C++ for OpenCL inherits rule from OpenCL C v2.0. // FIXME: Adding local AS in C++ for OpenCL might make sense. if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() || NewVD->hasExternalStorage()) { - if (!T->isSamplerT() && - !T->isDependentType() && + if (!T->isSamplerT() && !T->isDependentType() && !(T.getAddressSpace() == LangAS::opencl_constant || (T.getAddressSpace() == LangAS::opencl_global && - (getLangOpts().OpenCLVersion == 200 || - getLangOpts().OpenCLCPlusPlus)))) { + getOpenCLOptions().areProgramScopeVariablesSupported( + getLangOpts())))) { int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1; - if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus) + if (getOpenCLOptions().areProgramScopeVariablesSupported(getLangOpts())) Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) << Scope << "global or constant"; else diff --git a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl --- a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl +++ b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl @@ -2,6 +2,8 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN %s // RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN,AMDGCN20 %s // RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL1.2 -O0 -triple spir-unknown-unknown-unknown | FileCheck -enable-var-scope -check-prefixes=SPIR %s +// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL3.0 -O0 -triple amdgcn -cl-ext=+__opencl_c_program_scope_global_variables | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN,AMDGCN20 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL3.0 -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN %s typedef int int2 __attribute__((ext_vector_type(2))); @@ -39,7 +41,7 @@ int2 y[20]; }; -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ >= 300 && defined(__opencl_c_program_scope_global_variables)) struct LargeStructOneMember g_s; #endif @@ -98,7 +100,7 @@ // AMDGCN20: %[[r0:.*]] = bitcast %struct.LargeStructOneMember addrspace(5)* %[[byval_temp]] to i8 addrspace(5)* // AMDGCN20: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)* align 8 %[[r0]], i8 addrspace(1)* align 8 bitcast (%struct.LargeStructOneMember addrspace(1)* @g_s to i8 addrspace(1)*), i64 800, i1 false) // AMDGCN20: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval(%struct.LargeStructOneMember) align 8 %[[byval_temp]]) -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ >= 300 && defined(__opencl_c_program_scope_global_variables)) void test_indirect_arg_globl(void) { FuncOneLargeMember(g_s); } diff --git a/clang/test/SemaOpenCL/storageclass.cl b/clang/test/SemaOpenCL/storageclass.cl --- a/clang/test/SemaOpenCL/storageclass.cl +++ b/clang/test/SemaOpenCL/storageclass.cl @@ -1,28 +1,118 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 - +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space static constant int G1 = 0; constant int G2 = 0; -int G3 = 0; // expected-error{{program scope variable must reside in constant address space}} -global int G4 = 0; // expected-error{{program scope variable must reside in constant address space}} -static float g_implicit_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} +int G3 = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + +global int G4 = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + +static float g_implicit_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + static constant float g_constant_static_var = 0; -static global float g_global_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static local float g_local_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static private float g_private_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static generic float g_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}} -extern float g_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}} +static global float g_global_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + +static local float g_local_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#else +// expected-error@-4 {{program scope variable must reside in global or constant address space}} +#endif + +static private float g_private_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#else +// expected-error@-4 {{program scope variable must reside in global or constant address space}} +#endif + +static generic float g_generic_static_var = 0; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{program scope variable must reside in constant address space}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{program scope variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{program scope variable must reside in global or constant address space}} + #endif +#endif + +extern float g_implicit_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#endif + extern constant float g_constant_extern_var; -extern global float g_global_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern local float g_local_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern private float g_private_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern generic float g_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} + +extern global float g_global_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#endif + +extern local float g_local_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#else +// expected-error@-4 {{extern variable must reside in global or constant address space}} +#endif + +extern private float g_private_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#else +// expected-error@-4 {{extern variable must reside in global or constant address space}} +#endif + +extern generic float g_generic_extern_var; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{extern variable must reside in constant address space}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{extern variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{extern variable must reside in global or constant address space}} + #endif +#endif void kernel foo(int x) { // static is not allowed at local scope before CL2.0 - static int S1 = 5; // expected-error{{variables in function scope cannot be declared static}} - static constant int S2 = 5; // expected-error{{variables in function scope cannot be declared static}} + static int S1 = 5; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#endif + + static constant int S2 = 5; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#endif constant int L1 = 0; local int L2; @@ -32,12 +122,13 @@ constant int L1 = 42; // expected-error {{variables in the constant address space can only be declared in the outermost scope of a kernel function}} } - auto int L3 = 7; // expected-error{{OpenCL C version 1.2 does not support the 'auto' storage class specifier}} + auto int L3 = 7; // expected-error-re{{OpenCL C version {{1.2|3.0}} does not support the 'auto' storage class specifier}} global int L4; // expected-error{{function scope variable cannot be declared in global address space}} __attribute__((address_space(100))) int L5; // expected-error{{automatic variable qualified with an invalid address space}} constant int L6 = x; // expected-error {{initializer element is not a compile-time constant}} global int *constant L7 = &G4; + private int *constant L8 = &x; // expected-error {{initializer element is not a compile-time constant}} constant int *constant L9 = &L1; local int *constant L10 = &L2; // expected-error {{initializer element is not a compile-time constant}} @@ -59,17 +150,106 @@ __attribute__((address_space(100))) int L4; // expected-error{{automatic variable qualified with an invalid address space}} } - static float l_implicit_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static constant float l_constant_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static global float l_global_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static local float l_local_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static private float l_private_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static generic float l_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{variables in function scope cannot be declared static}} + static float l_implicit_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#endif + + static constant float l_constant_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#endif + + static global float l_global_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#endif + + static local float l_local_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{static local variable must reside in global or constant address space}} +#endif + + static private float l_private_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{static local variable must reside in global or constant address space}} +#endif + + static generic float l_generic_static_var = 0; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{variables in function scope cannot be declared static}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{static local variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{static local variable must reside in global or constant address space}} + #endif +#endif + + extern float l_implicit_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#endif - extern float l_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}} extern constant float l_constant_extern_var; - extern global float l_global_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern local float l_local_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern private float l_private_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern generic float l_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} + + extern global float l_global_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#endif + + extern local float l_local_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{extern variable must reside in global or constant address space}} +#endif + + extern private float l_private_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{extern variable must reside in global or constant address space}} +#endif + + extern generic float l_generic_extern_var; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{extern variable must reside in constant address space}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{extern variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{extern variable must reside in global or constant address space}} + #endif +#endif }