diff --git a/offload/liboffload/API/Common.td b/offload/liboffload/API/Common.td index 7674da0438c29..b3e7000628b58 100644 --- a/offload/liboffload/API/Common.td +++ b/offload/liboffload/API/Common.td @@ -77,10 +77,9 @@ def : Handle { let desc = "Handle of program object"; } -def : Typedef { +def : Handle { let name = "ol_kernel_handle_t"; let desc = "Handle of kernel object"; - let value = "void *"; } def ErrorCode : Enum { @@ -113,6 +112,7 @@ def ErrorCode : Enum { Etor<"INVALID_DEVICE", "invalid device">, Etor<"INVALID_QUEUE", "invalid queue">, Etor<"INVALID_EVENT", "invalid event">, + Etor<"INVALID_KERNEL", "invalid kernel">, ]; } diff --git a/offload/liboffload/API/Kernel.td b/offload/liboffload/API/Kernel.td index 247f9c1bf5b6a..765ffdf2f1860 100644 --- a/offload/liboffload/API/Kernel.td +++ b/offload/liboffload/API/Kernel.td @@ -10,6 +10,15 @@ // //===----------------------------------------------------------------------===// +def : Enum { + let name = "ol_kernel_info_t"; + let desc = "Supported kernel info."; + let is_typed = 1; + let etors =[ + TaggedEtor<"PROGRAM", "ol_program_handle_t", "the program associated with this kernel">, + ]; +} + def : Function { let name = "olGetKernel"; let desc = "Get a kernel from the function identified by `KernelName` in the given program."; @@ -59,3 +68,44 @@ def : Function { Return<"OL_ERRC_INVALID_DEVICE", ["If Queue is non-null but does not belong to Device"]>, ]; } + +def : Function { + let name = "olGetKernelInfo"; + let desc = "Queries the given property of the kernel."; + let details = []; + let params = [ + Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel instance", PARAM_IN>, + Param<"ol_kernel_info_t", "PropName", "type of the info to retrieve", PARAM_IN>, + Param<"size_t", "PropSize", "the number of bytes pointed to by PropValue.", PARAM_IN>, + TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. If PropSize is not equal to or greater than the real " + "number of bytes needed to return the info then the OL_ERRC_INVALID_SIZE error is returned and " + "PropValue is not used.", PARAM_OUT, TypeInfo<"PropName" , "PropSize">> + ]; + let returns = [ + Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [ + "If `PropName` is not supported by the kernel." + ]>, + Return<"OL_ERRC_INVALID_SIZE", [ + "`PropSize == 0`", + "If `PropSize` is less than the real number of bytes needed to return the info." + ]>, + Return<"OL_ERRC_INVALID_KERNEL"> + ]; +} + +def : Function { + let name = "olGetKernelInfoSize"; + let desc = "Returns the storage size of the given kernel query."; + let details = []; + let params = [ + Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel instance", PARAM_IN>, + Param<"ol_kernel_info_t", "PropName", "type of the info to retrieve", PARAM_IN>, + Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT> + ]; + let returns = [ + Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [ + "If `PropName` is not supported by the kernel." + ]>, + Return<"OL_ERRC_INVALID_KERNEL"> + ]; +} diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index 7b67cbba43e68..348dda0f06a5d 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -85,6 +85,13 @@ struct ol_program_impl_t { __tgt_device_image DeviceImage; }; +struct ol_kernel_impl_t { + ol_kernel_impl_t(plugin::GenericKernelTy *Kernel, ol_program_handle_t Program) + : Kernel(Kernel), Program(Program) {} + plugin::GenericKernelTy *Kernel; + ol_program_handle_t Program; +}; + namespace llvm { namespace offload { @@ -286,6 +293,34 @@ Error olGetDeviceInfoSize_impl(ol_device_handle_t Device, return olGetDeviceInfoImplDetail(Device, PropName, 0, nullptr, PropSizeRet); } +Error olGetKernelInfoImplDetail(ol_kernel_handle_t Kernel, + ol_kernel_info_t PropName, size_t PropSize, + void *PropValue, size_t *PropSizeRet) { + + ReturnHelper ReturnValue(PropSize, PropValue, PropSizeRet); + + switch (PropName) { + case OL_KERNEL_INFO_PROGRAM: + return ReturnValue(Kernel->Program); + default: + return createOffloadError(ErrorCode::INVALID_ENUMERATION, + "getKernelInfo enum '%i' is invalid", PropName); + } + + return Error::success(); +} + +Error olGetKernelInfo_impl(ol_kernel_handle_t Kernel, ol_kernel_info_t PropName, + size_t PropSize, void *PropValue) { + return olGetKernelInfoImplDetail(Kernel, PropName, PropSize, PropValue, + nullptr); +} + +Error olGetKernelInfoSize_impl(ol_kernel_handle_t Kernel, + ol_kernel_info_t PropName, size_t *PropSizeRet) { + return olGetKernelInfoImplDetail(Kernel, PropName, 0, nullptr, PropSizeRet); +} + Error olIterateDevices_impl(ol_device_iterate_cb_t Callback, void *UserData) { for (auto &Platform : Platforms()) { for (auto &Device : Platform.Devices) { @@ -479,7 +514,7 @@ Error olGetKernel_impl(ol_program_handle_t Program, const char *KernelName, if (auto Err = KernelImpl->init(Device, *Program->Image)) return Err; - *Kernel = &*KernelImpl; + *Kernel = new ol_kernel_impl_t(&*KernelImpl, Program); return Error::success(); } @@ -514,7 +549,7 @@ Error olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device, // Don't do anything with pointer indirection; use arg data as-is LaunchArgs.Flags.IsCUDA = true; - auto *KernelImpl = reinterpret_cast(Kernel); + auto *KernelImpl = Kernel->Kernel; auto Err = KernelImpl->launch(*DeviceImpl, LaunchArgs.ArgPtrs, nullptr, LaunchArgs, AsyncInfoWrapper); diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt b/offload/unittests/OffloadAPI/CMakeLists.txt index 2844b675e5de1..245710e7d8ac4 100644 --- a/offload/unittests/OffloadAPI/CMakeLists.txt +++ b/offload/unittests/OffloadAPI/CMakeLists.txt @@ -14,7 +14,9 @@ add_offload_unittest("event" add_offload_unittest("kernel" kernel/olGetKernel.cpp - kernel/olLaunchKernel.cpp) + kernel/olLaunchKernel.cpp + kernel/olGetKernelInfo.cpp + kernel/olGetKernelInfoSize.cpp) add_offload_unittest("memory" memory/olMemAlloc.cpp diff --git a/offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp b/offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp new file mode 100644 index 0000000000000..ceaf40fb0d353 --- /dev/null +++ b/offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp @@ -0,0 +1,55 @@ +//===------- Offload API tests - olGetKernelInfo --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#include "../common/Fixtures.hpp" + +using olGetKernelInfoTest = OffloadKernelTest; +OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetKernelInfoTest); + +TEST_P(olGetKernelInfoTest, SuccessProgram) { + ol_program_handle_t ReadProgram; + ASSERT_SUCCESS(olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM, + sizeof(ol_program_handle_t), &ReadProgram)); + ASSERT_EQ(Program, ReadProgram); +} + +TEST_P(olGetKernelInfoTest, InvalidNullHandle) { + ol_program_handle_t Program; + ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE, + olGetKernelInfo(nullptr, OL_KERNEL_INFO_PROGRAM, sizeof(Program), + &Program)); +} + +TEST_P(olGetKernelInfoTest, InvalidKernelInfoEnumeration) { + ol_program_handle_t Program; + ASSERT_ERROR(OL_ERRC_INVALID_ENUMERATION, + olGetKernelInfo(Kernel, OL_KERNEL_INFO_FORCE_UINT32, + sizeof(Program), &Program)); +} + +TEST_P(olGetKernelInfoTest, InvalidSizeZero) { + ol_program_handle_t Program; + ASSERT_ERROR(OL_ERRC_INVALID_SIZE, + olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM, 0, &Program)); +} + +TEST_P(olGetKernelInfoTest, InvalidSizeSmall) { + ol_program_handle_t Program; + ASSERT_ERROR(OL_ERRC_INVALID_SIZE, + olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM, + sizeof(Program) - 1, &Program)); +} + +TEST_P(olGetKernelInfoTest, InvalidNullPointerPropValue) { + ol_program_handle_t Program; + ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, + olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM, sizeof(Program), + nullptr)); +} diff --git a/offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp b/offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp new file mode 100644 index 0000000000000..4c726764f4e42 --- /dev/null +++ b/offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp @@ -0,0 +1,20 @@ +//===------- Offload API tests - olGetKernelInfoSize ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#include "../common/Fixtures.hpp" + +using olGetKernelInfoSizeTest = OffloadKernelTest; +OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetKernelInfoSizeTest); + +TEST_P(olGetKernelInfoSizeTest, SuccessProgram) { + size_t Size = 0; + ASSERT_SUCCESS(olGetKernelInfoSize(Kernel, OL_KERNEL_INFO_PROGRAM, &Size)); + ASSERT_EQ(Size, sizeof(ol_program_handle_t)); +}