Skip to content

Commit 659efdf

Browse files
Fznamznonbader
authored andcommitted
[SYCL] Diagnose __float128 type usage in device code, fixes and cleanups (#971)
The problem is that CheckSYCLCall used to get the caller incorrectly. getCurFunctionDecl gets the wrong thing. It will get the function containing the lambda at definition time, rather than the lambda operator(). Additional changes: Cleaned up unnecessary calls of CheckSYCLCall function. Fixed diagnosing of storage allocation through deferred diagnostics system. Renamed CheckSYCLCall with checkSYCLDeviceFunction since we don't really check calls as CUDA/OpenMP does. Removed unnecessary emitting of diagnostics from SemaSYCL. Signed-off-by: Mariya Podchishchaeva <[email protected]>
1 parent 8bed533 commit 659efdf

File tree

13 files changed

+75
-57
lines changed

13 files changed

+75
-57
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12079,11 +12079,33 @@ class Sema final {
1207912079
KernelCallDllimportFunction,
1208012080
KernelCallVariadicFunction
1208112081
};
12082-
DeviceDiagBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
1208312082
bool isKnownGoodSYCLDecl(const Decl *D);
1208412083
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC);
1208512084
void MarkDevice(void);
12086-
bool CheckSYCLCall(SourceLocation Loc, FunctionDecl *Callee);
12085+
12086+
/// Creates a DeviceDiagBuilder that emits the diagnostic if the current
12087+
/// context is "used as device code".
12088+
///
12089+
/// - If CurLexicalContext is a kernel function or it is known that the
12090+
/// function will be emitted for the device, emits the diagnostics
12091+
/// immediately.
12092+
/// - If CurLexicalContext is a function and we are compiling
12093+
/// for the device, but we don't know that this function will be codegen'ed
12094+
/// for devive yet, creates a diagnostic which is emitted if and when we
12095+
/// realize that the function will be codegen'ed.
12096+
///
12097+
/// Example usage:
12098+
///
12099+
/// Variables with thread storage duration are not allowed to be used in SYCL
12100+
/// device code
12101+
/// if (getLangOpts().SYCLIsDevice)
12102+
/// SYCLDiagIfDeviceCode(Loc, diag::err_thread_unsupported);
12103+
DeviceDiagBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
12104+
12105+
/// Checks if Callee function is a device function and emits
12106+
/// diagnostics if it is known that it is a device function, adds this
12107+
/// function to the DeviceCallGraph otherwise.
12108+
void checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee);
1208712109
};
1208812110

1208912111
/// RAII object that enters a new expression evaluation context.

clang/lib/Sema/Sema.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,9 @@ Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) {
16101610
if (getLangOpts().CUDA)
16111611
return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID)
16121612
: CUDADiagIfHostCode(Loc, DiagID);
1613+
// TODO: analyze which usages of targetDiag could be reused for SYCL.
1614+
// if (getLangOpts().SYCLIsDevice)
1615+
// return SYCLDiagIfDeviceCode(Loc, DiagID);
16131616
return DeviceDiagBuilder(DeviceDiagBuilder::K_Immediate, Loc, DiagID,
16141617
getCurFunctionDecl(), *this);
16151618
}

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14644,7 +14644,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
1464414644
if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor))
1464514645
return ExprError();
1464614646
if (getLangOpts().SYCLIsDevice)
14647-
CheckSYCLCall(ConstructLoc, Constructor);
14647+
checkSYCLDeviceFunction(ConstructLoc, Constructor);
1464814648

1464914649
return CXXConstructExpr::Create(
1465014650
Context, DeclInitType, ConstructLoc, Constructor, Elidable,

clang/lib/Sema/SemaExpr.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
269269
return true;
270270

271271
if (getLangOpts().SYCLIsDevice)
272-
CheckSYCLCall(Loc, FD);
272+
checkSYCLDeviceFunction(Loc, FD);
273273
}
274274

275275
if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
@@ -15649,7 +15649,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
1564915649
if (getLangOpts().CUDA)
1565015650
CheckCUDACall(Loc, Func);
1565115651
if (getLangOpts().SYCLIsDevice)
15652-
CheckSYCLCall(Loc, Func);
15652+
checkSYCLDeviceFunction(Loc, Func);
1565315653

1565415654
// If we need a definition, try to create one.
1565515655
if (NeedDefinition && !Func->getBody()) {
@@ -17219,15 +17219,7 @@ namespace {
1721917219
}
1722017220

1722117221
void VisitCXXNewExpr(CXXNewExpr *E) {
17222-
FunctionDecl *FD = E->getOperatorNew();
17223-
if (FD && S.getLangOpts().SYCLIsDevice) {
17224-
if (FD->isReplaceableGlobalAllocationFunction())
17225-
S.SYCLDiagIfDeviceCode(E->getExprLoc(), diag::err_sycl_restrict)
17226-
<< S.KernelAllocateStorage;
17227-
else if (FunctionDecl *Def = FD->getDefinition())
17228-
S.CheckSYCLCall(E->getExprLoc(), Def);
17229-
}
17230-
if (FD)
17222+
if (E->getOperatorNew())
1723117223
S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorNew());
1723217224
if (E->getOperatorDelete())
1723317225
S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,16 +2171,15 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
21712171
if (DiagnoseUseOfDecl(OperatorNew, StartLoc))
21722172
return ExprError();
21732173
MarkFunctionReferenced(StartLoc, OperatorNew);
2174-
if (getLangOpts().SYCLIsDevice) {
2175-
CheckSYCLCall(StartLoc, OperatorNew);
2176-
}
2174+
if (getLangOpts().SYCLIsDevice &&
2175+
OperatorNew->isReplaceableGlobalAllocationFunction())
2176+
SYCLDiagIfDeviceCode(StartLoc, diag::err_sycl_restrict)
2177+
<< KernelAllocateStorage;
21772178
}
21782179
if (OperatorDelete) {
21792180
if (DiagnoseUseOfDecl(OperatorDelete, StartLoc))
21802181
return ExprError();
21812182
MarkFunctionReferenced(StartLoc, OperatorDelete);
2182-
if (getLangOpts().SYCLIsDevice)
2183-
CheckSYCLCall(StartLoc, OperatorDelete);
21842183
}
21852184

21862185
return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete,

clang/lib/Sema/SemaOverload.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12916,8 +12916,6 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
1291612916
FnDecl->getType()->castAs<FunctionProtoType>()))
1291712917
return ExprError();
1291812918

12919-
if (getLangOpts().SYCLIsDevice)
12920-
CheckSYCLCall(OpLoc, FnDecl);
1292112919
return MaybeBindToTemporary(TheCall);
1292212920
} else {
1292312921
// We matched a built-in operator. Convert the arguments, then
@@ -13270,8 +13268,6 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
1327013268
isa<CXXMethodDecl>(FnDecl), OpLoc, TheCall->getSourceRange(),
1327113269
VariadicDoesNotApply);
1327213270

13273-
if (getLangOpts().SYCLIsDevice)
13274-
CheckSYCLCall(OpLoc, FnDecl);
1327513271
ExprResult R = MaybeBindToTemporary(TheCall);
1327613272
if (R.isInvalid())
1327713273
return ExprError();
@@ -13633,8 +13629,6 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
1363313629
Method->getType()->castAs<FunctionProtoType>()))
1363413630
return ExprError();
1363513631

13636-
if (getLangOpts().SYCLIsDevice)
13637-
CheckSYCLCall(RLoc, FnDecl);
1363813632
return MaybeBindToTemporary(TheCall);
1363913633
} else {
1364013634
// We matched a built-in operator. Convert the arguments, then

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -359,10 +359,7 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
359359
// new operator and any user-defined overloads that
360360
// do not allocate storage are permitted.
361361
if (FunctionDecl *FD = E->getOperatorNew()) {
362-
if (FD->isReplaceableGlobalAllocationFunction()) {
363-
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict)
364-
<< Sema::KernelAllocateStorage;
365-
} else if (FunctionDecl *Def = FD->getDefinition()) {
362+
if (FunctionDecl *Def = FD->getDefinition()) {
366363
if (!Def->hasAttr<SYCLDeviceAttr>()) {
367364
Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context));
368365
SemaRef.addSyclDeviceDecl(Def);
@@ -529,8 +526,7 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
529526
if (!CheckSYCLType(Field->getType(), Field->getSourceRange(),
530527
Visited)) {
531528
if (SemaRef.getLangOpts().SYCLIsDevice)
532-
SemaRef.SYCLDiagIfDeviceCode(Loc.getBegin(),
533-
diag::note_sycl_used_here);
529+
SemaRef.Diag(Loc.getBegin(), diag::note_sycl_used_here);
534530
return false;
535531
}
536532
}
@@ -539,8 +535,7 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
539535
if (!CheckSYCLType(Field->getType(), Field->getSourceRange(),
540536
Visited)) {
541537
if (SemaRef.getLangOpts().SYCLIsDevice)
542-
SemaRef.SYCLDiagIfDeviceCode(Loc.getBegin(),
543-
diag::note_sycl_used_here);
538+
SemaRef.Diag(Loc.getBegin(), diag::note_sycl_used_here);
544539
return false;
545540
}
546541
}
@@ -1399,8 +1394,7 @@ void Sema::MarkDevice(void) {
13991394

14001395
// Do we know that we will eventually codegen the given function?
14011396
static bool isKnownEmitted(Sema &S, FunctionDecl *FD) {
1402-
if (!FD)
1403-
return true; // Seen in LIT testing
1397+
assert(FD && "Given function may not be null.");
14041398

14051399
if (FD->hasAttr<SYCLDeviceAttr>() || FD->hasAttr<SYCLKernelAttr>())
14061400
return true;
@@ -1416,16 +1410,16 @@ Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
14161410
"Should only be called during SYCL compilation");
14171411
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
14181412
DeviceDiagBuilder::Kind DiagKind = [this, FD] {
1419-
if (ConstructingOpenCLKernel)
1413+
if (ConstructingOpenCLKernel || !FD)
14201414
return DeviceDiagBuilder::K_Nop;
1421-
else if (isKnownEmitted(*this, FD))
1415+
if (isKnownEmitted(*this, FD))
14221416
return DeviceDiagBuilder::K_ImmediateWithCallStack;
14231417
return DeviceDiagBuilder::K_Deferred;
14241418
}();
14251419
return DeviceDiagBuilder(DiagKind, Loc, DiagID, FD, *this);
14261420
}
14271421

1428-
bool Sema::CheckSYCLCall(SourceLocation Loc, FunctionDecl *Callee) {
1422+
void Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
14291423
assert(Callee && "Callee may not be null.");
14301424
FunctionDecl *Caller = dyn_cast<FunctionDecl>(getCurLexicalContext());
14311425

@@ -1435,7 +1429,6 @@ bool Sema::CheckSYCLCall(SourceLocation Loc, FunctionDecl *Callee) {
14351429
markKnownEmitted(*this, Caller, Callee, Loc, isKnownEmitted);
14361430
else if (Caller)
14371431
DeviceCallGraph[Caller].insert({Callee, Loc});
1438-
return true;
14391432
}
14401433

14411434
// -----------------------------------------------------------------------------

clang/lib/Sema/SemaStmtAsm.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
259259
// Skip all the checks if we are compiling SYCL device code, but the function
260260
// is not marked to be used on device, this code won't be codegen'ed anyway.
261261
if (getLangOpts().SYCLIsDevice) {
262-
SYCLDiagIfDeviceCode(AsmLoc, diag::err_sycl_restrict)
263-
<< KernelUseAssembly;
262+
SYCLDiagIfDeviceCode(AsmLoc, diag::err_sycl_restrict) << KernelUseAssembly;
264263
return new (Context)
265-
GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
266-
NumInputs, Names, Constraints, Exprs.data(), AsmString,
267-
NumClobbers, Clobbers, NumLabels, RParenLoc);
264+
GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs,
265+
Names, Constraints, Exprs.data(), AsmString, NumClobbers,
266+
Clobbers, NumLabels, RParenLoc);
268267
}
269268

270269
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());

clang/lib/Sema/SemaType.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,11 +1500,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
15001500
Result = Context.DoubleTy;
15011501
break;
15021502
case DeclSpec::TST_float128:
1503-
if (!S.Context.getTargetInfo().hasFloat128Type() &&
1504-
!S.getLangOpts().SYCLIsDevice &&
1505-
!(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
1503+
if (!S.Context.getTargetInfo().hasFloat128Type() &&
1504+
S.getLangOpts().SYCLIsDevice)
1505+
S.SYCLDiagIfDeviceCode(DS.getTypeSpecTypeLoc(),
1506+
diag::err_type_unsupported)
1507+
<< "__float128";
1508+
else if (!S.Context.getTargetInfo().hasFloat128Type() &&
1509+
!(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
15061510
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
1507-
<< "__float128";
1511+
<< "__float128";
15081512
Result = Context.Float128Ty;
15091513
break;
15101514
case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool

clang/test/SemaSYCL/inline-asm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ void bar() {
1919
#endif // LINUX_ASM
2020
}
2121

22-
template <typename name, typename Func>
22+
template <typename Name, typename Func>
2323
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
2424
// expected-note@+1 {{called by 'kernel_single_task<fake_kernel, (lambda}}
2525
kernelFunc();

clang/test/SemaSYCL/restrict-recursion3.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ void kernel3(void) {
1616
using myFuncDef = int(int,int);
1717

1818
void usage3(myFuncDef functionPtr) {
19+
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
20+
int *ip = new int;
1921
kernel3();
2022
}
2123

@@ -26,14 +28,14 @@ int addInt(int n, int m) {
2628
template <typename name, typename Func>
2729
// expected-note@+1 2{{function implemented using recursion declared here}}
2830
__attribute__((sycl_kernel)) void kernel_single_task2(Func kernelFunc) {
31+
// expected-note@+1 {{called by 'kernel_single_task2}}
2932
kernelFunc();
30-
// expected-error@+1 2{{SYCL kernel cannot allocate storage}}
31-
int *ip = new int;
3233
// expected-error@+1 2{{SYCL kernel cannot call a recursive function}}
3334
kernel_single_task2<name, Func>(kernelFunc);
3435
}
3536

3637
int main() {
38+
// expected-note@+1 {{called by 'operator()'}}
3739
kernel_single_task2<class fake_kernel>([]() { usage3( &addInt ); });
3840
return fib(5);
3941
}

clang/test/SemaSYCL/restrict-recursion4.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ void kernel2(void) {
1818
using myFuncDef = int(int,int);
1919

2020
void usage2(myFuncDef functionPtr) {
21+
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
22+
int *ip = new int;
2123
// expected-error@+1 {{SYCL kernel cannot call a recursive function}}
2224
kernel2();
2325
}
@@ -28,12 +30,12 @@ int addInt(int n, int m) {
2830

2931
template <typename name, typename Func>
3032
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
31-
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
32-
int *ip = new int;
33+
// expected-note@+1 {{called by 'kernel_single_task}}
3334
kernelFunc();
3435
}
3536

3637
int main() {
38+
// expected-note@+1 {{called by 'operator()'}}
3739
kernel_single_task<class fake_kernel>([]() {usage2(&addInt);});
3840
return fib(5);
3941
}

clang/test/SemaSYCL/sycl-restrict.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -Wno-return-type -verify -fsyntax-only -std=c++17 %s
2-
// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -fno-sycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -std=c++17 %s
3-
// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -DALLOW_FP=1 -fsycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -std=c++17 %s
1+
// RUN: %clang_cc1 -fcxx-exceptions -triple spir64 -fsycl-is-device -Wno-return-type -verify -fsyntax-only -std=c++17 %s
2+
// RUN: %clang_cc1 -fcxx-exceptions -triple spir64 -fsycl-is-device -fno-sycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -std=c++17 %s
3+
// RUN: %clang_cc1 -fcxx-exceptions -triple spir64 -fsycl-is-device -DALLOW_FP=1 -fsycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -std=c++17 %s
44

55

66
namespace std {
@@ -65,6 +65,7 @@ bool isa_B(A *a) {
6565
// expected-error@+1 {{SYCL kernel cannot allocate storage}}
6666
int *ip = new int;
6767
int i; int *p3 = new(&i) int; // no error on placement new
68+
// expected-note@+1 {{called by 'isa_B'}}
6869
OverloadedNewDelete *x = new( struct OverloadedNewDelete );
6970
auto y = new struct OverloadedNewDelete [5];
7071
// expected-error@+1 {{SYCL kernel cannot use rtti}}
@@ -102,6 +103,7 @@ using myFuncDef = int(int,int);
102103

103104
void eh_ok(void)
104105
{
106+
__float128 A;
105107
try {
106108
;
107109
} catch (...) {
@@ -138,6 +140,9 @@ void usage(myFuncDef functionPtr) {
138140
Check_RTTI_Restriction::kernel1<class kernel_name>([]() {
139141
Check_RTTI_Restriction::A *a;
140142
Check_RTTI_Restriction::isa_B(a); });
143+
144+
// expected-error@+1 {{__float128 is not supported on this target}}
145+
__float128 A;
141146
}
142147

143148
namespace ns {
@@ -172,9 +177,12 @@ int use2 ( a_type ab, a_type *abp ) {
172177
// expected-note@+1 {{called by 'use2'}}
173178
eh_not_ok();
174179
Check_RTTI_Restriction:: A *a;
180+
// expected-note@+1 2{{called by 'use2'}}
175181
Check_RTTI_Restriction:: isa_B(a);
182+
// expected-note@+1 {{called by 'use2'}}
176183
usage(&addInt);
177184
Check_User_Operators::Fraction f1(3, 8), f2(1, 2), f3(10, 2);
185+
// expected-note@+1 {{called by 'use2'}}
178186
if (f1 == f2) return false;
179187
}
180188

@@ -183,7 +191,7 @@ __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
183191
kernelFunc();
184192
a_type ab;
185193
a_type *p;
186-
// expected-note@+1 {{called by 'kernel_single_task'}}
194+
// expected-note@+1 5{{called by 'kernel_single_task'}}
187195
use2(ab, p);
188196
}
189197

0 commit comments

Comments
 (0)