Skip to content

Commit

Permalink
[SYCL] Add SYCL diagnostics for device side code.
Browse files Browse the repository at this point in the history
 - Disable allocation in kernel functions
 - Disallow virtual function calls in kernel functions
 - Disallow function pointer calls in kernel functions
 - Disable throwing/catching exceptions
 - Disallow global variables in kernel functions
 - Disallow non-const static data members in kernel functions
 - RTTI is disabled inside kernels

Signed-off-by: Vladimir Lazarev <vladimir.lazarev@intel.com>
  • Loading branch information
vladimirlaz committed Jan 22, 2019
1 parent 4609257 commit e1c447a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -9488,6 +9488,15 @@ def err_sycl_attribute_address_space_invalid : Error<
def err_sycl_kernel_name_class_not_top_level : Error<
"kernel name class and its template argument classes' declarations can only "
"nest in a namespace: %0">;
def err_sycl_restrict : Error<
"SYCL kernel cannot "
"%select{use a global variable"
"|use rtti"
"|use a non-const static data variable"
"|call a virtual function"
"|call through a function pointer"
"|allocate storage"
"|use exceptions}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
88 changes: 88 additions & 0 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ enum target {
image_array
};

enum RestrictKind {
KernelGlobalVariable,
KernelRTTI,
KernelNonConstStaticDataVariable,
KernelCallVirtualFunction,
KernelCallFunctionPointer,
KernelAllocateStorage,
KernelUseExceptions
};

using ParamDesc = std::tuple<QualType, IdentifierInfo *, TypeSourceInfo *>;

/// Various utilities.
Expand Down Expand Up @@ -70,6 +80,7 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
public:
MarkDeviceFunction(Sema &S)
: RecursiveASTVisitor<MarkDeviceFunction>(), SemaRef(S) {}

bool VisitCallExpr(CallExpr *e) {
for (const auto &Arg : e->arguments())
CheckTypeForVirtual(Arg->getType(), Arg->getSourceRange());
Expand All @@ -80,6 +91,11 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
// all functions used by kernel have already been parsed and have
// definitions.

if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Callee))
if (Method->isVirtual())
SemaRef.Diag(e->getExprLoc(), diag::err_sycl_restrict) <<
KernelCallVirtualFunction;

CheckTypeForVirtual(Callee->getReturnType(), Callee->getSourceRange());

if (FunctionDecl *Def = Callee->getDefinition()) {
Expand All @@ -89,6 +105,9 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
SemaRef.AddSyclKernel(Def);
}
}
} else {
SemaRef.Diag(e->getExprLoc(), diag::err_sycl_restrict) <<
KernelCallFunctionPointer;
}
return true;
}
Expand Down Expand Up @@ -118,6 +137,16 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
return true;
}

bool VisitCXXTypeidExpr(CXXTypeidExpr *E) {
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) << KernelRTTI;
return true;
}

bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) << KernelRTTI;
return true;
}

bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
CheckTypeForVirtual(TD->getUnderlyingType(), TD->getLocation());
return true;
Expand All @@ -138,8 +167,67 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
return true;
}

bool VisitMemberExpr(MemberExpr *E) {
if (VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) {
bool IsConst = VD->getType().getNonReferenceType().isConstQualified();
if (VD->isStaticDataMember() && !IsConst)
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) <<
KernelNonConstStaticDataVariable;
}
return true;
}

bool VisitDeclRefExpr(DeclRefExpr *E) {
CheckTypeForVirtual(E->getType(), E->getSourceRange());
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
bool IsConst = VD->getType().getNonReferenceType().isConstQualified();
if (!IsConst && VD->hasGlobalStorage() && !VD->isStaticLocal() &&
!VD->isStaticDataMember() && !isa<ParmVarDecl>(VD))
SemaRef.Diag(E->getLocation(), diag::err_sycl_restrict) <<
KernelGlobalVariable;
}
return true;
}

bool VisitCXXNewExpr(CXXNewExpr *E) {
// Memory storage allocation is not allowed in kernels.
// All memory allocation for the device is done on
// the host using accessor classes. Consequently, the default
// allocation operator new overloads that allocate
// storage are disallowed in a SYCL kernel. The placement
// new operator and any user-defined overloads that
// do not allocate storage are permitted.
const FunctionDecl *FD = E->getOperatorNew();
if (FD && !FD->isReservedGlobalPlacementOperator()) {
OverloadedOperatorKind Kind = FD->getOverloadedOperator();
if (Kind == OO_New || Kind == OO_Array_New)
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) <<
KernelAllocateStorage;
}
return true;
}

bool VisitCXXThrowExpr(CXXThrowExpr *E) {
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) <<
KernelUseExceptions;
return true;
}

bool VisitCXXCatchStmt(CXXCatchStmt *S) {
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict) <<
KernelUseExceptions;
return true;
}

bool VisitCXXTryStmt(CXXTryStmt *S) {
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict) <<
KernelUseExceptions;
return true;
}

bool VisitSEHTryStmt(SEHTryStmt *S) {
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict) <<
KernelUseExceptions;
return true;
}

Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaSYCL/no-vtables2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Inherit usage() {
using foo = Inherit;
// expected-note@+1{{used here}}
typedef Inherit bar;
// expected-error@+2 {{SYCL kernel cannot call a virtual function}}
// expected-note@+1{{used here}}
IH.f();

Expand Down

0 comments on commit e1c447a

Please sign in to comment.