xref: /llvm-project/offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp (revision 330d8983d25d08580fc1642fea48b2473f47a9da)
1 //===--- generic-elf-64bit/dynamic_ffi/ffi.cpp -------------------- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implement subset of the FFI api by calling into the FFI library via dlopen
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Support/DynamicLibrary.h"
14 
15 #include "Shared/Debug.h"
16 #include <memory>
17 
18 #include "DLWrap.h"
19 #include "ffi.h"
20 
21 DLWRAP_INITIALIZE()
22 
23 DLWRAP(ffi_call, 4);
24 DLWRAP(ffi_prep_cif, 5);
25 
26 DLWRAP_FINALIZE()
27 
28 ffi_type ffi_type_void;
29 ffi_type ffi_type_pointer;
30 
31 // Name of the FFI shared library.
32 constexpr const char *FFI_PATH = "libffi.so";
33 
34 #define DYNAMIC_FFI_SUCCESS 0
35 #define DYNAMIC_FFI_FAIL 1
36 
37 // Initializes the dynamic FFI wrapper.
ffi_init()38 uint32_t ffi_init() {
39   std::string ErrMsg;
40   auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
41       llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg));
42 
43   if (!DynlibHandle->isValid()) {
44     DP("Unable to load library '%s': %s!\n", FFI_PATH, ErrMsg.c_str());
45     return DYNAMIC_FFI_FAIL;
46   }
47 
48   for (size_t I = 0; I < dlwrap::size(); I++) {
49     const char *Sym = dlwrap::symbol(I);
50 
51     void *P = DynlibHandle->getAddressOfSymbol(Sym);
52     if (P == nullptr) {
53       DP("Unable to find '%s' in '%s'!\n", Sym, FFI_PATH);
54       return DYNAMIC_FFI_FAIL;
55     }
56     DP("Implementing %s with dlsym(%s) -> %p\n", Sym, Sym, P);
57 
58     *dlwrap::pointer(I) = P;
59   }
60 
61 #define DYNAMIC_INIT(SYMBOL)                                                   \
62   {                                                                            \
63     void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
64     if (!SymbolPtr) {                                                          \
65       DP("Unable to find '%s' in '%s'!\n", #SYMBOL, FFI_PATH);                 \
66       return DYNAMIC_FFI_FAIL;                                                 \
67     }                                                                          \
68     SYMBOL = *reinterpret_cast<decltype(SYMBOL) *>(SymbolPtr);                 \
69   }
70   DYNAMIC_INIT(ffi_type_void);
71   DYNAMIC_INIT(ffi_type_pointer);
72 #undef DYNAMIC_INIT
73 
74   return DYNAMIC_FFI_SUCCESS;
75 }
76