2021-06-15 18:26:51 +08:00
|
|
|
//===-------- SimplePackedSerializationTest.cpp - Test SPS scheme ---------===//
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::orc::shared;
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, SPSOutputBuffer) {
|
|
|
|
constexpr unsigned NumBytes = 8;
|
|
|
|
char Buffer[NumBytes];
|
|
|
|
char Zero = 0;
|
|
|
|
SPSOutputBuffer OB(Buffer, NumBytes);
|
|
|
|
|
|
|
|
// Expect that we can write NumBytes of content.
|
|
|
|
for (unsigned I = 0; I != NumBytes; ++I) {
|
|
|
|
char C = I;
|
|
|
|
EXPECT_TRUE(OB.write(&C, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Expect an error when we attempt to write an extra byte.
|
|
|
|
EXPECT_FALSE(OB.write(&Zero, 1));
|
|
|
|
|
|
|
|
// Check that the buffer contains the expected content.
|
|
|
|
for (unsigned I = 0; I != NumBytes; ++I)
|
|
|
|
EXPECT_EQ(Buffer[I], (char)I);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, SPSInputBuffer) {
|
|
|
|
char Buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
|
|
|
SPSInputBuffer IB(Buffer, sizeof(Buffer));
|
|
|
|
|
|
|
|
char C;
|
|
|
|
for (unsigned I = 0; I != sizeof(Buffer); ++I) {
|
|
|
|
EXPECT_TRUE(IB.read(&C, 1));
|
|
|
|
EXPECT_EQ(C, (char)I);
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPECT_FALSE(IB.read(&C, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename SPSTagT, typename T>
|
2021-08-22 08:58:58 +08:00
|
|
|
static void spsSerializationRoundTrip(const T &Value) {
|
2021-06-15 18:26:51 +08:00
|
|
|
using BST = SPSSerializationTraits<SPSTagT, T>;
|
|
|
|
|
|
|
|
size_t Size = BST::size(Value);
|
|
|
|
auto Buffer = std::make_unique<char[]>(Size);
|
|
|
|
SPSOutputBuffer OB(Buffer.get(), Size);
|
|
|
|
|
|
|
|
EXPECT_TRUE(BST::serialize(OB, Value));
|
|
|
|
|
|
|
|
SPSInputBuffer IB(Buffer.get(), Size);
|
|
|
|
|
|
|
|
T DSValue;
|
|
|
|
EXPECT_TRUE(BST::deserialize(IB, DSValue));
|
|
|
|
|
|
|
|
EXPECT_EQ(Value, DSValue)
|
|
|
|
<< "Incorrect value after serialization/deserialization round-trip";
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> static void testFixedIntegralTypeSerialization() {
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<T, T>(0);
|
|
|
|
spsSerializationRoundTrip<T, T>(static_cast<T>(1));
|
2021-06-15 18:26:51 +08:00
|
|
|
if (std::is_signed<T>::value) {
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<T, T>(static_cast<T>(-1));
|
|
|
|
spsSerializationRoundTrip<T, T>(std::numeric_limits<T>::min());
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<T, T>(std::numeric_limits<T>::max());
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, BoolSerialization) {
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<bool, bool>(true);
|
|
|
|
spsSerializationRoundTrip<bool, bool>(false);
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, CharSerialization) {
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<char, char>((char)0x00);
|
|
|
|
spsSerializationRoundTrip<char, char>((char)0xAA);
|
|
|
|
spsSerializationRoundTrip<char, char>((char)0xFF);
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, Int8Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<int8_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, UInt8Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<uint8_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, Int16Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<int16_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, UInt16Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<uint16_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, Int32Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<int32_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, UInt32Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<uint32_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, Int64Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<int64_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, UInt64Serialization) {
|
|
|
|
testFixedIntegralTypeSerialization<uint64_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, SequenceSerialization) {
|
|
|
|
std::vector<int32_t> V({1, 2, -47, 139});
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<SPSSequence<int32_t>>(V);
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, StringViewCharSequenceSerialization) {
|
|
|
|
const char *HW = "Hello, world!";
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<SPSString>(StringRef(HW));
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
|
|
|
|
2021-08-22 08:43:06 +08:00
|
|
|
TEST(SimplePackedSerializationTest, StdTupleSerialization) {
|
|
|
|
std::tuple<int32_t, std::string, bool> P(42, "foo", true);
|
|
|
|
spsSerializationRoundTrip<SPSTuple<int32_t, SPSString, bool>>(P);
|
|
|
|
}
|
|
|
|
|
2021-06-15 18:26:51 +08:00
|
|
|
TEST(SimplePackedSerializationTest, StdPairSerialization) {
|
|
|
|
std::pair<int32_t, std::string> P(42, "foo");
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<SPSTuple<int32_t, SPSString>>(P);
|
2021-06-15 18:26:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, ArgListSerialization) {
|
|
|
|
using BAL = SPSArgList<bool, int32_t, SPSString>;
|
|
|
|
|
|
|
|
bool Arg1 = true;
|
|
|
|
int32_t Arg2 = 42;
|
|
|
|
std::string Arg3 = "foo";
|
|
|
|
|
|
|
|
size_t Size = BAL::size(Arg1, Arg2, Arg3);
|
|
|
|
auto Buffer = std::make_unique<char[]>(Size);
|
|
|
|
SPSOutputBuffer OB(Buffer.get(), Size);
|
|
|
|
|
|
|
|
EXPECT_TRUE(BAL::serialize(OB, Arg1, Arg2, Arg3));
|
|
|
|
|
|
|
|
SPSInputBuffer IB(Buffer.get(), Size);
|
|
|
|
|
|
|
|
bool ArgOut1;
|
|
|
|
int32_t ArgOut2;
|
|
|
|
std::string ArgOut3;
|
|
|
|
|
|
|
|
EXPECT_TRUE(BAL::deserialize(IB, ArgOut1, ArgOut2, ArgOut3));
|
|
|
|
|
|
|
|
EXPECT_EQ(Arg1, ArgOut1);
|
|
|
|
EXPECT_EQ(Arg2, ArgOut2);
|
|
|
|
EXPECT_EQ(Arg3, ArgOut3);
|
|
|
|
}
|
[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
|
|
|
|
|
|
|
TEST(SimplePackedSerialization, StringMap) {
|
|
|
|
StringMap<int32_t> M({{"A", 1}, {"B", 2}});
|
2021-08-22 08:58:58 +08:00
|
|
|
spsSerializationRoundTrip<SPSSequence<SPSTuple<SPSString, int32_t>>>(M);
|
[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
|
|
|
}
|
2021-09-02 18:45:46 +08:00
|
|
|
|
|
|
|
TEST(SimplePackedSerializationTest, ArrayRef) {
|
|
|
|
constexpr unsigned BufferSize = 6 + 8; // "hello\0" + sizeof(uint64_t)
|
|
|
|
ArrayRef<char> HelloOut = "hello";
|
|
|
|
char Buffer[BufferSize];
|
|
|
|
memset(Buffer, 0, BufferSize);
|
|
|
|
|
|
|
|
SPSOutputBuffer OB(Buffer, BufferSize);
|
|
|
|
EXPECT_TRUE(SPSArgList<SPSSequence<char>>::serialize(OB, HelloOut));
|
|
|
|
|
|
|
|
ArrayRef<char> HelloIn;
|
|
|
|
SPSInputBuffer IB(Buffer, BufferSize);
|
|
|
|
EXPECT_TRUE(SPSArgList<SPSSequence<char>>::deserialize(IB, HelloIn));
|
|
|
|
|
|
|
|
// Output should be copied to buffer.
|
|
|
|
EXPECT_NE(HelloOut.data(), Buffer);
|
|
|
|
|
|
|
|
// Input should reference buffer.
|
|
|
|
EXPECT_LT(HelloIn.data() - Buffer, BufferSize);
|
|
|
|
}
|