[llvm] [Offload] Introduce offload-tblgen and initial new API implementation (PR #108413)

Callum Fare via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 30 04:55:44 PDT 2024


================
@@ -0,0 +1,190 @@
+//===- offload_impl.cpp - Implementation of the new LLVM/Offload API ------===//
+//
+// 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 contains the definitions of the new LLVM/Offload API entry points. See
+// new-api/API/README.md for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PluginManager.h"
+#include "helpers.hpp"
+#include "llvm/Support/FormatVariadic.h"
+#include <offload_api.h>
+
+#include <mutex>
+
+using namespace llvm;
+using namespace llvm::omp::target::plugin;
+
+// Handle type definitions. Ideally these would be 1:1 with the plugins
+struct offload_device_handle_t_ {
+  int DeviceNum;
+  GenericDeviceTy &Device;
+};
+
+struct offload_platform_handle_t_ {
+  std::unique_ptr<GenericPluginTy> Plugin;
+  std::vector<offload_device_handle_t_> Devices;
+};
+
+std::vector<offload_platform_handle_t_> &Platforms() {
+  static std::vector<offload_platform_handle_t_> Platforms;
+  return Platforms;
+}
+
+// Every plugin exports this method to create an instance of the plugin type.
+#define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name();
+#include "Shared/Targets.def"
+
+void initPlugins() {
+  // Attempt to create an instance of each supported plugin.
+#define PLUGIN_TARGET(Name)                                                    \
+  do {                                                                         \
+    Platforms().emplace_back(offload_platform_handle_t_{                       \
+        std::unique_ptr<GenericPluginTy>(createPlugin_##Name()), {}});         \
+  } while (false);
+#include "Shared/Targets.def"
+
+  // Preemptively initialize all devices in the plugin so we can just return
+  // them from deviceGet
+  for (auto &Platform : Platforms()) {
+    auto Err = Platform.Plugin->init();
+    [[maybe_unused]] std::string InfoMsg = toString(std::move(Err));
+    for (auto DevNum = 0; DevNum < Platform.Plugin->number_of_devices();
+         DevNum++) {
+      if (Platform.Plugin->init_device(DevNum) == OFFLOAD_SUCCESS) {
+        Platform.Devices.emplace_back(offload_device_handle_t_{
+            DevNum, Platform.Plugin->getDevice(DevNum)});
+      }
+    }
+  }
+}
+
+offload_result_t offloadPlatformGet_impl(uint32_t NumEntries,
+                                         offload_platform_handle_t *phPlatforms,
+                                         uint32_t *pNumPlatforms) {
+  // It is expected that offloadPlatformGet is the first function to be called.
+  // In future it may make sense to have a specific entry point for Offload
+  // initialization, or expose explicit initialization of plugins.
+  static std::once_flag InitFlag;
+  std::call_once(InitFlag, initPlugins);
+
+  if (NumEntries > Platforms().size()) {
+    return OFFLOAD_RESULT_ERROR_INVALID_SIZE;
+  }
+
+  if (phPlatforms) {
+    for (uint32_t PlatformIndex = 0; PlatformIndex < NumEntries;
+         PlatformIndex++) {
+      phPlatforms[PlatformIndex] = &(Platforms())[PlatformIndex];
+    }
+  }
+
+  if (pNumPlatforms) {
+    *pNumPlatforms = Platforms().size();
+  }
+
+  return OFFLOAD_RESULT_SUCCESS;
+}
+
+offload_result_t
+offloadPlatformGetInfo_impl(offload_platform_handle_t hPlatform,
+                            offload_platform_info_t propName, size_t propSize,
+                            void *pPropValue, size_t *pPropSizeRet) {
+  ReturnHelper ReturnValue(propSize, pPropValue, pPropSizeRet);
+
+  switch (propName) {
+  case OFFLOAD_PLATFORM_INFO_NAME:
+    return ReturnValue(hPlatform->Plugin->getName());
+  case OFFLOAD_PLATFORM_INFO_VENDOR_NAME:
+    // TODO: Implement this
+    return ReturnValue("Unknown platform vendor");
+  case OFFLOAD_PLATFORM_INFO_VERSION: {
+    // TODO: Implement this
+    return ReturnValue("v0.0.0");
----------------
callumfare wrote:

I've added version information to the tablegen directly. I've just set it to 0.0.1 for now. As we approach a stable-ish API we can decide how to handle versioning, whether it's just tied to the LLVM version etc.

https://github.com/llvm/llvm-project/pull/108413


More information about the llvm-commits mailing list