[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
//===-- wrapper_function_utils.h - Utilities for wrapper funcs --*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of the ORC runtime support library.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef ORC_RT_WRAPPER_FUNCTION_UTILS_H
|
|
|
|
#define ORC_RT_WRAPPER_FUNCTION_UTILS_H
|
|
|
|
|
|
|
|
#include "c_api.h"
|
|
|
|
#include "common.h"
|
|
|
|
#include "error.h"
|
2021-10-20 06:28:07 +08:00
|
|
|
#include "executor_address.h"
|
2021-06-13 06:55:47 +08:00
|
|
|
#include "simple_packed_serialization.h"
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
namespace __orc_rt {
|
|
|
|
|
|
|
|
/// C++ wrapper function result: Same as CWrapperFunctionResult but
|
|
|
|
/// auto-releases memory.
|
|
|
|
class WrapperFunctionResult {
|
|
|
|
public:
|
|
|
|
/// Create a default WrapperFunctionResult.
|
|
|
|
WrapperFunctionResult() { __orc_rt_CWrapperFunctionResultInit(&R); }
|
|
|
|
|
|
|
|
/// Create a WrapperFunctionResult from a CWrapperFunctionResult. This
|
|
|
|
/// instance takes ownership of the result object and will automatically
|
|
|
|
/// call dispose on the result upon destruction.
|
|
|
|
WrapperFunctionResult(__orc_rt_CWrapperFunctionResult R) : R(R) {}
|
|
|
|
|
|
|
|
WrapperFunctionResult(const WrapperFunctionResult &) = delete;
|
|
|
|
WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
|
|
|
|
|
|
|
|
WrapperFunctionResult(WrapperFunctionResult &&Other) {
|
|
|
|
__orc_rt_CWrapperFunctionResultInit(&R);
|
|
|
|
std::swap(R, Other.R);
|
|
|
|
}
|
|
|
|
|
|
|
|
WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
|
|
|
|
__orc_rt_CWrapperFunctionResult Tmp;
|
|
|
|
__orc_rt_CWrapperFunctionResultInit(&Tmp);
|
|
|
|
std::swap(Tmp, Other.R);
|
|
|
|
std::swap(R, Tmp);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~WrapperFunctionResult() { __orc_rt_DisposeCWrapperFunctionResult(&R); }
|
|
|
|
|
|
|
|
/// Relinquish ownership of and return the
|
|
|
|
/// __orc_rt_CWrapperFunctionResult.
|
|
|
|
__orc_rt_CWrapperFunctionResult release() {
|
|
|
|
__orc_rt_CWrapperFunctionResult Tmp;
|
|
|
|
__orc_rt_CWrapperFunctionResultInit(&Tmp);
|
|
|
|
std::swap(R, Tmp);
|
|
|
|
return Tmp;
|
|
|
|
}
|
|
|
|
|
2021-06-13 17:31:36 +08:00
|
|
|
/// Get a pointer to the data contained in this instance.
|
2021-08-24 15:16:20 +08:00
|
|
|
char *data() { return __orc_rt_CWrapperFunctionResultData(&R); }
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
|
|
|
|
/// Returns the size of the data contained in this instance.
|
|
|
|
size_t size() const { return __orc_rt_CWrapperFunctionResultSize(&R); }
|
|
|
|
|
|
|
|
/// Returns true if this value is equivalent to a default-constructed
|
|
|
|
/// WrapperFunctionResult.
|
|
|
|
bool empty() const { return __orc_rt_CWrapperFunctionResultEmpty(&R); }
|
|
|
|
|
|
|
|
/// Create a WrapperFunctionResult with the given size and return a pointer
|
|
|
|
/// to the underlying memory.
|
2021-08-24 15:16:20 +08:00
|
|
|
static WrapperFunctionResult allocate(size_t Size) {
|
|
|
|
WrapperFunctionResult R;
|
|
|
|
R.R = __orc_rt_CWrapperFunctionResultAllocate(Size);
|
|
|
|
return R;
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Copy from the given char range.
|
|
|
|
static WrapperFunctionResult copyFrom(const char *Source, size_t Size) {
|
|
|
|
return __orc_rt_CreateCWrapperFunctionResultFromRange(Source, Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copy from the given null-terminated string (includes the null-terminator).
|
|
|
|
static WrapperFunctionResult copyFrom(const char *Source) {
|
|
|
|
return __orc_rt_CreateCWrapperFunctionResultFromString(Source);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copy from the given std::string (includes the null terminator).
|
|
|
|
static WrapperFunctionResult copyFrom(const std::string &Source) {
|
|
|
|
return copyFrom(Source.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create an out-of-band error by copying the given string.
|
|
|
|
static WrapperFunctionResult createOutOfBandError(const char *Msg) {
|
|
|
|
return __orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(Msg);
|
|
|
|
}
|
|
|
|
|
2021-06-13 06:55:47 +08:00
|
|
|
/// Create an out-of-band error by copying the given string.
|
|
|
|
static WrapperFunctionResult createOutOfBandError(const std::string &Msg) {
|
|
|
|
return createOutOfBandError(Msg.c_str());
|
|
|
|
}
|
|
|
|
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
/// If this value is an out-of-band error then this returns the error message,
|
|
|
|
/// otherwise returns nullptr.
|
|
|
|
const char *getOutOfBandError() const {
|
|
|
|
return __orc_rt_CWrapperFunctionResultGetOutOfBandError(&R);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
__orc_rt_CWrapperFunctionResult R;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
|
2021-06-13 06:55:47 +08:00
|
|
|
template <typename SPSArgListT, typename... ArgTs>
|
2021-10-19 13:11:16 +08:00
|
|
|
WrapperFunctionResult
|
2021-06-13 06:55:47 +08:00
|
|
|
serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args) {
|
2021-08-24 15:16:20 +08:00
|
|
|
auto Result = WrapperFunctionResult::allocate(SPSArgListT::size(Args...));
|
|
|
|
SPSOutputBuffer OB(Result.data(), Result.size());
|
2021-06-13 06:55:47 +08:00
|
|
|
if (!SPSArgListT::serialize(OB, Args...))
|
2021-10-19 13:11:16 +08:00
|
|
|
return WrapperFunctionResult::createOutOfBandError(
|
2021-06-13 06:55:47 +08:00
|
|
|
"Error serializing arguments to blob in call");
|
2021-10-19 13:11:16 +08:00
|
|
|
return Result;
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
}
|
|
|
|
|
2021-06-15 09:56:37 +08:00
|
|
|
template <typename RetT> class WrapperFunctionHandlerCaller {
|
|
|
|
public:
|
|
|
|
template <typename HandlerT, typename ArgTupleT, std::size_t... I>
|
|
|
|
static decltype(auto) call(HandlerT &&H, ArgTupleT &Args,
|
|
|
|
std::index_sequence<I...>) {
|
|
|
|
return std::forward<HandlerT>(H)(std::get<I>(Args)...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> class WrapperFunctionHandlerCaller<void> {
|
|
|
|
public:
|
|
|
|
template <typename HandlerT, typename ArgTupleT, std::size_t... I>
|
|
|
|
static SPSEmpty call(HandlerT &&H, ArgTupleT &Args,
|
|
|
|
std::index_sequence<I...>) {
|
|
|
|
std::forward<HandlerT>(H)(std::get<I>(Args)...);
|
|
|
|
return SPSEmpty();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
template <typename WrapperFunctionImplT,
|
|
|
|
template <typename> class ResultSerializer, typename... SPSTagTs>
|
|
|
|
class WrapperFunctionHandlerHelper
|
|
|
|
: public WrapperFunctionHandlerHelper<
|
|
|
|
decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
|
|
|
|
ResultSerializer, SPSTagTs...> {};
|
|
|
|
|
|
|
|
template <typename RetT, typename... ArgTs,
|
|
|
|
template <typename> class ResultSerializer, typename... SPSTagTs>
|
|
|
|
class WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
|
|
|
|
SPSTagTs...> {
|
|
|
|
public:
|
|
|
|
using ArgTuple = std::tuple<std::decay_t<ArgTs>...>;
|
|
|
|
using ArgIndices = std::make_index_sequence<std::tuple_size<ArgTuple>::value>;
|
|
|
|
|
|
|
|
template <typename HandlerT>
|
|
|
|
static WrapperFunctionResult apply(HandlerT &&H, const char *ArgData,
|
|
|
|
size_t ArgSize) {
|
|
|
|
ArgTuple Args;
|
|
|
|
if (!deserialize(ArgData, ArgSize, Args, ArgIndices{}))
|
|
|
|
return WrapperFunctionResult::createOutOfBandError(
|
|
|
|
"Could not deserialize arguments for wrapper function call");
|
|
|
|
|
2021-06-15 09:56:37 +08:00
|
|
|
auto HandlerResult = WrapperFunctionHandlerCaller<RetT>::call(
|
|
|
|
std::forward<HandlerT>(H), Args, ArgIndices{});
|
|
|
|
|
2021-10-19 13:11:16 +08:00
|
|
|
return ResultSerializer<decltype(HandlerResult)>::serialize(
|
|
|
|
std::move(HandlerResult));
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <std::size_t... I>
|
|
|
|
static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
|
|
|
|
std::index_sequence<I...>) {
|
|
|
|
SPSInputBuffer IB(ArgData, ArgSize);
|
|
|
|
return SPSArgList<SPSTagTs...>::deserialize(IB, std::get<I>(Args)...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-10-19 13:16:44 +08:00
|
|
|
// Map function pointers to function types.
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
template <typename RetT, typename... ArgTs,
|
|
|
|
template <typename> class ResultSerializer, typename... SPSTagTs>
|
2021-10-19 13:16:44 +08:00
|
|
|
class WrapperFunctionHandlerHelper<RetT (*)(ArgTs...), ResultSerializer,
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
SPSTagTs...>
|
|
|
|
: public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
|
|
|
|
SPSTagTs...> {};
|
|
|
|
|
|
|
|
// Map non-const member function types to function types.
|
|
|
|
template <typename ClassT, typename RetT, typename... ArgTs,
|
|
|
|
template <typename> class ResultSerializer, typename... SPSTagTs>
|
|
|
|
class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer,
|
|
|
|
SPSTagTs...>
|
|
|
|
: public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
|
|
|
|
SPSTagTs...> {};
|
|
|
|
|
|
|
|
// Map const member function types to function types.
|
|
|
|
template <typename ClassT, typename RetT, typename... ArgTs,
|
|
|
|
template <typename> class ResultSerializer, typename... SPSTagTs>
|
|
|
|
class WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...) const,
|
|
|
|
ResultSerializer, SPSTagTs...>
|
|
|
|
: public WrapperFunctionHandlerHelper<RetT(ArgTs...), ResultSerializer,
|
|
|
|
SPSTagTs...> {};
|
|
|
|
|
|
|
|
template <typename SPSRetTagT, typename RetT> class ResultSerializer {
|
|
|
|
public:
|
2021-10-19 13:11:16 +08:00
|
|
|
static WrapperFunctionResult serialize(RetT Result) {
|
2021-06-13 06:55:47 +08:00
|
|
|
return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
|
|
|
|
Result);
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename SPSRetTagT> class ResultSerializer<SPSRetTagT, Error> {
|
|
|
|
public:
|
2021-10-19 13:11:16 +08:00
|
|
|
static WrapperFunctionResult serialize(Error Err) {
|
2021-06-13 06:55:47 +08:00
|
|
|
return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
|
|
|
|
toSPSSerializable(std::move(Err)));
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename SPSRetTagT, typename T>
|
|
|
|
class ResultSerializer<SPSRetTagT, Expected<T>> {
|
|
|
|
public:
|
2021-10-19 13:11:16 +08:00
|
|
|
static WrapperFunctionResult serialize(Expected<T> E) {
|
2021-06-13 06:55:47 +08:00
|
|
|
return serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSRetTagT>>(
|
|
|
|
toSPSSerializable(std::move(E)));
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename SPSRetTagT, typename RetT> class ResultDeserializer {
|
|
|
|
public:
|
|
|
|
static void makeSafe(RetT &Result) {}
|
|
|
|
|
|
|
|
static Error deserialize(RetT &Result, const char *ArgData, size_t ArgSize) {
|
|
|
|
SPSInputBuffer IB(ArgData, ArgSize);
|
|
|
|
if (!SPSArgList<SPSRetTagT>::deserialize(IB, Result))
|
|
|
|
return make_error<StringError>(
|
|
|
|
"Error deserializing return value from blob in call");
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> class ResultDeserializer<SPSError, Error> {
|
|
|
|
public:
|
|
|
|
static void makeSafe(Error &Err) { cantFail(std::move(Err)); }
|
|
|
|
|
|
|
|
static Error deserialize(Error &Err, const char *ArgData, size_t ArgSize) {
|
|
|
|
SPSInputBuffer IB(ArgData, ArgSize);
|
|
|
|
SPSSerializableError BSE;
|
|
|
|
if (!SPSArgList<SPSError>::deserialize(IB, BSE))
|
|
|
|
return make_error<StringError>(
|
|
|
|
"Error deserializing return value from blob in call");
|
|
|
|
Err = fromSPSSerializable(std::move(BSE));
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename SPSTagT, typename T>
|
|
|
|
class ResultDeserializer<SPSExpected<SPSTagT>, Expected<T>> {
|
|
|
|
public:
|
|
|
|
static void makeSafe(Expected<T> &E) { cantFail(E.takeError()); }
|
|
|
|
|
|
|
|
static Error deserialize(Expected<T> &E, const char *ArgData,
|
|
|
|
size_t ArgSize) {
|
|
|
|
SPSInputBuffer IB(ArgData, ArgSize);
|
|
|
|
SPSSerializableExpected<T> BSE;
|
|
|
|
if (!SPSArgList<SPSExpected<SPSTagT>>::deserialize(IB, BSE))
|
|
|
|
return make_error<StringError>(
|
|
|
|
"Error deserializing return value from blob in call");
|
|
|
|
E = fromSPSSerializable(std::move(BSE));
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace detail
|
|
|
|
|
|
|
|
template <typename SPSSignature> class WrapperFunction;
|
|
|
|
|
|
|
|
template <typename SPSRetTagT, typename... SPSTagTs>
|
|
|
|
class WrapperFunction<SPSRetTagT(SPSTagTs...)> {
|
|
|
|
private:
|
|
|
|
template <typename RetT>
|
|
|
|
using ResultSerializer = detail::ResultSerializer<SPSRetTagT, RetT>;
|
|
|
|
|
|
|
|
public:
|
|
|
|
template <typename RetT, typename... ArgTs>
|
|
|
|
static Error call(const void *FnTag, RetT &Result, const ArgTs &...Args) {
|
|
|
|
|
|
|
|
// RetT might be an Error or Expected value. Set the checked flag now:
|
|
|
|
// we don't want the user to have to check the unused result if this
|
|
|
|
// operation fails.
|
|
|
|
detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(Result);
|
|
|
|
|
|
|
|
if (ORC_RT_UNLIKELY(!&__orc_rt_jit_dispatch_ctx))
|
[ORC][ORC-RT] Introduce ORC-runtime based MachO-Platform.
Adds support for MachO static initializers/deinitializers and eh-frame
registration via the ORC runtime.
This commit introduces cooperative support code into the ORC runtime and ORC
LLVM libraries (especially the MachOPlatform class) to support macho runtime
features for JIT'd code. This commit introduces support for static
initializers, static destructors (via cxa_atexit interposition), and eh-frame
registration. Near-future commits will add support for MachO native
thread-local variables, and language runtime registration (e.g. for Objective-C
and Swift).
The llvm-jitlink tool is updated to use the ORC runtime where available, and
regression tests for the new MachOPlatform support are added to compiler-rt.
Notable changes on the ORC runtime side:
1. The new macho_platform.h / macho_platform.cpp files contain the bulk of the
runtime-side support. This includes eh-frame registration; jit versions of
dlopen, dlsym, and dlclose; a cxa_atexit interpose to record static destructors,
and an '__orc_rt_macho_run_program' function that defines running a JIT'd MachO
program in terms of the jit- dlopen/dlsym/dlclose functions.
2. Replaces JITTargetAddress (and casting operations) with ExecutorAddress
(copied from LLVM) to improve type-safety of address management.
3. Adds serialization support for ExecutorAddress and unordered_map types to
the runtime-side Simple Packed Serialization code.
4. Adds orc-runtime regression tests to ensure that static initializers and
cxa-atexit interposes work as expected.
Notable changes on the LLVM side:
1. The MachOPlatform class is updated to:
1.1. Load the ORC runtime into the ExecutionSession.
1.2. Set up standard aliases for macho-specific runtime functions. E.g.
___cxa_atexit -> ___orc_rt_macho_cxa_atexit.
1.3. Install the MachOPlatformPlugin to scrape LinkGraphs for information
needed to support MachO features (e.g. eh-frames, mod-inits), and
communicate this information to the runtime.
1.4. Provide entry-points that the runtime can call to request initializers,
perform symbol lookup, and request deinitialiers (the latter is
implemented as an empty placeholder as macho object deinits are rarely
used).
1.5. Create a MachO header object for each JITDylib (defining the __mh_header
and __dso_handle symbols).
2. The llvm-jitlink tool (and llvm-jitlink-executor) are updated to use the
runtime when available.
3. A `lookupInitSymbolsAsync` method is added to the Platform base class. This
can be used to issue an async lookup for initializer symbols. The existing
`lookupInitSymbols` method is retained (the GenericIRPlatform code is still
using it), but is deprecated and will be removed soon.
4. JIT-dispatch support code is added to ExecutorProcessControl.
The JIT-dispatch system allows handlers in the JIT process to be associated with
'tag' symbols in the executor, and allows the executor to make remote procedure
calls back to the JIT process (via __orc_rt_jit_dispatch) using those tags.
The primary use case is ORC runtime code that needs to call bakc to handlers in
orc::Platform subclasses. E.g. __orc_rt_macho_jit_dlopen calling back to
MachOPlatform::rt_getInitializers using __orc_rt_macho_get_initializers_tag.
(The system is generic however, and could be used by non-runtime code).
The new ExecutorProcessControl::JITDispatchInfo struct provides the address
(in the executor) of the jit-dispatch function and a jit-dispatch context
object, and implementations of the dispatch function are added to
SelfExecutorProcessControl and OrcRPCExecutorProcessControl.
5. OrcRPCTPCServer is updated to support JIT-dispatch calls over ORC-RPC.
6. Serialization support for StringMap is added to the LLVM-side Simple Packed
Serialization code.
7. A JITLink::allocateBuffer operation is introduced to allocate writable memory
attached to the graph. This is used by the MachO header synthesis code, and will
be generically useful for other clients who want to create new graph content
from scratch.
2021-07-14 19:09:36 +08:00
|
|
|
return make_error<StringError>("__orc_rt_jit_dispatch_ctx not set");
|
2021-06-14 08:35:20 +08:00
|
|
|
if (ORC_RT_UNLIKELY(!&__orc_rt_jit_dispatch))
|
[ORC][ORC-RT] Introduce ORC-runtime based MachO-Platform.
Adds support for MachO static initializers/deinitializers and eh-frame
registration via the ORC runtime.
This commit introduces cooperative support code into the ORC runtime and ORC
LLVM libraries (especially the MachOPlatform class) to support macho runtime
features for JIT'd code. This commit introduces support for static
initializers, static destructors (via cxa_atexit interposition), and eh-frame
registration. Near-future commits will add support for MachO native
thread-local variables, and language runtime registration (e.g. for Objective-C
and Swift).
The llvm-jitlink tool is updated to use the ORC runtime where available, and
regression tests for the new MachOPlatform support are added to compiler-rt.
Notable changes on the ORC runtime side:
1. The new macho_platform.h / macho_platform.cpp files contain the bulk of the
runtime-side support. This includes eh-frame registration; jit versions of
dlopen, dlsym, and dlclose; a cxa_atexit interpose to record static destructors,
and an '__orc_rt_macho_run_program' function that defines running a JIT'd MachO
program in terms of the jit- dlopen/dlsym/dlclose functions.
2. Replaces JITTargetAddress (and casting operations) with ExecutorAddress
(copied from LLVM) to improve type-safety of address management.
3. Adds serialization support for ExecutorAddress and unordered_map types to
the runtime-side Simple Packed Serialization code.
4. Adds orc-runtime regression tests to ensure that static initializers and
cxa-atexit interposes work as expected.
Notable changes on the LLVM side:
1. The MachOPlatform class is updated to:
1.1. Load the ORC runtime into the ExecutionSession.
1.2. Set up standard aliases for macho-specific runtime functions. E.g.
___cxa_atexit -> ___orc_rt_macho_cxa_atexit.
1.3. Install the MachOPlatformPlugin to scrape LinkGraphs for information
needed to support MachO features (e.g. eh-frames, mod-inits), and
communicate this information to the runtime.
1.4. Provide entry-points that the runtime can call to request initializers,
perform symbol lookup, and request deinitialiers (the latter is
implemented as an empty placeholder as macho object deinits are rarely
used).
1.5. Create a MachO header object for each JITDylib (defining the __mh_header
and __dso_handle symbols).
2. The llvm-jitlink tool (and llvm-jitlink-executor) are updated to use the
runtime when available.
3. A `lookupInitSymbolsAsync` method is added to the Platform base class. This
can be used to issue an async lookup for initializer symbols. The existing
`lookupInitSymbols` method is retained (the GenericIRPlatform code is still
using it), but is deprecated and will be removed soon.
4. JIT-dispatch support code is added to ExecutorProcessControl.
The JIT-dispatch system allows handlers in the JIT process to be associated with
'tag' symbols in the executor, and allows the executor to make remote procedure
calls back to the JIT process (via __orc_rt_jit_dispatch) using those tags.
The primary use case is ORC runtime code that needs to call bakc to handlers in
orc::Platform subclasses. E.g. __orc_rt_macho_jit_dlopen calling back to
MachOPlatform::rt_getInitializers using __orc_rt_macho_get_initializers_tag.
(The system is generic however, and could be used by non-runtime code).
The new ExecutorProcessControl::JITDispatchInfo struct provides the address
(in the executor) of the jit-dispatch function and a jit-dispatch context
object, and implementations of the dispatch function are added to
SelfExecutorProcessControl and OrcRPCExecutorProcessControl.
5. OrcRPCTPCServer is updated to support JIT-dispatch calls over ORC-RPC.
6. Serialization support for StringMap is added to the LLVM-side Simple Packed
Serialization code.
7. A JITLink::allocateBuffer operation is introduced to allocate writable memory
attached to the graph. This is used by the MachO header synthesis code, and will
be generically useful for other clients who want to create new graph content
from scratch.
2021-07-14 19:09:36 +08:00
|
|
|
return make_error<StringError>("__orc_rt_jit_dispatch not set");
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
|
2021-06-13 06:55:47 +08:00
|
|
|
auto ArgBuffer =
|
|
|
|
detail::serializeViaSPSToWrapperFunctionResult<SPSArgList<SPSTagTs...>>(
|
|
|
|
Args...);
|
2021-10-19 13:11:16 +08:00
|
|
|
if (const char *ErrMsg = ArgBuffer.getOutOfBandError())
|
|
|
|
return make_error<StringError>(ErrMsg);
|
2021-06-13 06:55:47 +08:00
|
|
|
|
2021-10-19 13:11:16 +08:00
|
|
|
WrapperFunctionResult ResultBuffer = __orc_rt_jit_dispatch(
|
|
|
|
&__orc_rt_jit_dispatch_ctx, FnTag, ArgBuffer.data(), ArgBuffer.size());
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
if (auto ErrMsg = ResultBuffer.getOutOfBandError())
|
|
|
|
return make_error<StringError>(ErrMsg);
|
|
|
|
|
|
|
|
return detail::ResultDeserializer<SPSRetTagT, RetT>::deserialize(
|
|
|
|
Result, ResultBuffer.data(), ResultBuffer.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename HandlerT>
|
|
|
|
static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize,
|
|
|
|
HandlerT &&Handler) {
|
|
|
|
using WFHH =
|
2021-10-20 06:28:07 +08:00
|
|
|
detail::WrapperFunctionHandlerHelper<std::remove_reference_t<HandlerT>,
|
|
|
|
ResultSerializer, SPSTagTs...>;
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <typename T> static const T &makeSerializable(const T &Value) {
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static detail::SPSSerializableError makeSerializable(Error Err) {
|
|
|
|
return detail::toSPSSerializable(std::move(Err));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static detail::SPSSerializableExpected<T> makeSerializable(Expected<T> E) {
|
|
|
|
return detail::toSPSSerializable(std::move(E));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename... SPSTagTs>
|
|
|
|
class WrapperFunction<void(SPSTagTs...)>
|
|
|
|
: private WrapperFunction<SPSEmpty(SPSTagTs...)> {
|
|
|
|
public:
|
|
|
|
template <typename... ArgTs>
|
|
|
|
static Error call(const void *FnTag, const ArgTs &...Args) {
|
|
|
|
SPSEmpty BE;
|
|
|
|
return WrapperFunction<SPSEmpty(SPSTagTs...)>::call(FnTag, BE, Args...);
|
|
|
|
}
|
|
|
|
|
|
|
|
using WrapperFunction<SPSEmpty(SPSTagTs...)>::handle;
|
|
|
|
};
|
|
|
|
|
2021-10-20 06:28:07 +08:00
|
|
|
/// A function object that takes an ExecutorAddr as its first argument,
|
|
|
|
/// casts that address to a ClassT*, then calls the given method on that
|
|
|
|
/// pointer passing in the remaining function arguments. This utility
|
|
|
|
/// removes some of the boilerplate from writing wrappers for method calls.
|
|
|
|
///
|
|
|
|
/// @code{.cpp}
|
|
|
|
/// class MyClass {
|
|
|
|
/// public:
|
|
|
|
/// void myMethod(uint32_t, bool) { ... }
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// // SPS Method signature -- note MyClass object address as first argument.
|
|
|
|
/// using SPSMyMethodWrapperSignature =
|
|
|
|
/// SPSTuple<SPSExecutorAddr, uint32_t, bool>;
|
|
|
|
///
|
|
|
|
/// WrapperFunctionResult
|
|
|
|
/// myMethodCallWrapper(const char *ArgData, size_t ArgSize) {
|
|
|
|
/// return WrapperFunction<SPSMyMethodWrapperSignature>::handle(
|
|
|
|
/// ArgData, ArgSize, makeMethodWrapperHandler(&MyClass::myMethod));
|
|
|
|
/// }
|
|
|
|
/// @endcode
|
|
|
|
///
|
|
|
|
template <typename RetT, typename ClassT, typename... ArgTs>
|
|
|
|
class MethodWrapperHandler {
|
|
|
|
public:
|
|
|
|
using MethodT = RetT (ClassT::*)(ArgTs...);
|
|
|
|
MethodWrapperHandler(MethodT M) : M(M) {}
|
|
|
|
RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args) {
|
|
|
|
return (ObjAddr.toPtr<ClassT *>()->*M)(std::forward<ArgTs>(Args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
MethodT M;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Create a MethodWrapperHandler object from the given method pointer.
|
|
|
|
template <typename RetT, typename ClassT, typename... ArgTs>
|
|
|
|
MethodWrapperHandler<RetT, ClassT, ArgTs...>
|
|
|
|
makeMethodWrapperHandler(RetT (ClassT::*Method)(ArgTs...)) {
|
|
|
|
return MethodWrapperHandler<RetT, ClassT, ArgTs...>(Method);
|
|
|
|
}
|
|
|
|
|
[ORC-RT] Add WrapperFunctionResult, Simple Packed Serialization (SPS) system.
WrapperFunctionResult is a C++ wrapper for __orc_rt_CWrapperFunctionResult
that automatically manages the underlying struct.
The Simple Packed Serialization (SPS) utilities support a simple serialization
scheme for wrapper function argument and result buffers:
Primitive typess (bool, char, int8_t, and uint8_t, int16_t, uint16_t, int32_t,
uint32_t, int64_t, uint64_t) are serialized in little-endian form.
SPSTuples are serialized by serializing each of the tuple members in order
without padding.
SPSSequences are serialized by serializing a sequence length (as a uint64_t)
followed by each of the elements of the sequence in order without padding.
Serialization/deserialization always involves a pair of SPS type tag (a tag
representing the serialized format to use, e.g. uint32_t, or
SPSTuple<bool, SPSString>) and a concrete type to be serialized from or
deserialized to (uint32_t, std::pair<bool, std::string>). Serialization for new
types can be implemented by specializing the SPSSerializationTraits type.
2021-06-01 06:50:26 +08:00
|
|
|
} // end namespace __orc_rt
|
|
|
|
|
|
|
|
#endif // ORC_RT_WRAPPER_FUNCTION_UTILS_H
|