1fe6060f1SDimitry Andric //===-- wrapper_function_utils.h - Utilities for wrapper funcs --*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This file is a part of the ORC runtime support library. 10fe6060f1SDimitry Andric // 11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 12fe6060f1SDimitry Andric 13fe6060f1SDimitry Andric #ifndef ORC_RT_WRAPPER_FUNCTION_UTILS_H 14fe6060f1SDimitry Andric #define ORC_RT_WRAPPER_FUNCTION_UTILS_H 15fe6060f1SDimitry Andric 16bdd1243dSDimitry Andric #include "orc_rt/c_api.h" 17fe6060f1SDimitry Andric #include "common.h" 18fe6060f1SDimitry Andric #include "error.h" 19349cc55cSDimitry Andric #include "executor_address.h" 20fe6060f1SDimitry Andric #include "simple_packed_serialization.h" 21fe6060f1SDimitry Andric #include <type_traits> 22fe6060f1SDimitry Andric 23fe6060f1SDimitry Andric namespace __orc_rt { 24fe6060f1SDimitry Andric 25fe6060f1SDimitry Andric /// C++ wrapper function result: Same as CWrapperFunctionResult but 26fe6060f1SDimitry Andric /// auto-releases memory. 27fe6060f1SDimitry Andric class WrapperFunctionResult { 28fe6060f1SDimitry Andric public: 29fe6060f1SDimitry Andric /// Create a default WrapperFunctionResult. 3006c3fb27SDimitry Andric WrapperFunctionResult() { orc_rt_CWrapperFunctionResultInit(&R); } 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric /// Create a WrapperFunctionResult from a CWrapperFunctionResult. This 33fe6060f1SDimitry Andric /// instance takes ownership of the result object and will automatically 34fe6060f1SDimitry Andric /// call dispose on the result upon destruction. 3506c3fb27SDimitry Andric WrapperFunctionResult(orc_rt_CWrapperFunctionResult R) : R(R) {} 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric WrapperFunctionResult(const WrapperFunctionResult &) = delete; 38fe6060f1SDimitry Andric WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete; 39fe6060f1SDimitry Andric 40fe6060f1SDimitry Andric WrapperFunctionResult(WrapperFunctionResult &&Other) { 4106c3fb27SDimitry Andric orc_rt_CWrapperFunctionResultInit(&R); 42fe6060f1SDimitry Andric std::swap(R, Other.R); 43fe6060f1SDimitry Andric } 44fe6060f1SDimitry Andric 45fe6060f1SDimitry Andric WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) { 4606c3fb27SDimitry Andric orc_rt_CWrapperFunctionResult Tmp; 4706c3fb27SDimitry Andric orc_rt_CWrapperFunctionResultInit(&Tmp); 48fe6060f1SDimitry Andric std::swap(Tmp, Other.R); 49fe6060f1SDimitry Andric std::swap(R, Tmp); 50fe6060f1SDimitry Andric return *this; 51fe6060f1SDimitry Andric } 52fe6060f1SDimitry Andric 5306c3fb27SDimitry Andric ~WrapperFunctionResult() { orc_rt_DisposeCWrapperFunctionResult(&R); } 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric /// Relinquish ownership of and return the 5606c3fb27SDimitry Andric /// orc_rt_CWrapperFunctionResult. 5706c3fb27SDimitry Andric orc_rt_CWrapperFunctionResult release() { 5806c3fb27SDimitry Andric orc_rt_CWrapperFunctionResult Tmp; 5906c3fb27SDimitry Andric orc_rt_CWrapperFunctionResultInit(&Tmp); 60fe6060f1SDimitry Andric std::swap(R, Tmp); 61fe6060f1SDimitry Andric return Tmp; 62fe6060f1SDimitry Andric } 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric /// Get a pointer to the data contained in this instance. 6506c3fb27SDimitry Andric char *data() { return orc_rt_CWrapperFunctionResultData(&R); } 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric /// Returns the size of the data contained in this instance. 6806c3fb27SDimitry Andric size_t size() const { return orc_rt_CWrapperFunctionResultSize(&R); } 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric /// Returns true if this value is equivalent to a default-constructed 71fe6060f1SDimitry Andric /// WrapperFunctionResult. 7206c3fb27SDimitry Andric bool empty() const { return orc_rt_CWrapperFunctionResultEmpty(&R); } 73fe6060f1SDimitry Andric 74fe6060f1SDimitry Andric /// Create a WrapperFunctionResult with the given size and return a pointer 75fe6060f1SDimitry Andric /// to the underlying memory. 76349cc55cSDimitry Andric static WrapperFunctionResult allocate(size_t Size) { 77349cc55cSDimitry Andric WrapperFunctionResult R; 7806c3fb27SDimitry Andric R.R = orc_rt_CWrapperFunctionResultAllocate(Size); 79349cc55cSDimitry Andric return R; 80fe6060f1SDimitry Andric } 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric /// Copy from the given char range. 83fe6060f1SDimitry Andric static WrapperFunctionResult copyFrom(const char *Source, size_t Size) { 8406c3fb27SDimitry Andric return orc_rt_CreateCWrapperFunctionResultFromRange(Source, Size); 85fe6060f1SDimitry Andric } 86fe6060f1SDimitry Andric 87fe6060f1SDimitry Andric /// Copy from the given null-terminated string (includes the null-terminator). 88fe6060f1SDimitry Andric static WrapperFunctionResult copyFrom(const char *Source) { 8906c3fb27SDimitry Andric return orc_rt_CreateCWrapperFunctionResultFromString(Source); 90fe6060f1SDimitry Andric } 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric /// Copy from the given std::string (includes the null terminator). 93fe6060f1SDimitry Andric static WrapperFunctionResult copyFrom(const std::string &Source) { 94fe6060f1SDimitry Andric return copyFrom(Source.c_str()); 95fe6060f1SDimitry Andric } 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric /// Create an out-of-band error by copying the given string. 98fe6060f1SDimitry Andric static WrapperFunctionResult createOutOfBandError(const char *Msg) { 9906c3fb27SDimitry Andric return orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(Msg); 100fe6060f1SDimitry Andric } 101fe6060f1SDimitry Andric 102fe6060f1SDimitry Andric /// Create an out-of-band error by copying the given string. 103fe6060f1SDimitry Andric static WrapperFunctionResult createOutOfBandError(const std::string &Msg) { 104fe6060f1SDimitry Andric return createOutOfBandError(Msg.c_str()); 105fe6060f1SDimitry Andric } 106fe6060f1SDimitry Andric 107349cc55cSDimitry Andric template <typename SPSArgListT, typename... ArgTs> 108349cc55cSDimitry Andric static WrapperFunctionResult fromSPSArgs(const ArgTs &...Args) { 109349cc55cSDimitry Andric auto Result = allocate(SPSArgListT::size(Args...)); 110349cc55cSDimitry Andric SPSOutputBuffer OB(Result.data(), Result.size()); 111349cc55cSDimitry Andric if (!SPSArgListT::serialize(OB, Args...)) 112349cc55cSDimitry Andric return createOutOfBandError( 113349cc55cSDimitry Andric "Error serializing arguments to blob in call"); 114349cc55cSDimitry Andric return Result; 115349cc55cSDimitry Andric } 116349cc55cSDimitry Andric 117fe6060f1SDimitry Andric /// If this value is an out-of-band error then this returns the error message, 118fe6060f1SDimitry Andric /// otherwise returns nullptr. 119fe6060f1SDimitry Andric const char *getOutOfBandError() const { 12006c3fb27SDimitry Andric return orc_rt_CWrapperFunctionResultGetOutOfBandError(&R); 121fe6060f1SDimitry Andric } 122fe6060f1SDimitry Andric 123fe6060f1SDimitry Andric private: 12406c3fb27SDimitry Andric orc_rt_CWrapperFunctionResult R; 125fe6060f1SDimitry Andric }; 126fe6060f1SDimitry Andric 127fe6060f1SDimitry Andric namespace detail { 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric template <typename RetT> class WrapperFunctionHandlerCaller { 130fe6060f1SDimitry Andric public: 131fe6060f1SDimitry Andric template <typename HandlerT, typename ArgTupleT, std::size_t... I> 132fe6060f1SDimitry Andric static decltype(auto) call(HandlerT &&H, ArgTupleT &Args, 133fe6060f1SDimitry Andric std::index_sequence<I...>) { 134fe6060f1SDimitry Andric return std::forward<HandlerT>(H)(std::get<I>(Args)...); 135fe6060f1SDimitry Andric } 136fe6060f1SDimitry Andric }; 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric template <> class WrapperFunctionHandlerCaller<void> { 139fe6060f1SDimitry Andric public: 140fe6060f1SDimitry Andric template <typename HandlerT, typename ArgTupleT, std::size_t... I> 141fe6060f1SDimitry Andric static SPSEmpty call(HandlerT &&H, ArgTupleT &Args, 142fe6060f1SDimitry Andric std::index_sequence<I...>) { 143fe6060f1SDimitry Andric std::forward<HandlerT>(H)(std::get<I>(Args)...); 144fe6060f1SDimitry Andric return SPSEmpty(); 145fe6060f1SDimitry Andric } 146fe6060f1SDimitry Andric }; 147fe6060f1SDimitry Andric 148fe6060f1SDimitry Andric template <typename WrapperFunctionImplT, 149fe6060f1SDimitry Andric template <typename> class ResultSerializer, typename... SPSTagTs> 150fe6060f1SDimitry Andric class WrapperFunctionHandlerHelper 151fe6060f1SDimitry Andric : public WrapperFunctionHandlerHelper< 152fe6060f1SDimitry Andric decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()), 153fe6060f1SDimitry Andric ResultSerializer, SPSTagTs...> {}; 154fe6060f1SDimitry Andric 155fe6060f1SDimitry Andric template <typename RetT, typename... ArgTs, 156fe6060f1SDimitry Andric template <typename> class ResultSerializer, typename... SPSTagTs> 157fe6060f1SDimitry Andric class WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer, 158fe6060f1SDimitry Andric SPSTagTs...> { 159fe6060f1SDimitry Andric public: 160fe6060f1SDimitry Andric using ArgTuple = std::tuple<std::decay_t<ArgTs>...>; 161fe6060f1SDimitry Andric using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>; 162fe6060f1SDimitry Andric 163fe6060f1SDimitry Andric template <typename HandlerT> 164fe6060f1SDimitry Andric static WrapperFunctionResult apply(HandlerT &&H, const char *ArgData, 165fe6060f1SDimitry Andric size_t ArgSize) { 166fe6060f1SDimitry Andric ArgTuple Args; 167fe6060f1SDimitry Andric if (!deserialize(ArgData, ArgSize, Args, ArgIndices{})) 168fe6060f1SDimitry Andric return WrapperFunctionResult::createOutOfBandError( 169fe6060f1SDimitry Andric "Could not deserialize arguments for wrapper function call"); 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric auto HandlerResult = WrapperFunctionHandlerCaller<RetT>::call( 172fe6060f1SDimitry Andric std::forward<HandlerT>(H), Args, ArgIndices{}); 173fe6060f1SDimitry Andric 174349cc55cSDimitry Andric return ResultSerializer<decltype(HandlerResult)>::serialize( 175349cc55cSDimitry Andric std::move(HandlerResult)); 176fe6060f1SDimitry Andric } 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric private: 179fe6060f1SDimitry Andric template <std::size_t... I> 180fe6060f1SDimitry Andric static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args, 181fe6060f1SDimitry Andric std::index_sequence<I...>) { 182fe6060f1SDimitry Andric SPSInputBuffer IB(ArgData, ArgSize); 183fe6060f1SDimitry Andric return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...); 184fe6060f1SDimitry Andric } 185fe6060f1SDimitry Andric }; 186fe6060f1SDimitry Andric 187349cc55cSDimitry Andric // Map function pointers to function types. 188fe6060f1SDimitry Andric template <typename RetT, typename... ArgTs, 189fe6060f1SDimitry Andric template <typename> class ResultSerializer, typename... SPSTagTs> 190349cc55cSDimitry Andric class WrapperFunctionHandlerHelper<RetT (*)(ArgTs...), ResultSerializer, 191fe6060f1SDimitry Andric SPSTagTs...> 192fe6060f1SDimitry Andric : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer, 193fe6060f1SDimitry Andric SPSTagTs...> {}; 194fe6060f1SDimitry Andric 195fe6060f1SDimitry Andric // Map non-const member function types to function types. 196fe6060f1SDimitry Andric template <typename ClassT, typename RetT, typename... ArgTs, 197fe6060f1SDimitry Andric template <typename> class ResultSerializer, typename... SPSTagTs> 198fe6060f1SDimitry Andric class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer, 199fe6060f1SDimitry Andric SPSTagTs...> 200fe6060f1SDimitry Andric : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer, 201fe6060f1SDimitry Andric SPSTagTs...> {}; 202fe6060f1SDimitry Andric 203fe6060f1SDimitry Andric // Map const member function types to function types. 204fe6060f1SDimitry Andric template <typename ClassT, typename RetT, typename... ArgTs, 205fe6060f1SDimitry Andric template <typename> class ResultSerializer, typename... SPSTagTs> 206fe6060f1SDimitry Andric class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...) const, 207fe6060f1SDimitry Andric ResultSerializer, SPSTagTs...> 208fe6060f1SDimitry Andric : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer, 209fe6060f1SDimitry Andric SPSTagTs...> {}; 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric template <typename SPSRetTagT, typename RetT> class ResultSerializer { 212fe6060f1SDimitry Andric public: 213349cc55cSDimitry Andric static WrapperFunctionResult serialize(RetT Result) { 214349cc55cSDimitry Andric return WrapperFunctionResult::fromSPSArgs<SPSArgList<SPSRetTagT>>(Result); 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric }; 217fe6060f1SDimitry Andric 218fe6060f1SDimitry Andric template <typename SPSRetTagT> class ResultSerializer<SPSRetTagT, Error> { 219fe6060f1SDimitry Andric public: 220349cc55cSDimitry Andric static WrapperFunctionResult serialize(Error Err) { 221349cc55cSDimitry Andric return WrapperFunctionResult::fromSPSArgs<SPSArgList<SPSRetTagT>>( 222fe6060f1SDimitry Andric toSPSSerializable(std::move(Err))); 223fe6060f1SDimitry Andric } 224fe6060f1SDimitry Andric }; 225fe6060f1SDimitry Andric 226fe6060f1SDimitry Andric template <typename SPSRetTagT, typename T> 227fe6060f1SDimitry Andric class ResultSerializer<SPSRetTagT, Expected<T>> { 228fe6060f1SDimitry Andric public: 229349cc55cSDimitry Andric static WrapperFunctionResult serialize(Expected<T> E) { 230349cc55cSDimitry Andric return WrapperFunctionResult::fromSPSArgs<SPSArgList<SPSRetTagT>>( 231fe6060f1SDimitry Andric toSPSSerializable(std::move(E))); 232fe6060f1SDimitry Andric } 233fe6060f1SDimitry Andric }; 234fe6060f1SDimitry Andric 235fe6060f1SDimitry Andric template <typename SPSRetTagT, typename RetT> class ResultDeserializer { 236fe6060f1SDimitry Andric public: 237fe6060f1SDimitry Andric static void makeSafe(RetT &Result) {} 238fe6060f1SDimitry Andric 239fe6060f1SDimitry Andric static Error deserialize(RetT &Result, const char *ArgData, size_t ArgSize) { 240fe6060f1SDimitry Andric SPSInputBuffer IB(ArgData, ArgSize); 241fe6060f1SDimitry Andric if (!SPSArgList<SPSRetTagT>::deserialize(IB, Result)) 242fe6060f1SDimitry Andric return make_error<StringError>( 243fe6060f1SDimitry Andric "Error deserializing return value from blob in call"); 244fe6060f1SDimitry Andric return Error::success(); 245fe6060f1SDimitry Andric } 246fe6060f1SDimitry Andric }; 247fe6060f1SDimitry Andric 248fe6060f1SDimitry Andric template <> class ResultDeserializer<SPSError, Error> { 249fe6060f1SDimitry Andric public: 250fe6060f1SDimitry Andric static void makeSafe(Error &Err) { cantFail(std::move(Err)); } 251fe6060f1SDimitry Andric 252fe6060f1SDimitry Andric static Error deserialize(Error &Err, const char *ArgData, size_t ArgSize) { 253fe6060f1SDimitry Andric SPSInputBuffer IB(ArgData, ArgSize); 254fe6060f1SDimitry Andric SPSSerializableError BSE; 255fe6060f1SDimitry Andric if (!SPSArgList<SPSError>::deserialize(IB, BSE)) 256fe6060f1SDimitry Andric return make_error<StringError>( 257fe6060f1SDimitry Andric "Error deserializing return value from blob in call"); 258fe6060f1SDimitry Andric Err = fromSPSSerializable(std::move(BSE)); 259fe6060f1SDimitry Andric return Error::success(); 260fe6060f1SDimitry Andric } 261fe6060f1SDimitry Andric }; 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric template <typename SPSTagT, typename T> 264fe6060f1SDimitry Andric class ResultDeserializer<SPSExpected<SPSTagT>, Expected<T>> { 265fe6060f1SDimitry Andric public: 266fe6060f1SDimitry Andric static void makeSafe(Expected<T> &E) { cantFail(E.takeError()); } 267fe6060f1SDimitry Andric 268fe6060f1SDimitry Andric static Error deserialize(Expected<T> &E, const char *ArgData, 269fe6060f1SDimitry Andric size_t ArgSize) { 270fe6060f1SDimitry Andric SPSInputBuffer IB(ArgData, ArgSize); 271fe6060f1SDimitry Andric SPSSerializableExpected<T> BSE; 272fe6060f1SDimitry Andric if (!SPSArgList<SPSExpected<SPSTagT>>::deserialize(IB, BSE)) 273fe6060f1SDimitry Andric return make_error<StringError>( 274fe6060f1SDimitry Andric "Error deserializing return value from blob in call"); 275fe6060f1SDimitry Andric E = fromSPSSerializable(std::move(BSE)); 276fe6060f1SDimitry Andric return Error::success(); 277fe6060f1SDimitry Andric } 278fe6060f1SDimitry Andric }; 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric } // end namespace detail 281fe6060f1SDimitry Andric 282fe6060f1SDimitry Andric template <typename SPSSignature> class WrapperFunction; 283fe6060f1SDimitry Andric 284fe6060f1SDimitry Andric template <typename SPSRetTagT, typename... SPSTagTs> 285fe6060f1SDimitry Andric class WrapperFunction<SPSRetTagT(SPSTagTs...)> { 286fe6060f1SDimitry Andric private: 287fe6060f1SDimitry Andric template <typename RetT> 288fe6060f1SDimitry Andric using ResultSerializer = detail::ResultSerializer<SPSRetTagT, RetT>; 289fe6060f1SDimitry Andric 290fe6060f1SDimitry Andric public: 291fe6060f1SDimitry Andric template <typename RetT, typename... ArgTs> 292fe6060f1SDimitry Andric static Error call(const void *FnTag, RetT &Result, const ArgTs &...Args) { 293fe6060f1SDimitry Andric 294fe6060f1SDimitry Andric // RetT might be an Error or Expected value. Set the checked flag now: 295fe6060f1SDimitry Andric // we don't want the user to have to check the unused result if this 296fe6060f1SDimitry Andric // operation fails. 297fe6060f1SDimitry Andric detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(Result); 298fe6060f1SDimitry Andric 299*7a6dacacSDimitry Andric // Since the functions cannot be zero/unresolved on Windows, the following 300*7a6dacacSDimitry Andric // reference taking would always be non-zero, thus generating a compiler 301*7a6dacacSDimitry Andric // warning otherwise. 302*7a6dacacSDimitry Andric #if !defined(_WIN32) 303fe6060f1SDimitry Andric if (ORC_RT_UNLIKELY(!&__orc_rt_jit_dispatch_ctx)) 304fe6060f1SDimitry Andric return make_error<StringError>("__orc_rt_jit_dispatch_ctx not set"); 305fe6060f1SDimitry Andric if (ORC_RT_UNLIKELY(!&__orc_rt_jit_dispatch)) 306fe6060f1SDimitry Andric return make_error<StringError>("__orc_rt_jit_dispatch not set"); 307*7a6dacacSDimitry Andric #endif 308fe6060f1SDimitry Andric auto ArgBuffer = 309349cc55cSDimitry Andric WrapperFunctionResult::fromSPSArgs<SPSArgList<SPSTagTs...>>(Args...); 310349cc55cSDimitry Andric if (const char *ErrMsg = ArgBuffer.getOutOfBandError()) 311349cc55cSDimitry Andric return make_error<StringError>(ErrMsg); 312fe6060f1SDimitry Andric 313349cc55cSDimitry Andric WrapperFunctionResult ResultBuffer = __orc_rt_jit_dispatch( 314349cc55cSDimitry Andric &__orc_rt_jit_dispatch_ctx, FnTag, ArgBuffer.data(), ArgBuffer.size()); 315fe6060f1SDimitry Andric if (auto ErrMsg = ResultBuffer.getOutOfBandError()) 316fe6060f1SDimitry Andric return make_error<StringError>(ErrMsg); 317fe6060f1SDimitry Andric 318fe6060f1SDimitry Andric return detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize( 319fe6060f1SDimitry Andric Result, ResultBuffer.data(), ResultBuffer.size()); 320fe6060f1SDimitry Andric } 321fe6060f1SDimitry Andric 322fe6060f1SDimitry Andric template <typename HandlerT> 323fe6060f1SDimitry Andric static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize, 324fe6060f1SDimitry Andric HandlerT &&Handler) { 325fe6060f1SDimitry Andric using WFHH = 326349cc55cSDimitry Andric detail::WrapperFunctionHandlerHelper<std::remove_reference_t<HandlerT>, 327349cc55cSDimitry Andric ResultSerializer, SPSTagTs...>; 328fe6060f1SDimitry Andric return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize); 329fe6060f1SDimitry Andric } 330fe6060f1SDimitry Andric 331fe6060f1SDimitry Andric private: 332fe6060f1SDimitry Andric template <typename T> static const T &makeSerializable(const T &Value) { 333fe6060f1SDimitry Andric return Value; 334fe6060f1SDimitry Andric } 335fe6060f1SDimitry Andric 336fe6060f1SDimitry Andric static detail::SPSSerializableError makeSerializable(Error Err) { 337fe6060f1SDimitry Andric return detail::toSPSSerializable(std::move(Err)); 338fe6060f1SDimitry Andric } 339fe6060f1SDimitry Andric 340fe6060f1SDimitry Andric template <typename T> 341fe6060f1SDimitry Andric static detail::SPSSerializableExpected<T> makeSerializable(Expected<T> E) { 342fe6060f1SDimitry Andric return detail::toSPSSerializable(std::move(E)); 343fe6060f1SDimitry Andric } 344fe6060f1SDimitry Andric }; 345fe6060f1SDimitry Andric 346fe6060f1SDimitry Andric template <typename... SPSTagTs> 347fe6060f1SDimitry Andric class WrapperFunction<void(SPSTagTs...)> 348fe6060f1SDimitry Andric : private WrapperFunction<SPSEmpty(SPSTagTs...)> { 349fe6060f1SDimitry Andric public: 350fe6060f1SDimitry Andric template <typename... ArgTs> 351fe6060f1SDimitry Andric static Error call(const void *FnTag, const ArgTs &...Args) { 352fe6060f1SDimitry Andric SPSEmpty BE; 353fe6060f1SDimitry Andric return WrapperFunction<SPSEmpty(SPSTagTs...)>::call(FnTag, BE, Args...); 354fe6060f1SDimitry Andric } 355fe6060f1SDimitry Andric 356fe6060f1SDimitry Andric using WrapperFunction<SPSEmpty(SPSTagTs...)>::handle; 357fe6060f1SDimitry Andric }; 358fe6060f1SDimitry Andric 359349cc55cSDimitry Andric /// A function object that takes an ExecutorAddr as its first argument, 360349cc55cSDimitry Andric /// casts that address to a ClassT*, then calls the given method on that 361349cc55cSDimitry Andric /// pointer passing in the remaining function arguments. This utility 362349cc55cSDimitry Andric /// removes some of the boilerplate from writing wrappers for method calls. 363349cc55cSDimitry Andric /// 364349cc55cSDimitry Andric /// @code{.cpp} 365349cc55cSDimitry Andric /// class MyClass { 366349cc55cSDimitry Andric /// public: 367349cc55cSDimitry Andric /// void myMethod(uint32_t, bool) { ... } 368349cc55cSDimitry Andric /// }; 369349cc55cSDimitry Andric /// 370349cc55cSDimitry Andric /// // SPS Method signature -- note MyClass object address as first argument. 371349cc55cSDimitry Andric /// using SPSMyMethodWrapperSignature = 372349cc55cSDimitry Andric /// SPSTuple<SPSExecutorAddr, uint32_t, bool>; 373349cc55cSDimitry Andric /// 374349cc55cSDimitry Andric /// WrapperFunctionResult 375349cc55cSDimitry Andric /// myMethodCallWrapper(const char *ArgData, size_t ArgSize) { 376349cc55cSDimitry Andric /// return WrapperFunction<SPSMyMethodWrapperSignature>::handle( 377349cc55cSDimitry Andric /// ArgData, ArgSize, makeMethodWrapperHandler(&MyClass::myMethod)); 378349cc55cSDimitry Andric /// } 379349cc55cSDimitry Andric /// @endcode 380349cc55cSDimitry Andric /// 381349cc55cSDimitry Andric template <typename RetT, typename ClassT, typename... ArgTs> 382349cc55cSDimitry Andric class MethodWrapperHandler { 383349cc55cSDimitry Andric public: 384349cc55cSDimitry Andric using MethodT = RetT (ClassT::*)(ArgTs...); 385349cc55cSDimitry Andric MethodWrapperHandler(MethodT M) : M(M) {} 386349cc55cSDimitry Andric RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args) { 387349cc55cSDimitry Andric return (ObjAddr.toPtr<ClassT *>()->*M)(std::forward<ArgTs>(Args)...); 388349cc55cSDimitry Andric } 389349cc55cSDimitry Andric 390349cc55cSDimitry Andric private: 391349cc55cSDimitry Andric MethodT M; 392349cc55cSDimitry Andric }; 393349cc55cSDimitry Andric 394349cc55cSDimitry Andric /// Create a MethodWrapperHandler object from the given method pointer. 395349cc55cSDimitry Andric template <typename RetT, typename ClassT, typename... ArgTs> 396349cc55cSDimitry Andric MethodWrapperHandler<RetT, ClassT, ArgTs...> 397349cc55cSDimitry Andric makeMethodWrapperHandler(RetT (ClassT::*Method)(ArgTs...)) { 398349cc55cSDimitry Andric return MethodWrapperHandler<RetT, ClassT, ArgTs...>(Method); 399349cc55cSDimitry Andric } 400349cc55cSDimitry Andric 401349cc55cSDimitry Andric /// Represents a call to a wrapper function. 40204eeddc0SDimitry Andric class WrapperFunctionCall { 40304eeddc0SDimitry Andric public: 40404eeddc0SDimitry Andric // FIXME: Switch to a SmallVector<char, 24> once ORC runtime has a 40504eeddc0SDimitry Andric // smallvector. 40604eeddc0SDimitry Andric using ArgDataBufferType = std::vector<char>; 40704eeddc0SDimitry Andric 40804eeddc0SDimitry Andric /// Create a WrapperFunctionCall using the given SPS serializer to serialize 40904eeddc0SDimitry Andric /// the arguments. 41004eeddc0SDimitry Andric template <typename SPSSerializer, typename... ArgTs> 41104eeddc0SDimitry Andric static Expected<WrapperFunctionCall> Create(ExecutorAddr FnAddr, 41204eeddc0SDimitry Andric const ArgTs &...Args) { 41304eeddc0SDimitry Andric ArgDataBufferType ArgData; 41404eeddc0SDimitry Andric ArgData.resize(SPSSerializer::size(Args...)); 415bdd1243dSDimitry Andric SPSOutputBuffer OB(ArgData.empty() ? nullptr : ArgData.data(), 416bdd1243dSDimitry Andric ArgData.size()); 41704eeddc0SDimitry Andric if (SPSSerializer::serialize(OB, Args...)) 41804eeddc0SDimitry Andric return WrapperFunctionCall(FnAddr, std::move(ArgData)); 41904eeddc0SDimitry Andric return make_error<StringError>("Cannot serialize arguments for " 42004eeddc0SDimitry Andric "AllocActionCall"); 42104eeddc0SDimitry Andric } 422349cc55cSDimitry Andric 423349cc55cSDimitry Andric WrapperFunctionCall() = default; 424349cc55cSDimitry Andric 42504eeddc0SDimitry Andric /// Create a WrapperFunctionCall from a target function and arg buffer. 42604eeddc0SDimitry Andric WrapperFunctionCall(ExecutorAddr FnAddr, ArgDataBufferType ArgData) 42704eeddc0SDimitry Andric : FnAddr(FnAddr), ArgData(std::move(ArgData)) {} 42804eeddc0SDimitry Andric 42904eeddc0SDimitry Andric /// Returns the address to be called. 43004eeddc0SDimitry Andric const ExecutorAddr &getCallee() const { return FnAddr; } 43104eeddc0SDimitry Andric 43204eeddc0SDimitry Andric /// Returns the argument data. 43304eeddc0SDimitry Andric const ArgDataBufferType &getArgData() const { return ArgData; } 43404eeddc0SDimitry Andric 43504eeddc0SDimitry Andric /// WrapperFunctionCalls convert to true if the callee is non-null. 43604eeddc0SDimitry Andric explicit operator bool() const { return !!FnAddr; } 43704eeddc0SDimitry Andric 43804eeddc0SDimitry Andric /// Run call returning raw WrapperFunctionResult. 43904eeddc0SDimitry Andric WrapperFunctionResult run() const { 44004eeddc0SDimitry Andric using FnTy = 44106c3fb27SDimitry Andric orc_rt_CWrapperFunctionResult(const char *ArgData, size_t ArgSize); 44204eeddc0SDimitry Andric return WrapperFunctionResult( 44304eeddc0SDimitry Andric FnAddr.toPtr<FnTy *>()(ArgData.data(), ArgData.size())); 444349cc55cSDimitry Andric } 445349cc55cSDimitry Andric 446349cc55cSDimitry Andric /// Run call and deserialize result using SPS. 44704eeddc0SDimitry Andric template <typename SPSRetT, typename RetT> 44804eeddc0SDimitry Andric std::enable_if_t<!std::is_same<SPSRetT, void>::value, Error> 44904eeddc0SDimitry Andric runWithSPSRet(RetT &RetVal) const { 450349cc55cSDimitry Andric auto WFR = run(); 451349cc55cSDimitry Andric if (const char *ErrMsg = WFR.getOutOfBandError()) 452349cc55cSDimitry Andric return make_error<StringError>(ErrMsg); 453349cc55cSDimitry Andric SPSInputBuffer IB(WFR.data(), WFR.size()); 454349cc55cSDimitry Andric if (!SPSSerializationTraits<SPSRetT, RetT>::deserialize(IB, RetVal)) 455349cc55cSDimitry Andric return make_error<StringError>("Could not deserialize result from " 456349cc55cSDimitry Andric "serialized wrapper function call"); 457349cc55cSDimitry Andric return Error::success(); 458349cc55cSDimitry Andric } 459349cc55cSDimitry Andric 460349cc55cSDimitry Andric /// Overload for SPS functions returning void. 46104eeddc0SDimitry Andric template <typename SPSRetT> 46204eeddc0SDimitry Andric std::enable_if_t<std::is_same<SPSRetT, void>::value, Error> 46304eeddc0SDimitry Andric runWithSPSRet() const { 464349cc55cSDimitry Andric SPSEmpty E; 465349cc55cSDimitry Andric return runWithSPSRet<SPSEmpty>(E); 466349cc55cSDimitry Andric } 46704eeddc0SDimitry Andric 46804eeddc0SDimitry Andric /// Run call and deserialize an SPSError result. SPSError returns and 46904eeddc0SDimitry Andric /// deserialization failures are merged into the returned error. 47004eeddc0SDimitry Andric Error runWithSPSRetErrorMerged() const { 47104eeddc0SDimitry Andric detail::SPSSerializableError RetErr; 47204eeddc0SDimitry Andric if (auto Err = runWithSPSRet<SPSError>(RetErr)) 47304eeddc0SDimitry Andric return Err; 47404eeddc0SDimitry Andric return detail::fromSPSSerializable(std::move(RetErr)); 47504eeddc0SDimitry Andric } 47604eeddc0SDimitry Andric 47704eeddc0SDimitry Andric private: 47804eeddc0SDimitry Andric ExecutorAddr FnAddr; 47904eeddc0SDimitry Andric std::vector<char> ArgData; 480349cc55cSDimitry Andric }; 481349cc55cSDimitry Andric 48204eeddc0SDimitry Andric using SPSWrapperFunctionCall = SPSTuple<SPSExecutorAddr, SPSSequence<char>>; 483349cc55cSDimitry Andric 484349cc55cSDimitry Andric template <> 485349cc55cSDimitry Andric class SPSSerializationTraits<SPSWrapperFunctionCall, WrapperFunctionCall> { 486349cc55cSDimitry Andric public: 487349cc55cSDimitry Andric static size_t size(const WrapperFunctionCall &WFC) { 48804eeddc0SDimitry Andric return SPSArgList<SPSExecutorAddr, SPSSequence<char>>::size( 48904eeddc0SDimitry Andric WFC.getCallee(), WFC.getArgData()); 490349cc55cSDimitry Andric } 491349cc55cSDimitry Andric 492349cc55cSDimitry Andric static bool serialize(SPSOutputBuffer &OB, const WrapperFunctionCall &WFC) { 49304eeddc0SDimitry Andric return SPSArgList<SPSExecutorAddr, SPSSequence<char>>::serialize( 49404eeddc0SDimitry Andric OB, WFC.getCallee(), WFC.getArgData()); 495349cc55cSDimitry Andric } 496349cc55cSDimitry Andric 497349cc55cSDimitry Andric static bool deserialize(SPSInputBuffer &IB, WrapperFunctionCall &WFC) { 49804eeddc0SDimitry Andric ExecutorAddr FnAddr; 49904eeddc0SDimitry Andric WrapperFunctionCall::ArgDataBufferType ArgData; 50004eeddc0SDimitry Andric if (!SPSWrapperFunctionCall::AsArgList::deserialize(IB, FnAddr, ArgData)) 50104eeddc0SDimitry Andric return false; 50204eeddc0SDimitry Andric WFC = WrapperFunctionCall(FnAddr, std::move(ArgData)); 50304eeddc0SDimitry Andric return true; 504349cc55cSDimitry Andric } 505349cc55cSDimitry Andric }; 506349cc55cSDimitry Andric 507fe6060f1SDimitry Andric } // end namespace __orc_rt 508fe6060f1SDimitry Andric 509fe6060f1SDimitry Andric #endif // ORC_RT_WRAPPER_FUNCTION_UTILS_H 510