Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,18 @@ def SYCLDevice : InheritableAttr {
let Documentation = [SYCLDeviceDocs];
}

def SYCLGlobalVarSubject : SubsetSubject<Var, [{S->hasGlobalStorage() &&
!S->isLocalVarDecl()}],
"global variables">;

def SYCLGlobalVar : InheritableAttr {
let Spellings = [GNU<"sycl_global_var">];
let Subjects = SubjectList<[SYCLGlobalVarSubject], ErrorDiag>;
let LangOpts = [SYCLIsDevice];
let Documentation = [SYCLGlobalVarDocs];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this is only usable in system headers, this can go back to being undocumented with a comment about it only being used internally by the SYCL implementation (and the docs can be removed from AttrDocs.td).

let SimpleHandler = 1;
}

def SYCLKernel : InheritableAttr {
let Spellings = [Clang<"sycl_kernel">];
let Subjects = SubjectList<[FunctionTmpl]>;
Expand Down
24 changes: 24 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3155,6 +3155,30 @@ implicitly inherit this attribute.
}];
}

def SYCLGlobalVarDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Normally, a SYCL kernel cannot access a global variable, but there are cases
where it is desirable to use a global variable allocated and accessed on a SYCL device. This
attribute is only available to a SYCL device compiler (that is, when passing
``-fsycl-is-device``) and only applies to global variables. It affects semantic
checks to allow use of a marked global within a SYCL kernel.

.. code-block:: c++

#ifdef __SYCL_DEVICE_ONLY__
__attribute__((sycl_global_var)) int Var;
#endif

void F1(cl::sycl::handler& CGH) {
CGH.parallel_for_impl<class TU1>([=] () {
Var = 42; // device code
});
}

}];
}

def RISCVInterruptDocs : Documentation {
let Category = DocCatFunction;
let Heading = "interrupt (RISCV)";
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (IsRuntimeEvaluated && !IsConst && VD->getStorageClass() == SC_Static)
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
<< Sema::KernelNonConstStaticDataVariable;
// Non-const globals are allowed for SYCL explicit SIMD.
// Non-const globals are allowed for SYCL explicit SIMD or with the
// SYCLGlobalVar attribute.
else if (IsRuntimeEvaluated && !IsEsimdPrivateGlobal && !IsConst &&
VD->hasGlobalStorage())
VD->hasGlobalStorage() &&
!(VD->hasAttr<SYCLGlobalVarAttr>() &&
getSourceManager().isInSystemHeader(*Locs.begin())))
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
<< Sema::KernelGlobalVariable;
// ESIMD globals cannot be used in a SYCL context.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@
// CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function)
// CHECK-NEXT: SYCLDevice (SubjectMatchRule_function)
// CHECK-NEXT: SYCLDeviceIndirectlyCallable (SubjectMatchRule_function)
// CHECK-NEXT: SYCLGlobalVar (SubjectMatchRule_variable_is_global)
// CHECK-NEXT: SYCLIntelFPGADisableLoopPipelining (SubjectMatchRule_function)
// CHECK-NEXT: SYCLIntelFPGAInitiationInterval (SubjectMatchRule_function)
// CHECK-NEXT: SYCLIntelFPGAMaxConcurrency (SubjectMatchRule_function)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "../../Inputs/sycl.hpp"

__attribute__((sycl_global_var)) int HppGlobalWithAttribute;

__attribute__((sycl_global_var)) extern int HppExternGlobalWithAttribute;

namespace NS {
__attribute__((sycl_global_var)) int HppNSGlobalWithAttribute;
}

struct HppS {
__attribute__((sycl_global_var)) static int StaticMember;

// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) int InstanceMember;
};
int HppS::StaticMember = 0;

__attribute__((sycl_global_var)) HppS HppGlobalStruct;

__attribute__((sycl_global_var)) static HppS HppStaticGlobal;

static union {
// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) int HppAnonymousStaticUnionInstanceMember;
};

// expected-error@+1 {{attribute takes no arguments}}
__attribute__((sycl_global_var(42))) int HppGlobalWithAttributeArg;

int HppGlobalNoAttribute;

// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) void HppF() {
// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) static int StaticLocalVar;

// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) int Local;

cl::sycl::kernel_single_task<class kernel_name>([=] () {
(void)HppGlobalWithAttribute;
(void)HppExternGlobalWithAttribute;
(void)NS::HppNSGlobalWithAttribute;
(void)HppS::StaticMember;
(void)HppGlobalStruct.InstanceMember;
(void)HppStaticGlobal.InstanceMember; // expected-error {{SYCL kernel cannot use a non-const static data variable}}
(void)StaticLocalVar; // expected-error {{SYCL kernel cannot use a non-const static data variable}}
(void)HppAnonymousStaticUnionInstanceMember; // expected-error {{SYCL kernel cannot use a non-const static data variable}}
(void)HppGlobalNoAttribute; // expected-error {{SYCL kernel cannot use a non-const global variable}} expected-note@../../Inputs/sycl.hpp:* {{called by}}
});
}
55 changes: 55 additions & 0 deletions clang/test/SemaSYCL/attr-syclglobalvar/attr-syclglobalvar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only -isystem %S %s

#include <Inputs-isystem/attr-syclglobalvar.hpp>
#include "../Inputs/sycl.hpp"

__attribute__((sycl_global_var)) int GlobalWithAttribute;

__attribute__((sycl_global_var)) extern int ExternGlobalWithAttribute;

namespace NS {
__attribute__((sycl_global_var)) int NSGlobalWithAttribute;
}

struct S {
__attribute__((sycl_global_var)) static int StaticMember;

// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) int InstanceMember;
};
int S::StaticMember = 0;

__attribute__((sycl_global_var)) S GlobalStruct;

__attribute__((sycl_global_var)) static S StaticGlobal;

static union {
// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) int AnonymousStaticUnionInstanceMember;
};

// expected-error@+1 {{attribute takes no arguments}}
__attribute__((sycl_global_var(42))) int GlobalWithAttributeArg;

int GlobalNoAttribute;

// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) void F() {
// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) static int StaticLocalVar;

// expected-error@+1 {{attribute only applies to global variables}}
__attribute__((sycl_global_var)) int Local;

cl::sycl::kernel_single_task<class kernel_name>([=] () {
(void)GlobalWithAttribute; // expected-error {{SYCL kernel cannot use a non-const global variable}}
(void)ExternGlobalWithAttribute; // expected-error {{SYCL kernel cannot use a non-const global variable}}
(void)NS::NSGlobalWithAttribute; // expected-error {{SYCL kernel cannot use a non-const global variable}}
(void)S::StaticMember; // expected-error {{SYCL kernel cannot use a non-const global variable}}
(void)GlobalStruct.InstanceMember; // expected-error {{SYCL kernel cannot use a non-const global variable}}
(void)StaticGlobal.InstanceMember; // expected-error {{SYCL kernel cannot use a non-const static data variable}}
(void)StaticLocalVar; // expected-error {{SYCL kernel cannot use a non-const static data variable}}
(void)AnonymousStaticUnionInstanceMember; // expected-error {{SYCL kernel cannot use a non-const static data variable}}
(void)GlobalNoAttribute; // expected-error {{SYCL kernel cannot use a non-const global variable}} expected-note@../Inputs/sycl.hpp:* {{called by}}
});
}