summaryrefslogtreecommitdiff
path: root/offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp')
-rw-r--r--offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp b/offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp
new file mode 100644
index 000000000000..c586ad1c1969
--- /dev/null
+++ b/offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp
@@ -0,0 +1,75 @@
+//===--- generic-elf-64bit/dynamic_ffi/ffi.cpp -------------------- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement subset of the FFI api by calling into the FFI library via dlopen
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/DynamicLibrary.h"
+
+#include "Shared/Debug.h"
+#include <memory>
+
+#include "DLWrap.h"
+#include "ffi.h"
+
+DLWRAP_INITIALIZE()
+
+DLWRAP(ffi_call, 4);
+DLWRAP(ffi_prep_cif, 5);
+
+DLWRAP_FINALIZE()
+
+ffi_type ffi_type_void;
+ffi_type ffi_type_pointer;
+
+// Name of the FFI shared library.
+constexpr const char *FFI_PATH = "libffi.so";
+
+#define DYNAMIC_FFI_SUCCESS 0
+#define DYNAMIC_FFI_FAIL 1
+
+// Initializes the dynamic FFI wrapper.
+uint32_t ffi_init() {
+ std::string ErrMsg;
+ auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
+ llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg));
+
+ if (!DynlibHandle->isValid()) {
+ DP("Unable to load library '%s': %s!\n", FFI_PATH, ErrMsg.c_str());
+ return DYNAMIC_FFI_FAIL;
+ }
+
+ for (size_t I = 0; I < dlwrap::size(); I++) {
+ const char *Sym = dlwrap::symbol(I);
+
+ void *P = DynlibHandle->getAddressOfSymbol(Sym);
+ if (P == nullptr) {
+ DP("Unable to find '%s' in '%s'!\n", Sym, FFI_PATH);
+ return DYNAMIC_FFI_FAIL;
+ }
+ DP("Implementing %s with dlsym(%s) -> %p\n", Sym, Sym, P);
+
+ *dlwrap::pointer(I) = P;
+ }
+
+#define DYNAMIC_INIT(SYMBOL) \
+ { \
+ void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \
+ if (!SymbolPtr) { \
+ DP("Unable to find '%s' in '%s'!\n", #SYMBOL, FFI_PATH); \
+ return DYNAMIC_FFI_FAIL; \
+ } \
+ SYMBOL = *reinterpret_cast<decltype(SYMBOL) *>(SymbolPtr); \
+ }
+ DYNAMIC_INIT(ffi_type_void);
+ DYNAMIC_INIT(ffi_type_pointer);
+#undef DYNAMIC_INIT
+
+ return DYNAMIC_FFI_SUCCESS;
+}