Skip to content

Commit 07c9c1c

Browse files
committed
Misc cleanup.
- Added/edited lots of comments. - Expanded testing for sycl_kernel_launch lookup and reorganized the tests to make it easier to identify and/or plug testing gaps. - Added a missing sycl_kernel_entry_point attribute in a test. - Reordered various declarations for better grouping and consistency. - Renamed some variables and functions. - Removed an unnecessary include directive. - Adjusted the location used for the implicit sycl_kernel_launch call. The opening brace of the original function body is used where available and the general function location is used otherwise. - Corrected lookup to unconditionally look for a template name; previously a spurious error about a 'template' keyword could be issued. - Added missing code gen checks for use of a member function as the SYCL kernel entry point function. - Other misc style edits for consistency.
1 parent 9779525 commit 07c9c1c

21 files changed

+750
-445
lines changed

clang/include/clang/AST/StmtSYCL.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,23 +100,30 @@ class SYCLKernelCallStmt : public Stmt {
100100
};
101101

102102
// UnresolvedSYCLKernelCallStmt represents an invocation of a SYCL kernel in
103-
// a dependent context for which lookup of the sycl_enqueue_kernel_launch
104-
// identifier cannot be performed. These statements are transformed to
105-
// SYCLKernelCallStmt during template instantiation.
103+
// a dependent context for which lookup of the sycl_kernel_launch identifier
104+
// cannot be performed. These statements are transformed to SYCLKernelCallStmt
105+
// during template instantiation.
106106
class UnresolvedSYCLKernelCallStmt : public Stmt {
107107
friend class ASTStmtReader;
108+
friend class ASTStmtWriter;
109+
110+
private:
108111
Stmt *OriginalStmt = nullptr;
109112
// KernelLaunchIdExpr stores an UnresolvedLookupExpr or UnresolvedMemberExpr
110113
// corresponding to the SYCL kernel launch function for which a call
111114
// will be synthesized during template instantiation.
112115
Expr *KernelLaunchIdExpr = nullptr;
116+
113117
UnresolvedSYCLKernelCallStmt(CompoundStmt *CS, Expr *IdExpr)
114118
: Stmt(UnresolvedSYCLKernelCallStmtClass), OriginalStmt(CS),
115119
KernelLaunchIdExpr(IdExpr) {}
116120

117-
void setKernelLaunchIdExpr(Expr *IdExpr) { KernelLaunchIdExpr = IdExpr; }
121+
/// Set the original statement.
118122
void setOriginalStmt(CompoundStmt *CS) { OriginalStmt = CS; }
119123

124+
/// Set the kernel launch ID expression.
125+
void setKernelLaunchIdExpr(Expr *IdExpr) { KernelLaunchIdExpr = IdExpr; }
126+
120127
public:
121128
static UnresolvedSYCLKernelCallStmt *
122129
Create(const ASTContext &C, CompoundStmt *CS, Expr *IdExpr) {
@@ -127,12 +134,16 @@ class UnresolvedSYCLKernelCallStmt : public Stmt {
127134
return new (C) UnresolvedSYCLKernelCallStmt(nullptr, nullptr);
128135
}
129136

130-
Expr *getKernelLaunchIdExpr() const { return KernelLaunchIdExpr; }
137+
/// Retrieve the original statement.
131138
CompoundStmt *getOriginalStmt() { return cast<CompoundStmt>(OriginalStmt); }
132139
const CompoundStmt *getOriginalStmt() const {
133140
return cast<CompoundStmt>(OriginalStmt);
134141
}
135142

143+
/// Retrieve the kernel launch ID expression.
144+
Expr *getKernelLaunchIdExpr() { return KernelLaunchIdExpr; }
145+
const Expr *getKernelLaunchIdExpr() const { return KernelLaunchIdExpr; }
146+
136147
SourceLocation getBeginLoc() const LLVM_READONLY {
137148
return getOriginalStmt()->getBeginLoc();
138149
}

clang/include/clang/Sema/SemaSYCL.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,32 @@ class SemaSYCL : public SemaBase {
6666

6767
void CheckSYCLExternalFunctionDecl(FunctionDecl *FD);
6868
void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD);
69+
70+
/// Builds an expression for the lookup of a 'sycl_kernel_launch' template
71+
/// with 'KernelName' as an explicit template argument. Lookup is performed
72+
/// as if from the first statement of the body of 'FD' and thus requires
73+
/// searching the scopes that exist at parse time. This function therefore
74+
/// requires the current semantic context to be the definition of 'FD'. In a
75+
/// dependent context, the returned expression will be an UnresolvedLookupExpr
76+
/// or an UnresolvedMemberExpr. In a non-dependent context, the returned
77+
/// expression will be a DeclRefExpr or MemberExpr. If lookup fails, a null
78+
/// error result is returned. The resulting expression is intended to be
79+
/// passed as the 'LaunchIdExpr' argument in a call to either
80+
/// BuildSYCLKernelCallStmt() or BuildUnresolvedSYCLKernelCallStmt() after
81+
/// the function body has been parsed.
82+
ExprResult BuildSYCLKernelLaunchIdExpr(FunctionDecl *FD, QualType KernelName);
83+
84+
/// Builds a SYCLKernelCallStmt to wrap 'Body' and to be used as the body of
85+
/// 'FD'. 'LaunchIdExpr' specifies the lookup result returned by a previous
86+
/// call to BuildSYCLKernelLaunchIdExpr().
6987
StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body,
7088
Expr *LaunchIdExpr);
71-
ExprResult BuildSYCLKernelLaunchIdExpr(FunctionDecl *FD, QualType KNT);
72-
StmtResult BuildUnresolvedSYCLKernelCallStmt(CompoundStmt *CS,
73-
Expr *IdExpr);
89+
90+
/// Builds an UnresolvedSYCLKernelCallStmt to wrap 'Body'. 'LaunchIdExpr'
91+
/// specifies the lookup result returned by a previous call to
92+
/// BuildSYCLKernelLaunchIdExpr().
93+
StmtResult BuildUnresolvedSYCLKernelCallStmt(CompoundStmt *Body,
94+
Expr *LaunchIdExpr);
7495
};
7596

7697
} // namespace clang

clang/lib/AST/ComputeDependence.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "clang/AST/ExprConcepts.h"
1717
#include "clang/AST/ExprObjC.h"
1818
#include "clang/AST/ExprOpenMP.h"
19-
#include "clang/AST/StmtSYCL.h"
2019
#include "clang/Basic/ExceptionSpecificationType.h"
2120
#include "llvm/ADT/ArrayRef.h"
2221

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
104104
case Stmt::SEHExceptStmtClass:
105105
case Stmt::SEHFinallyStmtClass:
106106
case Stmt::MSDependentExistsStmtClass:
107+
case Stmt::UnresolvedSYCLKernelCallStmtClass:
107108
llvm_unreachable("invalid statement class to emit generically");
108109
case Stmt::NullStmtClass:
109110
case Stmt::CompoundStmtClass:
@@ -117,7 +118,6 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
117118
case Stmt::CaseStmtClass:
118119
case Stmt::SEHLeaveStmtClass:
119120
case Stmt::SYCLKernelCallStmtClass:
120-
case Stmt::UnresolvedSYCLKernelCallStmtClass:
121121
llvm_unreachable("should have emitted these statements as simple");
122122

123123
#define STMT(Type, Base)

clang/lib/Sema/SemaDecl.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16228,10 +16228,15 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
1622816228

1622916229
if (FD && !FD->isInvalidDecl() &&
1623016230
FD->hasAttr<SYCLKernelEntryPointAttr>() && FnBodyScope) {
16231-
// Building KernelLaunchIdExpr requires performing an unqualified lookup
16232-
// which can only be done correctly while the stack of parsing scopes is
16233-
// alive, so we do it here when we start parsing function body even if it is
16234-
// a templated function.
16231+
// An implicit call expression is synthesized for functions declared with
16232+
// the sycl_kernel_entry_point attribute. The call may resolve to a
16233+
// function template, a member function template, or a call operator
16234+
// of a variable template depending on the results of unqualified lookup
16235+
// for 'sycl_kernel_launch' from the beginning of the function body.
16236+
// Performing that lookup requires the stack of parsing scopes active
16237+
// when the definition is parsed and is thus done here; the result is
16238+
// cached in FunctionScopeInfo and used to synthesize the (possibly
16239+
// unresolved) call expression after the function body has been parsed.
1623516240
const auto *SKEPAttr = FD->getAttr<SYCLKernelEntryPointAttr>();
1623616241
if (!SKEPAttr->isInvalidAttr()) {
1623716242
ExprResult LaunchIdExpr =
@@ -16441,8 +16446,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation,
1644116446
SKEPAttr->setInvalidAttr();
1644216447
}
1644316448

16444-
// We don't need to build SYCLKernelCallStmt for template instantiations
16445-
// since it was already created by template instantiator.
16449+
// Build an unresolved SYCL kernel call statement for a function template,
16450+
// validate that a SYCL kernel call statement was instantiated for an
16451+
// (implicit or explicit) instantiation of a function template, or otherwise
16452+
// build a (resolved) SYCL kernel call statement for a non-templated
16453+
// function or an explicit specialization.
1644616454
if (Body && !SKEPAttr->isInvalidAttr()) {
1644716455
StmtResult SR;
1644816456
if (FD->isTemplated()) {

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 66 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -392,85 +392,82 @@ void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
392392

393393
ExprResult SemaSYCL::BuildSYCLKernelLaunchIdExpr(FunctionDecl *FD,
394394
QualType KNT) {
395+
// The current context must be the function definition context to ensure
396+
// that name lookup is performed within the correct scope.
397+
assert(SemaRef.CurContext == FD);
395398

396-
ASTContext &Ctx = SemaRef.getASTContext();
397-
// Some routines need a valid source location to work correctly.
398-
SourceLocation BodyLoc =
399-
FD->getEndLoc().isValid() ? FD->getEndLoc() : FD->getLocation();
399+
// An appropriate source location is required to emit diagnostics if
400+
// lookup fails to produce an overload set. The desired location is the
401+
// start of the function body, but that is not yet available since the
402+
// body of the function has not yet been set when this function is called.
403+
// The general location of the function is used instead.
404+
SourceLocation Loc = FD->getLocation();
400405

401-
IdentifierInfo &LaunchFooName =
406+
ASTContext &Ctx = SemaRef.getASTContext();
407+
IdentifierInfo &SYCLKernelLaunchID =
402408
Ctx.Idents.get("sycl_kernel_launch", tok::TokenKind::identifier);
403409

404-
// Perform overload resolution for a call to an accessible (member) function
405-
// template named 'sycl_kernel_launch' "from within the definition of
406-
// FD where":
407-
// - The kernel name type is passed as the first template argument.
408-
// - Any remaining template parameters are deduced from the function
409-
// arguments or assigned by default template arguments.
410-
// - 'this' is passed as the implicit function argument if 'FD' is a
411-
// non-static member function.
412-
// - The name of the kernel, expressed as a string literal, is passed as the
413-
// first function argument.
414-
// - The parameters of FD are forwarded as-if by 'std::forward()' as the
415-
// remaining explicit function arguments.
416-
// - Any remaining function arguments are initialized by default arguments.
417-
LookupResult Result(SemaRef, &LaunchFooName, BodyLoc,
410+
// Perform ordinary name lookup for a function or variable template that
411+
// accepts a single type template argument.
412+
LookupResult Result(SemaRef, &SYCLKernelLaunchID, Loc,
418413
Sema::LookupOrdinaryName);
419-
CXXScopeSpec SS;
420-
SemaRef.LookupTemplateName(Result, SemaRef.getCurScope(), SS,
421-
/*ObjectType=*/QualType(),
422-
/*EnteringContext=*/false, BodyLoc);
414+
CXXScopeSpec EmptySS;
415+
SemaRef.LookupTemplateName(Result, SemaRef.getCurScope(), EmptySS,
416+
/*ObjectType*/ QualType(),
417+
/*EnteringContext*/ false,
418+
Sema::TemplateNameIsRequired);
423419

424420
if (Result.empty() || Result.isAmbiguous()) {
425-
SemaRef.Diag(BodyLoc, SemaRef.getLangOpts().SYCLIsHost
426-
? diag::err_sycl_host_no_launch_function
427-
: diag::warn_sycl_device_no_host_launch_function);
428-
SemaRef.Diag(BodyLoc, diag::note_sycl_host_launch_function);
421+
SemaRef.Diag(Loc, SemaRef.getLangOpts().SYCLIsHost
422+
? diag::err_sycl_host_no_launch_function
423+
: diag::warn_sycl_device_no_host_launch_function);
424+
SemaRef.Diag(Loc, diag::note_sycl_host_launch_function);
429425

430426
return ExprError();
431427
}
432428

433-
TemplateArgumentListInfo TALI{BodyLoc, BodyLoc};
429+
TemplateArgumentListInfo TALI{Loc, Loc};
434430
TemplateArgument KNTA = TemplateArgument(KNT);
435431
TemplateArgumentLoc TAL =
436-
SemaRef.getTrivialTemplateArgumentLoc(KNTA, QualType(), BodyLoc);
432+
SemaRef.getTrivialTemplateArgumentLoc(KNTA, QualType(), Loc);
437433
TALI.addArgument(TAL);
438434
ExprResult IdExpr;
439-
if (SemaRef.isPotentialImplicitMemberAccess(SS, Result,
440-
/*IsAddressOfOperand=*/false))
441-
// BuildPossibleImplicitMemberExpr creates UnresolvedMemberExpr. Using it
442-
// allows to pass implicit/explicit this argument automatically.
443-
IdExpr = SemaRef.BuildPossibleImplicitMemberExpr(SS, BodyLoc, Result, &TALI,
435+
if (SemaRef.isPotentialImplicitMemberAccess(EmptySS, Result,
436+
/*IsAddressOfOperand*/ false))
437+
// The lookup result allows for a possible implicit member access that
438+
// would require an implicit or explicit 'this' argument.
439+
IdExpr = SemaRef.BuildPossibleImplicitMemberExpr(EmptySS, SourceLocation(),
440+
Result, &TALI,
444441
SemaRef.getCurScope());
445442
else
446-
IdExpr = SemaRef.BuildTemplateIdExpr(SS, BodyLoc, Result,
447-
/*RequiresADL=*/true, &TALI);
443+
IdExpr = SemaRef.BuildTemplateIdExpr(EmptySS, SourceLocation(), Result,
444+
/*RequiresADL*/ true, &TALI);
448445

449-
// Can happen if SKEP attributed function is a static member, but the launcher
450-
// is a regular member. Perhaps emit a note saying that we're in host code
451-
// synthesis.
446+
// The resulting expression may be invalid if, for example, 'FD' is a
447+
// non-static member function and sycl_kernel_launch lookup selects a
448+
// member function (which would require a 'this' argument which is
449+
// not available).
452450
if (IdExpr.isInvalid())
453451
return ExprError();
454452

455453
return IdExpr;
456454
}
457455

458-
StmtResult SemaSYCL::BuildUnresolvedSYCLKernelCallStmt(CompoundStmt *CS,
459-
Expr *IdExpr) {
460-
return UnresolvedSYCLKernelCallStmt::Create(SemaRef.getASTContext(), CS,
461-
IdExpr);
462-
}
463-
464456
namespace {
465457

466-
void PrepareKernelArgumentsForKernelLaunch(SmallVectorImpl<Expr *> &Args,
467-
const SYCLKernelInfo *SKI,
468-
Sema &SemaRef,
469-
SourceLocation Loc) {
470-
assert(SKI && "Need a kernel!");
471-
ASTContext &Ctx = SemaRef.getASTContext();
458+
// Constructs the arguments to be passed for the SYCL kernel launch call.
459+
// The first argument is a string literal that contains the SYCL kernel
460+
// name. The remaining arguments are the parameters of 'FD'.
461+
void BuildSYCLKernelLaunchCallArgs(Sema &SemaRef, FunctionDecl *FD,
462+
const SYCLKernelInfo *SKI,
463+
SmallVectorImpl<Expr *> &Args,
464+
SourceLocation Loc) {
465+
// The current context must be the function definition context to ensure
466+
// that parameter references occur within the correct scope.
467+
assert(SemaRef.CurContext == FD);
472468

473469
// Prepare a string literal that contains the kernel name.
470+
ASTContext &Ctx = SemaRef.getASTContext();
474471
const std::string KernelName = SKI->GetKernelName();
475472
QualType KernelNameCharTy = Ctx.CharTy.withConst();
476473
llvm::APInt KernelNameSize(Ctx.getTypeSize(Ctx.getSizeType()),
@@ -482,30 +479,23 @@ void PrepareKernelArgumentsForKernelLaunch(SmallVectorImpl<Expr *> &Args,
482479
/*Pascal*/ false, KernelNameArrayTy, Loc);
483480
Args.push_back(KernelNameExpr);
484481

485-
// Right now we simply forward the arguments of the skep-attributed function.
486-
// With decomposition present there can be another logic.
487-
// Make sure to use CurContext to avoid diagnostics that we're using a
488-
// variable coming from another context. The function should be the same as in
489-
// the kernel info though.
490-
auto *FD = cast<FunctionDecl>(SemaRef.CurContext);
491-
assert(declaresSameEntity(FD, SKI->getKernelEntryPointDecl()));
492482
for (ParmVarDecl *PVD : FD->parameters()) {
493483
QualType ParamType = PVD->getOriginalType().getNonReferenceType();
494484
Expr *DRE = SemaRef.BuildDeclRefExpr(PVD, ParamType, VK_LValue, Loc);
495-
assert(DRE);
496485
Args.push_back(DRE);
497486
}
498487
}
499488

500-
StmtResult BuildSYCLKernelLaunchStmt(Sema &SemaRef,
501-
const SYCLKernelInfo *SKI,
502-
Expr *IdExpr, SourceLocation Loc) {
489+
// Constructs the SYCL kernel launch call.
490+
StmtResult BuildSYCLKernelLaunchCallStmt(Sema &SemaRef, FunctionDecl *FD,
491+
const SYCLKernelInfo *SKI,
492+
Expr *IdExpr, SourceLocation Loc) {
503493
SmallVector<Stmt *> Stmts;
504-
assert(SKI && "Need a Kernel!");
505494

495+
// IdExpr may be null if name lookup failed.
506496
if (IdExpr) {
507497
llvm::SmallVector<Expr *, 12> Args;
508-
PrepareKernelArgumentsForKernelLaunch(Args, SKI, SemaRef, Loc);
498+
BuildSYCLKernelLaunchCallArgs(SemaRef, FD, SKI, Args, Loc);
509499
ExprResult LaunchResult =
510500
SemaRef.BuildCallExpr(SemaRef.getCurScope(), IdExpr, Loc, Args, Loc);
511501
if (LaunchResult.isInvalid())
@@ -630,14 +620,20 @@ StmtResult SemaSYCL::BuildSYCLKernelCallStmt(FunctionDecl *FD,
630620
BuildSYCLKernelEntryPointOutline(SemaRef, FD, Body);
631621
assert(OFD);
632622

633-
// Build host kernel launch stmt.
634-
SourceLocation BodyLoc =
635-
FD->getEndLoc().isValid() ? FD->getEndLoc() : FD->getLocation();
636-
StmtResult LaunchRes =
637-
BuildSYCLKernelLaunchStmt(SemaRef, &SKI, LaunchIdExpr, BodyLoc);
623+
// Build the host kernel launch statement. An appropriate source location
624+
// is required to emit diagnostics.
625+
SourceLocation Loc = Body->getLBracLoc();
626+
StmtResult LaunchResult =
627+
BuildSYCLKernelLaunchCallStmt(SemaRef, FD, &SKI, LaunchIdExpr, Loc);
638628

639629
Stmt *NewBody =
640-
new (getASTContext()) SYCLKernelCallStmt(Body, LaunchRes.get(), OFD);
630+
new (getASTContext()) SYCLKernelCallStmt(Body, LaunchResult.get(), OFD);
641631

642632
return NewBody;
643633
}
634+
635+
StmtResult SemaSYCL::BuildUnresolvedSYCLKernelCallStmt(CompoundStmt *Body,
636+
Expr *LaunchIdExpr) {
637+
return UnresolvedSYCLKernelCallStmt::Create(SemaRef.getASTContext(), Body,
638+
LaunchIdExpr);
639+
}

clang/lib/Sema/TreeTransform.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12975,7 +12975,6 @@ StmtResult TreeTransform<Derived>::TransformUnresolvedSYCLKernelCallStmt(
1297512975
return StmtError();
1297612976

1297712977
ExprResult IdExpr = getDerived().TransformExpr(S->getKernelLaunchIdExpr());
12978-
1297912978
if (IdExpr.isInvalid())
1298012979
return StmtError();
1298112980

clang/test/ASTSYCL/ast-dump-sycl-kernel-call-stmt.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ template<int> struct K {
3434
void operator()(Ts...) const {}
3535
};
3636

37-
template <typename KernelName, typename... Ts>
37+
template<typename KernelName, typename... Ts>
3838
void sycl_kernel_launch(const char *, Ts...) {}
3939

4040
[[clang::sycl_kernel_entry_point(KN<1>)]]
@@ -373,18 +373,18 @@ void skep8(S8 k) {
373373
// CHECK: | `-SYCLKernelEntryPointAttr {{.*}}
374374

375375
class Handler {
376-
template <typename KernelName, typename... Ts>
377-
void sycl_kernel_launch(const char *, Ts...) {}
376+
template <typename KNT, typename... Ts>
377+
void sycl_kernel_launch(const char *, Ts...) {}
378378
public:
379-
template<typename KNT, typename KT>
380-
[[clang::sycl_kernel_entry_point(KNT)]]
381-
void skep9(KT k, int a, int b) {
382-
k(a, b);
383-
}
379+
template<typename KNT, typename KT>
380+
[[clang::sycl_kernel_entry_point(KNT)]]
381+
void skep9(KT k, int a, int b) {
382+
k(a, b);
383+
}
384384
};
385385
void foo() {
386386
Handler H;
387-
H.skep9<KN<9>>([=](int a, int b){return a+b;}, 1, 2);
387+
H.skep9<KN<9>>([=] (int a, int b) { return a+b; }, 1, 2);
388388
}
389389

390390
// CHECK: | |-FunctionTemplateDecl {{.*}} skep9

clang/test/ASTSYCL/ast-dump-sycl-kernel-entry-point.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
// A unique kernel name type is required for each declared kernel entry point.
2929
template<int, int=0> struct KN;
3030

31-
template <typename KernelName, typename... Tys>
32-
void sycl_kernel_launch(const char *, Tys &&...Args) {}
31+
template<typename KernelName, typename... Ts>
32+
void sycl_kernel_launch(const char *, Ts... Args) {}
3333

3434
[[clang::sycl_kernel_entry_point(KN<1>)]]
3535
void skep1() {

0 commit comments

Comments
 (0)