Skip to content

Commit 5b42f6b

Browse files
committed
[SYCL] SYCL host kernel launch support for the sycl_kernel_entry_point attribute.
The `sycl_kernel_entry_point` attribute facilitates the generation of an offload kernel entry point function with parameters corresponding to the (potentially decomposed) kernel arguments and a body that (potentially reconstructs the arguments and) executes the kernel. This change adds symmetric support for the SYCL host through an interface that provides symbol names and (potentially decomposed) kernel arguments to the SYCL library. Consider the following function declared with the `sycl_kernel_entry_point` attribute with a call to this function occurring in the implementation of a SYCL kernel invocation function such as `sycl::handler::single_task()`. template<typename KernelNameType, typename KernelType> [[clang::sycl_kernel_entry_point(KernelNameType)]] void kernel_entry_point(KernelType kerne) { kernel(); } The body of the above function specifies the parameters and body of the generated offload kernel entry point. Clearly, a call to the above function by a SYCL kernel invocation function is not intended to execute the body as written. Previously, code generation emitted an empty function body so that calls to the function had no effect other than to trigger the generation of the offload kernel entry point. The function body is therefore available to hook for SYCL library support and is now substituted with a call to a (SYCL library provided) function template named `sycl_enqueue_kernel_launch()` with the kernel name type passed as the first template argument, the symbol name of the offload kernel entry point passed as a string literal for the first function argument, and the (possibly decomposed) parameters passed as the remaining explicit function arguments. Given a call like this: kernel_entry_point<struct KN>([]{}) the body of the instantiated `kernel_entry_point()` specialization would be substituted as follows with "kernel-symbol-name" substituted for the generated symbol name and `kernel` forwarded (This assumes no kernel argument decomposition; if decomposition was required, `kernel` would be replaced with its corresponding decomposed arguments). sycl_enqueue_kernel_launch<KN>("kernel-symbol-name", kernel) Name lookup and overload resolution for the `sycl_enqueue_kernel_launch()` function is performed at the point of definition of the `sycl_kernel_entry_point` attributed function (or the point of instantiation for an instantiated function template specialization). If overload resolution fails, the program is ill-formed. Implementation of the `sycl_enqueue_kernel_launch()` function might require additional information provided by the SYCL library. This is facilitated by removing the previous prohibition against use of the `sycl_kernel_entry_point` attribute with a non-static member function. If the `sycl_kernel_entry_point` attributed function is a non-static member function, then overload resolution for the `sycl_enqueue_kernel_launch()` function template may select a non-static member function in which case, `this` will be implicitly passed as the implicit object argument. If a `sycl_kernel_entry_point` attributed function is a non-static member function, use of `this` in a potentially evaluated expression is prohibited in the definition (since `this` is not a kernel argument and will not be available within the generated offload kernel entry point function). Support for kernel argument decomposition and reconstruction is not yet implemented.
1 parent a196281 commit 5b42f6b

22 files changed

+385
-139
lines changed

clang/include/clang/AST/ASTNodeTraverser.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,8 +848,10 @@ class ASTNodeTraverser
848848

849849
void VisitSYCLKernelCallStmt(const SYCLKernelCallStmt *Node) {
850850
Visit(Node->getOriginalStmt());
851-
if (Traversal != TK_IgnoreUnlessSpelledInSource)
851+
if (Traversal != TK_IgnoreUnlessSpelledInSource) {
852+
Visit(Node->getKernelLaunchStmt());
852853
Visit(Node->getOutlinedFunctionDecl());
854+
}
853855
}
854856

855857
void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) {

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2942,6 +2942,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
29422942
DEF_TRAVERSE_STMT(SYCLKernelCallStmt, {
29432943
if (getDerived().shouldVisitImplicitCode()) {
29442944
TRY_TO(TraverseStmt(S->getOriginalStmt()));
2945+
TRY_TO(TraverseStmt(S->getKernelLaunchStmt()));
29452946
TRY_TO(TraverseDecl(S->getOutlinedFunctionDecl()));
29462947
ShouldVisitChildren = false;
29472948
}

clang/include/clang/AST/StmtSYCL.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,35 +28,45 @@ namespace clang {
2828
/// of such a function specifies the statements to be executed on a SYCL device
2929
/// to invoke a SYCL kernel with a particular set of kernel arguments. The
3030
/// SYCLKernelCallStmt associates an original statement (the compound statement
31-
/// that is the function body) with an OutlinedFunctionDecl that holds the
32-
/// kernel parameters and the transformed body. During code generation, the
33-
/// OutlinedFunctionDecl is used to emit an offload kernel entry point suitable
34-
/// for invocation from a SYCL library implementation. If executed, the
35-
/// SYCLKernelCallStmt behaves as a no-op; no code generation is performed for
36-
/// it.
31+
/// that is the function body) with a kernel launch statement to execute on a
32+
/// SYCL host and an OutlinedFunctionDecl that holds the kernel parameters and
33+
/// the transformed body to execute on a SYCL device. During code generation,
34+
/// the OutlinedFunctionDecl is used to emit an offload kernel entry point
35+
/// suitable for invocation from a SYCL library implementation.
3736
class SYCLKernelCallStmt : public Stmt {
3837
friend class ASTStmtReader;
3938
friend class ASTStmtWriter;
4039

4140
private:
4241
Stmt *OriginalStmt = nullptr;
42+
Stmt *KernelLaunchStmt = nullptr;
4343
OutlinedFunctionDecl *OFDecl = nullptr;
4444

4545
public:
4646
/// Construct a SYCL kernel call statement.
47-
SYCLKernelCallStmt(CompoundStmt *CS, OutlinedFunctionDecl *OFD)
48-
: Stmt(SYCLKernelCallStmtClass), OriginalStmt(CS), OFDecl(OFD) {}
47+
SYCLKernelCallStmt(CompoundStmt *CS, Stmt *S, OutlinedFunctionDecl *OFD)
48+
: Stmt(SYCLKernelCallStmtClass), OriginalStmt(CS), KernelLaunchStmt(S),
49+
OFDecl(OFD) {}
4950

5051
/// Construct an empty SYCL kernel call statement.
5152
SYCLKernelCallStmt(EmptyShell Empty) : Stmt(SYCLKernelCallStmtClass, Empty) {}
5253

53-
/// Retrieve the model statement.
54+
/// Retrieve the original statement.
5455
CompoundStmt *getOriginalStmt() { return cast<CompoundStmt>(OriginalStmt); }
5556
const CompoundStmt *getOriginalStmt() const {
5657
return cast<CompoundStmt>(OriginalStmt);
5758
}
59+
60+
/// Set the original statement.
5861
void setOriginalStmt(CompoundStmt *CS) { OriginalStmt = CS; }
5962

63+
/// Retrieve the kernel launch statement.
64+
Stmt *getKernelLaunchStmt() { return KernelLaunchStmt; }
65+
const Stmt *getKernelLaunchStmt() const { return KernelLaunchStmt; }
66+
67+
/// Set the kernel launch statement.
68+
void setKernelLaunchStmt(Stmt *S) { KernelLaunchStmt = S; }
69+
6070
/// Retrieve the outlined function declaration.
6171
OutlinedFunctionDecl *getOutlinedFunctionDecl() { return OFDecl; }
6272
const OutlinedFunctionDecl *getOutlinedFunctionDecl() const { return OFDecl; }

clang/include/clang/Basic/AttrDocs.td

Lines changed: 97 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -479,13 +479,13 @@ The SYCL kernel in the previous code sample meets these expectations.
479479
def SYCLKernelEntryPointDocs : Documentation {
480480
let Category = DocCatFunction;
481481
let Content = [{
482-
The ``sycl_kernel_entry_point`` attribute facilitates the generation of an
483-
offload kernel entry point, sometimes called a SYCL kernel caller function,
484-
suitable for invoking a SYCL kernel on an offload device. The attribute is
485-
intended for use in the implementation of SYCL kernel invocation functions
486-
like the ``single_task`` and ``parallel_for`` member functions of the
487-
``sycl::handler`` class specified in section 4.9.4, "Command group ``handler``
488-
class", of the SYCL 2020 specification.
482+
The ``sycl_kernel_entry_point`` attribute facilitates the launch of a SYCL
483+
kernel and the generation of an offload kernel entry point, sometimes called
484+
a SYCL kernel caller function, suitable for invoking a SYCL kernel on an
485+
offload device. The attribute is intended for use in the implementation of
486+
SYCL kernel invocation functions like the ``single_task`` and ``parallel_for``
487+
member functions of the ``sycl::handler`` class specified in section 4.9.4,
488+
"Command group ``handler`` class", of the SYCL 2020 specification.
489489

490490
The attribute requires a single type argument that specifies a class type that
491491
meets the requirements for a SYCL kernel name as described in section 5.2,
@@ -497,7 +497,7 @@ The attribute only appertains to functions and only those that meet the
497497
following requirements.
498498

499499
* Has a non-deduced ``void`` return type.
500-
* Is not a non-static member function, constructor, or destructor.
500+
* Is not a constructor or destructor.
501501
* Is not a C variadic function.
502502
* Is not a coroutine.
503503
* Is not defined as deleted or as defaulted.
@@ -512,39 +512,43 @@ follows.
512512

513513
namespace sycl {
514514
class handler {
515+
template<typename KernelNameType, typename... Ts>
516+
void sycl_enqueue_kernel_launch(const char *KernelName, Ts...) {
517+
// Call functions appropriate for the desired offload backend
518+
// (OpenCL, CUDA, HIP, Level Zero, etc...) to enqueue kernel invocation.
519+
}
520+
515521
template<typename KernelNameType, typename KernelType>
516522
[[ clang::sycl_kernel_entry_point(KernelNameType) ]]
517-
static void kernel_entry_point(KernelType kernel) {
518-
kernel();
523+
void kernel_entry_point(KernelType Kernel) {
524+
Kernel();
519525
}
520526

521527
public:
522528
template<typename KernelNameType, typename KernelType>
523-
void single_task(KernelType kernel) {
524-
// Call kernel_entry_point() to trigger generation of an offload
525-
// kernel entry point.
526-
kernel_entry_point<KernelNameType>(kernel);
527-
// Call functions appropriate for the desired offload backend
528-
// (OpenCL, CUDA, HIP, Level Zero, etc...).
529+
void single_task(KernelType Kernel) {
530+
// Call kernel_entry_point() to launch the kernel and to trigger
531+
// generation of an offload kernel entry point.
532+
kernel_entry_point<KernelNameType>(Kernel);
529533
}
530534
};
531535
} // namespace sycl
532536

533-
A SYCL kernel is a callable object of class type that is constructed on a host,
534-
often via a lambda expression, and then passed to a SYCL kernel invocation
535-
function to be executed on an offload device. A SYCL kernel invocation function
536-
is responsible for copying the provided SYCL kernel object to an offload
537-
device and initiating a call to it. The SYCL kernel object and its data members
538-
constitute the parameters of an offload kernel.
539-
540-
A SYCL kernel type is required to satisfy the device copyability requirements
541-
specified in section 3.13.1, "Device copyable", of the SYCL 2020 specification.
542-
Additionally, any data members of the kernel object type are required to satisfy
543-
section 4.12.4, "Rules for parameter passing to kernels". For most types, these
544-
rules require that the type is trivially copyable. However, the SYCL
545-
specification mandates that certain special SYCL types, such as
546-
``sycl::accessor`` and ``sycl::stream`` be device copyable even if they are not
547-
trivially copyable. These types require special handling because they cannot
537+
A SYCL kernel object is a callable object of class type that is constructed on
538+
a host, often via a lambda expression, and then passed to a SYCL kernel
539+
invocation function to be executed on an offload device. A SYCL kernel
540+
invocation function is responsible for copying the provided SYCL kernel object
541+
to an offload device and initiating a call to it. The SYCL kernel object and
542+
its data members constitute the parameters of an offload kernel.
543+
544+
A SYCL kernel object type is required to satisfy the device copyability
545+
requirements specified in section 3.13.1, "Device copyable", of the SYCL 2020
546+
specification. Additionally, any data members of the kernel object type are
547+
required to satisfy section 4.12.4, "Rules for parameter passing to kernels".
548+
For most types, these rules require that the type is trivially copyable.
549+
However, the SYCL specification mandates that certain special SYCL types, such
550+
as ``sycl::accessor`` and ``sycl::stream`` be device copyable even if they are
551+
not trivially copyable. These types require special handling because they cannot
548552
be copied to device memory as if by ``memcpy()``. Additionally, some offload
549553
backends, OpenCL for example, require objects of some of these types to be
550554
passed as individual arguments to the offload kernel.
@@ -559,7 +563,7 @@ like OpenCL):
559563

560564
#. Identifying the offload kernel entry point to be used for the SYCL kernel.
561565

562-
#. Deconstructing the SYCL kernel object, if necessary, to produce the set of
566+
#. Decomposing the SYCL kernel object, if necessary, to produce the set of
563567
offload kernel arguments required by the offload kernel entry point.
564568

565569
#. Copying the offload kernel arguments to device memory.
@@ -568,17 +572,23 @@ like OpenCL):
568572

569573
The offload kernel entry point for a SYCL kernel performs the following tasks:
570574

571-
#. Reconstituting the SYCL kernel object, if necessary, using the offload
575+
#. Reconstructing the SYCL kernel object, if necessary, using the offload
572576
kernel parameters.
573577

574-
#. Calling the ``operator()`` member function of the (reconstituted) SYCL kernel
578+
#. Calling the ``operator()`` member function of the (reconstructed) SYCL kernel
575579
object.
576580

577-
The ``sycl_kernel_entry_point`` attribute automates generation of an offload
578-
kernel entry point that performs those latter tasks. The parameters and body of
579-
a function declared with the ``sycl_kernel_entry_point`` attribute specify a
580-
pattern from which the parameters and body of the entry point function are
581-
derived. Consider the following call to a SYCL kernel invocation function.
581+
The ``sycl_kernel_entry_point`` attribute facilitates or automates these tasks
582+
by generating the offload kernel entry point, generating a unique symbol name
583+
for it, synthesizing code for kernel argument decomposition and reconstruction,
584+
and synthesizing a call to a ``sycl_enqueue_kernel_launch`` function template
585+
with the kernel name type, kernel symbol name, and (decomposed) kernel arguments
586+
passed as template or function arguments.
587+
588+
A function declared with the ``sycl_kernel_entry_point`` attribute specifies
589+
the parameters and body of the offload entry point function. Consider the
590+
following call to the ``single_task()`` SYCL kernel invocation function assuming
591+
an implementation similar to the one shown above.
582592

583593
.. code-block:: c++
584594

@@ -592,31 +602,33 @@ derived. Consider the following call to a SYCL kernel invocation function.
592602
The SYCL kernel object is the result of the lambda expression. It has two
593603
data members corresponding to the captures of ``sout`` and ``s``. Since one
594604
of these data members corresponds to a special SYCL type that must be passed
595-
individually as an offload kernel parameter, it is necessary to decompose the
596-
SYCL kernel object into its constituent parts; the offload kernel will have
597-
two kernel parameters. Given a SYCL implementation that uses a
598-
``sycl_kernel_entry_point`` attributed function like the one shown above, an
605+
individually as an offload kernel argument, it is necessary to decompose the
606+
SYCL kernel object into its constituent parts and pass them individually. An
599607
offload kernel entry point function will be generated that looks approximately
600608
as follows.
601609

602610
.. code-block:: c++
603611

604612
void sycl-kernel-caller-for-KN(sycl::stream sout, S s) {
605-
kernel-type kernel = { sout, s );
606-
kernel();
613+
kernel-type Kernel = { sout, s );
614+
Kernel();
607615
}
608616

609617
There are a few items worthy of note:
610618

611619
#. The name of the generated function incorporates the SYCL kernel name,
612620
``KN``, that was passed as the ``KernelNameType`` template parameter to
613-
``kernel_entry_point()`` and provided as the argument to the
621+
``single_task()`` and eventually provided as the argument to the
614622
``sycl_kernel_entry_point`` attribute. There is a one-to-one correspondence
615623
between SYCL kernel names and offload kernel entry points.
616624

625+
#. The parameters and the call to ``Kernel()`` correspond to the definition of
626+
``kernel_entry_point()`` called by ``single_task()`` with the SYCL kernel
627+
object argument decomposed and reconstructed.
628+
617629
#. The SYCL kernel is a lambda closure type and therefore has no name;
618630
``kernel-type`` is substituted above and corresponds to the ``KernelType``
619-
template parameter deduced in the call to ``kernel_entry_point()``.
631+
template parameter deduced in the call to ``single_task()``.
620632
Lambda types cannot be declared and initialized using the aggregate
621633
initialization syntax used above, but the intended behavior should be clear.
622634

@@ -630,24 +642,55 @@ There are a few items worthy of note:
630642
or more parameters depending on how the SYCL library implementation defines
631643
these types.
632644

633-
#. The call to ``kernel_entry_point()`` has no effect other than to trigger
634-
emission of the entry point function. The statments that make up the body
635-
of the function are not executed when the function is called; they are
636-
only used in the generation of the entry point function.
645+
The call to ``kernel_entry_point()`` by ``single_task()`` is effectively
646+
replaced with synthesized code that looks approximately as follows.
647+
648+
.. code-block:: c++
649+
650+
sycl::stream sout = Kernel.sout;
651+
S s = Kernel.s;
652+
sycl_enqueue_kernel_launch<KN>("kernel-symbol-name", sout, s);
653+
654+
There are a few items worthy of note:
655+
656+
#. The SYCL kernel object is a lambda closure type and its captures do not
657+
have formal names and cannot be accessed using the member access syntax used
658+
above, but the intended behavior should be clear.
659+
660+
#. ``kernel-symbol-name`` is substituted for the actual symbol name that would
661+
be generated; these names are implementation details subject to change.
662+
663+
#. Lookup for the ``sycl_enqueue_kernel_launch()`` function template is
664+
performed from the (possibly instantiated) location of the definition of
665+
``kernel_entry_point()``. If overload resolution fails, the program is
666+
ill-formed. If the selected overload is a non-static member function, then
667+
``this`` is passed for the implicit object parameter.
668+
669+
#. Function arguments passed to ``sycl_enqueue_kernel_launch()`` are passed
670+
as if by ``std::forward<X>(x)``.
671+
672+
#. The ``sycl_enqueue_kernel_launch()`` function is expected to be provided by
673+
the SYCL library implementation. It is responsible for scheduling execution
674+
of the generated offload kernel entry point identified by
675+
``kernel-symbol-name`` and copying the (decomposed) kernel arguments to
676+
device memory, presumably via an offload backend such as OpenCL.
637677

638678
It is not necessary for a function declared with the ``sycl_kernel_entry_point``
639679
attribute to be called for the offload kernel entry point to be emitted. For
640680
inline functions and function templates, any ODR-use will suffice. For other
641681
functions, an ODR-use is not required; the offload kernel entry point will be
642-
emitted if the function is defined.
682+
emitted if the function is defined. In any case, a call to the function is
683+
required for the synthesized call to ``sycl_enqueue_kernel_launch()`` to occur.
643684

644685
Functions declared with the ``sycl_kernel_entry_point`` attribute are not
645686
limited to the simple example shown above. They may have additional template
646687
parameters, declare additional function parameters, and have complex control
647-
flow in the function body. Function parameter decomposition and reconstitution
688+
flow in the function body. Function parameter decomposition and reconstruction
648689
is performed for all function parameters. The function must abide by the
649690
language feature restrictions described in section 5.4, "Language restrictions
650-
for device functions" in the SYCL 2020 specification.
691+
for device functions" in the SYCL 2020 specification. If the function is a
692+
non-static member function, ``this`` shall not be used in a potentially
693+
evaluated expression.
651694
}];
652695
}
653696

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12945,9 +12945,10 @@ def err_sycl_special_type_num_init_method : Error<
1294512945
// SYCL kernel entry point diagnostics
1294612946
def err_sycl_entry_point_invalid : Error<
1294712947
"the %0 attribute cannot be applied to a"
12948-
" %select{non-static member function|variadic function|deleted function|"
12949-
"defaulted function|constexpr function|consteval function|"
12950-
"function declared with the 'noreturn' attribute|coroutine|"
12948+
" %select{variadic function|deleted function|defaulted function|"
12949+
"constructor|destructor|coroutine|"
12950+
"constexpr function|consteval function|"
12951+
"function declared with the 'noreturn' attribute|"
1295112952
"function defined with a function try block}1">;
1295212953
def err_sycl_entry_point_invalid_redeclaration : Error<
1295312954
"the %0 kernel name argument does not match prior"

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15034,6 +15034,10 @@ static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context,
1503415034
MC->mangleCanonicalTypeName(KernelNameType, Out);
1503515035
std::string KernelName = Out.str();
1503615036

15037+
// FIXME: Diagnose kernel names that are not representable in the ordinary
15038+
// literal encoding. This is not necessarily the right place to add such
15039+
// a diagnostic.
15040+
1503715041
return {KernelNameType, FD, KernelName};
1503815042
}
1503915043

clang/lib/AST/StmtPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ void StmtPrinter::VisitCapturedStmt(CapturedStmt *Node) {
589589
}
590590

591591
void StmtPrinter::VisitSYCLKernelCallStmt(SYCLKernelCallStmt *Node) {
592-
PrintStmt(Node->getOutlinedFunctionDecl()->getBody());
592+
PrintStmt(Node->getOriginalStmt());
593593
}
594594

595595
void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/Attr.h"
2020
#include "clang/AST/Expr.h"
2121
#include "clang/AST/Stmt.h"
22+
#include "clang/AST/StmtSYCL.h"
2223
#include "clang/AST/StmtVisitor.h"
2324
#include "clang/Basic/Builtins.h"
2425
#include "clang/Basic/DiagnosticSema.h"
@@ -540,21 +541,7 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S,
540541
EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S));
541542
break;
542543
case Stmt::SYCLKernelCallStmtClass:
543-
// SYCL kernel call statements are generated as wrappers around the body
544-
// of functions declared with the sycl_kernel_entry_point attribute. Such
545-
// functions are used to specify how a SYCL kernel (a function object) is
546-
// to be invoked; the SYCL kernel call statement contains a transformed
547-
// variation of the function body and is used to generate a SYCL kernel
548-
// caller function; a function that serves as the device side entry point
549-
// used to execute the SYCL kernel. The sycl_kernel_entry_point attributed
550-
// function is invoked by host code in order to trigger emission of the
551-
// device side SYCL kernel caller function and to generate metadata needed
552-
// by SYCL run-time library implementations; the function is otherwise
553-
// intended to have no effect. As such, the function body is not evaluated
554-
// as part of the invocation during host compilation (and the function
555-
// should not be called or emitted during device compilation); the SYCL
556-
// kernel call statement is thus handled as a null statement for the
557-
// purpose of code generation.
544+
EmitSYCLKernelCallStmt(cast<SYCLKernelCallStmt>(*S));
558545
break;
559546
}
560547
return true;

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,8 @@ class CodeGenFunction : public CodeGenTypeCache {
36263626
LValue EmitCoyieldLValue(const CoyieldExpr *E);
36273627
RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID);
36283628

3629+
void EmitSYCLKernelCallStmt(const SYCLKernelCallStmt &S);
3630+
36293631
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
36303632
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
36313633

0 commit comments

Comments
 (0)