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