Skip to content

Commit

Permalink
[SYCL] Ignore inline assembler in host code.
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Lazarev <vladimir.lazarev@intel.com>
  • Loading branch information
vladimirlaz committed Jan 22, 2019
1 parent e1c447a commit adddf4e
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 3 deletions.
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -9496,7 +9496,8 @@ def err_sycl_restrict : Error<
"|call a virtual function"
"|call through a function pointer"
"|allocate storage"
"|use exceptions}0">;
"|use exceptions"
"|use inline assembly}0">;
def err_sycl_virtual_types : Error<
"No class with a vtable can be used in a SYCL kernel or any code included in the kernel">;
def note_sycl_used_here : Note<"used here">;
Expand Down
17 changes: 15 additions & 2 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ enum RestrictKind {
KernelCallVirtualFunction,
KernelCallFunctionPointer,
KernelAllocateStorage,
KernelUseExceptions
KernelUseExceptions,
KernelUseAssembly
};

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

bool VisitGCCAsmStmt(GCCAsmStmt *S) {
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict)
<< KernelUseAssembly;
return true;
}

bool VisitMSAsmStmt(MSAsmStmt *S) {
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict)
<< KernelUseAssembly;
return true;
}

private:
bool CheckTypeForVirtual(QualType Ty, SourceRange Loc) {
while (Ty->isAnyPointerType() || Ty->isArrayType())
Expand Down Expand Up @@ -378,7 +391,7 @@ CreateSYCLKernelBody(Sema &S, FunctionDecl *KernelCallerFunc, DeclContext *DC) {
// Since this is an accessor next 3 TargetFuncParams including current
// should be set in __init method: _ValueType*, range<int>, id<int>
const size_t NumParams = 3;
llvm::SmallVector<DeclRefExpr *, NumParams> ParamDREs;
llvm::SmallVector<DeclRefExpr *, NumParams> ParamDREs(NumParams);
auto TFP = TargetFuncParam;
for (size_t I = 0; I < NumParams; ++TFP, ++I) {
QualType ParamType = (*TFP)->getOriginalType();
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Sema/SemaStmtAsm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,15 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return NS;
}

// Skip all the checks if we are compiling SYCL device code, but the function
// is not marked to be used on device, this code won't be codegen'ed anyway.
if (getLangOpts().SYCL) {
GCCAsmStmt *NS = new (Context) GCCAsmStmt(
Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
return NS;
}

for (unsigned i = 0; i != NumOutputs; i++) {
StringLiteral *Literal = Constraints[i];
assert(Literal->isAscii());
Expand Down
141 changes: 141 additions & 0 deletions clang/test/SemaSYCL/sycl-restrict.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -Wno-return-type -verify -fsyntax-only -x c++ -emit-llvm-only -std=c++17 %s


namespace std {
class type_info;
typedef __typeof__(sizeof(int)) size_t;
}
void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
namespace Check_RTTI_Restriction {
// expected-error@+1 5{{No class with a vtable can be used in a SYCL kernel or any code included in the kernel}}
struct A {
virtual ~A(){};
};

struct B : public A {
B() : A() {}
};

struct OverloadedNewDelete {
// These overloads do not allocate.
void *operator new(std::size_t size) throw() {return 0;}
void *operator new[](std::size_t size) throw() {return 0;}
void operator delete(void *){};
void operator delete[](void *){};
};

bool isa_B(A *a) {

// expected-error@+1 {{SYCL kernel cannot allocate storage}}
int *ip = new int;
int i; int *p3 = new(&i) int; // no error on placement new
//FIXME call to overloaded new should not get error message
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
OverloadedNewDelete *x = new( struct OverloadedNewDelete );
// expected-error@+1 {{SYCL kernel cannot use rtti}}
(void)typeid(int);
// expected-error@+2 {{SYCL kernel cannot use rtti}}
// expected-note@+1{{used here}}
return dynamic_cast<B *>(a) != 0;
}

__attribute__((sycl_kernel)) void kernel1(void) {
// expected-note@+1{{used here}}
A *a;
// expected-note@+1 3{{used here}}
isa_B(a);
}
}
// expected-error@+1 {{No class with a vtable can be used in a SYCL kernel or any code included in the kernel}}
typedef struct Base {
virtual void f() const {}
} b_type;

typedef struct A {
static int stat_member;
const static int const_stat_member;
constexpr static int constexpr_stat_member=0;
} a_type;


b_type b;

using myFuncDef = int(int,int);

void eh_ok(void)
{
try {
;
} catch (...) {
;
}
throw 20;
}

void eh_not_ok(void)
{
// expected-error@+1 {{SYCL kernel cannot use exceptions}}
try {
;
// expected-error@+1 {{SYCL kernel cannot use exceptions}}
} catch (...) {
;
}
// expected-error@+1 {{SYCL kernel cannot use exceptions}}
throw 20;
}

void usage( myFuncDef functionPtr ) {

eh_not_ok();

// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
if ((*functionPtr)(1,2))
// expected-note@+3{{used here}}
// expected-error@+2 {{SYCL kernel cannot use a global variable}}
// expected-error@+1 {{SYCL kernel cannot call a virtual function}}
b.f();
Check_RTTI_Restriction::kernel1();
}

namespace ns {
int glob;
}
extern "C++" {
int another_global = 5;
namespace AnotherNS {
int moar_globals = 5;
}
}

int use2 ( a_type ab ) {

if (ab.constexpr_stat_member) return 2;
if (ab.const_stat_member) return 1;
// expected-error@+1 {{SYCL kernel cannot use a non-const static data variable}}
if (ab.stat_member) return 0;
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
return another_global ;
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
return ns::glob +
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
AnotherNS::moar_globals;
}

int addInt(int n, int m) {
return n+m;
}

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
kernelFunc();
a_type ab;
use2(ab);
}

int main() {
a_type ab;
kernel_single_task<class fake_kernel>([]() { usage( &addInt ); });
return 0;
}

0 comments on commit adddf4e

Please sign in to comment.