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