[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / openmp / libomptarget / include / dlwrap.h
blob2784bd8594c1c96c75baf2ef4e4a1929fea1abd7
1 //===------- dlwrap.h - Convenience wrapper around 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // The openmp plugins depend on extern libraries. These can be used via:
10 // - bitcode file statically linked
11 // - (relocatable) object file statically linked
12 // - static library
13 // - dynamic library, linked at build time
14 // - dynamic library, loaded at application run time by dlopen
16 // This file factors out most boilerplate for using a dlopened library.
17 // - Function symbols are generated that are statically linked against
18 // - The dlopen can be done implicitly when initializing the library
19 // - dlsym lookups are done once and cached
20 // - The abstraction is very thin to permit varied uses of the library
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 // }
29 // Multiple calls to DLWRAP(symbol_name, arity) with bespoke
30 // 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 the
37 // dynamic library would do, with the right function types.
39 //===----------------------------------------------------------------------===//
41 #ifndef DLWRAP_H_INCLUDED
42 #define DLWRAP_H_INCLUDED
44 #include <array>
45 #include <cstddef>
46 #include <tuple>
47 #include <type_traits>
49 // Where symbol is a function, these expand to some book keeping and an
50 // implementation of that function
51 #define DLWRAP(SYMBOL, ARITY) DLWRAP_IMPL(SYMBOL, ARITY)
52 #define DLWRAP_INTERNAL(SYMBOL, ARITY) DLWRAP_INTERNAL_IMPL(SYMBOL, ARITY)
54 // For example, given a prototype:
55 // int foo(char, double);
57 // DLWRAP(foo, 2) expands to:
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); }
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 code
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()) */ \
84 // DLWRAP_FINALIZE() implements the functions from DLWRAP_INITIALIZE
85 #define DLWRAP_FINALIZE() DLWRAP_FINALIZE_IMPL()
87 // Implementation details follow.
89 namespace dlwrap {
91 // Extract return / argument types from address of function symbol
92 template <typename F> struct trait;
93 template <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;
100 typedef R (*FunctionType)(Ts...);
103 namespace type {
104 // Book keeping is by type specialization
106 template <size_t S> struct count {
107 static constexpr size_t N = count<S - 1>::N;
110 template <> struct count<0> { static constexpr size_t N = 0; };
112 // Get a constexpr size_t ID, starts at zero
113 #define DLWRAP_ID() (dlwrap::type::count<__LINE__>::N)
115 // Increment value returned by DLWRAP_ID
116 #define DLWRAP_INC() \
117 template <> struct dlwrap::type::count<__LINE__> { \
118 static constexpr size_t N = 1 + dlwrap::type::count<__LINE__ - 1>::N; \
121 template <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; } \
126 } // namespace type
128 template <size_t N, size_t... Is>
129 constexpr std::array<const char *, N> static getSymbolArray(
130 std::index_sequence<Is...>) {
131 return {{dlwrap::type::symbol<Is>::call()...}};
134 template <size_t Requested, size_t Required> constexpr void verboseAssert() {
135 static_assert(Requested == Required, "Arity Error");
138 } // namespace dlwrap
140 #define DLWRAP_INSTANTIATE(SYM_DEF, SYM_USE, ARITY) \
141 DLWRAP_INSTANTIATE_##ARITY(SYM_DEF, SYM_USE, \
142 dlwrap::trait<decltype(&SYM_USE)>)
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]; \
152 static void **dlwrap::pointer(size_t i) { \
153 static std::array<void *, DLWRAP_ID()> dlwrap_pointers; \
154 return &dlwrap_pointers.data()[i]; \
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); \
169 }; \
172 #define DLWRAP_IMPL(SYMBOL, ARITY) \
173 DLWRAP_COMMON(SYMBOL, ARITY) \
174 DLWRAP_INSTANTIATE(SYMBOL, SYMBOL, ARITY)
176 #define DLWRAP_INTERNAL_IMPL(SYMBOL, ARITY) \
177 DLWRAP_COMMON(SYMBOL, ARITY) \
178 static DLWRAP_INSTANTIATE(dlwrap_##SYMBOL, SYMBOL, ARITY)
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); \
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); \
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); \
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); \
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); \
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); \
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); \
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); \
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); \
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); \
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); \
286 #endif