• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef BERBERIS_GUEST_ABI_FUNCTION_WRAPPERS_H_
18 #define BERBERIS_GUEST_ABI_FUNCTION_WRAPPERS_H_
19 
20 #include <utility>
21 
22 #include <jni.h>
23 
24 #include "berberis/guest_abi/guest_abi.h"  // IWYU pragma: export.
25 #include "berberis/guest_abi/guest_function_wrapper.h"
26 #include "berberis/guest_abi/guest_params.h"
27 #include "berberis/guest_abi/guest_type.h"
28 #include "berberis/runtime_primitives/host_code.h"
29 #include "berberis/runtime_primitives/host_function_wrapper_impl.h"
30 
31 namespace berberis {
32 
33 extern JNIEnv* ToHostJNIEnv(GuestType<JNIEnv*> guest_jni_env);
34 
35 // Setup and run trampoline function.
36 template <typename Func,
37           GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi>
38 class TrampolineFuncGenerator;
39 
40 template <typename Arg,
41           GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi>
42 struct GetGuestArgumentClass {
43  public:
44   static_assert(!std::is_pointer_v<Arg> || !std::is_function_v<std::remove_pointer_t<Arg>>);
45   static_assert(!std::is_pointer_v<Arg> || !std::is_same_v<std::remove_pointer_t<Arg>, JNIEnv>);
operatorGetGuestArgumentClass46   decltype(auto) operator()(Arg arg) const { return arg; }
47 };
48 
49 template <typename Res,
50           typename... Args,
51           GuestAbi::CallingConventionsVariant kCallingConventionsVariant>
52 struct GetGuestArgumentClass<Res (*)(Args...), kCallingConventionsVariant> {
53  public:
54   decltype(auto) operator()(GuestType<Res (*)(Args...)> func) const {
55     return WrapGuestFunction(func, "AutoGeneratedWrapper");
56   }
57 };
58 
59 template <GuestAbi::CallingConventionsVariant kCallingConventionsVariant>
60 struct GetGuestArgumentClass<JNIEnv*, kCallingConventionsVariant> {
61  public:
62   decltype(auto) operator()(GuestType<JNIEnv*> guest_jni_env) const {
63     return ToHostJNIEnv(guest_jni_env);
64   }
65 };
66 
67 template <typename Arg,
68           GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi>
69 inline constexpr auto GetGuestArgument = GetGuestArgumentClass<Arg, kCallingConventionsVariant>{};
70 
71 template <typename Arg,
72           GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi>
73 struct GetGuestResultClass {
74  public:
75   static_assert(!std::is_pointer_v<Arg> || !std::is_function_v<std::remove_pointer_t<Arg>>);
76   decltype(auto) operator()(Arg arg) const { return arg; }
77 };
78 
79 template <typename Res,
80           typename... Args,
81           GuestAbi::CallingConventionsVariant kCallingConventionsVariant>
82 struct GetGuestResultClass<Res (*)(Args...), kCallingConventionsVariant> {
83  public:
84   decltype(auto) operator()(Res (*func)(Args...)) const {
85     WrapHostFunctionImpl(reinterpret_cast<HostCode>(func),
86                          TrampolineFuncGenerator<Res(Args...), kCallingConventionsVariant>::Func,
87                          "AutoGeneratedWrapper");
88     return func;
89   }
90 };
91 
92 template <typename Arg,
93           GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi>
94 inline constexpr auto GetGuestResult = GetGuestResultClass<Arg, kCallingConventionsVariant>{};
95 
96 template <typename Res,
97           typename... Args,
98           GuestAbi::CallingConventionsVariant kCallingConventionsVariant>
99 class TrampolineFuncGenerator<Res(Args...), kCallingConventionsVariant> {
100  public:
101   static void Func(HostCode callee, ThreadState* state) {
102     using Func = Res (*)(Args...);
103     auto func = reinterpret_cast<Func>(const_cast<void*>(callee));
104     FuncImpl(func, state, std::make_index_sequence<sizeof...(Args)>());
105   }
106 
107  private:
108   template <typename Func, typename std::size_t... I>
109   static void FuncImpl(Func func, ThreadState* state, std::index_sequence<I...>) {
110     GuestParamsValues<Func, kCallingConventionsVariant> params(state);
111     if constexpr (std::is_same_v<Res, void>) {
112       func(GetGuestArgument<std::tuple_element_t<I, std::tuple<Args...>>,
113                             kCallingConventionsVariant>(params.template get<I>())...);
114     } else {
115       auto&& [ret] = GuestReturnReference<Func, kCallingConventionsVariant>(state);
116       ret = GetGuestResult<Res, kCallingConventionsVariant>(
117           func(GetGuestArgument<std::tuple_element_t<I, std::tuple<Args...>>,
118                                 kCallingConventionsVariant>(params.template get<I>())...));
119     }
120   }
121 };
122 
123 // Pointer to function.
124 template <typename Res,
125           typename... Args,
126           GuestAbi::CallingConventionsVariant kCallingConventionsVariant>
127 class TrampolineFuncGenerator<Res (*)(Args...), kCallingConventionsVariant>
128     : public TrampolineFuncGenerator<Res(Args...), kCallingConventionsVariant> {};
129 
130 // Syntax sugar.
131 template <typename Func,
132           GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi>
133 constexpr TrampolineFunc GetTrampolineFunc() {
134   return TrampolineFuncGenerator<Func, kCallingConventionsVariant>::Func;
135 }
136 
137 template <GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi,
138           typename Func>
139 inline void WrapHostFunction(Func func, const char* name) {
140   WrapHostFunctionImpl(reinterpret_cast<HostCode>(func),
141                        GetTrampolineFunc<Func, kCallingConventionsVariant>(),
142                        name);
143 }
144 
145 }  // namespace berberis
146 
147 #endif  // BERBERIS_GUEST_ABI_FUNCTION_WRAPPERS_H_
148