WrapperFunctionUtils.h 28 KB

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