brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.0 KiB · 8934e7e Raw
287 lines · c
1//===-- Shared/DLWrap.h - Convenience wrapper for dlopen/dlsym --*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// The openmp plugins depend on extern libraries. These can be used via:10//  - bitcode file statically linked11//  - (relocatable) object file statically linked12//  - static library13//  - dynamic library, linked at build time14//  - dynamic library, loaded at application run time by dlopen15//16// This file factors out most boilerplate for using a dlopened library.17// - Function symbols are generated that are statically linked against18// - The dlopen can be done implicitly when initializing the library19// - dlsym lookups are done once and cached20// - The abstraction is very thin to permit varied uses of the library21//22// Given int foo(char, double, void*);, writing DLWRAP(foo, 3) will expand to:23// int foo(char x0, double x1, void* x2) {24//   constexpr size_t index = id();25//   void * dlsymResult = pointer(index);26//   return ((int (*)(char, double, void*))dlsymResult)(x0, x1, x2);27// }28//29// Multiple calls to DLWRAP(symbol_name, arity) with bespoke30// initialization code that can use the thin abstraction:31// namespace dlwrap {32//   static size_t size();33//   static const char *symbol(size_t);34//   static void **pointer(size_t);35// }36// will compile to an object file that only exposes the symbols that the37// dynamic library would do, with the right function types.38//39//===----------------------------------------------------------------------===//40 41#ifndef OMPTARGET_SHARED_DLWRAP_H42#define OMPTARGET_SHARED_DLWRAP_H43 44#include <array>45#include <cstddef>46#include <tuple>47#include <type_traits>48 49// Where symbol is a function, these expand to some book keeping and an50// implementation of that function51#define DLWRAP(SYMBOL, ARITY) DLWRAP_IMPL(SYMBOL, ARITY)52#define DLWRAP_INTERNAL(SYMBOL, ARITY) DLWRAP_INTERNAL_IMPL(SYMBOL, ARITY)53 54// For example, given a prototype:55// int foo(char, double);56//57// DLWRAP(foo, 2) expands to:58//59// namespace dlwrap {60// struct foo_Trait : public dlwrap::trait<decltype(&foo)> {61//   using T = dlwrap::trait<decltype(&foo)>;62//   static T::FunctionType get() {63//     constexpr size_t Index = getIndex();64//     void *P = *dlwrap::pointer(Index);65//     return reinterpret_cast<T::FunctionType>(P);66//   }67// };68// }69// int foo(char x0, double x1) { return dlwrap::foo_Trait::get()(x0, x1); }70//71// DLWRAP_INTERNAL is similar, except the function it expands to is:72// static int dlwrap_foo(char x0, double x1) { ... }73// so that the function pointer call can be wrapped in library-specific code74//75// DLWRAP_INITIALIZE() declares static functions:76#define DLWRAP_INITIALIZE()                                                    \77  namespace dlwrap {                                                           \78  static size_t size();                                                        \79  static const char *symbol(size_t); /* get symbol name in [0, size()) */      \80  static void **                                                               \81      pointer(size_t); /* get pointer to function pointer in [0, size()) */    \82  }83 84// DLWRAP_FINALIZE() implements the functions from DLWRAP_INITIALIZE85#define DLWRAP_FINALIZE() DLWRAP_FINALIZE_IMPL()86 87// Implementation details follow.88 89namespace dlwrap {90 91// Extract return / argument types from address of function symbol92template <typename F> struct trait;93template <typename R, typename... Ts> struct trait<R (*)(Ts...)> {94  constexpr static const size_t nargs = sizeof...(Ts);95  typedef R ReturnType;96  template <size_t i> struct arg {97    typedef typename std::tuple_element<i, std::tuple<Ts...>>::type type;98  };99 100  typedef R (*FunctionType)(Ts...);101};102 103namespace type {104// Book keeping is by type specialization105 106template <size_t S> struct count {107  static constexpr size_t N = count<S - 1>::N;108};109 110template <> struct count<0> { static constexpr size_t N = 0; };111 112// Get a constexpr size_t ID, starts at zero113#define DLWRAP_ID() (dlwrap::type::count<__LINE__>::N)114 115// Increment value returned by DLWRAP_ID116#define DLWRAP_INC()                                                           \117  template <> struct dlwrap::type::count<__LINE__> {                           \118    static constexpr size_t N = 1 + dlwrap::type::count<__LINE__ - 1>::N;      \119  }120 121template <size_t N> struct symbol;122#define DLWRAP_SYMBOL(SYMBOL, ID)                                              \123  template <> struct dlwrap::type::symbol<ID> {                                \124    static constexpr const char *call() { return #SYMBOL; }                    \125  }126} // namespace type127 128template <size_t N, size_t... Is>129constexpr std::array<const char *, N> static getSymbolArray(130    std::index_sequence<Is...>) {131  return {{dlwrap::type::symbol<Is>::call()...}};132}133 134template <size_t Requested, size_t Required> constexpr void verboseAssert() {135  static_assert(Requested == Required, "Arity Error");136}137 138} // namespace dlwrap139 140#define DLWRAP_INSTANTIATE(SYM_DEF, SYM_USE, ARITY)                            \141  DLWRAP_INSTANTIATE_##ARITY(SYM_DEF, SYM_USE,                                 \142                             dlwrap::trait<decltype(&SYM_USE)>)143 144#define DLWRAP_FINALIZE_IMPL()                                                 \145  static size_t dlwrap::size() { return DLWRAP_ID(); }                         \146  static const char *dlwrap::symbol(size_t i) {                                \147    static constexpr const std::array<const char *, DLWRAP_ID()>               \148        dlwrap_symbols = getSymbolArray<DLWRAP_ID()>(                          \149            std::make_index_sequence<DLWRAP_ID()>());                          \150    return dlwrap_symbols[i];                                                  \151  }                                                                            \152  static void **dlwrap::pointer(size_t i) {                                    \153    static std::array<void *, DLWRAP_ID()> dlwrap_pointers;                    \154    return &dlwrap_pointers.data()[i];                                         \155  }156 157#define DLWRAP_COMMON(SYMBOL, ARITY)                                           \158  DLWRAP_INC();                                                                \159  DLWRAP_SYMBOL(SYMBOL, DLWRAP_ID() - 1);                                      \160  namespace dlwrap {                                                           \161  struct SYMBOL##_Trait : public dlwrap::trait<decltype(&SYMBOL)> {            \162    using T = dlwrap::trait<decltype(&SYMBOL)>;                                \163    static T::FunctionType get() {                                             \164      verboseAssert<ARITY, trait<decltype(&SYMBOL)>::nargs>();                 \165      constexpr size_t Index = DLWRAP_ID() - 1;                                \166      void *P = *dlwrap::pointer(Index);                                       \167      return reinterpret_cast<T::FunctionType>(P);                             \168    }                                                                          \169  };                                                                           \170  }171 172#define DLWRAP_IMPL(SYMBOL, ARITY)                                             \173  DLWRAP_COMMON(SYMBOL, ARITY)                                                 \174  DLWRAP_INSTANTIATE(SYMBOL, SYMBOL, ARITY)175 176#define DLWRAP_INTERNAL_IMPL(SYMBOL, ARITY)                                    \177  DLWRAP_COMMON(SYMBOL, ARITY)                                                 \178  static DLWRAP_INSTANTIATE(dlwrap_##SYMBOL, SYMBOL, ARITY)179 180#define DLWRAP_INSTANTIATE_0(SYM_DEF, SYM_USE, T)                              \181  T::ReturnType SYM_DEF() { return dlwrap::SYM_USE##_Trait::get()(); }182#define DLWRAP_INSTANTIATE_1(SYM_DEF, SYM_USE, T)                              \183  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0) {                \184    return dlwrap::SYM_USE##_Trait::get()(x0);                                 \185  }186#define DLWRAP_INSTANTIATE_2(SYM_DEF, SYM_USE, T)                              \187  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \188                        typename T::template arg<1>::type x1) {                \189    return dlwrap::SYM_USE##_Trait::get()(x0, x1);                             \190  }191#define DLWRAP_INSTANTIATE_3(SYM_DEF, SYM_USE, T)                              \192  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \193                        typename T::template arg<1>::type x1,                  \194                        typename T::template arg<2>::type x2) {                \195    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2);                         \196  }197#define DLWRAP_INSTANTIATE_4(SYM_DEF, SYM_USE, T)                              \198  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \199                        typename T::template arg<1>::type x1,                  \200                        typename T::template arg<2>::type x2,                  \201                        typename T::template arg<3>::type x3) {                \202    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3);                     \203  }204#define DLWRAP_INSTANTIATE_5(SYM_DEF, SYM_USE, T)                              \205  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \206                        typename T::template arg<1>::type x1,                  \207                        typename T::template arg<2>::type x2,                  \208                        typename T::template arg<3>::type x3,                  \209                        typename T::template arg<4>::type x4) {                \210    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4);                 \211  }212#define DLWRAP_INSTANTIATE_6(SYM_DEF, SYM_USE, T)                              \213  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \214                        typename T::template arg<1>::type x1,                  \215                        typename T::template arg<2>::type x2,                  \216                        typename T::template arg<3>::type x3,                  \217                        typename T::template arg<4>::type x4,                  \218                        typename T::template arg<5>::type x5) {                \219    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4, x5);             \220  }221 222#define DLWRAP_INSTANTIATE_7(SYM_DEF, SYM_USE, T)                              \223  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \224                        typename T::template arg<1>::type x1,                  \225                        typename T::template arg<2>::type x2,                  \226                        typename T::template arg<3>::type x3,                  \227                        typename T::template arg<4>::type x4,                  \228                        typename T::template arg<5>::type x5,                  \229                        typename T::template arg<6>::type x6) {                \230    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4, x5, x6);         \231  }232 233#define DLWRAP_INSTANTIATE_8(SYM_DEF, SYM_USE, T)                              \234  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \235                        typename T::template arg<1>::type x1,                  \236                        typename T::template arg<2>::type x2,                  \237                        typename T::template arg<3>::type x3,                  \238                        typename T::template arg<4>::type x4,                  \239                        typename T::template arg<5>::type x5,                  \240                        typename T::template arg<6>::type x6,                  \241                        typename T::template arg<7>::type x7) {                \242    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4, x5, x6, x7);     \243  }244#define DLWRAP_INSTANTIATE_9(SYM_DEF, SYM_USE, T)                              \245  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \246                        typename T::template arg<1>::type x1,                  \247                        typename T::template arg<2>::type x2,                  \248                        typename T::template arg<3>::type x3,                  \249                        typename T::template arg<4>::type x4,                  \250                        typename T::template arg<5>::type x5,                  \251                        typename T::template arg<6>::type x6,                  \252                        typename T::template arg<7>::type x7,                  \253                        typename T::template arg<8>::type x8) {                \254    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4, x5, x6, x7, x8); \255  }256#define DLWRAP_INSTANTIATE_10(SYM_DEF, SYM_USE, T)                             \257  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \258                        typename T::template arg<1>::type x1,                  \259                        typename T::template arg<2>::type x2,                  \260                        typename T::template arg<3>::type x3,                  \261                        typename T::template arg<4>::type x4,                  \262                        typename T::template arg<5>::type x5,                  \263                        typename T::template arg<6>::type x6,                  \264                        typename T::template arg<7>::type x7,                  \265                        typename T::template arg<8>::type x8,                  \266                        typename T::template arg<9>::type x9) {                \267    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4, x5, x6, x7, x8,  \268                                          x9);                                 \269  }270#define DLWRAP_INSTANTIATE_11(SYM_DEF, SYM_USE, T)                             \271  T::ReturnType SYM_DEF(typename T::template arg<0>::type x0,                  \272                        typename T::template arg<1>::type x1,                  \273                        typename T::template arg<2>::type x2,                  \274                        typename T::template arg<3>::type x3,                  \275                        typename T::template arg<4>::type x4,                  \276                        typename T::template arg<5>::type x5,                  \277                        typename T::template arg<6>::type x6,                  \278                        typename T::template arg<7>::type x7,                  \279                        typename T::template arg<8>::type x8,                  \280                        typename T::template arg<9>::type x9,                  \281                        typename T::template arg<10>::type x10) {              \282    return dlwrap::SYM_USE##_Trait::get()(x0, x1, x2, x3, x4, x5, x6, x7, x8,  \283                                          x9, x10);                            \284  }285 286#endif // OMPTARGET_SHARED_DLWRAP_H287