Skip to content

Commit 919cd88

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 17e2641 commit 919cd88

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
@@ -836,8 +836,10 @@ class ASTNodeTraverser
836836

837837
void VisitSYCLKernelCallStmt(const SYCLKernelCallStmt *Node) {
838838
Visit(Node->getOriginalStmt());
839-
if (Traversal != TK_IgnoreUnlessSpelledInSource)
839+
if (Traversal != TK_IgnoreUnlessSpelledInSource) {
840+
Visit(Node->getKernelLaunchStmt());
840841
Visit(Node->getOutlinedFunctionDecl());
842+
}
841843
}
842844

843845
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
@@ -3027,6 +3027,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
30273027
DEF_TRAVERSE_STMT(SYCLKernelCallStmt, {
30283028
if (getDerived().shouldVisitImplicitCode()) {
30293029
TRY_TO(TraverseStmt(S->getOriginalStmt()));
3030+
TRY_TO(TraverseStmt(S->getKernelLaunchStmt()));
30303031
TRY_TO(TraverseDecl(S->getOutlinedFunctionDecl()));
30313032
ShouldVisitChildren = false;
30323033
}

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
@@ -532,13 +532,13 @@ The following examples demonstrate the use of this attribute:
532532
def SYCLKernelEntryPointDocs : Documentation {
533533
let Category = DocCatFunction;
534534
let Content = [{
535-
The ``sycl_kernel_entry_point`` attribute facilitates the generation of an
536-
offload kernel entry point, sometimes called a SYCL kernel caller function,
537-
suitable for invoking a SYCL kernel on an offload device. The attribute is
538-
intended for use in the implementation of SYCL kernel invocation functions
539-
like the ``single_task`` and ``parallel_for`` member functions of the
540-
``sycl::handler`` class specified in section 4.9.4, "Command group ``handler``
541-
class", of the SYCL 2020 specification.
535+
The ``sycl_kernel_entry_point`` attribute facilitates the launch of a SYCL
536+
kernel and the generation of an offload kernel entry point, sometimes called
537+
a SYCL kernel caller function, suitable for invoking a SYCL kernel on an
538+
offload device. The attribute is intended for use in the implementation of
539+
SYCL kernel invocation functions like the ``single_task`` and ``parallel_for``
540+
member functions of the ``sycl::handler`` class specified in section 4.9.4,
541+
"Command group ``handler`` class", of the SYCL 2020 specification.
542542

543543
The attribute requires a single type argument that specifies a class type that
544544
meets the requirements for a SYCL kernel name as described in section 5.2,
@@ -550,7 +550,7 @@ The attribute only appertains to functions and only those that meet the
550550
following requirements.
551551

552552
* Has a non-deduced ``void`` return type.
553-
* Is not a non-static member function, constructor, or destructor.
553+
* Is not a constructor or destructor.
554554
* Is not a C variadic function.
555555
* Is not a coroutine.
556556
* Is not defined as deleted or as defaulted.
@@ -565,39 +565,43 @@ follows.
565565

566566
namespace sycl {
567567
class handler {
568+
template<typename KernelNameType, typename... Ts>
569+
void sycl_enqueue_kernel_launch(const char *KernelName, Ts...) {
570+
// Call functions appropriate for the desired offload backend
571+
// (OpenCL, CUDA, HIP, Level Zero, etc...) to enqueue kernel invocation.
572+
}
573+
568574
template<typename KernelNameType, typename KernelType>
569575
[[ clang::sycl_kernel_entry_point(KernelNameType) ]]
570-
static void kernel_entry_point(KernelType kernel) {
571-
kernel();
576+
void kernel_entry_point(KernelType Kernel) {
577+
Kernel();
572578
}
573579

574580
public:
575581
template<typename KernelNameType, typename KernelType>
576-
void single_task(KernelType kernel) {
577-
// Call kernel_entry_point() to trigger generation of an offload
578-
// kernel entry point.
579-
kernel_entry_point<KernelNameType>(kernel);
580-
// Call functions appropriate for the desired offload backend
581-
// (OpenCL, CUDA, HIP, Level Zero, etc...).
582+
void single_task(KernelType Kernel) {
583+
// Call kernel_entry_point() to launch the kernel and to trigger
584+
// generation of an offload kernel entry point.
585+
kernel_entry_point<KernelNameType>(Kernel);
582586
}
583587
};
584588
} // namespace sycl
585589

586-
A SYCL kernel is a callable object of class type that is constructed on a host,
587-
often via a lambda expression, and then passed to a SYCL kernel invocation
588-
function to be executed on an offload device. A SYCL kernel invocation function
589-
is responsible for copying the provided SYCL kernel object to an offload
590-
device and initiating a call to it. The SYCL kernel object and its data members
591-
constitute the parameters of an offload kernel.
592-
593-
A SYCL kernel type is required to satisfy the device copyability requirements
594-
specified in section 3.13.1, "Device copyable", of the SYCL 2020 specification.
595-
Additionally, any data members of the kernel object type are required to satisfy
596-
section 4.12.4, "Rules for parameter passing to kernels". For most types, these
597-
rules require that the type is trivially copyable. However, the SYCL
598-
specification mandates that certain special SYCL types, such as
599-
``sycl::accessor`` and ``sycl::stream`` be device copyable even if they are not
600-
trivially copyable. These types require special handling because they cannot
590+
A SYCL kernel object is a callable object of class type that is constructed on
591+
a host, often via a lambda expression, and then passed to a SYCL kernel
592+
invocation function to be executed on an offload device. A SYCL kernel
593+
invocation function is responsible for copying the provided SYCL kernel object
594+
to an offload device and initiating a call to it. The SYCL kernel object and
595+
its data members constitute the parameters of an offload kernel.
596+
597+
A SYCL kernel object type is required to satisfy the device copyability
598+
requirements specified in section 3.13.1, "Device copyable", of the SYCL 2020
599+
specification. Additionally, any data members of the kernel object type are
600+
required to satisfy section 4.12.4, "Rules for parameter passing to kernels".
601+
For most types, these rules require that the type is trivially copyable.
602+
However, the SYCL specification mandates that certain special SYCL types, such
603+
as ``sycl::accessor`` and ``sycl::stream`` be device copyable even if they are
604+
not trivially copyable. These types require special handling because they cannot
601605
be copied to device memory as if by ``memcpy()``. Additionally, some offload
602606
backends, OpenCL for example, require objects of some of these types to be
603607
passed as individual arguments to the offload kernel.
@@ -612,7 +616,7 @@ like OpenCL):
612616

613617
#. Identifying the offload kernel entry point to be used for the SYCL kernel.
614618

615-
#. Deconstructing the SYCL kernel object, if necessary, to produce the set of
619+
#. Decomposing the SYCL kernel object, if necessary, to produce the set of
616620
offload kernel arguments required by the offload kernel entry point.
617621

618622
#. Copying the offload kernel arguments to device memory.
@@ -621,17 +625,23 @@ like OpenCL):
621625

622626
The offload kernel entry point for a SYCL kernel performs the following tasks:
623627

624-
#. Reconstituting the SYCL kernel object, if necessary, using the offload
628+
#. Reconstructing the SYCL kernel object, if necessary, using the offload
625629
kernel parameters.
626630

627-
#. Calling the ``operator()`` member function of the (reconstituted) SYCL kernel
631+
#. Calling the ``operator()`` member function of the (reconstructed) SYCL kernel
628632
object.
629633

630-
The ``sycl_kernel_entry_point`` attribute automates generation of an offload
631-
kernel entry point that performs those latter tasks. The parameters and body of
632-
a function declared with the ``sycl_kernel_entry_point`` attribute specify a
633-
pattern from which the parameters and body of the entry point function are
634-
derived. Consider the following call to a SYCL kernel invocation function.
634+
The ``sycl_kernel_entry_point`` attribute facilitates or automates these tasks
635+
by generating the offload kernel entry point, generating a unique symbol name
636+
for it, synthesizing code for kernel argument decomposition and reconstruction,
637+
and synthesizing a call to a ``sycl_enqueue_kernel_launch`` function template
638+
with the kernel name type, kernel symbol name, and (decomposed) kernel arguments
639+
passed as template or function arguments.
640+
641+
A function declared with the ``sycl_kernel_entry_point`` attribute specifies
642+
the parameters and body of the offload entry point function. Consider the
643+
following call to the ``single_task()`` SYCL kernel invocation function assuming
644+
an implementation similar to the one shown above.
635645

636646
.. code-block:: c++
637647

@@ -645,31 +655,33 @@ derived. Consider the following call to a SYCL kernel invocation function.
645655
The SYCL kernel object is the result of the lambda expression. It has two
646656
data members corresponding to the captures of ``sout`` and ``s``. Since one
647657
of these data members corresponds to a special SYCL type that must be passed
648-
individually as an offload kernel parameter, it is necessary to decompose the
649-
SYCL kernel object into its constituent parts; the offload kernel will have
650-
two kernel parameters. Given a SYCL implementation that uses a
651-
``sycl_kernel_entry_point`` attributed function like the one shown above, an
658+
individually as an offload kernel argument, it is necessary to decompose the
659+
SYCL kernel object into its constituent parts and pass them individually. An
652660
offload kernel entry point function will be generated that looks approximately
653661
as follows.
654662

655663
.. code-block:: c++
656664

657665
void sycl-kernel-caller-for-KN(sycl::stream sout, S s) {
658-
kernel-type kernel = { sout, s );
659-
kernel();
666+
kernel-type Kernel = { sout, s );
667+
Kernel();
660668
}
661669

662670
There are a few items worthy of note:
663671

664672
#. The name of the generated function incorporates the SYCL kernel name,
665673
``KN``, that was passed as the ``KernelNameType`` template parameter to
666-
``kernel_entry_point()`` and provided as the argument to the
674+
``single_task()`` and eventually provided as the argument to the
667675
``sycl_kernel_entry_point`` attribute. There is a one-to-one correspondence
668676
between SYCL kernel names and offload kernel entry points.
669677

678+
#. The parameters and the call to ``Kernel()`` correspond to the definition of
679+
``kernel_entry_point()`` called by ``single_task()`` with the SYCL kernel
680+
object argument decomposed and reconstructed.
681+
670682
#. The SYCL kernel is a lambda closure type and therefore has no name;
671683
``kernel-type`` is substituted above and corresponds to the ``KernelType``
672-
template parameter deduced in the call to ``kernel_entry_point()``.
684+
template parameter deduced in the call to ``single_task()``.
673685
Lambda types cannot be declared and initialized using the aggregate
674686
initialization syntax used above, but the intended behavior should be clear.
675687

@@ -683,24 +695,55 @@ There are a few items worthy of note:
683695
or more parameters depending on how the SYCL library implementation defines
684696
these types.
685697

686-
#. The call to ``kernel_entry_point()`` has no effect other than to trigger
687-
emission of the entry point function. The statments that make up the body
688-
of the function are not executed when the function is called; they are
689-
only used in the generation of the entry point function.
698+
The call to ``kernel_entry_point()`` by ``single_task()`` is effectively
699+
replaced with synthesized code that looks approximately as follows.
700+
701+
.. code-block:: c++
702+
703+
sycl::stream sout = Kernel.sout;
704+
S s = Kernel.s;
705+
sycl_enqueue_kernel_launch<KN>("kernel-symbol-name", sout, s);
706+
707+
There are a few items worthy of note:
708+
709+
#. The SYCL kernel object is a lambda closure type and its captures do not
710+
have formal names and cannot be accessed using the member access syntax used
711+
above, but the intended behavior should be clear.
712+
713+
#. ``kernel-symbol-name`` is substituted for the actual symbol name that would
714+
be generated; these names are implementation details subject to change.
715+
716+
#. Lookup for the ``sycl_enqueue_kernel_launch()`` function template is
717+
performed from the (possibly instantiated) location of the definition of
718+
``kernel_entry_point()``. If overload resolution fails, the program is
719+
ill-formed. If the selected overload is a non-static member function, then
720+
``this`` is passed for the implicit object parameter.
721+
722+
#. Function arguments passed to ``sycl_enqueue_kernel_launch()`` are passed
723+
as if by ``std::forward<X>(x)``.
724+
725+
#. The ``sycl_enqueue_kernel_launch()`` function is expected to be provided by
726+
the SYCL library implementation. It is responsible for scheduling execution
727+
of the generated offload kernel entry point identified by
728+
``kernel-symbol-name`` and copying the (decomposed) kernel arguments to
729+
device memory, presumably via an offload backend such as OpenCL.
690730

691731
It is not necessary for a function declared with the ``sycl_kernel_entry_point``
692732
attribute to be called for the offload kernel entry point to be emitted. For
693733
inline functions and function templates, any ODR-use will suffice. For other
694734
functions, an ODR-use is not required; the offload kernel entry point will be
695-
emitted if the function is defined.
735+
emitted if the function is defined. In any case, a call to the function is
736+
required for the synthesized call to ``sycl_enqueue_kernel_launch()`` to occur.
696737

697738
Functions declared with the ``sycl_kernel_entry_point`` attribute are not
698739
limited to the simple example shown above. They may have additional template
699740
parameters, declare additional function parameters, and have complex control
700-
flow in the function body. Function parameter decomposition and reconstitution
741+
flow in the function body. Function parameter decomposition and reconstruction
701742
is performed for all function parameters. The function must abide by the
702743
language feature restrictions described in section 5.4, "Language restrictions
703-
for device functions" in the SYCL 2020 specification.
744+
for device functions" in the SYCL 2020 specification. If the function is a
745+
non-static member function, ``this`` shall not be used in a potentially
746+
evaluated expression.
704747
}];
705748
}
706749

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13062,9 +13062,10 @@ def warn_sycl_external_missing_on_first_decl : Warning<
1306213062
// SYCL kernel entry point diagnostics
1306313063
def err_sycl_entry_point_invalid : Error<
1306413064
"the %0 attribute cannot be applied to a"
13065-
" %select{non-static member function|variadic function|deleted function|"
13066-
"defaulted function|constexpr function|consteval function|"
13067-
"function declared with the 'noreturn' attribute|coroutine|"
13065+
" %select{variadic function|deleted function|defaulted function|"
13066+
"constructor|destructor|coroutine|"
13067+
"constexpr function|consteval function|"
13068+
"function declared with the 'noreturn' attribute|"
1306813069
"function defined with a function try block}1">;
1306913070
def err_sycl_entry_point_invalid_redeclaration : Error<
1307013071
"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
@@ -14975,6 +14975,10 @@ static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context,
1497514975
MC->mangleCanonicalTypeName(KernelNameType, Out);
1497614976
std::string KernelName = Out.str();
1497714977

14978+
// FIXME: Diagnose kernel names that are not representable in the ordinary
14979+
// literal encoding. This is not necessarily the right place to add such
14980+
// a diagnostic.
14981+
1497814982
return {KernelNameType, FD, KernelName};
1497914983
}
1498014984

clang/lib/AST/StmtPrinter.cpp

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

597597
void StmtPrinter::VisitSYCLKernelCallStmt(SYCLKernelCallStmt *Node) {
598-
PrintStmt(Node->getOutlinedFunctionDecl()->getBody());
598+
PrintStmt(Node->getOriginalStmt());
599599
}
600600

601601
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"
@@ -543,21 +544,7 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S,
543544
EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S));
544545
break;
545546
case Stmt::SYCLKernelCallStmtClass:
546-
// SYCL kernel call statements are generated as wrappers around the body
547-
// of functions declared with the sycl_kernel_entry_point attribute. Such
548-
// functions are used to specify how a SYCL kernel (a function object) is
549-
// to be invoked; the SYCL kernel call statement contains a transformed
550-
// variation of the function body and is used to generate a SYCL kernel
551-
// caller function; a function that serves as the device side entry point
552-
// used to execute the SYCL kernel. The sycl_kernel_entry_point attributed
553-
// function is invoked by host code in order to trigger emission of the
554-
// device side SYCL kernel caller function and to generate metadata needed
555-
// by SYCL run-time library implementations; the function is otherwise
556-
// intended to have no effect. As such, the function body is not evaluated
557-
// as part of the invocation during host compilation (and the function
558-
// should not be called or emitted during device compilation); the SYCL
559-
// kernel call statement is thus handled as a null statement for the
560-
// purpose of code generation.
547+
EmitSYCLKernelCallStmt(cast<SYCLKernelCallStmt>(*S));
561548
break;
562549
}
563550
return true;

clang/lib/CodeGen/CodeGenFunction.h

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

3646+
void EmitSYCLKernelCallStmt(const SYCLKernelCallStmt &S);
3647+
36463648
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
36473649
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
36483650

0 commit comments

Comments
 (0)