diff --git a/sycl/include/sycl/detail/cg_types.hpp b/sycl/include/sycl/detail/cg_types.hpp index 7db3171ba28fc..ef0ef198c40d0 100644 --- a/sycl/include/sycl/detail/cg_types.hpp +++ b/sycl/include/sycl/detail/cg_types.hpp @@ -154,6 +154,8 @@ runKernelWithArg(KernelType KernelName, ArgType Arg) { // The pure virtual class aimed to store lambda/functors of any type. class HostKernelBase { public: + // NOTE: InstatitateKernelOnHost() should not be called. + virtual void InstatitateKernelOnHost() = 0; // Return pointer to the lambda object. // Used to extract captured variables. virtual char *getPtr() = 0; @@ -172,6 +174,50 @@ class HostKernel : public HostKernelBase { public: HostKernel(KernelType Kernel) : MKernel(Kernel) {} + // This function is needed for host-side compilation to keep kernels + // instantitated. This is important for debuggers to be able to associate + // kernel code instructions with source code lines. + // NOTE: InstatitateKernelOnHost() should not be called. + void InstatitateKernelOnHost() override { + if constexpr (std::is_same_v) { + runKernelWithoutArg(MKernel); + } else if constexpr (std::is_same_v>) { + sycl::id ID = InitializedVal::template get<0>(); + runKernelWithArg(MKernel, ID); + } else if constexpr (std::is_same_v> || + std::is_same_v>) { + constexpr bool HasOffset = + std::is_same_v>; + KernelArgType Item = IDBuilder::createItem( + InitializedVal::template get<1>(), + InitializedVal::template get<0>()); + runKernelWithArg(MKernel, Item); + } else if constexpr (std::is_same_v>) { + sycl::range Range = InitializedVal::template get<1>(); + sycl::id ID = InitializedVal::template get<0>(); + sycl::group Group = + IDBuilder::createGroup(Range, Range, Range, ID); + sycl::item GlobalItem = + IDBuilder::createItem(Range, ID, ID); + sycl::item LocalItem = + IDBuilder::createItem(Range, ID); + KernelArgType NDItem = + IDBuilder::createNDItem(GlobalItem, LocalItem, Group); + runKernelWithArg(MKernel, NDItem); + } else if constexpr (std::is_same_v>) { + sycl::range Range = InitializedVal::template get<1>(); + sycl::id ID = InitializedVal::template get<0>(); + KernelArgType Group = + IDBuilder::createGroup(Range, Range, Range, ID); + runKernelWithArg(MKernel, Group); + } else { + // Assume that anything else can be default-constructed. If not, this + // should fail to compile and the implementor should implement a generic + // case for the new argument type. + runKernelWithArg(MKernel, KernelArgType{}); + } + } + char *getPtr() override { return reinterpret_cast(&MKernel); } ~HostKernel() = default; diff --git a/sycl/test/abi/vtable.cpp b/sycl/test/abi/vtable.cpp index f1ff7e02f1900..b3d16e3c4381d 100644 --- a/sycl/test/abi/vtable.cpp +++ b/sycl/test/abi/vtable.cpp @@ -8,6 +8,18 @@ // Changing vtable breaks ABI. If this test fails, please, refer to ABI Policy // Guide for further instructions. +void foo(sycl::detail::HostKernelBase &HKB) { + HKB.InstatitateKernelOnHost(); +} +// CHECK: Vtable for 'sycl::detail::HostKernelBase' (6 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | sycl::detail::HostKernelBase RTTI +// CHECK-NEXT: -- (sycl::detail::HostKernelBase, 0) vtable address -- +// CHECK-NEXT: 2 | void sycl::detail::HostKernelBase::InstatitateKernelOnHost() [pure] +// CHECK-NEXT: 3 | char *sycl::detail::HostKernelBase::getPtr() [pure] +// CHECK-NEXT: 4 | sycl::detail::HostKernelBase::~HostKernelBase() [complete] +// CHECK-NEXT: 5 | sycl::detail::HostKernelBase::~HostKernelBase() [deleting] + void foo(sycl::detail::PropertyWithDataBase *Prop) { delete Prop; } // CHECK: Vtable for 'sycl::detail::PropertyWithDataBase' (4 entries). // CHECK-NEXT: 0 | offset_to_top (0)