13#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
14#define LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
89 "Cannot get data for out-of-band error value");
96 "Cannot get data for out-of-band error value");
103 "Cannot get data for out-of-band error value");
125 memcpy(WFR.data(), Source,
Size);
131 return copyFrom(Source, strlen(Source) + 1);
143 char *Tmp = (
char *)malloc(strlen(Msg) + 1);
162 R.Data.ValuePtr =
nullptr;
166 CWrapperFunctionResult R;
171template <
typename SPSArgListT,
typename... ArgTs>
176 if (!SPSArgListT::serialize(OB, Args...))
178 "Error serializing arguments to blob in call");
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)...);
193 template <
typename HandlerT,
typename ArgTupleT, std::size_t...
I>
195 std::index_sequence<I...>) {
196 std::forward<HandlerT>(
H)(std::get<I>(Args)...);
201template <
typename WrapperFunctionImplT,
202 template <
typename>
class ResultSerializer,
typename... SPSTagTs>
205 decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
206 ResultSerializer, SPSTagTs...> {};
208template <
typename RetT,
typename... ArgTs,
213 using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
214 using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
216 template <
typename HandlerT>
220 if (!deserialize(ArgData, ArgSize, Args,
ArgIndices{}))
222 "Could not deserialize arguments for wrapper function call");
228 std::move(HandlerResult));
232 template <std::size_t...
I>
233 static bool deserialize(
const char *ArgData,
size_t ArgSize, ArgTuple &Args,
234 std::index_sequence<I...>) {
241template <
typename RetT,
typename... ArgTs,
242 template <
typename>
class ResultSerializer,
typename... SPSTagTs>
249template <
typename ClassT,
typename RetT,
typename... ArgTs,
257template <
typename ClassT,
typename RetT,
typename... ArgTs,
264template <
typename WrapperFunctionImplT,
268 decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
269 ResultSerializer, SPSTagTs...> {};
271template <
typename RetT,
typename SendResultT,
typename... ArgTs,
276 using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
277 using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
279 template <
typename HandlerT,
typename SendWrapperFunctionResultT>
281 SendWrapperFunctionResultT &&SendWrapperFunctionResult,
282 const char *ArgData,
size_t ArgSize) {
284 if (!deserialize(ArgData, ArgSize, Args,
ArgIndices{})) {
286 "Could not deserialize arguments for wrapper function call"));
291 [SendWFR = std::move(SendWrapperFunctionResult)](
auto Result)
mutable {
292 using ResultT =
decltype(
Result);
296 callAsync(std::forward<HandlerT>(
H), std::move(SendResult), std::move(Args),
301 template <std::size_t...
I>
302 static bool deserialize(
const char *ArgData,
size_t ArgSize, ArgTuple &Args,
303 std::index_sequence<I...>) {
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...>) {
314 return std::forward<HandlerT>(
H)(std::move(SerializeAndSendResult),
315 std::move(std::get<I>(Args))...);
320template <
typename RetT,
typename... ArgTs,
321 template <
typename>
class ResultSerializer,
typename... SPSTagTs>
328template <
typename ClassT,
typename RetT,
typename... ArgTs,
336template <
typename ClassT,
typename RetT,
typename... ArgTs,
346 return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
354 return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
359template <
typename SPSRetTagT>
363 return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
368template <
typename SPSRetTagT,
typename T>
372 return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
385 return make_error<StringError>(
386 "Error deserializing return value from blob in call",
401 return make_error<StringError>(
402 "Error deserializing return value from blob in call",
409template <
typename SPSTagT,
typename T>
420 return make_error<StringError>(
421 "Error deserializing return value from blob in call",
436template <
typename SPSRetTagT,
typename... SPSTagTs>
439 template <
typename RetT>
445 template <
typename CallerFn,
typename RetT,
typename... ArgTs>
447 const ArgTs &...Args) {
457 if (
const char *ErrMsg = ArgBuffer.getOutOfBandError())
461 Caller(ArgBuffer.data(), ArgBuffer.size());
473 template <
typename AsyncCallerFn,
typename SendDeserializedResultFn,
476 SendDeserializedResultFn &&SendDeserializedResult,
477 const ArgTs &...Args) {
478 using RetT =
typename std::tuple_element<
480 std::remove_reference_t<SendDeserializedResultFn>,
486 if (
auto *ErrMsg = ArgBuffer.getOutOfBandError()) {
487 SendDeserializedResult(
493 auto SendSerializedResult = [SDR = std::move(SendDeserializedResult)](
498 if (
auto *ErrMsg = R.getOutOfBandError()) {
506 RetVal, R.data(), R.size())) {
507 SDR(std::move(Err), std::move(RetVal));
514 Caller(std::move(SendSerializedResult), ArgBuffer.data(), ArgBuffer.size());
518 template <
typename HandlerT>
520 HandlerT &&Handler) {
524 return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize);
528 template <
typename HandlerT,
typename SendResultT>
530 SendResultT &&SendResult, HandlerT &&Handler) {
533 WFAHH::applyAsync(std::forward<HandlerT>(Handler),
534 std::forward<SendResultT>(SendResult), ArgData, ArgSize);
538 template <
typename T>
static const T &makeSerializable(
const T &
Value) {
542 static detail::SPSSerializableError makeSerializable(
Error Err) {
546 template <
typename T>
547 static detail::SPSSerializableExpected<T> makeSerializable(
Expected<T> E) {
552template <
typename... SPSTagTs>
557 template <
typename CallerFn,
typename... ArgTs>
558 static Error call(
const CallerFn &Caller,
const ArgTs &...Args) {
563 template <
typename AsyncCallerFn,
typename SendDeserializedResultFn,
566 SendDeserializedResultFn &&SendDeserializedResult,
567 const ArgTs &...Args) {
569 std::forward<AsyncCallerFn>(Caller),
570 [SDR = std::move(SendDeserializedResult)](
Error SerializeErr,
572 SDR(std::move(SerializeErr));
603template <
typename RetT,
typename ClassT,
typename... ArgTs>
609 return (ObjAddr.
toPtr<ClassT*>()->*M)(std::forward<ArgTs>(Args)...);
617template <
typename RetT,
typename ClassT,
typename... ArgTs>
618MethodWrapperHandler<RetT, ClassT, ArgTs...>
636 template <
typename SPSSerializer,
typename... ArgTs>
638 const ArgTs &...Args) {
640 ArgData.
resize(SPSSerializer::size(Args...));
643 if (SPSSerializer::serialize(OB, Args...))
645 return make_error<StringError>(
"Cannot serialize arguments for "
654 : FnAddr(FnAddr), ArgData(
std::
move(ArgData)) {}
663 explicit operator bool()
const {
return !!FnAddr; }
670 FnAddr.
toPtr<FnTy *>()(ArgData.data(), ArgData.size()));
674 template <
typename SPSRetT,
typename RetT>
675 std::enable_if_t<!std::is_same<SPSRetT, void>::value,
Error>
678 if (
const char *ErrMsg = WFR.getOutOfBandError())
682 return make_error<StringError>(
"Could not deserialize result from "
683 "serialized wrapper function call",
689 template <
typename SPSRetT>
690 std::enable_if_t<std::is_same<SPSRetT, void>::value,
Error>
693 return runWithSPSRet<shared::SPSEmpty>(
E);
700 if (
auto Err = runWithSPSRet<SPSError>(RetErr))
716 return SPSWrapperFunctionCall::AsArgList::size(WFC.
getCallee(),
721 return SPSWrapperFunctionCall::AsArgList::serialize(OB, WFC.
getCallee(),
728 if (!SPSWrapperFunctionCall::AsArgList::deserialize(IB, FnAddr, ArgData))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
pointer data()
Return a pointer to the vector's buffer, even if empty().
LLVM Value Representation.
Represents an address in the executor process.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
A function object that takes an ExecutorAddr as its first argument, casts that address to a ClassT*,...
RetT(ClassT::*)(ArgTs...) MethodT
MethodWrapperHandler(MethodT M)
RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args)
A utility class for serializing to a blob from a variadic list.
SPS tag type for expecteds, which are either a T or a string representing an error.
Output char buffer with overflow check.
static size_t size(const WrapperFunctionCall &WFC)
static bool deserialize(SPSInputBuffer &IB, WrapperFunctionCall &WFC)
static bool serialize(SPSOutputBuffer &OB, const WrapperFunctionCall &WFC)
Specialize to describe how to serialize/deserialize to/from the given concrete type.
Represents a serialized wrapper function call.
const ArgDataBufferType & getArgData() const
Returns the argument data.
WrapperFunctionCall(ExecutorAddr FnAddr, ArgDataBufferType ArgData)
Create a WrapperFunctionCall from a target function and arg buffer.
WrapperFunctionCall()=default
Error runWithSPSRetErrorMerged() const
Run call and deserialize an SPSError result.
std::enable_if_t<!std::is_same< SPSRetT, void >::value, Error > runWithSPSRet(RetT &RetVal) const
Run call and deserialize result using SPS.
const ExecutorAddr & getCallee() const
Returns the address to be called.
SmallVector< char, 24 > ArgDataBufferType
shared::WrapperFunctionResult run() const
Run call returning raw WrapperFunctionResult.
static Expected< WrapperFunctionCall > Create(ExecutorAddr FnAddr, const ArgTs &...Args)
Create a WrapperFunctionCall using the given SPS serializer to serialize the arguments.
std::enable_if_t< std::is_same< SPSRetT, void >::value, Error > runWithSPSRet() const
Overload for SPS functions returning void.
C++ wrapper function result: Same as CWrapperFunctionResult but auto-releases memory.
static WrapperFunctionResult copyFrom(const std::string &Source)
Copy from the given std::string (includes the null terminator).
static WrapperFunctionResult copyFrom(const char *Source, size_t Size)
Copy from the given char range.
static WrapperFunctionResult allocate(size_t Size)
Create a WrapperFunctionResult with the given size and return a pointer to the underlying memory.
WrapperFunctionResult(CWrapperFunctionResult R)
Create a WrapperFunctionResult by taking ownership of a CWrapperFunctionResult.
WrapperFunctionResult(const WrapperFunctionResult &)=delete
static WrapperFunctionResult createOutOfBandError(const std::string &Msg)
Create an out-of-band error by copying the given string.
CWrapperFunctionResult release()
Release ownership of the contained CWrapperFunctionResult.
bool empty() const
Returns true if this value is equivalent to a default-constructed WrapperFunctionResult.
WrapperFunctionResult & operator=(const WrapperFunctionResult &)=delete
const char * getOutOfBandError() const
If this value is an out-of-band error then this returns the error message, otherwise returns nullptr.
WrapperFunctionResult()
Create a default WrapperFunctionResult.
static WrapperFunctionResult copyFrom(const char *Source)
Copy from the given null-terminated string (includes the null-terminator).
WrapperFunctionResult(WrapperFunctionResult &&Other)
const char * data() const
Get a const pointer to the data contained in this instance.
static WrapperFunctionResult createOutOfBandError(const char *Msg)
Create an out-of-band error by copying the given string.
size_t size() const
Returns the size of the data contained in this instance.
WrapperFunctionResult & operator=(WrapperFunctionResult &&Other)
char * data()
Get a pointer to the data contained in this instance.
static void handleAsync(const char *ArgData, size_t ArgSize, SendResultT &&SendResult, HandlerT &&Handler)
Handle a call to an async wrapper function.
static void callAsync(AsyncCallerFn &&Caller, SendDeserializedResultFn &&SendDeserializedResult, const ArgTs &...Args)
Call an async wrapper function.
static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize, HandlerT &&Handler)
Handle a call to a wrapper function.
static Error call(const CallerFn &Caller, RetT &Result, const ArgTs &...Args)
Call a wrapper function.
static Error call(const CallerFn &Caller, const ArgTs &...Args)
static void callAsync(AsyncCallerFn &&Caller, SendDeserializedResultFn &&SendDeserializedResult, const ArgTs &...Args)
static void makeSafe(Error &Err)
static Error deserialize(Error &Err, const char *ArgData, size_t ArgSize)
static Error deserialize(Expected< T > &E, const char *ArgData, size_t ArgSize)
static Expected< T > makeValue()
static void makeSafe(Expected< T > &E)
static Error deserialize(RetT &Result, const char *ArgData, size_t ArgSize)
static void makeSafe(RetT &Result)
static WrapperFunctionResult serialize(ErrorSuccess Err)
static WrapperFunctionResult serialize(Error Err)
static WrapperFunctionResult serialize(Expected< T > E)
static WrapperFunctionResult serialize(RetT Result)
static void applyAsync(HandlerT &&H, SendWrapperFunctionResultT &&SendWrapperFunctionResult, const char *ArgData, size_t ArgSize)
std::tuple< std::decay_t< ArgTs >... > ArgTuple
std::make_index_sequence< std::tuple_size< ArgTuple >::value > ArgIndices
static SPSEmpty call(HandlerT &&H, ArgTupleT &Args, std::index_sequence< I... >)
static decltype(auto) call(HandlerT &&H, ArgTupleT &Args, std::index_sequence< I... >)
static WrapperFunctionResult apply(HandlerT &&H, const char *ArgData, size_t ArgSize)
std::tuple< std::decay_t< ArgTs >... > ArgTuple
std::make_index_sequence< std::tuple_size< ArgTuple >::value > ArgIndices
SPSSerializableError toSPSSerializable(Error Err)
WrapperFunctionResult serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args)
Error fromSPSSerializable(SPSSerializableError BSE)
MethodWrapperHandler< RetT, ClassT, ArgTs... > makeMethodWrapperHandler(RetT(ClassT::*Method)(ArgTs...))
Create a MethodWrapperHandler object from the given method pointer.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
CWrapperFunctionResultDataUnion Data
Helper type for serializing Errors.
Helper type for serializing Expected<T>s.
char Value[sizeof(ValuePtr)]