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 HandlerT &&Handler, SendResultT &&SendResult) {
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))
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 callAsync(AsyncCallerFn &&Caller, SendDeserializedResultFn &&SendDeserializedResult, const ArgTs &...Args)
Call an async wrapper function.
static void handleAsync(const char *ArgData, size_t ArgSize, HandlerT &&Handler, SendResultT &&SendResult)
Handle a call to 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.
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)]