LLVM 22.0.0git
CallViaEPC.h
Go to the documentation of this file.
1//===------ CallViaEPC.h - Call wrapper functions via EPC -------*- 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// Call executor functions with common signatures via
10// ExecutorProcessControl::callWrapperAsync.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_ORC_CALLVIAEPC_H
15#define LLVM_EXECUTIONENGINE_ORC_CALLVIAEPC_H
16
19#include "llvm/Support/Error.h"
21
22#include <type_traits>
23
24namespace llvm::orc {
25
26namespace detail {
27
28template <typename HandlerArgT> struct CallViaEPCRetValueTraits;
29
30template <typename RetT> struct CallViaEPCRetValueTraits<Expected<RetT>> {
31 using value_type = RetT;
32};
33
34template <> struct CallViaEPCRetValueTraits<Error> {
35 using value_type = void;
36};
37
38template <typename RetT> struct CallViaEPCRetValueTraits<MSVCPExpected<RetT>> {
39 using value_type = RetT;
40};
41
43 using value_type = void;
44};
45
46// Helper to extract the argument type from a handler callable.
47template <typename HandlerT> struct CallViaEPCHandlerTraits {
49 using ArgsTuple = typename ArgInfo::ArgsTupleType;
50 static_assert(std::tuple_size_v<ArgsTuple> == 1,
51 "Handler must take exactly one argument");
52 using HandlerArgT = std::tuple_element_t<0, ArgsTuple>;
54 std::remove_cv_t<std::remove_reference_t<HandlerArgT>>>::value_type;
55};
56
57} // namespace detail
58
59/// Call a wrapper function via EPC asynchronously.
60template <typename HandlerFn, typename Serializer, typename... ArgTs>
61std::enable_if_t<std::is_invocable_v<HandlerFn, Error>>
62callViaEPC(HandlerFn &&H, ExecutorProcessControl &EPC, Serializer S,
63 ExecutorSymbolDef Fn, ArgTs &&...Args) {
65
66 if (auto ArgBytes = S.serialize(std::forward<ArgTs>(Args)...))
68 Fn.getAddress(),
69 [S = std::move(S), H = std::forward<HandlerFn>(H)](
71 if (const char *ErrMsg = R.getOutOfBandError())
72 H(make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
73 else
74 H(S.template deserialize<RetT>(std::move(R)));
75 },
76 {ArgBytes->data(), ArgBytes->size()});
77 else
78 H(ArgBytes.takeError());
79}
80
81/// Call a wrapper function via EPC synchronously using the given promise.
82///
83/// This performs a blocking call by making an asynchronous call to set the
84/// promise and waiting on a future.
85///
86/// Blocking calls should only be used for convenience by ORC clients, never
87/// internally.
88template <typename PromiseT, typename Serializer, typename... ArgTs>
89std::enable_if_t<!std::is_invocable_v<PromiseT, Error>,
90 decltype(std::declval<PromiseT>().get_future().get())>
91callViaEPC(PromiseT &&P, ExecutorProcessControl &EPC, Serializer S,
92 ExecutorSymbolDef Fn, ArgTs &&...Args) {
93 auto F = P.get_future();
94 using RetT = decltype(F.get());
95 callViaEPC([P = std::move(P)](RetT R) mutable { P.set_value(std::move(R)); },
96 EPC, std::move(S), std::move(Fn), std::forward<ArgTs>(Args)...);
97 return F.get();
98}
99
100/// Encapsulates calls via EPC to any function that's compatible with the given
101/// serialization scheme.
102template <typename Serializer> class EPCCaller {
103public:
104 EPCCaller(ExecutorProcessControl &EPC, Serializer &&S)
105 : EPC(EPC), S(std::move(S)) {}
106
107 // TODO: Add an ExecutionSession constructor once ExecutionSession has been
108 // moved to its own header.
109
110 // Make a call to the given function using callViaEPC.
111 //
112 // The PromiseOrHandlerT value is forwarded. Its type will determine both the
113 // return value type and the dispatch method (asynchronous vs synchronous).
114 template <typename PromiseOrHandlerT, typename... ArgTs>
115 decltype(auto) operator()(PromiseOrHandlerT &&R, ExecutorSymbolDef Fn,
116 ArgTs &&...Args) {
117 return callViaEPC(std::forward<PromiseOrHandlerT>(R), EPC, S, Fn,
118 std::forward<ArgTs>(Args)...);
119 }
120
121private:
123 Serializer S;
124};
125
126/// Encapsulates calls via EPC to a specific function, using the given
127/// serialization scheme.
128template <typename Serializer> class EPCCall {
129public:
131 : Caller(EPC, std::move(S)), Fn(std::move(Fn)) {}
132
133 // TODO: Add an ExecutionSession constructor once ExecutionSession has been
134 // moved to its own header.
135
136 // Make a call using callViaEPC.
137 //
138 // The PromiseOrHandlerT value is forwarded. Its type will determine both the
139 // return value type and the dispatch method (asynchronous vs synchronous).
140 template <typename PromiseOrHandlerT, typename... ArgTs>
141 decltype(auto) operator()(PromiseOrHandlerT &&R, ArgTs &&...Args) {
142 return Caller(std::forward<PromiseOrHandlerT>(R), Fn,
143 std::forward<ArgTs>(Args)...);
144 }
145
146private:
149};
150
151} // namespace llvm::orc
152
153#endif // LLVM_EXECUTIONENGINE_ORC_CALLVIAEPC_H
#define F(x, y, z)
Definition MD5.cpp:54
#define H(x, y, z)
Definition MD5.cpp:56
#define P(N)
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
EPCCall(ExecutorProcessControl &EPC, Serializer &&S, ExecutorSymbolDef Fn)
Definition CallViaEPC.h:130
decltype(auto) operator()(PromiseOrHandlerT &&R, ArgTs &&...Args)
Definition CallViaEPC.h:141
Encapsulates calls via EPC to any function that's compatible with the given serialization scheme.
Definition CallViaEPC.h:102
decltype(auto) operator()(PromiseOrHandlerT &&R, ExecutorSymbolDef Fn, ArgTs &&...Args)
Definition CallViaEPC.h:115
EPCCaller(ExecutorProcessControl &EPC, Serializer &&S)
Definition CallViaEPC.h:104
ExecutorProcessControl supports interaction with a JIT target process.
virtual void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer)=0
Run a wrapper function in the executor.
Represents a defining location for a JIT symbol.
const ExecutorAddr & getAddress() const
C++ wrapper function result: Same as CWrapperFunctionResult but auto-releases memory.
std::enable_if_t< std::is_invocable_v< HandlerFn, Error > > callViaEPC(HandlerFn &&H, ExecutorProcessControl &EPC, Serializer S, ExecutorSymbolDef Fn, ArgTs &&...Args)
Call a wrapper function via EPC asynchronously.
Definition CallViaEPC.h:62
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1867
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
CallableArgInfo provides typedefs for the return type and argument types (as a tuple) of the given ca...
typename CallViaEPCRetValueTraits< std::remove_cv_t< std::remove_reference_t< HandlerArgT > > >::value_type RetT
Definition CallViaEPC.h:53
std::tuple_element_t< 0, ArgsTuple > HandlerArgT
Definition CallViaEPC.h:52
CallableArgInfo< HandlerT > ArgInfo
Definition CallViaEPC.h:48
typename ArgInfo::ArgsTupleType ArgsTuple
Definition CallViaEPC.h:49