Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- WrapperFunctionUtils.h - Utilities for wrapper functions -*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // A buffer for serialized results.
  10. //
  11. //===----------------------------------------------------------------------===//
  12.  
  13. #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
  14. #define LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
  15.  
  16. #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
  17. #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
  18. #include "llvm/Support/Error.h"
  19.  
  20. #include <type_traits>
  21.  
  22. namespace llvm {
  23. namespace orc {
  24. namespace shared {
  25.  
  26. // Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
  27. union CWrapperFunctionResultDataUnion {
  28.   char *ValuePtr;
  29.   char Value[sizeof(ValuePtr)];
  30. };
  31.  
  32. // Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
  33. typedef struct {
  34.   CWrapperFunctionResultDataUnion Data;
  35.   size_t Size;
  36. } CWrapperFunctionResult;
  37.  
  38. /// C++ wrapper function result: Same as CWrapperFunctionResult but
  39. /// auto-releases memory.
  40. class WrapperFunctionResult {
  41. public:
  42.   /// Create a default WrapperFunctionResult.
  43.   WrapperFunctionResult() { init(R); }
  44.  
  45.   /// Create a WrapperFunctionResult by taking ownership of a
  46.   /// CWrapperFunctionResult.
  47.   ///
  48.   /// Warning: This should only be used by clients writing wrapper-function
  49.   /// caller utilities (like TargetProcessControl).
  50.   WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {
  51.     // Reset R.
  52.     init(R);
  53.   }
  54.  
  55.   WrapperFunctionResult(const WrapperFunctionResult &) = delete;
  56.   WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
  57.  
  58.   WrapperFunctionResult(WrapperFunctionResult &&Other) {
  59.     init(R);
  60.     std::swap(R, Other.R);
  61.   }
  62.  
  63.   WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
  64.     WrapperFunctionResult Tmp(std::move(Other));
  65.     std::swap(R, Tmp.R);
  66.     return *this;
  67.   }
  68.  
  69.   ~WrapperFunctionResult() {
  70.     if ((R.Size > sizeof(R.Data.Value)) ||
  71.         (R.Size == 0 && R.Data.ValuePtr != nullptr))
  72.       free(R.Data.ValuePtr);
  73.   }
  74.  
  75.   /// Release ownership of the contained CWrapperFunctionResult.
  76.   /// Warning: Do not use -- this method will be removed in the future. It only
  77.   /// exists to temporarily support some code that will eventually be moved to
  78.   /// the ORC runtime.
  79.   CWrapperFunctionResult release() {
  80.     CWrapperFunctionResult Tmp;
  81.     init(Tmp);
  82.     std::swap(R, Tmp);
  83.     return Tmp;
  84.   }
  85.  
  86.   /// Get a pointer to the data contained in this instance.
  87.   char *data() {
  88.     assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
  89.            "Cannot get data for out-of-band error value");
  90.     return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
  91.   }
  92.  
  93.   /// Get a const pointer to the data contained in this instance.
  94.   const char *data() const {
  95.     assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
  96.            "Cannot get data for out-of-band error value");
  97.     return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
  98.   }
  99.  
  100.   /// Returns the size of the data contained in this instance.
  101.   size_t size() const {
  102.     assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
  103.            "Cannot get data for out-of-band error value");
  104.     return R.Size;
  105.   }
  106.  
  107.   /// Returns true if this value is equivalent to a default-constructed
  108.   /// WrapperFunctionResult.
  109.   bool empty() const { return R.Size == 0 && R.Data.ValuePtr == nullptr; }
  110.  
  111.   /// Create a WrapperFunctionResult with the given size and return a pointer
  112.   /// to the underlying memory.
  113.   static WrapperFunctionResult allocate(size_t Size) {
  114.     // Reset.
  115.     WrapperFunctionResult WFR;
  116.     WFR.R.Size = Size;
  117.     if (WFR.R.Size > sizeof(WFR.R.Data.Value))
  118.       WFR.R.Data.ValuePtr = (char *)malloc(WFR.R.Size);
  119.     return WFR;
  120.   }
  121.  
  122.   /// Copy from the given char range.
  123.   static WrapperFunctionResult copyFrom(const char *Source, size_t Size) {
  124.     auto WFR = allocate(Size);
  125.     memcpy(WFR.data(), Source, Size);
  126.     return WFR;
  127.   }
  128.  
  129.   /// Copy from the given null-terminated string (includes the null-terminator).
  130.   static WrapperFunctionResult copyFrom(const char *Source) {
  131.     return copyFrom(Source, strlen(Source) + 1);
  132.   }
  133.  
  134.   /// Copy from the given std::string (includes the null terminator).
  135.   static WrapperFunctionResult copyFrom(const std::string &Source) {
  136.     return copyFrom(Source.c_str());
  137.   }
  138.  
  139.   /// Create an out-of-band error by copying the given string.
  140.   static WrapperFunctionResult createOutOfBandError(const char *Msg) {
  141.     // Reset.
  142.     WrapperFunctionResult WFR;
  143.     char *Tmp = (char *)malloc(strlen(Msg) + 1);
  144.     strcpy(Tmp, Msg);
  145.     WFR.R.Data.ValuePtr = Tmp;
  146.     return WFR;
  147.   }
  148.  
  149.   /// Create an out-of-band error by copying the given string.
  150.   static WrapperFunctionResult createOutOfBandError(const std::string &Msg) {
  151.     return createOutOfBandError(Msg.c_str());
  152.   }
  153.  
  154.   /// If this value is an out-of-band error then this returns the error message,
  155.   /// otherwise returns nullptr.
  156.   const char *getOutOfBandError() const {
  157.     return R.Size == 0 ? R.Data.ValuePtr : nullptr;
  158.   }
  159.  
  160. private:
  161.   static void init(CWrapperFunctionResult &R) {
  162.     R.Data.ValuePtr = nullptr;
  163.     R.Size = 0;
  164.   }
  165.  
  166.   CWrapperFunctionResult R;
  167. };
  168.  
  169. namespace detail {
  170.  
  171. template <typename SPSArgListT, typename... ArgTs>
  172. WrapperFunctionResult
  173. serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args) {
  174.   auto Result = WrapperFunctionResult::allocate(SPSArgListT::size(Args...));
  175.   SPSOutputBuffer OB(Result.data(), Result.size());
  176.   if (!SPSArgListT::serialize(OB, Args...))
  177.     return WrapperFunctionResult::createOutOfBandError(
  178.         "Error serializing arguments to blob in call");
  179.   return Result;
  180. }
  181.  
  182. template <typename RetT> class WrapperFunctionHandlerCaller {
  183. public:
  184.   template <typename HandlerT, typename ArgTupleT, std::size_t... I>
  185.   static decltype(auto) call(HandlerT &&H, ArgTupleT &Args,
  186.                              std::index_sequence<I...>) {
  187.     return std::forward<HandlerT>(H)(std::get<I>(Args)...);
  188.   }
  189. };
  190.  
  191. template <> class WrapperFunctionHandlerCaller<void> {
  192. public:
  193.   template <typename HandlerT, typename ArgTupleT, std::size_t... I>
  194.   static SPSEmpty call(HandlerT &&H, ArgTupleT &Args,
  195.                        std::index_sequence<I...>) {
  196.     std::forward<HandlerT>(H)(std::get<I>(Args)...);
  197.     return SPSEmpty();
  198.   }
  199. };
  200.  
  201. template <typename WrapperFunctionImplT,
  202.           template <typename> class ResultSerializer, typename... SPSTagTs>
  203. class WrapperFunctionHandlerHelper
  204.     : public WrapperFunctionHandlerHelper<
  205.           decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
  206.           ResultSerializer, SPSTagTs...> {};
  207.  
  208. template <typename RetT, typename... ArgTs,
  209.           template <typename> class ResultSerializer, typename... SPSTagTs>
  210. class WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
  211.                                    SPSTagTs...> {
  212. public:
  213.   using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
  214.   using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
  215.  
  216.   template <typename HandlerT>
  217.   static WrapperFunctionResult apply(HandlerT &&H, const char *ArgData,
  218.                                      size_t ArgSize) {
  219.     ArgTuple Args;
  220.     if (!deserialize(ArgData, ArgSize, Args, ArgIndices{}))
  221.       return WrapperFunctionResult::createOutOfBandError(
  222.           "Could not deserialize arguments for wrapper function call");
  223.  
  224.     auto HandlerResult = WrapperFunctionHandlerCaller<RetT>::call(
  225.         std::forward<HandlerT>(H), Args, ArgIndices{});
  226.  
  227.     return ResultSerializer<decltype(HandlerResult)>::serialize(
  228.         std::move(HandlerResult));
  229.   }
  230.  
  231. private:
  232.   template <std::size_t... I>
  233.   static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
  234.                           std::index_sequence<I...>) {
  235.     SPSInputBuffer IB(ArgData, ArgSize);
  236.     return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
  237.   }
  238. };
  239.  
  240. // Map function pointers to function types.
  241. template <typename RetT, typename... ArgTs,
  242.           template <typename> class ResultSerializer, typename... SPSTagTs>
  243. class WrapperFunctionHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
  244.                                    SPSTagTs...>
  245.     : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
  246.                                           SPSTagTs...> {};
  247.  
  248. // Map non-const member function types to function types.
  249. template <typename ClassT, typename RetT, typename... ArgTs,
  250.           template <typename> class ResultSerializer, typename... SPSTagTs>
  251. class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer,
  252.                                    SPSTagTs...>
  253.     : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
  254.                                           SPSTagTs...> {};
  255.  
  256. // Map const member function types to function types.
  257. template <typename ClassT, typename RetT, typename... ArgTs,
  258.           template <typename> class ResultSerializer, typename... SPSTagTs>
  259. class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
  260.                                    ResultSerializer, SPSTagTs...>
  261.     : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
  262.                                           SPSTagTs...> {};
  263.  
  264. template <typename WrapperFunctionImplT,
  265.           template <typename> class ResultSerializer, typename... SPSTagTs>
  266. class WrapperFunctionAsyncHandlerHelper
  267.     : public WrapperFunctionAsyncHandlerHelper<
  268.           decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
  269.           ResultSerializer, SPSTagTs...> {};
  270.  
  271. template <typename RetT, typename SendResultT, typename... ArgTs,
  272.           template <typename> class ResultSerializer, typename... SPSTagTs>
  273. class WrapperFunctionAsyncHandlerHelper<RetT(SendResultT, ArgTs...),
  274.                                         ResultSerializer, SPSTagTs...> {
  275. public:
  276.   using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
  277.   using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
  278.  
  279.   template <typename HandlerT, typename SendWrapperFunctionResultT>
  280.   static void applyAsync(HandlerT &&H,
  281.                          SendWrapperFunctionResultT &&SendWrapperFunctionResult,
  282.                          const char *ArgData, size_t ArgSize) {
  283.     ArgTuple Args;
  284.     if (!deserialize(ArgData, ArgSize, Args, ArgIndices{})) {
  285.       SendWrapperFunctionResult(WrapperFunctionResult::createOutOfBandError(
  286.           "Could not deserialize arguments for wrapper function call"));
  287.       return;
  288.     }
  289.  
  290.     auto SendResult =
  291.         [SendWFR = std::move(SendWrapperFunctionResult)](auto Result) mutable {
  292.           using ResultT = decltype(Result);
  293.           SendWFR(ResultSerializer<ResultT>::serialize(std::move(Result)));
  294.         };
  295.  
  296.     callAsync(std::forward<HandlerT>(H), std::move(SendResult), std::move(Args),
  297.               ArgIndices{});
  298.   }
  299.  
  300. private:
  301.   template <std::size_t... I>
  302.   static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
  303.                           std::index_sequence<I...>) {
  304.     SPSInputBuffer IB(ArgData, ArgSize);
  305.     return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
  306.   }
  307.  
  308.   template <typename HandlerT, typename SerializeAndSendResultT,
  309.             typename ArgTupleT, std::size_t... I>
  310.   static void callAsync(HandlerT &&H,
  311.                         SerializeAndSendResultT &&SerializeAndSendResult,
  312.                         ArgTupleT Args, std::index_sequence<I...>) {
  313.     (void)Args; // Silence a buggy GCC warning.
  314.     return std::forward<HandlerT>(H)(std::move(SerializeAndSendResult),
  315.                                      std::move(std::get<I>(Args))...);
  316.   }
  317. };
  318.  
  319. // Map function pointers to function types.
  320. template <typename RetT, typename... ArgTs,
  321.           template <typename> class ResultSerializer, typename... SPSTagTs>
  322. class WrapperFunctionAsyncHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
  323.                                         SPSTagTs...>
  324.     : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
  325.                                                SPSTagTs...> {};
  326.  
  327. // Map non-const member function types to function types.
  328. template <typename ClassT, typename RetT, typename... ArgTs,
  329.           template <typename> class ResultSerializer, typename... SPSTagTs>
  330. class WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...),
  331.                                         ResultSerializer, SPSTagTs...>
  332.     : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
  333.                                                SPSTagTs...> {};
  334.  
  335. // Map const member function types to function types.
  336. template <typename ClassT, typename RetT, typename... ArgTs,
  337.           template <typename> class ResultSerializer, typename... SPSTagTs>
  338. class WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
  339.                                         ResultSerializer, SPSTagTs...>
  340.     : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
  341.                                                SPSTagTs...> {};
  342.  
  343. template <typename SPSRetTagT, typename RetT> class ResultSerializer {
  344. public:
  345.   static WrapperFunctionResult serialize(RetT Result) {
  346.     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
  347.         Result);
  348.   }
  349. };
  350.  
  351. template <typename SPSRetTagT> class ResultSerializer<SPSRetTagT, Error> {
  352. public:
  353.   static WrapperFunctionResult serialize(Error Err) {
  354.     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
  355.         toSPSSerializable(std::move(Err)));
  356.   }
  357. };
  358.  
  359. template <typename SPSRetTagT>
  360. class ResultSerializer<SPSRetTagT, ErrorSuccess> {
  361. public:
  362.   static WrapperFunctionResult serialize(ErrorSuccess Err) {
  363.     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
  364.         toSPSSerializable(std::move(Err)));
  365.   }
  366. };
  367.  
  368. template <typename SPSRetTagT, typename T>
  369. class ResultSerializer<SPSRetTagT, Expected<T>> {
  370. public:
  371.   static WrapperFunctionResult serialize(Expected<T> E) {
  372.     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
  373.         toSPSSerializable(std::move(E)));
  374.   }
  375. };
  376.  
  377. template <typename SPSRetTagT, typename RetT> class ResultDeserializer {
  378. public:
  379.   static RetT makeValue() { return RetT(); }
  380.   static void makeSafe(RetT &Result) {}
  381.  
  382.   static Error deserialize(RetT &Result, const char *ArgData, size_t ArgSize) {
  383.     SPSInputBuffer IB(ArgData, ArgSize);
  384.     if (!SPSArgList<SPSRetTagT>::deserialize(IB, Result))
  385.       return make_error<StringError>(
  386.           "Error deserializing return value from blob in call",
  387.           inconvertibleErrorCode());
  388.     return Error::success();
  389.   }
  390. };
  391.  
  392. template <> class ResultDeserializer<SPSError, Error> {
  393. public:
  394.   static Error makeValue() { return Error::success(); }
  395.   static void makeSafe(Error &Err) { cantFail(std::move(Err)); }
  396.  
  397.   static Error deserialize(Error &Err, const char *ArgData, size_t ArgSize) {
  398.     SPSInputBuffer IB(ArgData, ArgSize);
  399.     SPSSerializableError BSE;
  400.     if (!SPSArgList<SPSError>::deserialize(IB, BSE))
  401.       return make_error<StringError>(
  402.           "Error deserializing return value from blob in call",
  403.           inconvertibleErrorCode());
  404.     Err = fromSPSSerializable(std::move(BSE));
  405.     return Error::success();
  406.   }
  407. };
  408.  
  409. template <typename SPSTagT, typename T>
  410. class ResultDeserializer<SPSExpected<SPSTagT>, Expected<T>> {
  411. public:
  412.   static Expected<T> makeValue() { return T(); }
  413.   static void makeSafe(Expected<T> &E) { cantFail(E.takeError()); }
  414.  
  415.   static Error deserialize(Expected<T> &E, const char *ArgData,
  416.                            size_t ArgSize) {
  417.     SPSInputBuffer IB(ArgData, ArgSize);
  418.     SPSSerializableExpected<T> BSE;
  419.     if (!SPSArgList<SPSExpected<SPSTagT>>::deserialize(IB, BSE))
  420.       return make_error<StringError>(
  421.           "Error deserializing return value from blob in call",
  422.           inconvertibleErrorCode());
  423.     E = fromSPSSerializable(std::move(BSE));
  424.     return Error::success();
  425.   }
  426. };
  427.  
  428. template <typename SPSRetTagT, typename RetT> class AsyncCallResultHelper {
  429.   // Did you forget to use Error / Expected in your handler?
  430. };
  431.  
  432. } // end namespace detail
  433.  
  434. template <typename SPSSignature> class WrapperFunction;
  435.  
  436. template <typename SPSRetTagT, typename... SPSTagTs>
  437. class WrapperFunction<SPSRetTagT(SPSTagTs...)> {
  438. private:
  439.   template <typename RetT>
  440.   using ResultSerializer = detail::ResultSerializer<SPSRetTagT, RetT>;
  441.  
  442. public:
  443.   /// Call a wrapper function. Caller should be callable as
  444.   /// WrapperFunctionResult Fn(const char *ArgData, size_t ArgSize);
  445.   template <typename CallerFn, typename RetT, typename... ArgTs>
  446.   static Error call(const CallerFn &Caller, RetT &Result,
  447.                     const ArgTs &...Args) {
  448.  
  449.     // RetT might be an Error or Expected value. Set the checked flag now:
  450.     // we don't want the user to have to check the unused result if this
  451.     // operation fails.
  452.     detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(Result);
  453.  
  454.     auto ArgBuffer =
  455.         detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
  456.             Args...);
  457.     if (const char *ErrMsg = ArgBuffer.getOutOfBandError())
  458.       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
  459.  
  460.     WrapperFunctionResult ResultBuffer =
  461.         Caller(ArgBuffer.data(), ArgBuffer.size());
  462.     if (auto ErrMsg = ResultBuffer.getOutOfBandError())
  463.       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
  464.  
  465.     return detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
  466.         Result, ResultBuffer.data(), ResultBuffer.size());
  467.   }
  468.  
  469.   /// Call an async wrapper function.
  470.   /// Caller should be callable as
  471.   /// void Fn(unique_function<void(WrapperFunctionResult)> SendResult,
  472.   ///         WrapperFunctionResult ArgBuffer);
  473.   template <typename AsyncCallerFn, typename SendDeserializedResultFn,
  474.             typename... ArgTs>
  475.   static void callAsync(AsyncCallerFn &&Caller,
  476.                         SendDeserializedResultFn &&SendDeserializedResult,
  477.                         const ArgTs &...Args) {
  478.     using RetT = typename std::tuple_element<
  479.         1, typename detail::WrapperFunctionHandlerHelper<
  480.                std::remove_reference_t<SendDeserializedResultFn>,
  481.                ResultSerializer, SPSRetTagT>::ArgTuple>::type;
  482.  
  483.     auto ArgBuffer =
  484.         detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
  485.             Args...);
  486.     if (auto *ErrMsg = ArgBuffer.getOutOfBandError()) {
  487.       SendDeserializedResult(
  488.           make_error<StringError>(ErrMsg, inconvertibleErrorCode()),
  489.           detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue());
  490.       return;
  491.     }
  492.  
  493.     auto SendSerializedResult = [SDR = std::move(SendDeserializedResult)](
  494.                                     WrapperFunctionResult R) mutable {
  495.       RetT RetVal = detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue();
  496.       detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(RetVal);
  497.  
  498.       if (auto *ErrMsg = R.getOutOfBandError()) {
  499.         SDR(make_error<StringError>(ErrMsg, inconvertibleErrorCode()),
  500.             std::move(RetVal));
  501.         return;
  502.       }
  503.  
  504.       SPSInputBuffer IB(R.data(), R.size());
  505.       if (auto Err = detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
  506.               RetVal, R.data(), R.size()))
  507.         SDR(std::move(Err), std::move(RetVal));
  508.  
  509.       SDR(Error::success(), std::move(RetVal));
  510.     };
  511.  
  512.     Caller(std::move(SendSerializedResult), ArgBuffer.data(), ArgBuffer.size());
  513.   }
  514.  
  515.   /// Handle a call to a wrapper function.
  516.   template <typename HandlerT>
  517.   static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize,
  518.                                       HandlerT &&Handler) {
  519.     using WFHH =
  520.         detail::WrapperFunctionHandlerHelper<std::remove_reference_t<HandlerT>,
  521.                                              ResultSerializer, SPSTagTs...>;
  522.     return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize);
  523.   }
  524.  
  525.   /// Handle a call to an async wrapper function.
  526.   template <typename HandlerT, typename SendResultT>
  527.   static void handleAsync(const char *ArgData, size_t ArgSize,
  528.                           HandlerT &&Handler, SendResultT &&SendResult) {
  529.     using WFAHH = detail::WrapperFunctionAsyncHandlerHelper<
  530.         std::remove_reference_t<HandlerT>, ResultSerializer, SPSTagTs...>;
  531.     WFAHH::applyAsync(std::forward<HandlerT>(Handler),
  532.                       std::forward<SendResultT>(SendResult), ArgData, ArgSize);
  533.   }
  534.  
  535. private:
  536.   template <typename T> static const T &makeSerializable(const T &Value) {
  537.     return Value;
  538.   }
  539.  
  540.   static detail::SPSSerializableError makeSerializable(Error Err) {
  541.     return detail::toSPSSerializable(std::move(Err));
  542.   }
  543.  
  544.   template <typename T>
  545.   static detail::SPSSerializableExpected<T> makeSerializable(Expected<T> E) {
  546.     return detail::toSPSSerializable(std::move(E));
  547.   }
  548. };
  549.  
  550. template <typename... SPSTagTs>
  551. class WrapperFunction<void(SPSTagTs...)>
  552.     : private WrapperFunction<SPSEmpty(SPSTagTs...)> {
  553.  
  554. public:
  555.   template <typename CallerFn, typename... ArgTs>
  556.   static Error call(const CallerFn &Caller, const ArgTs &...Args) {
  557.     SPSEmpty BE;
  558.     return WrapperFunction<SPSEmpty(SPSTagTs...)>::call(Caller, BE, Args...);
  559.   }
  560.  
  561.   template <typename AsyncCallerFn, typename SendDeserializedResultFn,
  562.             typename... ArgTs>
  563.   static void callAsync(AsyncCallerFn &&Caller,
  564.                         SendDeserializedResultFn &&SendDeserializedResult,
  565.                         const ArgTs &...Args) {
  566.     WrapperFunction<SPSEmpty(SPSTagTs...)>::callAsync(
  567.         std::forward<AsyncCallerFn>(Caller),
  568.         [SDR = std::move(SendDeserializedResult)](Error SerializeErr,
  569.                                                   SPSEmpty E) mutable {
  570.           SDR(std::move(SerializeErr));
  571.         },
  572.         Args...);
  573.   }
  574.  
  575.   using WrapperFunction<SPSEmpty(SPSTagTs...)>::handle;
  576.   using WrapperFunction<SPSEmpty(SPSTagTs...)>::handleAsync;
  577. };
  578.  
  579. /// A function object that takes an ExecutorAddr as its first argument,
  580. /// casts that address to a ClassT*, then calls the given method on that
  581. /// pointer passing in the remaining function arguments. This utility
  582. /// removes some of the boilerplate from writing wrappers for method calls.
  583. ///
  584. ///   @code{.cpp}
  585. ///   class MyClass {
  586. ///   public:
  587. ///     void myMethod(uint32_t, bool) { ... }
  588. ///   };
  589. ///
  590. ///   // SPS Method signature -- note MyClass object address as first argument.
  591. ///   using SPSMyMethodWrapperSignature =
  592. ///     SPSTuple<SPSExecutorAddr, uint32_t, bool>;
  593. ///
  594. ///   WrapperFunctionResult
  595. ///   myMethodCallWrapper(const char *ArgData, size_t ArgSize) {
  596. ///     return WrapperFunction<SPSMyMethodWrapperSignature>::handle(
  597. ///        ArgData, ArgSize, makeMethodWrapperHandler(&MyClass::myMethod));
  598. ///   }
  599. ///   @endcode
  600. ///
  601. template <typename RetT, typename ClassT, typename... ArgTs>
  602. class MethodWrapperHandler {
  603. public:
  604.   using MethodT = RetT (ClassT::*)(ArgTs...);
  605.   MethodWrapperHandler(MethodT M) : M(M) {}
  606.   RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args) {
  607.     return (ObjAddr.toPtr<ClassT*>()->*M)(std::forward<ArgTs>(Args)...);
  608.   }
  609.  
  610. private:
  611.   MethodT M;
  612. };
  613.  
  614. /// Create a MethodWrapperHandler object from the given method pointer.
  615. template <typename RetT, typename ClassT, typename... ArgTs>
  616. MethodWrapperHandler<RetT, ClassT, ArgTs...>
  617. makeMethodWrapperHandler(RetT (ClassT::*Method)(ArgTs...)) {
  618.   return MethodWrapperHandler<RetT, ClassT, ArgTs...>(Method);
  619. }
  620.  
  621. /// Represents a serialized wrapper function call.
  622. /// Serializing calls themselves allows us to batch them: We can make one
  623. /// "run-wrapper-functions" utility and send it a list of calls to run.
  624. ///
  625. /// The motivating use-case for this API is JITLink allocation actions, where
  626. /// we want to run multiple functions to finalize linked memory without having
  627. /// to make separate IPC calls for each one.
  628. class WrapperFunctionCall {
  629. public:
  630.   using ArgDataBufferType = SmallVector<char, 24>;
  631.  
  632.   /// Create a WrapperFunctionCall using the given SPS serializer to serialize
  633.   /// the arguments.
  634.   template <typename SPSSerializer, typename... ArgTs>
  635.   static Expected<WrapperFunctionCall> Create(ExecutorAddr FnAddr,
  636.                                               const ArgTs &...Args) {
  637.     ArgDataBufferType ArgData;
  638.     ArgData.resize(SPSSerializer::size(Args...));
  639.     SPSOutputBuffer OB(ArgData.empty() ? nullptr : ArgData.data(),
  640.                        ArgData.size());
  641.     if (SPSSerializer::serialize(OB, Args...))
  642.       return WrapperFunctionCall(FnAddr, std::move(ArgData));
  643.     return make_error<StringError>("Cannot serialize arguments for "
  644.                                    "AllocActionCall",
  645.                                    inconvertibleErrorCode());
  646.   }
  647.  
  648.   WrapperFunctionCall() = default;
  649.  
  650.   /// Create a WrapperFunctionCall from a target function and arg buffer.
  651.   WrapperFunctionCall(ExecutorAddr FnAddr, ArgDataBufferType ArgData)
  652.       : FnAddr(FnAddr), ArgData(std::move(ArgData)) {}
  653.  
  654.   /// Returns the address to be called.
  655.   const ExecutorAddr &getCallee() const { return FnAddr; }
  656.  
  657.   /// Returns the argument data.
  658.   const ArgDataBufferType &getArgData() const { return ArgData; }
  659.  
  660.   /// WrapperFunctionCalls convert to true if the callee is non-null.
  661.   explicit operator bool() const { return !!FnAddr; }
  662.  
  663.   /// Run call returning raw WrapperFunctionResult.
  664.   shared::WrapperFunctionResult run() const {
  665.     using FnTy =
  666.         shared::CWrapperFunctionResult(const char *ArgData, size_t ArgSize);
  667.     return shared::WrapperFunctionResult(
  668.         FnAddr.toPtr<FnTy *>()(ArgData.data(), ArgData.size()));
  669.   }
  670.  
  671.   /// Run call and deserialize result using SPS.
  672.   template <typename SPSRetT, typename RetT>
  673.   std::enable_if_t<!std::is_same<SPSRetT, void>::value, Error>
  674.   runWithSPSRet(RetT &RetVal) const {
  675.     auto WFR = run();
  676.     if (const char *ErrMsg = WFR.getOutOfBandError())
  677.       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
  678.     shared::SPSInputBuffer IB(WFR.data(), WFR.size());
  679.     if (!shared::SPSSerializationTraits<SPSRetT, RetT>::deserialize(IB, RetVal))
  680.       return make_error<StringError>("Could not deserialize result from "
  681.                                      "serialized wrapper function call",
  682.                                      inconvertibleErrorCode());
  683.     return Error::success();
  684.   }
  685.  
  686.   /// Overload for SPS functions returning void.
  687.   template <typename SPSRetT>
  688.   std::enable_if_t<std::is_same<SPSRetT, void>::value, Error>
  689.   runWithSPSRet() const {
  690.     shared::SPSEmpty E;
  691.     return runWithSPSRet<shared::SPSEmpty>(E);
  692.   }
  693.  
  694.   /// Run call and deserialize an SPSError result. SPSError returns and
  695.   /// deserialization failures are merged into the returned error.
  696.   Error runWithSPSRetErrorMerged() const {
  697.     detail::SPSSerializableError RetErr;
  698.     if (auto Err = runWithSPSRet<SPSError>(RetErr))
  699.       return Err;
  700.     return detail::fromSPSSerializable(std::move(RetErr));
  701.   }
  702.  
  703. private:
  704.   orc::ExecutorAddr FnAddr;
  705.   ArgDataBufferType ArgData;
  706. };
  707.  
  708. using SPSWrapperFunctionCall = SPSTuple<SPSExecutorAddr, SPSSequence<char>>;
  709.  
  710. template <>
  711. class SPSSerializationTraits<SPSWrapperFunctionCall, WrapperFunctionCall> {
  712. public:
  713.   static size_t size(const WrapperFunctionCall &WFC) {
  714.     return SPSWrapperFunctionCall::AsArgList::size(WFC.getCallee(),
  715.                                                    WFC.getArgData());
  716.   }
  717.  
  718.   static bool serialize(SPSOutputBuffer &OB, const WrapperFunctionCall &WFC) {
  719.     return SPSWrapperFunctionCall::AsArgList::serialize(OB, WFC.getCallee(),
  720.                                                         WFC.getArgData());
  721.   }
  722.  
  723.   static bool deserialize(SPSInputBuffer &IB, WrapperFunctionCall &WFC) {
  724.     ExecutorAddr FnAddr;
  725.     WrapperFunctionCall::ArgDataBufferType ArgData;
  726.     if (!SPSWrapperFunctionCall::AsArgList::deserialize(IB, FnAddr, ArgData))
  727.       return false;
  728.     WFC = WrapperFunctionCall(FnAddr, std::move(ArgData));
  729.     return true;
  730.   }
  731. };
  732.  
  733. } // end namespace shared
  734. } // end namespace orc
  735. } // end namespace llvm
  736.  
  737. #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
  738.