[llvm] [Offload] Add olCreateContext / olDestroyContext / olGetContextInfo API (PR #209144)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 04:37:59 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-offload
Author: Łukasz Plewa (lplewa)
<details>
<summary>Changes</summary>
Add the initial Context handle API to liboffload:
- olCreateContext / olDestroyContext
- olGetContextInfo / olGetContextInfoSize
- OL_ERRC_INVALID_CONTEXT error code
- OL_CONTEXT_INFO_{NUM_DEVICES,DEVICES,PLATFORM} queries
This is the first patch in a series. I decided to split the original change into multiple smaller PRs to make the review process faster and more manageable.
This patch introduces context management functions, but the context handle is not used anywhere yet. The following patches will extend the API to use contexts in:
``` c
ol_result_t olMemAlloc(ol_context_handle_t, ol_device_handle_t, ol_alloc_type_t, size_t, void**);
ol_result_t olMemFree(ol_context_handle_t, void*);
ol_result_t olGetMemInfo(ol_context_handle_t, const void*, ol_mem_info_t, size_t, void*);
ol_result_t olGetMemInfoSize(ol_context_handle_t, const void*, ol_mem_info_t, size_t*);
ol_result_t olCreateQueue(ol_context_handle_t, ol_device_handle_t, ol_queue_handle_t*);
ol_result_t olCreateProgram(ol_context_handle_t, ol_device_handle_t, const void*, size_t, ol_program_handle_t*);
```
You can also take a look at #<!-- -->201398, which contains the first version of the complete change. I'm cleaning it up as I go, so the patches in this series are not a direct 1:1 split of that PR.
---
Patch is 25.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/209144.diff
14 Files Affected:
- (modified) offload/liboffload/API/Common.td (+1)
- (added) offload/liboffload/API/Context.td (+92)
- (modified) offload/liboffload/API/OffloadAPI.td (+1)
- (modified) offload/liboffload/src/OffloadImpl.cpp (+81)
- (modified) offload/plugins-nextgen/common/include/PluginInterface.h (+34)
- (modified) offload/plugins-nextgen/level_zero/include/L0Context.h (+7)
- (modified) offload/plugins-nextgen/level_zero/include/L0Plugin.h (+25)
- (modified) offload/plugins-nextgen/level_zero/src/L0Context.cpp (+5)
- (modified) offload/plugins-nextgen/level_zero/src/L0Plugin.cpp (+50)
- (modified) offload/unittests/OffloadAPI/CMakeLists.txt (+6)
- (added) offload/unittests/OffloadAPI/context/olCreateContext.cpp (+37)
- (added) offload/unittests/OffloadAPI/context/olDestroyContext.cpp (+24)
- (added) offload/unittests/OffloadAPI/context/olGetContextInfo.cpp (+66)
- (added) offload/unittests/OffloadAPI/context/olGetContextInfoSize.cpp (+60)
``````````diff
diff --git a/offload/liboffload/API/Common.td b/offload/liboffload/API/Common.td
index 9bdd4291e096e..b670195b19f70 100644
--- a/offload/liboffload/API/Common.td
+++ b/offload/liboffload/API/Common.td
@@ -98,6 +98,7 @@ def ol_errc_t : Enum {
Etor<"INVALID_DEVICE", "invalid device">,
Etor<"INVALID_QUEUE", "invalid queue">,
Etor<"INVALID_EVENT", "invalid event">,
+ Etor<"INVALID_CONTEXT", "invalid context">,
Etor<"SYMBOL_KIND", "the operation does not support this symbol kind">,
];
}
diff --git a/offload/liboffload/API/Context.td b/offload/liboffload/API/Context.td
new file mode 100644
index 0000000000000..1b407265cd879
--- /dev/null
+++ b/offload/liboffload/API/Context.td
@@ -0,0 +1,92 @@
+//===-- Context.td - Context definitions for Offload -------*- tablegen -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains Offload API definitions related to the Context
+//
+//===----------------------------------------------------------------------===//
+
+def olCreateContext : Function {
+ let desc = "Create a context grouping the given devices.";
+ let details = [
+ "All devices must belong to the same platform.",
+ "A context enables resource sharing between the devices it groups and "
+ "isolates those resources from other contexts: resources (such as memory "
+ "allocations) created within a context cannot be used outside of it.",
+ "The returned context must be released with a subsequent call to "
+ "`olDestroyContext`.",
+ "This function is thread safe."
+ ];
+ let params = [
+ Param<"size_t", "DevicesCount", "number of devices in `Devices`", PARAM_IN>,
+ Param<"ol_device_handle_t*", "Devices", "array of device handles to include in the context", PARAM_IN>,
+ Param<"ol_context_handle_t*", "Context", "output pointer for the created context", PARAM_OUT>
+ ];
+ let returns = [
+ Return<"OL_ERRC_INVALID_SIZE", [
+ "`DevicesCount == 0`"
+ ]>,
+ Return<"OL_ERRC_INVALID_DEVICE", [
+ "the devices in `Devices` do not all belong to the same platform"
+ ]>
+ ];
+}
+
+def olDestroyContext : Function {
+ let desc = "Destroy the context and free all underlying resources.";
+ let details = [
+ "All resources tied to the context (such as memory allocations) "
+ "should be released before destroying it. Any resource that is still "
+ "tied to the context at this point is left in an undefined state and "
+ "must not be used afterwards.",
+ "Thread safe with respect to other contexts."
+ ];
+ let params = [
+ Param<"ol_context_handle_t", "Context", "handle of the context to destroy", PARAM_IN>
+ ];
+ let returns = [];
+}
+
+def ol_context_info_t : Enum {
+ let desc = "Supported context info.";
+ let is_typed = 1;
+ let etors = [
+ TaggedEtor<"NUM_DEVICES", "size_t", "The number of devices in the context.">,
+ TaggedEtor<"DEVICES", "ol_device_handle_t *", "The devices in the context. The returned array has NUM_DEVICES entries.">,
+ TaggedEtor<"PLATFORM", "ol_platform_handle_t", "The platform associated with the context.">,
+ ];
+}
+
+def olGetContextInfo : Function {
+ let desc = "Queries the given property of the context.";
+ let params = [
+ Param<"ol_context_handle_t", "Context", "handle of the context", PARAM_IN>,
+ Param<"ol_context_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 Size is not equal to or greater to 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_INVALID_SIZE", [
+ "`PropSize == 0`",
+ "If `PropSize` is less than the real number of bytes needed to return the info."
+ ]>
+ ];
+}
+
+def olGetContextInfoSize : Function {
+ let desc = "Returns the storage size of the given context query.";
+ let details = [];
+ let params = [
+ Param<"ol_context_handle_t", "Context", "handle of the context", PARAM_IN>,
+ Param<"ol_context_info_t", "PropName", "type of the info to query", PARAM_IN>,
+ Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT>
+ ];
+ let returns = [];
+}
diff --git a/offload/liboffload/API/OffloadAPI.td b/offload/liboffload/API/OffloadAPI.td
index 1b78edf4c7745..e28f79f2e34af 100644
--- a/offload/liboffload/API/OffloadAPI.td
+++ b/offload/liboffload/API/OffloadAPI.td
@@ -13,6 +13,7 @@ include "APIDefs.td"
include "Common.td"
include "Platform.td"
include "Device.td"
+include "Context.td"
include "Memory.td"
include "Queue.td"
include "Event.td"
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index a36081f27b5ee..f8f9b4cc75f00 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -208,6 +208,18 @@ struct ol_symbol_impl_t {
llvm::StringRef Name;
};
+struct ol_context_impl_t {
+ ol_context_impl_t(ol_platform_impl_t *Platform,
+ llvm::SmallVector<ol_device_handle_t> Devices,
+ std::unique_ptr<plugin::PluginContextTy> PluginCtx)
+ : Platform(Platform), Devices(std::move(Devices)),
+ PluginCtx(std::move(PluginCtx)) {}
+
+ ol_platform_impl_t *Platform;
+ llvm::SmallVector<ol_device_handle_t> Devices;
+ std::unique_ptr<plugin::PluginContextTy> PluginCtx;
+};
+
namespace llvm {
namespace offload {
@@ -584,6 +596,75 @@ Error olIterateDevices_impl(ol_device_iterate_cb_t Callback, void *UserData) {
return Error::success();
}
+Error olCreateContext_impl(size_t DevicesCount, ol_device_handle_t *Devices,
+ ol_context_handle_t *Context) {
+ ol_platform_impl_t *Platform = &Devices[0]->Platform;
+ llvm::SmallVector<ol_device_handle_t> DeviceList;
+ llvm::SmallVector<plugin::GenericDeviceTy *> PluginDevices;
+ DeviceList.reserve(DevicesCount);
+ PluginDevices.reserve(DevicesCount);
+ for (size_t I = 0; I < DevicesCount; I++) {
+ if (&Devices[I]->Platform != Platform)
+ return createOffloadError(
+ ErrorCode::INVALID_DEVICE,
+ "all devices in a context must belong to the same platform");
+ DeviceList.push_back(Devices[I]);
+ PluginDevices.push_back(Devices[I]->Device);
+ }
+
+ // The host plugin has no GenericPluginTy instance; skip the plugin-side
+ // context in that case and just record the device set.
+ std::unique_ptr<plugin::PluginContextTy> PluginCtx;
+ if (Platform->Plugin) {
+ auto PluginCtxOrErr = Platform->Plugin->createPluginContext(PluginDevices);
+ if (!PluginCtxOrErr)
+ return PluginCtxOrErr.takeError();
+ PluginCtx = std::move(*PluginCtxOrErr);
+ }
+
+ *Context = new ol_context_impl_t(Platform, std::move(DeviceList),
+ std::move(PluginCtx));
+ return Error::success();
+}
+
+Error olDestroyContext_impl(ol_context_handle_t Context) {
+ return olDestroy(Context);
+}
+
+Error olGetContextInfoImplDetail(ol_context_handle_t Context,
+ ol_context_info_t PropName, size_t PropSize,
+ void *PropValue, size_t *PropSizeRet) {
+ InfoWriter Info(PropSize, PropValue, PropSizeRet);
+
+ switch (PropName) {
+ case OL_CONTEXT_INFO_NUM_DEVICES:
+ return Info.write<size_t>(Context->Devices.size());
+ case OL_CONTEXT_INFO_DEVICES:
+ return Info.writeArray(Context->Devices.data(), Context->Devices.size());
+ case OL_CONTEXT_INFO_PLATFORM:
+ return Info.write<ol_platform_handle_t>(Context->Platform);
+ default:
+ return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+ "olGetContextInfo enum '%i' is invalid",
+ PropName);
+ }
+
+ return Error::success();
+}
+
+Error olGetContextInfo_impl(ol_context_handle_t Context,
+ ol_context_info_t PropName, size_t PropSize,
+ void *PropValue) {
+ return olGetContextInfoImplDetail(Context, PropName, PropSize, PropValue,
+ nullptr);
+}
+
+Error olGetContextInfoSize_impl(ol_context_handle_t Context,
+ ol_context_info_t PropName,
+ size_t *PropSizeRet) {
+ return olGetContextInfoImplDetail(Context, PropName, 0, nullptr, PropSizeRet);
+}
+
TargetAllocTy convertOlToPluginAllocTy(ol_alloc_type_t Type) {
switch (Type) {
case OL_ALLOC_TYPE_DEVICE:
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index dc21abf1a334a..f912e6b122056 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -66,6 +66,7 @@ namespace plugin {
struct GenericPluginTy;
struct GenericKernelTy;
struct GenericDeviceTy;
+struct PluginContextTy;
template <typename ResourceRef> class GenericDeviceResourceManagerTy;
namespace Plugin {
@@ -838,6 +839,30 @@ class PinnedAllocationMapTy {
}
};
+/// A plugin-side context grouping a set of devices. Plugins that need to hold
+/// native context state (e.g. Level Zero's ze_context_handle_t) override this
+/// through GenericPluginTy::createPluginContext. The base class is a plain
+/// device set used by plugins that do not need native context state.
+struct PluginContextTy {
+ PluginContextTy(GenericPluginTy &Plugin,
+ llvm::ArrayRef<GenericDeviceTy *> Devices)
+ : Plugin(Plugin), Devices(Devices.begin(), Devices.end()) {}
+
+ PluginContextTy(const PluginContextTy &) = delete;
+ PluginContextTy &operator=(const PluginContextTy &) = delete;
+ PluginContextTy(PluginContextTy &&) = delete;
+ PluginContextTy &operator=(PluginContextTy &&) = delete;
+
+ virtual ~PluginContextTy() = default;
+
+ llvm::ArrayRef<GenericDeviceTy *> getDevices() const { return Devices; }
+ GenericPluginTy &getPlugin() const { return Plugin; }
+
+protected:
+ GenericPluginTy &Plugin;
+ llvm::SmallVector<GenericDeviceTy *> Devices;
+};
+
/// Class implementing common functionalities of offload devices. Each plugin
/// should define the specific device class, derive from this generic one, and
/// implement the necessary virtual function members.
@@ -1559,6 +1584,15 @@ struct GenericPluginTy {
"async_barrier not supported");
}
+ /// Create a plugin-side context grouping the given devices. The default
+ /// implementation returns a plain PluginContextTy that only tracks the
+ /// device set. Plugins that own native context state (e.g. Level Zero)
+ /// override this to instantiate a plugin-specific subclass.
+ virtual Expected<std::unique_ptr<PluginContextTy>>
+ createPluginContext(llvm::ArrayRef<GenericDeviceTy *> Devices) {
+ return std::make_unique<PluginContextTy>(*this, Devices);
+ }
+
protected:
/// Indicate whether a device id is valid.
bool isValidDeviceId(int32_t DeviceId) const {
diff --git a/offload/plugins-nextgen/level_zero/include/L0Context.h b/offload/plugins-nextgen/level_zero/include/L0Context.h
index 1bb5b76c61a84..7bd082571b1a1 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Context.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Context.h
@@ -147,6 +147,13 @@ class L0ContextTy {
ze_command_list_handle_t hCommandList, void *pfnHostFunction,
void *pUserData, void *pReserved, ze_event_handle_t hSignalEvent,
uint32_t numWaitEvents, ze_event_handle_t *phWaitEvents) = nullptr;
+
+ /// Level Zero extension function pointer for querying the driver's default
+ /// ze_context, when the extension is supported. Used by
+ /// LevelZeroPluginTy::createPluginContext to reuse the driver default
+ /// context when the user asks for every device on the driver.
+ ze_context_handle_t(ZE_APICALL *zeDriverGetDefaultContext)(
+ ze_driver_handle_t hDriver) = nullptr;
};
} // namespace llvm::omp::target::plugin
diff --git a/offload/plugins-nextgen/level_zero/include/L0Plugin.h b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
index 665da5edb0e59..7240e80f9fcbf 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Plugin.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
@@ -21,6 +21,28 @@
namespace llvm::omp::target::plugin {
+/// Plugin-side context for Level Zero. Owns a ze_context_handle_t that is
+/// scoped to the set of devices grouped by the user through olCreateContext.
+class LevelZeroPluginContextTy final : public PluginContextTy {
+public:
+ LevelZeroPluginContextTy(GenericPluginTy &Plugin,
+ llvm::ArrayRef<GenericDeviceTy *> Devices,
+ ze_driver_handle_t Driver,
+ ze_context_handle_t ZeContext, bool OwnsZeContext)
+ : PluginContextTy(Plugin, Devices), Driver(Driver), ZeContext(ZeContext),
+ OwnsZeContext(OwnsZeContext) {}
+
+ ~LevelZeroPluginContextTy() override;
+
+ ze_driver_handle_t getZeDriver() const { return Driver; }
+ ze_context_handle_t getZeContext() const { return ZeContext; }
+
+private:
+ ze_driver_handle_t Driver;
+ ze_context_handle_t ZeContext;
+ bool OwnsZeContext;
+};
+
/// Class implementing the LevelZero specific functionalities of the plugin.
class LevelZeroPluginTy final : public GenericPluginTy {
private:
@@ -68,6 +90,9 @@ class LevelZeroPluginTy final : public GenericPluginTy {
int32_t NumDevices) override;
GenericGlobalHandlerTy *createGlobalHandler() override;
+ Expected<std::unique_ptr<PluginContextTy>>
+ createPluginContext(llvm::ArrayRef<GenericDeviceTy *> Devices) override;
+
uint16_t getMagicElfBits() const override { return ELF::EM_INTELGT; }
Triple::ArchType getTripleArch() const override { return Triple::spirv64; }
const char *getName() const override { return GETNAME(TARGET_NAME); }
diff --git a/offload/plugins-nextgen/level_zero/src/L0Context.cpp b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
index c1556dc5b37f7..a656a99b8f98b 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Context.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
@@ -63,6 +63,11 @@ Error L0ContextTy::init() {
if (RC != ZE_RESULT_SUCCESS)
zeCommandListAppendHostFunction = nullptr;
+ CALL_ZE(RC, zeDriverGetExtensionFunctionAddress, zeDriver,
+ "zeDriverGetDefaultContext", (void **)&zeDriverGetDefaultContext);
+ if (RC != ZE_RESULT_SUCCESS)
+ zeDriverGetDefaultContext = nullptr;
+
return Plugin::success();
}
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index c5688e574254c..5d7a3e0399b31 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -242,6 +242,56 @@ Error LevelZeroPluginTy::asyncBarrierImpl(omp_interop_val_t *Interop) {
return Plugin::success();
}
+LevelZeroPluginContextTy::~LevelZeroPluginContextTy() {
+ if (OwnsZeContext && ZeContext)
+ zeContextDestroy(ZeContext);
+}
+
+Expected<std::unique_ptr<PluginContextTy>>
+LevelZeroPluginTy::createPluginContext(
+ llvm::ArrayRef<GenericDeviceTy *> Devices) {
+ if (Devices.empty())
+ return Plugin::error(ErrorCode::INVALID_ARGUMENT,
+ "createPluginContext called with no devices");
+
+ // All devices must share the same L0 driver context, since a ze_context is
+ // scoped to a single driver.
+ auto &First = static_cast<L0DeviceTy &>(*Devices[0]);
+ L0ContextTy &DriverCtx = First.getL0Context();
+ ze_driver_handle_t Driver = DriverCtx.getZeDriver();
+ for (auto *D : Devices.drop_front()) {
+ auto &L0D = static_cast<L0DeviceTy &>(*D);
+ if (&L0D.getL0Context() != &DriverCtx)
+ return Plugin::error(
+ ErrorCode::INVALID_DEVICE,
+ "all devices in an L0 context must share the same driver");
+ }
+
+ // When the user requests every device on the driver, share the driver's
+ // default ze_context so we interop cleanly with other L0 clients on the
+ // same driver. Partial device sets get their own fresh context.
+ size_t DriverDeviceCount = 0;
+ for (int32_t I = 0, N = getNumDevices(); I != N; ++I) {
+ auto &L0D = static_cast<const L0DeviceTy &>(getDevice(I));
+ if (&L0D.getL0Context() == &DriverCtx)
+ ++DriverDeviceCount;
+ }
+ const bool IsFullDriver = (Devices.size() == DriverDeviceCount);
+
+ ze_context_handle_t ZeContext = nullptr;
+ bool OwnsZeContext = false;
+ if (IsFullDriver && DriverCtx.zeDriverGetDefaultContext)
+ ZeContext = DriverCtx.zeDriverGetDefaultContext(Driver);
+ if (!ZeContext) {
+ ze_context_desc_t Desc{ZE_STRUCTURE_TYPE_CONTEXT_DESC, nullptr, 0};
+ CALL_ZE_RET_ERROR(zeContextCreate, Driver, &Desc, &ZeContext);
+ OwnsZeContext = true;
+ }
+
+ return std::make_unique<LevelZeroPluginContextTy>(*this, Devices, Driver,
+ ZeContext, OwnsZeContext);
+}
+
} // namespace llvm::omp::target::plugin
extern "C" {
diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt b/offload/unittests/OffloadAPI/CMakeLists.txt
index d960da4b98f82..f9dc6c74d926f 100644
--- a/offload/unittests/OffloadAPI/CMakeLists.txt
+++ b/offload/unittests/OffloadAPI/CMakeLists.txt
@@ -3,6 +3,12 @@ set(PLUGINS_TEST_INCLUDE ${LIBOMPTARGET_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
add_subdirectory(device_code)
+add_offload_unittest("context"
+ context/olCreateContext.cpp
+ context/olDestroyContext.cpp
+ context/olGetContextInfo.cpp
+ context/olGetContextInfoSize.cpp)
+
add_offload_unittest("device"
device/olIterateDevices.cpp
device/olGetDeviceInfo.cpp
diff --git a/offload/unittests/OffloadAPI/context/olCreateContext.cpp b/offload/unittests/OffloadAPI/context/olCreateContext.cpp
new file mode 100644
index 0000000000000..81777eb21e8ed
--- /dev/null
+++ b/offload/unittests/OffloadAPI/context/olCreateContext.cpp
@@ -0,0 +1,37 @@
+//===------- Offload API tests - olCreateContext --------------------------===//
+//
+// 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 "../common/Fixtures.hpp"
+#include <OffloadAPI.h>
+#include <gtest/gtest.h>
+
+using olCreateContextTest = OffloadDeviceTest;
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olCreateContextTest);
+
+TEST_P(olCreateContextTest, Success) {
+ ol_context_handle_t Context = nullptr;
+ ASSERT_SUCCESS(olCreateContext(1, &Device, &Context));
+ ASSERT_NE(Context, nullptr);
+ ASSERT_SUCCESS(olDestroyContext(Context));
+}
+
+TEST_P(olCreateContextTest, InvalidNullDevices) {
+ ol_context_handle_t Context = nullptr;
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
+ olCreateContext(1, nullptr, &Context));
+}
+
+TEST_P(olCreateContextTest, InvalidZeroSize) {
+ ol_context_handle_t Context = nullptr;
+ ASSERT_ERROR(OL_ERRC_INVALID_SIZE, olCreateContext(0, &Device, &Context));
+}
+
+TEST_P(olCreateContextTest, InvalidNullOut) {
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
+ olCreateContext(1, &Device, nullptr));
+}
diff --git a/offload/unittests/OffloadAPI/context/olDestroyContext.cpp b/offload/unittests/OffloadAPI/context/olDestroyContext.cpp
new file mode 100644
index 0000000000000..8bdb5516f7349
--- /dev/null
+++ b/offload/unittests/OffloadAPI/context/olDestroyContext.cpp
@@ -0,0 +1,24 @@
+//===------- Offload API tests - olDestroyContext -------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/209144
More information about the llvm-commits
mailing list