LLVM 24.0.0git
SPSProxySpec.h
Go to the documentation of this file.
1//===------- SPSProxySpec.h - SPS dispatch for orc::Proxy -------*- 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// ProxySpec implements an orc::Proxy's dispatch by invoking an executor-side
10// wrapper function in the runtime's controller interface, using Simple Packed
11// Serialization to encode arguments and decode results.
12//
13// A ProxySpec is built from a controller-interface descriptor from
14// Shared/SPSCI, which supplies the wrapper name and wire signature. It can
15// dispatch for any Proxy whose argument and result types are serializable
16// with that signature. Specs for specific operation families live alongside
17// the utilities that use them (e.g. CallProxiesSPS.h,
18// EPCGenericMemoryAccessSPS.h).
19//
20//===----------------------------------------------------------------------===//
21
22#ifndef LLVM_EXECUTIONENGINE_ORC_SPSPROXYSPEC_H
23#define LLVM_EXECUTIONENGINE_ORC_SPSPROXYSPEC_H
24
28
29#include <type_traits>
30
31namespace llvm::orc::sps {
32
33/// Dispatches proxies for the call described by CI, which must provide:
34///
35/// static constexpr SymbolNameSpec Name; // The default wrapper name.
36/// using SPSSig = ...; // The call's SPS signature.
37template <typename CI, typename SPSSigT = typename CI::SPSSig> class ProxySpec;
38
39template <typename CI, typename SPSRetTagT, typename... SPSArgTagTs>
40class ProxySpec<CI, SPSRetTagT(SPSArgTagTs...)> {
41
42 using SPSSigT = SPSRetTagT(SPSArgTagTs...);
43
44 template <typename X> struct IsSPSExpected : std::false_type {};
45 template <typename X>
46 struct IsSPSExpected<shared::SPSExpected<X>> : std::true_type {};
47
48 /// Recovers a proxy's callee return type from the result type delivered to
49 /// the client (see Proxy::ErrorRetT) and the SPS return tag:
50 ///
51 /// Error with void -> void
52 /// Error with SPSError -> Error
53 /// Expected<T> with SPSExpected -> Expected<T>
54 /// Expected<T> with any other -> T
55 ///
56 /// The primary template handles Error.
57 template <typename ErrorRetT> struct CalleeRet {
58 static_assert(std::is_same_v<ErrorRetT, Error>,
59 "ErrorRetT must be Error or Expected<T>");
60 using type = std::conditional_t<std::is_void_v<SPSRetTagT>, void, Error>;
61 };
62 template <typename T> struct CalleeRet<Expected<T>> {
63 using type =
64 std::conditional_t<IsSPSExpected<SPSRetTagT>::value, Expected<T>, T>;
65 };
66
67 static void consumeResult(Error &Err) { consumeError(std::move(Err)); }
68
69 template <typename T> static void consumeResult(T &V) {}
70
71 template <typename T> static void consumeResult(Expected<T> &E) {
72 consumeError(E.takeError());
73 }
74
75public:
76 static constexpr SymbolNameSpec Name = CI::Name;
77
78 /// Dispatch function for any Proxy whose arguments and result are
79 /// serializable with CI::SPSSig. Its template arguments are deduced when it
80 /// is converted to the Proxy's DispatchFn type.
81 template <typename ErrorRetT, typename... ArgTs>
82 static void dispatch(unique_function<void(ErrorRetT)> OnComplete,
83 ExecutionSession &ES, ExecutorAddr CalleeAddr,
84 const ArgTs &...Args) {
85 using CalleeRetT = typename CalleeRet<ErrorRetT>::type;
86 static_assert(
87 std::is_same_v<typename orc::detail::ProxyErrorRet<CalleeRetT>::type,
88 ErrorRetT>,
89 "CalleeRet must invert ProxyErrorRet");
90
91 auto Caller = [&ES, CalleeAddr](auto &&SendResult, const char *ArgData,
92 size_t ArgSize) {
93 ES.callWrapperAsync(CalleeAddr,
94 std::forward<decltype(SendResult)>(SendResult),
95 ArrayRef<char>(ArgData, ArgSize));
96 };
97
98 if constexpr (std::is_void_v<CalleeRetT>) {
99 // Void result: the executor-side function produces no value, so the only
100 // thing to report is the dispatch error (success if the call ran).
101 shared::WrapperFunction<SPSSigT>::callAsync(Caller, std::move(OnComplete),
102 Args...);
103 } else {
105 Caller,
106 [OnComplete = std::move(OnComplete)](Error SerErr,
107 CalleeRetT Result) mutable {
108 if (SerErr) {
109 consumeResult(Result);
110 return OnComplete(std::move(SerErr));
111 }
112 // For an Error/Expected callee this forwards the callee's own
113 // result; for a plain value it is wrapped into Expected.
114 return OnComplete(std::move(Result));
115 },
116 Args...);
117 }
118 }
119};
120
121} // namespace llvm::orc::sps
122
123#endif // LLVM_EXECUTIONENGINE_ORC_SPSPROXYSPEC_H
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define T
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
An ExecutionSession represents a running JIT program.
Definition Core.h:1104
void callWrapperAsync(ExecutorAddr WrapperFnAddr, ExecutorProcessControl::IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer)
Run a wrapper function in the executor.
Definition Core.h:1394
Represents an address in the executor process.
A symbol name together with the naming level (SymbolNameKind) it is expressed in, so that a Mangler /...
static void dispatch(unique_function< void(ErrorRetT)> OnComplete, ExecutionSession &ES, ExecutorAddr CalleeAddr, const ArgTs &...Args)
Dispatch function for any Proxy whose arguments and result are serializable with CI::SPSSig.
Dispatches proxies for the call described by CI, which must provide:
unique_function is a type-erasing functor similar to std::function.
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106