Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9240a18
Add support for host kernel launch stmt generation
Fznamznon Aug 20, 2025
e0bb6e9
Remove a fixme from SemaSYCL
Fznamznon Sep 3, 2025
ad0065b
Do not crash if original body was invalid
Fznamznon Sep 3, 2025
145e850
Add AST test for skep-attributed member
Fznamznon Sep 3, 2025
9c91fce
Fix a warning
Fznamznon Sep 3, 2025
07967ea
Extend codegen test a bit
Fznamznon Sep 3, 2025
520a4e6
Find and replace
Fznamznon Sep 10, 2025
319caa5
Implement the thing
Fznamznon Sep 12, 2025
2c89c01
One more find and replace
Fznamznon Sep 12, 2025
aa02c24
I don't know how it looks like
Fznamznon Sep 12, 2025
c3d3035
Find and replace again
Fznamznon Sep 16, 2025
cb314fe
Switch to UnresolvedSYCLKernelEntryPointStmt
Fznamznon Sep 17, 2025
76d904b
Apply suggestions from code review
Fznamznon Sep 18, 2025
6f2541b
Remove log.txt
Fznamznon Sep 18, 2025
db002bb
Implement visiting
Fznamznon Sep 18, 2025
345e7b7
Add tests
Fznamznon Sep 19, 2025
2c155ef
Apply suggestions from code review
Fznamznon Sep 19, 2025
6d7e4c1
IdExpr -> KernelLaunchIdExpr
Fznamznon Sep 19, 2025
7e3a0bf
Don't rely on compound
Fznamznon Sep 19, 2025
b48996e
UnresolvedSYCLKernelEntryPointStmt -> UnresolvedSYCLKernelCall
Fznamznon Sep 19, 2025
1193734
Fix warnings
Fznamznon Sep 24, 2025
c83509b
Rename sycl_enqueue_kernel_launch -> sycl_kernel_launch
Fznamznon Sep 24, 2025
cb21a34
Apply suggestions from code review
Fznamznon Sep 24, 2025
07402a9
Remove array decay
Fznamznon Sep 25, 2025
1b2d1dd
Add windows run line to the sema test
Fznamznon Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2999,6 +2999,13 @@ DEF_TRAVERSE_STMT(ParenListExpr, {})
DEF_TRAVERSE_STMT(SYCLUniqueStableNameExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(UnresolvedSYCLKernelEntryPointStmt, {
if (getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(S->getOriginalStmt()));
TRY_TO(TraverseStmt(S->getIdExpr()));
ShouldVisitChildren = false;
}
})
DEF_TRAVERSE_STMT(OpenACCAsteriskSizeExpr, {})
DEF_TRAVERSE_STMT(PredefinedExpr, {})
DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
Expand Down
51 changes: 51 additions & 0 deletions clang/include/clang/AST/StmtSYCL.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,57 @@ class SYCLKernelCallStmt : public Stmt {
}
};

// UnresolvedSYCLKernelEntryPointStmt represents a SYCL kernel entry point function for a
// kernel that has not been instantiated yet. This Stmt should be transformed to
// a SYCLKernelCallStmt once the kernel and its name is known.
class UnresolvedSYCLKernelEntryPointStmt : public Stmt {
friend class ASTStmtReader;
Stmt *OriginalStmt = nullptr;
// This is either UnresolvedLookupExpr or UnresolvedMemberExpr.
Expr *IdExpr = nullptr;
UnresolvedSYCLKernelEntryPointStmt(CompoundStmt *CS, Expr *_IdExpr)
: Stmt(UnresolvedSYCLKernelEntryPointStmtClass),
OriginalStmt(CS), IdExpr(_IdExpr) {
}

void setIdExpr(Expr *Id) { IdExpr = Id; }
void setOriginalStmt(CompoundStmt *CS) { OriginalStmt = CS; }

public:
static UnresolvedSYCLKernelEntryPointStmt *
Create(const ASTContext &C, CompoundStmt *CS, Expr *IdExpr) {
return new (C) UnresolvedSYCLKernelEntryPointStmt(CS, IdExpr);
}

static UnresolvedSYCLKernelEntryPointStmt *CreateEmpty(const ASTContext &C) {
return new (C) UnresolvedSYCLKernelEntryPointStmt(nullptr, nullptr);
}

Expr *getIdExpr() const { return IdExpr; }
CompoundStmt *getOriginalStmt() { return cast<CompoundStmt>(OriginalStmt); }
const CompoundStmt *getOriginalStmt() const {
return cast<CompoundStmt>(OriginalStmt);
}

SourceLocation getBeginLoc() const LLVM_READONLY {
return getOriginalStmt()->getBeginLoc();
}

SourceLocation getEndLoc() const LLVM_READONLY {
return getOriginalStmt()->getEndLoc();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedSYCLKernelEntryPointStmtClass;
}
child_range children() {
return child_range(&OriginalStmt, &OriginalStmt + 1);
}

const_child_range children() const {
return const_child_range(&OriginalStmt, &OriginalStmt + 1);
}
};

} // end namespace clang

#endif // LLVM_CLANG_AST_STMTSYCL_H
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -13015,6 +13015,15 @@ def err_sycl_entry_point_return_type : Error<
def err_sycl_entry_point_deduced_return_type : Error<
"the %0 attribute only applies to functions with a non-deduced 'void' return"
" type">;
def err_sycl_host_no_launch_function : Error<
"unable to find suitable 'sycl_enqueue_kernel_launch' function for host code "
"synthesis">;
def warn_sycl_device_no_host_launch_function : Warning<
"unable to find suitable 'sycl_enqueue_kernel_launch' function for host code "
"synthesis">,
InGroup<DiagGroup<"sycl-host-launcher">>;
def note_sycl_host_launch_function : Note<
"define 'sycl_enqueue_kernel_launch' function template to fix this problem">;

def warn_cuda_maxclusterrank_sm_90 : Warning<
"maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring "
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def CaseStmt : StmtNode<SwitchCase>;
def DefaultStmt : StmtNode<SwitchCase>;
def CapturedStmt : StmtNode<Stmt>;
def SYCLKernelCallStmt : StmtNode<Stmt>;
def UnresolvedSYCLKernelEntryPointStmt : StmtNode<Stmt>;

// Statements that might produce a value (for example, as the last non-null
// statement in a GNU statement-expression).
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Sema/ScopeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ class FunctionScopeInfo {
/// The set of GNU address of label extension "&&label".
llvm::SmallVector<AddrLabelExpr *, 4> AddrLabels;

Expr *SYCLKernelLaunchIdExpr = nullptr;

public:
/// Represents a simple identification of a weak object.
///
Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang/Sema/SemaSYCL.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ class SemaSYCL : public SemaBase {

void CheckSYCLExternalFunctionDecl(FunctionDecl *FD);
void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD);
StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body);
StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body,
Expr *LaunchIdExpr);
ExprResult BuildSYCLKernelLaunchIdExpr(FunctionDecl *FD, QualType KNT);
StmtResult BuildUnresolvedSYCLKernelEntryPointStmt(CompoundStmt *CS,
Expr *IdExpr);
};

} // namespace clang
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,9 @@ enum StmtCode {
/// A SYCLKernelCallStmt record.
STMT_SYCLKERNELCALL,

/// A SYCLKernelCallStmt record.
STMT_UNRESOLVED_SYCL_KERNEL_ENTRY_POINT,

/// A GCC-style AsmStmt record.
STMT_GCCASM,

Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtSYCL.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "llvm/ADT/ArrayRef.h"

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,11 @@ void StmtPrinter::VisitSYCLUniqueStableNameExpr(
OS << ")";
}

void StmtPrinter::VisitUnresolvedSYCLKernelEntryPointStmt(
UnresolvedSYCLKernelEntryPointStmt *Node) {
PrintStmt(Node->getOriginalStmt());
}

void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
}
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,11 @@ void StmtProfiler::VisitSYCLUniqueStableNameExpr(
VisitType(S->getTypeSourceInfo()->getType());
}

void StmtProfiler::VisitUnresolvedSYCLKernelEntryPointStmt(
const UnresolvedSYCLKernelEntryPointStmt *S) {
VisitStmt(S);
}

void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
VisitExpr(S);
ID.AddInteger(llvm::to_underlying(S->getIdentKind()));
Expand Down
30 changes: 26 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15754,7 +15754,6 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
if (!Bases.empty())
OpenMP().ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl,
Bases);

return Dcl;
}

Expand Down Expand Up @@ -16167,6 +16166,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,

maybeAddDeclWithEffects(FD);

if (FD && !FD->isInvalidDecl() &&
FD->hasAttr<SYCLKernelEntryPointAttr>() && FnBodyScope) {
// Building KernelLaunchIdExpr requires performing an unqualified lookup
// which can only be done correctly while the stack of parsing scopes is
// alive, so we do it here when we start parsing function body even if it is
// a templated function.
const auto *SKEPAttr = FD->getAttr<SYCLKernelEntryPointAttr>();
if (!SKEPAttr->isInvalidAttr()) {
ExprResult LaunchIdExpr =
SYCL().BuildSYCLKernelLaunchIdExpr(FD, SKEPAttr->getKernelName());
getCurFunction()->SYCLKernelLaunchIdExpr = LaunchIdExpr.get();
}
}

return D;
}

Expand Down Expand Up @@ -16368,9 +16381,18 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation,
SKEPAttr->setInvalidAttr();
}

if (Body && !FD->isTemplated() && !SKEPAttr->isInvalidAttr()) {
StmtResult SR =
SYCL().BuildSYCLKernelCallStmt(FD, cast<CompoundStmt>(Body));
auto *BodyCompound = dyn_cast_or_null<CompoundStmt>(Body);
// If Body is not a compound, that was a templated function and we don't
// need to build SYCLKernelCallStmt for it since it was already created by
// template instantiator.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little nervous about relying on a check for CompountStmt specifically here to determine what to build. I think there are three cases to consider:

  1. A function template or templated function for which an UnresolvedSYCLKernelEntryPointStmt is needed.
  2. An instantiated function template for which a SYCLKernelCallStmt was already instantiated.
  3. An explicit function template specialization or a non-template function for which a SYCLKernelCallStmt is needed.

I think these can be differentiated as follows:

  1. if FD->isTemplated() is true.
  2. otherwise, if FD->getTemplateSpecializationInfo() is non-null and isTemplateInstantiation(FD->getTemplateSpecializationKind())` is true.
  3. everything else.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. FD->getTemplateSpecializationInfo() && isTemplateInstantiation(FD->getTemplateSpecializationKind()) seems to be breaking some tests. I used FD->isTemplateInstantiation() to detect the case instead.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I added the FD->getTemplateSpecializationInfo() condition because I wasn't sure what FD->getTemplateSpecializationKind() would return for a non-template function. But if it works as expected, then great.

There is a comment in the FunctionDecl::isTemplateInstantiation() definition that I don't really know what to make of. My best guess is that it relates to a possible ambiguous classification of an instantiated dependent explicit specialization. It could also be that the FIXME comment is old/stale; I didn't dig into it. The isTemplateInstantiation() name certainly suggests it is what we want here.

bool FunctionDecl::isTemplateInstantiation() const {
  // FIXME: Remove this, it's not clear what it means. (Which template
  // specialization kind?)
  return clang::isTemplateInstantiation(getTemplateSpecializationKind());
}

if (BodyCompound && !SKEPAttr->isInvalidAttr()) {
StmtResult SR;
if (FD->isTemplated())
SR = SYCL().BuildUnresolvedSYCLKernelEntryPointStmt(
BodyCompound, getCurFunction()->SYCLKernelLaunchIdExpr);
else
SR = SYCL().BuildSYCLKernelCallStmt(
FD, BodyCompound, getCurFunction()->SYCLKernelLaunchIdExpr);
if (SR.isInvalid())
return nullptr;
Body = SR.get();
Expand Down
Loading