Skip to content

Commit adddf4e

Browse files
committed
[SYCL] Ignore inline assembler in host code.
Signed-off-by: Vladimir Lazarev <[email protected]>
1 parent e1c447a commit adddf4e

File tree

4 files changed

+167
-3
lines changed

4 files changed

+167
-3
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9496,7 +9496,8 @@ def err_sycl_restrict : Error<
94969496
"|call a virtual function"
94979497
"|call through a function pointer"
94989498
"|allocate storage"
9499-
"|use exceptions}0">;
9499+
"|use exceptions"
9500+
"|use inline assembly}0">;
95009501
def err_sycl_virtual_types : Error<
95019502
"No class with a vtable can be used in a SYCL kernel or any code included in the kernel">;
95029503
def note_sycl_used_here : Note<"used here">;

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ enum RestrictKind {
4646
KernelCallVirtualFunction,
4747
KernelCallFunctionPointer,
4848
KernelAllocateStorage,
49-
KernelUseExceptions
49+
KernelUseExceptions,
50+
KernelUseAssembly
5051
};
5152

5253
using ParamDesc = std::tuple<QualType, IdentifierInfo *, TypeSourceInfo *>;
@@ -231,6 +232,18 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
231232
return true;
232233
}
233234

235+
bool VisitGCCAsmStmt(GCCAsmStmt *S) {
236+
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict)
237+
<< KernelUseAssembly;
238+
return true;
239+
}
240+
241+
bool VisitMSAsmStmt(MSAsmStmt *S) {
242+
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict)
243+
<< KernelUseAssembly;
244+
return true;
245+
}
246+
234247
private:
235248
bool CheckTypeForVirtual(QualType Ty, SourceRange Loc) {
236249
while (Ty->isAnyPointerType() || Ty->isArrayType())
@@ -378,7 +391,7 @@ CreateSYCLKernelBody(Sema &S, FunctionDecl *KernelCallerFunc, DeclContext *DC) {
378391
// Since this is an accessor next 3 TargetFuncParams including current
379392
// should be set in __init method: _ValueType*, range<int>, id<int>
380393
const size_t NumParams = 3;
381-
llvm::SmallVector<DeclRefExpr *, NumParams> ParamDREs;
394+
llvm::SmallVector<DeclRefExpr *, NumParams> ParamDREs(NumParams);
382395
auto TFP = TargetFuncParam;
383396
for (size_t I = 0; I < NumParams; ++TFP, ++I) {
384397
QualType ParamType = (*TFP)->getOriginalType();

clang/lib/Sema/SemaStmtAsm.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,15 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
263263
return NS;
264264
}
265265

266+
// Skip all the checks if we are compiling SYCL device code, but the function
267+
// is not marked to be used on device, this code won't be codegen'ed anyway.
268+
if (getLangOpts().SYCL) {
269+
GCCAsmStmt *NS = new (Context) GCCAsmStmt(
270+
Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
271+
Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
272+
return NS;
273+
}
274+
266275
for (unsigned i = 0; i != NumOutputs; i++) {
267276
StringLiteral *Literal = Constraints[i];
268277
assert(Literal->isAscii());

clang/test/SemaSYCL/sycl-restrict.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -Wno-return-type -verify -fsyntax-only -x c++ -emit-llvm-only -std=c++17 %s
2+
3+
4+
namespace std {
5+
class type_info;
6+
typedef __typeof__(sizeof(int)) size_t;
7+
}
8+
void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
9+
namespace Check_RTTI_Restriction {
10+
// expected-error@+1 5{{No class with a vtable can be used in a SYCL kernel or any code included in the kernel}}
11+
struct A {
12+
virtual ~A(){};
13+
};
14+
15+
struct B : public A {
16+
B() : A() {}
17+
};
18+
19+
struct OverloadedNewDelete {
20+
// These overloads do not allocate.
21+
void *operator new(std::size_t size) throw() {return 0;}
22+
void *operator new[](std::size_t size) throw() {return 0;}
23+
void operator delete(void *){};
24+
void operator delete[](void *){};
25+
};
26+
27+
bool isa_B(A *a) {
28+
29+
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
30+
int *ip = new int;
31+
int i; int *p3 = new(&i) int; // no error on placement new
32+
//FIXME call to overloaded new should not get error message
33+
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
34+
OverloadedNewDelete *x = new( struct OverloadedNewDelete );
35+
// expected-error@+1 {{SYCL kernel cannot use rtti}}
36+
(void)typeid(int);
37+
// expected-error@+2 {{SYCL kernel cannot use rtti}}
38+
// expected-note@+1{{used here}}
39+
return dynamic_cast<B *>(a) != 0;
40+
}
41+
42+
__attribute__((sycl_kernel)) void kernel1(void) {
43+
// expected-note@+1{{used here}}
44+
A *a;
45+
// expected-note@+1 3{{used here}}
46+
isa_B(a);
47+
}
48+
}
49+
// expected-error@+1 {{No class with a vtable can be used in a SYCL kernel or any code included in the kernel}}
50+
typedef struct Base {
51+
virtual void f() const {}
52+
} b_type;
53+
54+
typedef struct A {
55+
static int stat_member;
56+
const static int const_stat_member;
57+
constexpr static int constexpr_stat_member=0;
58+
} a_type;
59+
60+
61+
b_type b;
62+
63+
using myFuncDef = int(int,int);
64+
65+
void eh_ok(void)
66+
{
67+
try {
68+
;
69+
} catch (...) {
70+
;
71+
}
72+
throw 20;
73+
}
74+
75+
void eh_not_ok(void)
76+
{
77+
// expected-error@+1 {{SYCL kernel cannot use exceptions}}
78+
try {
79+
;
80+
// expected-error@+1 {{SYCL kernel cannot use exceptions}}
81+
} catch (...) {
82+
;
83+
}
84+
// expected-error@+1 {{SYCL kernel cannot use exceptions}}
85+
throw 20;
86+
}
87+
88+
void usage( myFuncDef functionPtr ) {
89+
90+
eh_not_ok();
91+
92+
// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
93+
if ((*functionPtr)(1,2))
94+
// expected-note@+3{{used here}}
95+
// expected-error@+2 {{SYCL kernel cannot use a global variable}}
96+
// expected-error@+1 {{SYCL kernel cannot call a virtual function}}
97+
b.f();
98+
Check_RTTI_Restriction::kernel1();
99+
}
100+
101+
namespace ns {
102+
int glob;
103+
}
104+
extern "C++" {
105+
int another_global = 5;
106+
namespace AnotherNS {
107+
int moar_globals = 5;
108+
}
109+
}
110+
111+
int use2 ( a_type ab ) {
112+
113+
if (ab.constexpr_stat_member) return 2;
114+
if (ab.const_stat_member) return 1;
115+
// expected-error@+1 {{SYCL kernel cannot use a non-const static data variable}}
116+
if (ab.stat_member) return 0;
117+
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
118+
return another_global ;
119+
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
120+
return ns::glob +
121+
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
122+
AnotherNS::moar_globals;
123+
}
124+
125+
int addInt(int n, int m) {
126+
return n+m;
127+
}
128+
129+
template <typename name, typename Func>
130+
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
131+
kernelFunc();
132+
a_type ab;
133+
use2(ab);
134+
}
135+
136+
int main() {
137+
a_type ab;
138+
kernel_single_task<class fake_kernel>([]() { usage( &addInt ); });
139+
return 0;
140+
}
141+

0 commit comments

Comments
 (0)