123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- WrapperFunctionUtils.h - Utilities for wrapper functions -*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // A buffer for serialized results.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
- #define LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
- #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
- #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
- #include "llvm/Support/Error.h"
- #include <type_traits>
- namespace llvm {
- namespace orc {
- namespace shared {
- // Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
- union CWrapperFunctionResultDataUnion {
- char *ValuePtr;
- char Value[sizeof(ValuePtr)];
- };
- // Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
- typedef struct {
- CWrapperFunctionResultDataUnion Data;
- size_t Size;
- } CWrapperFunctionResult;
- /// C++ wrapper function result: Same as CWrapperFunctionResult but
- /// auto-releases memory.
- class WrapperFunctionResult {
- public:
- /// Create a default WrapperFunctionResult.
- WrapperFunctionResult() { init(R); }
- /// Create a WrapperFunctionResult by taking ownership of a
- /// CWrapperFunctionResult.
- ///
- /// Warning: This should only be used by clients writing wrapper-function
- /// caller utilities (like TargetProcessControl).
- WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {
- // Reset R.
- init(R);
- }
- WrapperFunctionResult(const WrapperFunctionResult &) = delete;
- WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
- WrapperFunctionResult(WrapperFunctionResult &&Other) {
- init(R);
- std::swap(R, Other.R);
- }
- WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
- WrapperFunctionResult Tmp(std::move(Other));
- std::swap(R, Tmp.R);
- return *this;
- }
- ~WrapperFunctionResult() {
- if ((R.Size > sizeof(R.Data.Value)) ||
- (R.Size == 0 && R.Data.ValuePtr != nullptr))
- free(R.Data.ValuePtr);
- }
- /// Release ownership of the contained CWrapperFunctionResult.
- /// Warning: Do not use -- this method will be removed in the future. It only
- /// exists to temporarily support some code that will eventually be moved to
- /// the ORC runtime.
- CWrapperFunctionResult release() {
- CWrapperFunctionResult Tmp;
- init(Tmp);
- std::swap(R, Tmp);
- return Tmp;
- }
- /// Get a pointer to the data contained in this instance.
- char *data() {
- assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
- "Cannot get data for out-of-band error value");
- return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
- }
- /// Get a const pointer to the data contained in this instance.
- const char *data() const {
- assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
- "Cannot get data for out-of-band error value");
- return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
- }
- /// Returns the size of the data contained in this instance.
- size_t size() const {
- assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
- "Cannot get data for out-of-band error value");
- return R.Size;
- }
- /// Returns true if this value is equivalent to a default-constructed
- /// WrapperFunctionResult.
- bool empty() const { return R.Size == 0 && R.Data.ValuePtr == nullptr; }
- /// Create a WrapperFunctionResult with the given size and return a pointer
- /// to the underlying memory.
- static WrapperFunctionResult allocate(size_t Size) {
- // Reset.
- WrapperFunctionResult WFR;
- WFR.R.Size = Size;
- if (WFR.R.Size > sizeof(WFR.R.Data.Value))
- WFR.R.Data.ValuePtr = (char *)malloc(WFR.R.Size);
- return WFR;
- }
- /// Copy from the given char range.
- static WrapperFunctionResult copyFrom(const char *Source, size_t Size) {
- auto WFR = allocate(Size);
- memcpy(WFR.data(), Source, Size);
- return WFR;
- }
- /// Copy from the given null-terminated string (includes the null-terminator).
- static WrapperFunctionResult copyFrom(const char *Source) {
- return copyFrom(Source, strlen(Source) + 1);
- }
- /// Copy from the given std::string (includes the null terminator).
- static WrapperFunctionResult copyFrom(const std::string &Source) {
- return copyFrom(Source.c_str());
- }
- /// Create an out-of-band error by copying the given string.
- static WrapperFunctionResult createOutOfBandError(const char *Msg) {
- // Reset.
- WrapperFunctionResult WFR;
- char *Tmp = (char *)malloc(strlen(Msg) + 1);
- strcpy(Tmp, Msg);
- WFR.R.Data.ValuePtr = Tmp;
- return WFR;
- }
- /// Create an out-of-band error by copying the given string.
- static WrapperFunctionResult createOutOfBandError(const std::string &Msg) {
- return createOutOfBandError(Msg.c_str());
- }
- /// If this value is an out-of-band error then this returns the error message,
- /// otherwise returns nullptr.
- const char *getOutOfBandError() const {
- return R.Size == 0 ? R.Data.ValuePtr : nullptr;
- }
- private:
- static void init(CWrapperFunctionResult &R) {
- R.Data.ValuePtr = nullptr;
- R.Size = 0;
- }
- CWrapperFunctionResult R;
- };
- namespace detail {
- template <typename SPSArgListT, typename... ArgTs>
- WrapperFunctionResult
- serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args) {
- auto Result = WrapperFunctionResult::allocate(SPSArgListT::size(Args...));
- SPSOutputBuffer OB(Result.data(), Result.size());
- if (!SPSArgListT::serialize(OB, Args...))
- return WrapperFunctionResult::createOutOfBandError(
- "Error serializing arguments to blob in call");
- return Result;
- }
- template <typename RetT> class WrapperFunctionHandlerCaller {
- public:
- template <typename HandlerT, typename ArgTupleT, std::size_t... I>
- static decltype(auto) call(HandlerT &&H, ArgTupleT &Args,
- std::index_sequence<I...>) {
- return std::forward<HandlerT>(H)(std::get<I>(Args)...);
- }
- };
- template <> class WrapperFunctionHandlerCaller<void> {
- public:
- template <typename HandlerT, typename ArgTupleT, std::size_t... I>
- static SPSEmpty call(HandlerT &&H, ArgTupleT &Args,
- std::index_sequence<I...>) {
- std::forward<HandlerT>(H)(std::get<I>(Args)...);
- return SPSEmpty();
- }
- };
- template <typename WrapperFunctionImplT,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionHandlerHelper
- : public WrapperFunctionHandlerHelper<
- decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
- ResultSerializer, SPSTagTs...> {};
- template <typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {
- public:
- using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
- using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
- template <typename HandlerT>
- static WrapperFunctionResult apply(HandlerT &&H, const char *ArgData,
- size_t ArgSize) {
- ArgTuple Args;
- if (!deserialize(ArgData, ArgSize, Args, ArgIndices{}))
- return WrapperFunctionResult::createOutOfBandError(
- "Could not deserialize arguments for wrapper function call");
- auto HandlerResult = WrapperFunctionHandlerCaller<RetT>::call(
- std::forward<HandlerT>(H), Args, ArgIndices{});
- return ResultSerializer<decltype(HandlerResult)>::serialize(
- std::move(HandlerResult));
- }
- private:
- template <std::size_t... I>
- static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
- std::index_sequence<I...>) {
- SPSInputBuffer IB(ArgData, ArgSize);
- return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
- }
- };
- // Map function pointers to function types.
- template <typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
- SPSTagTs...>
- : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {};
- // Map non-const member function types to function types.
- template <typename ClassT, typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer,
- SPSTagTs...>
- : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {};
- // Map const member function types to function types.
- template <typename ClassT, typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
- ResultSerializer, SPSTagTs...>
- : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {};
- template <typename WrapperFunctionImplT,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionAsyncHandlerHelper
- : public WrapperFunctionAsyncHandlerHelper<
- decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
- ResultSerializer, SPSTagTs...> {};
- template <typename RetT, typename SendResultT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionAsyncHandlerHelper<RetT(SendResultT, ArgTs...),
- ResultSerializer, SPSTagTs...> {
- public:
- using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
- using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
- template <typename HandlerT, typename SendWrapperFunctionResultT>
- static void applyAsync(HandlerT &&H,
- SendWrapperFunctionResultT &&SendWrapperFunctionResult,
- const char *ArgData, size_t ArgSize) {
- ArgTuple Args;
- if (!deserialize(ArgData, ArgSize, Args, ArgIndices{})) {
- SendWrapperFunctionResult(WrapperFunctionResult::createOutOfBandError(
- "Could not deserialize arguments for wrapper function call"));
- return;
- }
- auto SendResult =
- [SendWFR = std::move(SendWrapperFunctionResult)](auto Result) mutable {
- using ResultT = decltype(Result);
- SendWFR(ResultSerializer<ResultT>::serialize(std::move(Result)));
- };
- callAsync(std::forward<HandlerT>(H), std::move(SendResult), std::move(Args),
- ArgIndices{});
- }
- private:
- template <std::size_t... I>
- static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
- std::index_sequence<I...>) {
- SPSInputBuffer IB(ArgData, ArgSize);
- return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
- }
- template <typename HandlerT, typename SerializeAndSendResultT,
- typename ArgTupleT, std::size_t... I>
- static void callAsync(HandlerT &&H,
- SerializeAndSendResultT &&SerializeAndSendResult,
- ArgTupleT Args, std::index_sequence<I...>) {
- (void)Args; // Silence a buggy GCC warning.
- return std::forward<HandlerT>(H)(std::move(SerializeAndSendResult),
- std::move(std::get<I>(Args))...);
- }
- };
- // Map function pointers to function types.
- template <typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionAsyncHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
- SPSTagTs...>
- : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {};
- // Map non-const member function types to function types.
- template <typename ClassT, typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...),
- ResultSerializer, SPSTagTs...>
- : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {};
- // Map const member function types to function types.
- template <typename ClassT, typename RetT, typename... ArgTs,
- template <typename> class ResultSerializer, typename... SPSTagTs>
- class WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
- ResultSerializer, SPSTagTs...>
- : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
- SPSTagTs...> {};
- template <typename SPSRetTagT, typename RetT> class ResultSerializer {
- public:
- static WrapperFunctionResult serialize(RetT Result) {
- return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
- Result);
- }
- };
- template <typename SPSRetTagT> class ResultSerializer<SPSRetTagT, Error> {
- public:
- static WrapperFunctionResult serialize(Error Err) {
- return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
- toSPSSerializable(std::move(Err)));
- }
- };
- template <typename SPSRetTagT>
- class ResultSerializer<SPSRetTagT, ErrorSuccess> {
- public:
- static WrapperFunctionResult serialize(ErrorSuccess Err) {
- return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
- toSPSSerializable(std::move(Err)));
- }
- };
- template <typename SPSRetTagT, typename T>
- class ResultSerializer<SPSRetTagT, Expected<T>> {
- public:
- static WrapperFunctionResult serialize(Expected<T> E) {
- return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
- toSPSSerializable(std::move(E)));
- }
- };
- template <typename SPSRetTagT, typename RetT> class ResultDeserializer {
- public:
- static RetT makeValue() { return RetT(); }
- static void makeSafe(RetT &Result) {}
- static Error deserialize(RetT &Result, const char *ArgData, size_t ArgSize) {
- SPSInputBuffer IB(ArgData, ArgSize);
- if (!SPSArgList<SPSRetTagT>::deserialize(IB, Result))
- return make_error<StringError>(
- "Error deserializing return value from blob in call",
- inconvertibleErrorCode());
- return Error::success();
- }
- };
- template <> class ResultDeserializer<SPSError, Error> {
- public:
- static Error makeValue() { return Error::success(); }
- static void makeSafe(Error &Err) { cantFail(std::move(Err)); }
- static Error deserialize(Error &Err, const char *ArgData, size_t ArgSize) {
- SPSInputBuffer IB(ArgData, ArgSize);
- SPSSerializableError BSE;
- if (!SPSArgList<SPSError>::deserialize(IB, BSE))
- return make_error<StringError>(
- "Error deserializing return value from blob in call",
- inconvertibleErrorCode());
- Err = fromSPSSerializable(std::move(BSE));
- return Error::success();
- }
- };
- template <typename SPSTagT, typename T>
- class ResultDeserializer<SPSExpected<SPSTagT>, Expected<T>> {
- public:
- static Expected<T> makeValue() { return T(); }
- static void makeSafe(Expected<T> &E) { cantFail(E.takeError()); }
- static Error deserialize(Expected<T> &E, const char *ArgData,
- size_t ArgSize) {
- SPSInputBuffer IB(ArgData, ArgSize);
- SPSSerializableExpected<T> BSE;
- if (!SPSArgList<SPSExpected<SPSTagT>>::deserialize(IB, BSE))
- return make_error<StringError>(
- "Error deserializing return value from blob in call",
- inconvertibleErrorCode());
- E = fromSPSSerializable(std::move(BSE));
- return Error::success();
- }
- };
- template <typename SPSRetTagT, typename RetT> class AsyncCallResultHelper {
- // Did you forget to use Error / Expected in your handler?
- };
- } // end namespace detail
- template <typename SPSSignature> class WrapperFunction;
- template <typename SPSRetTagT, typename... SPSTagTs>
- class WrapperFunction<SPSRetTagT(SPSTagTs...)> {
- private:
- template <typename RetT>
- using ResultSerializer = detail::ResultSerializer<SPSRetTagT, RetT>;
- public:
- /// Call a wrapper function. Caller should be callable as
- /// WrapperFunctionResult Fn(const char *ArgData, size_t ArgSize);
- template <typename CallerFn, typename RetT, typename... ArgTs>
- static Error call(const CallerFn &Caller, RetT &Result,
- const ArgTs &...Args) {
- // RetT might be an Error or Expected value. Set the checked flag now:
- // we don't want the user to have to check the unused result if this
- // operation fails.
- detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(Result);
- auto ArgBuffer =
- detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
- Args...);
- if (const char *ErrMsg = ArgBuffer.getOutOfBandError())
- return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
- WrapperFunctionResult ResultBuffer =
- Caller(ArgBuffer.data(), ArgBuffer.size());
- if (auto ErrMsg = ResultBuffer.getOutOfBandError())
- return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
- return detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
- Result, ResultBuffer.data(), ResultBuffer.size());
- }
- /// Call an async wrapper function.
- /// Caller should be callable as
- /// void Fn(unique_function<void(WrapperFunctionResult)> SendResult,
- /// WrapperFunctionResult ArgBuffer);
- template <typename AsyncCallerFn, typename SendDeserializedResultFn,
- typename... ArgTs>
- static void callAsync(AsyncCallerFn &&Caller,
- SendDeserializedResultFn &&SendDeserializedResult,
- const ArgTs &...Args) {
- using RetT = typename std::tuple_element<
- 1, typename detail::WrapperFunctionHandlerHelper<
- std::remove_reference_t<SendDeserializedResultFn>,
- ResultSerializer, SPSRetTagT>::ArgTuple>::type;
- auto ArgBuffer =
- detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
- Args...);
- if (auto *ErrMsg = ArgBuffer.getOutOfBandError()) {
- SendDeserializedResult(
- make_error<StringError>(ErrMsg, inconvertibleErrorCode()),
- detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue());
- return;
- }
- auto SendSerializedResult = [SDR = std::move(SendDeserializedResult)](
- WrapperFunctionResult R) mutable {
- RetT RetVal = detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue();
- detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(RetVal);
- if (auto *ErrMsg = R.getOutOfBandError()) {
- SDR(make_error<StringError>(ErrMsg, inconvertibleErrorCode()),
- std::move(RetVal));
- return;
- }
- SPSInputBuffer IB(R.data(), R.size());
- if (auto Err = detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
- RetVal, R.data(), R.size()))
- SDR(std::move(Err), std::move(RetVal));
- SDR(Error::success(), std::move(RetVal));
- };
- Caller(std::move(SendSerializedResult), ArgBuffer.data(), ArgBuffer.size());
- }
- /// Handle a call to a wrapper function.
- template <typename HandlerT>
- static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize,
- HandlerT &&Handler) {
- using WFHH =
- detail::WrapperFunctionHandlerHelper<std::remove_reference_t<HandlerT>,
- ResultSerializer, SPSTagTs...>;
- return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize);
- }
- /// Handle a call to an async wrapper function.
- template <typename HandlerT, typename SendResultT>
- static void handleAsync(const char *ArgData, size_t ArgSize,
- HandlerT &&Handler, SendResultT &&SendResult) {
- using WFAHH = detail::WrapperFunctionAsyncHandlerHelper<
- std::remove_reference_t<HandlerT>, ResultSerializer, SPSTagTs...>;
- WFAHH::applyAsync(std::forward<HandlerT>(Handler),
- std::forward<SendResultT>(SendResult), ArgData, ArgSize);
- }
- private:
- template <typename T> static const T &makeSerializable(const T &Value) {
- return Value;
- }
- static detail::SPSSerializableError makeSerializable(Error Err) {
- return detail::toSPSSerializable(std::move(Err));
- }
- template <typename T>
- static detail::SPSSerializableExpected<T> makeSerializable(Expected<T> E) {
- return detail::toSPSSerializable(std::move(E));
- }
- };
- template <typename... SPSTagTs>
- class WrapperFunction<void(SPSTagTs...)>
- : private WrapperFunction<SPSEmpty(SPSTagTs...)> {
- public:
- template <typename CallerFn, typename... ArgTs>
- static Error call(const CallerFn &Caller, const ArgTs &...Args) {
- SPSEmpty BE;
- return WrapperFunction<SPSEmpty(SPSTagTs...)>::call(Caller, BE, Args...);
- }
- template <typename AsyncCallerFn, typename SendDeserializedResultFn,
- typename... ArgTs>
- static void callAsync(AsyncCallerFn &&Caller,
- SendDeserializedResultFn &&SendDeserializedResult,
- const ArgTs &...Args) {
- WrapperFunction<SPSEmpty(SPSTagTs...)>::callAsync(
- std::forward<AsyncCallerFn>(Caller),
- [SDR = std::move(SendDeserializedResult)](Error SerializeErr,
- SPSEmpty E) mutable {
- SDR(std::move(SerializeErr));
- },
- Args...);
- }
- using WrapperFunction<SPSEmpty(SPSTagTs...)>::handle;
- using WrapperFunction<SPSEmpty(SPSTagTs...)>::handleAsync;
- };
- /// A function object that takes an ExecutorAddr as its first argument,
- /// casts that address to a ClassT*, then calls the given method on that
- /// pointer passing in the remaining function arguments. This utility
- /// removes some of the boilerplate from writing wrappers for method calls.
- ///
- /// @code{.cpp}
- /// class MyClass {
- /// public:
- /// void myMethod(uint32_t, bool) { ... }
- /// };
- ///
- /// // SPS Method signature -- note MyClass object address as first argument.
- /// using SPSMyMethodWrapperSignature =
- /// SPSTuple<SPSExecutorAddr, uint32_t, bool>;
- ///
- /// WrapperFunctionResult
- /// myMethodCallWrapper(const char *ArgData, size_t ArgSize) {
- /// return WrapperFunction<SPSMyMethodWrapperSignature>::handle(
- /// ArgData, ArgSize, makeMethodWrapperHandler(&MyClass::myMethod));
- /// }
- /// @endcode
- ///
- template <typename RetT, typename ClassT, typename... ArgTs>
- class MethodWrapperHandler {
- public:
- using MethodT = RetT (ClassT::*)(ArgTs...);
- MethodWrapperHandler(MethodT M) : M(M) {}
- RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args) {
- return (ObjAddr.toPtr<ClassT*>()->*M)(std::forward<ArgTs>(Args)...);
- }
- private:
- MethodT M;
- };
- /// Create a MethodWrapperHandler object from the given method pointer.
- template <typename RetT, typename ClassT, typename... ArgTs>
- MethodWrapperHandler<RetT, ClassT, ArgTs...>
- makeMethodWrapperHandler(RetT (ClassT::*Method)(ArgTs...)) {
- return MethodWrapperHandler<RetT, ClassT, ArgTs...>(Method);
- }
- /// Represents a serialized wrapper function call.
- /// Serializing calls themselves allows us to batch them: We can make one
- /// "run-wrapper-functions" utility and send it a list of calls to run.
- ///
- /// The motivating use-case for this API is JITLink allocation actions, where
- /// we want to run multiple functions to finalize linked memory without having
- /// to make separate IPC calls for each one.
- class WrapperFunctionCall {
- public:
- using ArgDataBufferType = SmallVector<char, 24>;
- /// Create a WrapperFunctionCall using the given SPS serializer to serialize
- /// the arguments.
- template <typename SPSSerializer, typename... ArgTs>
- static Expected<WrapperFunctionCall> Create(ExecutorAddr FnAddr,
- const ArgTs &...Args) {
- ArgDataBufferType ArgData;
- ArgData.resize(SPSSerializer::size(Args...));
- SPSOutputBuffer OB(&ArgData[0], ArgData.size());
- if (SPSSerializer::serialize(OB, Args...))
- return WrapperFunctionCall(FnAddr, std::move(ArgData));
- return make_error<StringError>("Cannot serialize arguments for "
- "AllocActionCall",
- inconvertibleErrorCode());
- }
- WrapperFunctionCall() = default;
- /// Create a WrapperFunctionCall from a target function and arg buffer.
- WrapperFunctionCall(ExecutorAddr FnAddr, ArgDataBufferType ArgData)
- : FnAddr(FnAddr), ArgData(std::move(ArgData)) {}
- /// Returns the address to be called.
- const ExecutorAddr &getCallee() const { return FnAddr; }
- /// Returns the argument data.
- const ArgDataBufferType &getArgData() const { return ArgData; }
- /// WrapperFunctionCalls convert to true if the callee is non-null.
- explicit operator bool() const { return !!FnAddr; }
- /// Run call returning raw WrapperFunctionResult.
- shared::WrapperFunctionResult run() const {
- using FnTy =
- shared::CWrapperFunctionResult(const char *ArgData, size_t ArgSize);
- return shared::WrapperFunctionResult(
- FnAddr.toPtr<FnTy *>()(ArgData.data(), ArgData.size()));
- }
- /// Run call and deserialize result using SPS.
- template <typename SPSRetT, typename RetT>
- std::enable_if_t<!std::is_same<SPSRetT, void>::value, Error>
- runWithSPSRet(RetT &RetVal) const {
- auto WFR = run();
- if (const char *ErrMsg = WFR.getOutOfBandError())
- return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
- shared::SPSInputBuffer IB(WFR.data(), WFR.size());
- if (!shared::SPSSerializationTraits<SPSRetT, RetT>::deserialize(IB, RetVal))
- return make_error<StringError>("Could not deserialize result from "
- "serialized wrapper function call",
- inconvertibleErrorCode());
- return Error::success();
- }
- /// Overload for SPS functions returning void.
- template <typename SPSRetT>
- std::enable_if_t<std::is_same<SPSRetT, void>::value, Error>
- runWithSPSRet() const {
- shared::SPSEmpty E;
- return runWithSPSRet<shared::SPSEmpty>(E);
- }
- /// Run call and deserialize an SPSError result. SPSError returns and
- /// deserialization failures are merged into the returned error.
- Error runWithSPSRetErrorMerged() const {
- detail::SPSSerializableError RetErr;
- if (auto Err = runWithSPSRet<SPSError>(RetErr))
- return Err;
- return detail::fromSPSSerializable(std::move(RetErr));
- }
- private:
- orc::ExecutorAddr FnAddr;
- ArgDataBufferType ArgData;
- };
- using SPSWrapperFunctionCall = SPSTuple<SPSExecutorAddr, SPSSequence<char>>;
- template <>
- class SPSSerializationTraits<SPSWrapperFunctionCall, WrapperFunctionCall> {
- public:
- static size_t size(const WrapperFunctionCall &WFC) {
- return SPSWrapperFunctionCall::AsArgList::size(WFC.getCallee(),
- WFC.getArgData());
- }
- static bool serialize(SPSOutputBuffer &OB, const WrapperFunctionCall &WFC) {
- return SPSWrapperFunctionCall::AsArgList::serialize(OB, WFC.getCallee(),
- WFC.getArgData());
- }
- static bool deserialize(SPSInputBuffer &IB, WrapperFunctionCall &WFC) {
- ExecutorAddr FnAddr;
- WrapperFunctionCall::ArgDataBufferType ArgData;
- if (!SPSWrapperFunctionCall::AsArgList::deserialize(IB, FnAddr, ArgData))
- return false;
- WFC = WrapperFunctionCall(FnAddr, std::move(ArgData));
- return true;
- }
- };
- } // end namespace shared
- } // end namespace orc
- } // end namespace llvm
- #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|