Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:51

0001 //===- WrapperFunctionUtils.h - Utilities for wrapper functions -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // A buffer for serialized results.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
0014 #define LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
0015 
0016 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
0017 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
0018 #include "llvm/Support/Error.h"
0019 
0020 #include <type_traits>
0021 
0022 namespace llvm {
0023 namespace orc {
0024 namespace shared {
0025 
0026 // Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
0027 union CWrapperFunctionResultDataUnion {
0028   char *ValuePtr;
0029   char Value[sizeof(ValuePtr)];
0030 };
0031 
0032 // Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
0033 typedef struct {
0034   CWrapperFunctionResultDataUnion Data;
0035   size_t Size;
0036 } CWrapperFunctionResult;
0037 
0038 /// C++ wrapper function result: Same as CWrapperFunctionResult but
0039 /// auto-releases memory.
0040 class WrapperFunctionResult {
0041 public:
0042   /// Create a default WrapperFunctionResult.
0043   WrapperFunctionResult() { init(R); }
0044 
0045   /// Create a WrapperFunctionResult by taking ownership of a
0046   /// CWrapperFunctionResult.
0047   ///
0048   /// Warning: This should only be used by clients writing wrapper-function
0049   /// caller utilities (like TargetProcessControl).
0050   WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {
0051     // Reset R.
0052     init(R);
0053   }
0054 
0055   WrapperFunctionResult(const WrapperFunctionResult &) = delete;
0056   WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
0057 
0058   WrapperFunctionResult(WrapperFunctionResult &&Other) {
0059     init(R);
0060     std::swap(R, Other.R);
0061   }
0062 
0063   WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
0064     WrapperFunctionResult Tmp(std::move(Other));
0065     std::swap(R, Tmp.R);
0066     return *this;
0067   }
0068 
0069   ~WrapperFunctionResult() {
0070     if ((R.Size > sizeof(R.Data.Value)) ||
0071         (R.Size == 0 && R.Data.ValuePtr != nullptr))
0072       free(R.Data.ValuePtr);
0073   }
0074 
0075   /// Release ownership of the contained CWrapperFunctionResult.
0076   /// Warning: Do not use -- this method will be removed in the future. It only
0077   /// exists to temporarily support some code that will eventually be moved to
0078   /// the ORC runtime.
0079   CWrapperFunctionResult release() {
0080     CWrapperFunctionResult Tmp;
0081     init(Tmp);
0082     std::swap(R, Tmp);
0083     return Tmp;
0084   }
0085 
0086   /// Get a pointer to the data contained in this instance.
0087   char *data() {
0088     assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
0089            "Cannot get data for out-of-band error value");
0090     return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
0091   }
0092 
0093   /// Get a const pointer to the data contained in this instance.
0094   const char *data() const {
0095     assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
0096            "Cannot get data for out-of-band error value");
0097     return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
0098   }
0099 
0100   /// Returns the size of the data contained in this instance.
0101   size_t size() const {
0102     assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
0103            "Cannot get data for out-of-band error value");
0104     return R.Size;
0105   }
0106 
0107   /// Returns true if this value is equivalent to a default-constructed
0108   /// WrapperFunctionResult.
0109   bool empty() const { return R.Size == 0 && R.Data.ValuePtr == nullptr; }
0110 
0111   /// Create a WrapperFunctionResult with the given size and return a pointer
0112   /// to the underlying memory.
0113   static WrapperFunctionResult allocate(size_t Size) {
0114     // Reset.
0115     WrapperFunctionResult WFR;
0116     WFR.R.Size = Size;
0117     if (WFR.R.Size > sizeof(WFR.R.Data.Value))
0118       WFR.R.Data.ValuePtr = (char *)malloc(WFR.R.Size);
0119     return WFR;
0120   }
0121 
0122   /// Copy from the given char range.
0123   static WrapperFunctionResult copyFrom(const char *Source, size_t Size) {
0124     auto WFR = allocate(Size);
0125     memcpy(WFR.data(), Source, Size);
0126     return WFR;
0127   }
0128 
0129   /// Copy from the given null-terminated string (includes the null-terminator).
0130   static WrapperFunctionResult copyFrom(const char *Source) {
0131     return copyFrom(Source, strlen(Source) + 1);
0132   }
0133 
0134   /// Copy from the given std::string (includes the null terminator).
0135   static WrapperFunctionResult copyFrom(const std::string &Source) {
0136     return copyFrom(Source.c_str());
0137   }
0138 
0139   /// Create an out-of-band error by copying the given string.
0140   static WrapperFunctionResult createOutOfBandError(const char *Msg) {
0141     // Reset.
0142     WrapperFunctionResult WFR;
0143     char *Tmp = (char *)malloc(strlen(Msg) + 1);
0144     strcpy(Tmp, Msg);
0145     WFR.R.Data.ValuePtr = Tmp;
0146     return WFR;
0147   }
0148 
0149   /// Create an out-of-band error by copying the given string.
0150   static WrapperFunctionResult createOutOfBandError(const std::string &Msg) {
0151     return createOutOfBandError(Msg.c_str());
0152   }
0153 
0154   /// If this value is an out-of-band error then this returns the error message,
0155   /// otherwise returns nullptr.
0156   const char *getOutOfBandError() const {
0157     return R.Size == 0 ? R.Data.ValuePtr : nullptr;
0158   }
0159 
0160 private:
0161   static void init(CWrapperFunctionResult &R) {
0162     R.Data.ValuePtr = nullptr;
0163     R.Size = 0;
0164   }
0165 
0166   CWrapperFunctionResult R;
0167 };
0168 
0169 namespace detail {
0170 
0171 template <typename SPSArgListT, typename... ArgTs>
0172 WrapperFunctionResult
0173 serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args) {
0174   auto Result = WrapperFunctionResult::allocate(SPSArgListT::size(Args...));
0175   SPSOutputBuffer OB(Result.data(), Result.size());
0176   if (!SPSArgListT::serialize(OB, Args...))
0177     return WrapperFunctionResult::createOutOfBandError(
0178         "Error serializing arguments to blob in call");
0179   return Result;
0180 }
0181 
0182 template <typename RetT> class WrapperFunctionHandlerCaller {
0183 public:
0184   template <typename HandlerT, typename ArgTupleT, std::size_t... I>
0185   static decltype(auto) call(HandlerT &&H, ArgTupleT &Args,
0186                              std::index_sequence<I...>) {
0187     return std::forward<HandlerT>(H)(std::get<I>(Args)...);
0188   }
0189 };
0190 
0191 template <> class WrapperFunctionHandlerCaller<void> {
0192 public:
0193   template <typename HandlerT, typename ArgTupleT, std::size_t... I>
0194   static SPSEmpty call(HandlerT &&H, ArgTupleT &Args,
0195                        std::index_sequence<I...>) {
0196     std::forward<HandlerT>(H)(std::get<I>(Args)...);
0197     return SPSEmpty();
0198   }
0199 };
0200 
0201 template <typename WrapperFunctionImplT,
0202           template <typename> class ResultSerializer, typename... SPSTagTs>
0203 class WrapperFunctionHandlerHelper
0204     : public WrapperFunctionHandlerHelper<
0205           decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
0206           ResultSerializer, SPSTagTs...> {};
0207 
0208 template <typename RetT, typename... ArgTs,
0209           template <typename> class ResultSerializer, typename... SPSTagTs>
0210 class WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
0211                                    SPSTagTs...> {
0212 public:
0213   using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
0214   using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
0215 
0216   template <typename HandlerT>
0217   static WrapperFunctionResult apply(HandlerT &&H, const char *ArgData,
0218                                      size_t ArgSize) {
0219     ArgTuple Args;
0220     if (!deserialize(ArgData, ArgSize, Args, ArgIndices{}))
0221       return WrapperFunctionResult::createOutOfBandError(
0222           "Could not deserialize arguments for wrapper function call");
0223 
0224     auto HandlerResult = WrapperFunctionHandlerCaller<RetT>::call(
0225         std::forward<HandlerT>(H), Args, ArgIndices{});
0226 
0227     return ResultSerializer<decltype(HandlerResult)>::serialize(
0228         std::move(HandlerResult));
0229   }
0230 
0231 private:
0232   template <std::size_t... I>
0233   static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
0234                           std::index_sequence<I...>) {
0235     SPSInputBuffer IB(ArgData, ArgSize);
0236     return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
0237   }
0238 };
0239 
0240 // Map function pointers to function types.
0241 template <typename RetT, typename... ArgTs,
0242           template <typename> class ResultSerializer, typename... SPSTagTs>
0243 class WrapperFunctionHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
0244                                    SPSTagTs...>
0245     : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
0246                                           SPSTagTs...> {};
0247 
0248 // Map non-const member function types to function types.
0249 template <typename ClassT, typename RetT, typename... ArgTs,
0250           template <typename> class ResultSerializer, typename... SPSTagTs>
0251 class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer,
0252                                    SPSTagTs...>
0253     : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
0254                                           SPSTagTs...> {};
0255 
0256 // Map const member function types to function types.
0257 template <typename ClassT, typename RetT, typename... ArgTs,
0258           template <typename> class ResultSerializer, typename... SPSTagTs>
0259 class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
0260                                    ResultSerializer, SPSTagTs...>
0261     : public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
0262                                           SPSTagTs...> {};
0263 
0264 template <typename WrapperFunctionImplT,
0265           template <typename> class ResultSerializer, typename... SPSTagTs>
0266 class WrapperFunctionAsyncHandlerHelper
0267     : public WrapperFunctionAsyncHandlerHelper<
0268           decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
0269           ResultSerializer, SPSTagTs...> {};
0270 
0271 template <typename RetT, typename SendResultT, typename... ArgTs,
0272           template <typename> class ResultSerializer, typename... SPSTagTs>
0273 class WrapperFunctionAsyncHandlerHelper<RetT(SendResultT, ArgTs...),
0274                                         ResultSerializer, SPSTagTs...> {
0275 public:
0276   using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
0277   using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
0278 
0279   template <typename HandlerT, typename SendWrapperFunctionResultT>
0280   static void applyAsync(HandlerT &&H,
0281                          SendWrapperFunctionResultT &&SendWrapperFunctionResult,
0282                          const char *ArgData, size_t ArgSize) {
0283     ArgTuple Args;
0284     if (!deserialize(ArgData, ArgSize, Args, ArgIndices{})) {
0285       SendWrapperFunctionResult(WrapperFunctionResult::createOutOfBandError(
0286           "Could not deserialize arguments for wrapper function call"));
0287       return;
0288     }
0289 
0290     auto SendResult =
0291         [SendWFR = std::move(SendWrapperFunctionResult)](auto Result) mutable {
0292           using ResultT = decltype(Result);
0293           SendWFR(ResultSerializer<ResultT>::serialize(std::move(Result)));
0294         };
0295 
0296     callAsync(std::forward<HandlerT>(H), std::move(SendResult), std::move(Args),
0297               ArgIndices{});
0298   }
0299 
0300 private:
0301   template <std::size_t... I>
0302   static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
0303                           std::index_sequence<I...>) {
0304     SPSInputBuffer IB(ArgData, ArgSize);
0305     return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
0306   }
0307 
0308   template <typename HandlerT, typename SerializeAndSendResultT,
0309             typename ArgTupleT, std::size_t... I>
0310   static void callAsync(HandlerT &&H,
0311                         SerializeAndSendResultT &&SerializeAndSendResult,
0312                         ArgTupleT Args, std::index_sequence<I...>) {
0313     (void)Args; // Silence a buggy GCC warning.
0314     return std::forward<HandlerT>(H)(std::move(SerializeAndSendResult),
0315                                      std::move(std::get<I>(Args))...);
0316   }
0317 };
0318 
0319 // Map function pointers to function types.
0320 template <typename RetT, typename... ArgTs,
0321           template <typename> class ResultSerializer, typename... SPSTagTs>
0322 class WrapperFunctionAsyncHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
0323                                         SPSTagTs...>
0324     : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
0325                                                SPSTagTs...> {};
0326 
0327 // Map non-const member function types to function types.
0328 template <typename ClassT, typename RetT, typename... ArgTs,
0329           template <typename> class ResultSerializer, typename... SPSTagTs>
0330 class WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...),
0331                                         ResultSerializer, SPSTagTs...>
0332     : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
0333                                                SPSTagTs...> {};
0334 
0335 // Map const member function types to function types.
0336 template <typename ClassT, typename RetT, typename... ArgTs,
0337           template <typename> class ResultSerializer, typename... SPSTagTs>
0338 class WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
0339                                         ResultSerializer, SPSTagTs...>
0340     : public WrapperFunctionAsyncHandlerHelper<RetT(ArgTs...), ResultSerializer,
0341                                                SPSTagTs...> {};
0342 
0343 template <typename SPSRetTagT, typename RetT> class ResultSerializer {
0344 public:
0345   static WrapperFunctionResult serialize(RetT Result) {
0346     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
0347         Result);
0348   }
0349 };
0350 
0351 template <typename SPSRetTagT> class ResultSerializer<SPSRetTagT, Error> {
0352 public:
0353   static WrapperFunctionResult serialize(Error Err) {
0354     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
0355         toSPSSerializable(std::move(Err)));
0356   }
0357 };
0358 
0359 template <typename SPSRetTagT>
0360 class ResultSerializer<SPSRetTagT, ErrorSuccess> {
0361 public:
0362   static WrapperFunctionResult serialize(ErrorSuccess Err) {
0363     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
0364         toSPSSerializable(std::move(Err)));
0365   }
0366 };
0367 
0368 template <typename SPSRetTagT, typename T>
0369 class ResultSerializer<SPSRetTagT, Expected<T>> {
0370 public:
0371   static WrapperFunctionResult serialize(Expected<T> E) {
0372     return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
0373         toSPSSerializable(std::move(E)));
0374   }
0375 };
0376 
0377 template <typename SPSRetTagT, typename RetT> class ResultDeserializer {
0378 public:
0379   static RetT makeValue() { return RetT(); }
0380   static void makeSafe(RetT &Result) {}
0381 
0382   static Error deserialize(RetT &Result, const char *ArgData, size_t ArgSize) {
0383     SPSInputBuffer IB(ArgData, ArgSize);
0384     if (!SPSArgList<SPSRetTagT>::deserialize(IB, Result))
0385       return make_error<StringError>(
0386           "Error deserializing return value from blob in call",
0387           inconvertibleErrorCode());
0388     return Error::success();
0389   }
0390 };
0391 
0392 template <> class ResultDeserializer<SPSError, Error> {
0393 public:
0394   static Error makeValue() { return Error::success(); }
0395   static void makeSafe(Error &Err) { cantFail(std::move(Err)); }
0396 
0397   static Error deserialize(Error &Err, const char *ArgData, size_t ArgSize) {
0398     SPSInputBuffer IB(ArgData, ArgSize);
0399     SPSSerializableError BSE;
0400     if (!SPSArgList<SPSError>::deserialize(IB, BSE))
0401       return make_error<StringError>(
0402           "Error deserializing return value from blob in call",
0403           inconvertibleErrorCode());
0404     Err = fromSPSSerializable(std::move(BSE));
0405     return Error::success();
0406   }
0407 };
0408 
0409 template <typename SPSTagT, typename T>
0410 class ResultDeserializer<SPSExpected<SPSTagT>, Expected<T>> {
0411 public:
0412   static Expected<T> makeValue() { return T(); }
0413   static void makeSafe(Expected<T> &E) { cantFail(E.takeError()); }
0414 
0415   static Error deserialize(Expected<T> &E, const char *ArgData,
0416                            size_t ArgSize) {
0417     SPSInputBuffer IB(ArgData, ArgSize);
0418     SPSSerializableExpected<T> BSE;
0419     if (!SPSArgList<SPSExpected<SPSTagT>>::deserialize(IB, BSE))
0420       return make_error<StringError>(
0421           "Error deserializing return value from blob in call",
0422           inconvertibleErrorCode());
0423     E = fromSPSSerializable(std::move(BSE));
0424     return Error::success();
0425   }
0426 };
0427 
0428 template <typename SPSRetTagT, typename RetT> class AsyncCallResultHelper {
0429   // Did you forget to use Error / Expected in your handler?
0430 };
0431 
0432 } // end namespace detail
0433 
0434 template <typename SPSSignature> class WrapperFunction;
0435 
0436 template <typename SPSRetTagT, typename... SPSTagTs>
0437 class WrapperFunction<SPSRetTagT(SPSTagTs...)> {
0438 private:
0439   template <typename RetT>
0440   using ResultSerializer = detail::ResultSerializer<SPSRetTagT, RetT>;
0441 
0442 public:
0443   /// Call a wrapper function. Caller should be callable as
0444   /// WrapperFunctionResult Fn(const char *ArgData, size_t ArgSize);
0445   template <typename CallerFn, typename RetT, typename... ArgTs>
0446   static Error call(const CallerFn &Caller, RetT &Result,
0447                     const ArgTs &...Args) {
0448 
0449     // RetT might be an Error or Expected value. Set the checked flag now:
0450     // we don't want the user to have to check the unused result if this
0451     // operation fails.
0452     detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(Result);
0453 
0454     auto ArgBuffer =
0455         detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
0456             Args...);
0457     if (const char *ErrMsg = ArgBuffer.getOutOfBandError())
0458       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
0459 
0460     WrapperFunctionResult ResultBuffer =
0461         Caller(ArgBuffer.data(), ArgBuffer.size());
0462     if (auto ErrMsg = ResultBuffer.getOutOfBandError())
0463       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
0464 
0465     return detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
0466         Result, ResultBuffer.data(), ResultBuffer.size());
0467   }
0468 
0469   /// Call an async wrapper function.
0470   /// Caller should be callable as
0471   /// void Fn(unique_function<void(WrapperFunctionResult)> SendResult,
0472   ///         WrapperFunctionResult ArgBuffer);
0473   template <typename AsyncCallerFn, typename SendDeserializedResultFn,
0474             typename... ArgTs>
0475   static void callAsync(AsyncCallerFn &&Caller,
0476                         SendDeserializedResultFn &&SendDeserializedResult,
0477                         const ArgTs &...Args) {
0478     using RetT = typename std::tuple_element<
0479         1, typename detail::WrapperFunctionHandlerHelper<
0480                std::remove_reference_t<SendDeserializedResultFn>,
0481                ResultSerializer, SPSRetTagT>::ArgTuple>::type;
0482 
0483     auto ArgBuffer =
0484         detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
0485             Args...);
0486     if (auto *ErrMsg = ArgBuffer.getOutOfBandError()) {
0487       SendDeserializedResult(
0488           make_error<StringError>(ErrMsg, inconvertibleErrorCode()),
0489           detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue());
0490       return;
0491     }
0492 
0493     auto SendSerializedResult = [SDR = std::move(SendDeserializedResult)](
0494                                     WrapperFunctionResult R) mutable {
0495       RetT RetVal = detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue();
0496       detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(RetVal);
0497 
0498       if (auto *ErrMsg = R.getOutOfBandError()) {
0499         SDR(make_error<StringError>(ErrMsg, inconvertibleErrorCode()),
0500             std::move(RetVal));
0501         return;
0502       }
0503 
0504       SPSInputBuffer IB(R.data(), R.size());
0505       if (auto Err = detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
0506               RetVal, R.data(), R.size())) {
0507         SDR(std::move(Err), std::move(RetVal));
0508         return;
0509       }
0510 
0511       SDR(Error::success(), std::move(RetVal));
0512     };
0513 
0514     Caller(std::move(SendSerializedResult), ArgBuffer.data(), ArgBuffer.size());
0515   }
0516 
0517   /// Handle a call to a wrapper function.
0518   template <typename HandlerT>
0519   static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize,
0520                                       HandlerT &&Handler) {
0521     using WFHH =
0522         detail::WrapperFunctionHandlerHelper<std::remove_reference_t<HandlerT>,
0523                                              ResultSerializer, SPSTagTs...>;
0524     return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize);
0525   }
0526 
0527   /// Handle a call to an async wrapper function.
0528   template <typename HandlerT, typename SendResultT>
0529   static void handleAsync(const char *ArgData, size_t ArgSize,
0530                           HandlerT &&Handler, SendResultT &&SendResult) {
0531     using WFAHH = detail::WrapperFunctionAsyncHandlerHelper<
0532         std::remove_reference_t<HandlerT>, ResultSerializer, SPSTagTs...>;
0533     WFAHH::applyAsync(std::forward<HandlerT>(Handler),
0534                       std::forward<SendResultT>(SendResult), ArgData, ArgSize);
0535   }
0536 
0537 private:
0538   template <typename T> static const T &makeSerializable(const T &Value) {
0539     return Value;
0540   }
0541 
0542   static detail::SPSSerializableError makeSerializable(Error Err) {
0543     return detail::toSPSSerializable(std::move(Err));
0544   }
0545 
0546   template <typename T>
0547   static detail::SPSSerializableExpected<T> makeSerializable(Expected<T> E) {
0548     return detail::toSPSSerializable(std::move(E));
0549   }
0550 };
0551 
0552 template <typename... SPSTagTs>
0553 class WrapperFunction<void(SPSTagTs...)>
0554     : private WrapperFunction<SPSEmpty(SPSTagTs...)> {
0555 
0556 public:
0557   template <typename CallerFn, typename... ArgTs>
0558   static Error call(const CallerFn &Caller, const ArgTs &...Args) {
0559     SPSEmpty BE;
0560     return WrapperFunction<SPSEmpty(SPSTagTs...)>::call(Caller, BE, Args...);
0561   }
0562 
0563   template <typename AsyncCallerFn, typename SendDeserializedResultFn,
0564             typename... ArgTs>
0565   static void callAsync(AsyncCallerFn &&Caller,
0566                         SendDeserializedResultFn &&SendDeserializedResult,
0567                         const ArgTs &...Args) {
0568     WrapperFunction<SPSEmpty(SPSTagTs...)>::callAsync(
0569         std::forward<AsyncCallerFn>(Caller),
0570         [SDR = std::move(SendDeserializedResult)](Error SerializeErr,
0571                                                   SPSEmpty E) mutable {
0572           SDR(std::move(SerializeErr));
0573         },
0574         Args...);
0575   }
0576 
0577   using WrapperFunction<SPSEmpty(SPSTagTs...)>::handle;
0578   using WrapperFunction<SPSEmpty(SPSTagTs...)>::handleAsync;
0579 };
0580 
0581 /// A function object that takes an ExecutorAddr as its first argument,
0582 /// casts that address to a ClassT*, then calls the given method on that
0583 /// pointer passing in the remaining function arguments. This utility
0584 /// removes some of the boilerplate from writing wrappers for method calls.
0585 ///
0586 ///   @code{.cpp}
0587 ///   class MyClass {
0588 ///   public:
0589 ///     void myMethod(uint32_t, bool) { ... }
0590 ///   };
0591 ///
0592 ///   // SPS Method signature -- note MyClass object address as first argument.
0593 ///   using SPSMyMethodWrapperSignature =
0594 ///     SPSTuple<SPSExecutorAddr, uint32_t, bool>;
0595 ///
0596 ///   WrapperFunctionResult
0597 ///   myMethodCallWrapper(const char *ArgData, size_t ArgSize) {
0598 ///     return WrapperFunction<SPSMyMethodWrapperSignature>::handle(
0599 ///        ArgData, ArgSize, makeMethodWrapperHandler(&MyClass::myMethod));
0600 ///   }
0601 ///   @endcode
0602 ///
0603 template <typename RetT, typename ClassT, typename... ArgTs>
0604 class MethodWrapperHandler {
0605 public:
0606   using MethodT = RetT (ClassT::*)(ArgTs...);
0607   MethodWrapperHandler(MethodT M) : M(M) {}
0608   RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args) {
0609     return (ObjAddr.toPtr<ClassT*>()->*M)(std::forward<ArgTs>(Args)...);
0610   }
0611 
0612 private:
0613   MethodT M;
0614 };
0615 
0616 /// Create a MethodWrapperHandler object from the given method pointer.
0617 template <typename RetT, typename ClassT, typename... ArgTs>
0618 MethodWrapperHandler<RetT, ClassT, ArgTs...>
0619 makeMethodWrapperHandler(RetT (ClassT::*Method)(ArgTs...)) {
0620   return MethodWrapperHandler<RetT, ClassT, ArgTs...>(Method);
0621 }
0622 
0623 /// Represents a serialized wrapper function call.
0624 /// Serializing calls themselves allows us to batch them: We can make one
0625 /// "run-wrapper-functions" utility and send it a list of calls to run.
0626 ///
0627 /// The motivating use-case for this API is JITLink allocation actions, where
0628 /// we want to run multiple functions to finalize linked memory without having
0629 /// to make separate IPC calls for each one.
0630 class WrapperFunctionCall {
0631 public:
0632   using ArgDataBufferType = SmallVector<char, 24>;
0633 
0634   /// Create a WrapperFunctionCall using the given SPS serializer to serialize
0635   /// the arguments.
0636   template <typename SPSSerializer, typename... ArgTs>
0637   static Expected<WrapperFunctionCall> Create(ExecutorAddr FnAddr,
0638                                               const ArgTs &...Args) {
0639     ArgDataBufferType ArgData;
0640     ArgData.resize(SPSSerializer::size(Args...));
0641     SPSOutputBuffer OB(ArgData.empty() ? nullptr : ArgData.data(),
0642                        ArgData.size());
0643     if (SPSSerializer::serialize(OB, Args...))
0644       return WrapperFunctionCall(FnAddr, std::move(ArgData));
0645     return make_error<StringError>("Cannot serialize arguments for "
0646                                    "AllocActionCall",
0647                                    inconvertibleErrorCode());
0648   }
0649 
0650   WrapperFunctionCall() = default;
0651 
0652   /// Create a WrapperFunctionCall from a target function and arg buffer.
0653   WrapperFunctionCall(ExecutorAddr FnAddr, ArgDataBufferType ArgData)
0654       : FnAddr(FnAddr), ArgData(std::move(ArgData)) {}
0655 
0656   /// Returns the address to be called.
0657   const ExecutorAddr &getCallee() const { return FnAddr; }
0658 
0659   /// Returns the argument data.
0660   const ArgDataBufferType &getArgData() const { return ArgData; }
0661 
0662   /// WrapperFunctionCalls convert to true if the callee is non-null.
0663   explicit operator bool() const { return !!FnAddr; }
0664 
0665   /// Run call returning raw WrapperFunctionResult.
0666   shared::WrapperFunctionResult run() const {
0667     using FnTy =
0668         shared::CWrapperFunctionResult(const char *ArgData, size_t ArgSize);
0669     return shared::WrapperFunctionResult(
0670         FnAddr.toPtr<FnTy *>()(ArgData.data(), ArgData.size()));
0671   }
0672 
0673   /// Run call and deserialize result using SPS.
0674   template <typename SPSRetT, typename RetT>
0675   std::enable_if_t<!std::is_same<SPSRetT, void>::value, Error>
0676   runWithSPSRet(RetT &RetVal) const {
0677     auto WFR = run();
0678     if (const char *ErrMsg = WFR.getOutOfBandError())
0679       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
0680     shared::SPSInputBuffer IB(WFR.data(), WFR.size());
0681     if (!shared::SPSSerializationTraits<SPSRetT, RetT>::deserialize(IB, RetVal))
0682       return make_error<StringError>("Could not deserialize result from "
0683                                      "serialized wrapper function call",
0684                                      inconvertibleErrorCode());
0685     return Error::success();
0686   }
0687 
0688   /// Overload for SPS functions returning void.
0689   template <typename SPSRetT>
0690   std::enable_if_t<std::is_same<SPSRetT, void>::value, Error>
0691   runWithSPSRet() const {
0692     shared::SPSEmpty E;
0693     return runWithSPSRet<shared::SPSEmpty>(E);
0694   }
0695 
0696   /// Run call and deserialize an SPSError result. SPSError returns and
0697   /// deserialization failures are merged into the returned error.
0698   Error runWithSPSRetErrorMerged() const {
0699     detail::SPSSerializableError RetErr;
0700     if (auto Err = runWithSPSRet<SPSError>(RetErr))
0701       return Err;
0702     return detail::fromSPSSerializable(std::move(RetErr));
0703   }
0704 
0705 private:
0706   orc::ExecutorAddr FnAddr;
0707   ArgDataBufferType ArgData;
0708 };
0709 
0710 using SPSWrapperFunctionCall = SPSTuple<SPSExecutorAddr, SPSSequence<char>>;
0711 
0712 template <>
0713 class SPSSerializationTraits<SPSWrapperFunctionCall, WrapperFunctionCall> {
0714 public:
0715   static size_t size(const WrapperFunctionCall &WFC) {
0716     return SPSWrapperFunctionCall::AsArgList::size(WFC.getCallee(),
0717                                                    WFC.getArgData());
0718   }
0719 
0720   static bool serialize(SPSOutputBuffer &OB, const WrapperFunctionCall &WFC) {
0721     return SPSWrapperFunctionCall::AsArgList::serialize(OB, WFC.getCallee(),
0722                                                         WFC.getArgData());
0723   }
0724 
0725   static bool deserialize(SPSInputBuffer &IB, WrapperFunctionCall &WFC) {
0726     ExecutorAddr FnAddr;
0727     WrapperFunctionCall::ArgDataBufferType ArgData;
0728     if (!SPSWrapperFunctionCall::AsArgList::deserialize(IB, FnAddr, ArgData))
0729       return false;
0730     WFC = WrapperFunctionCall(FnAddr, std::move(ArgData));
0731     return true;
0732   }
0733 };
0734 
0735 } // end namespace shared
0736 } // end namespace orc
0737 } // end namespace llvm
0738 
0739 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H