[llvm] 7f99337 - [ORC] Add EPCGenericMemoryAccess: generic executor memory access via EPC calls.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 21 02:44:07 PDT 2021
Author: Lang Hames
Date: 2021-08-21T19:33:39+10:00
New Revision: 7f99337f9bcf03eb19e40e664743078d65325a37
URL: https://github.com/llvm/llvm-project/commit/7f99337f9bcf03eb19e40e664743078d65325a37
DIFF: https://github.com/llvm/llvm-project/commit/7f99337f9bcf03eb19e40e664743078d65325a37.diff
LOG: [ORC] Add EPCGenericMemoryAccess: generic executor memory access via EPC calls.
All ExecutorProcessControl subclasses must provide an
ExecutorProcessControl::MemoryAccess object that can be used to access executor
memory from the JIT process. The EPCGenericMemoryAccess class provides an
off-the-shelf MemoryAccess implementation for JITs that do not need (or cannot
provide) a specialized MemoryAccess implementation. This simplifies the process
of creating new ExecutorProcessControl implementations.
Added:
llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccess.cpp
llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
Modified:
llvm/include/llvm/ExecutionEngine/Orc/Core.h
llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h
llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h
llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
index 03a7b4b05d200..e047e5ef5a45c 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -1489,14 +1489,8 @@ class ExecutionSession {
void callSPSWrapperAsync(SendResultT &&SendResult,
JITTargetAddress WrapperFnAddr,
const ArgTs &...Args) {
- shared::WrapperFunction<SPSSignature>::callAsync(
- [this,
- WrapperFnAddr](ExecutorProcessControl::SendResultFunction SendResult,
- const char *ArgData, size_t ArgSize) {
- callWrapperAsync(std::move(SendResult), WrapperFnAddr,
- ArrayRef<char>(ArgData, ArgSize));
- },
- std::move(SendResult), Args...);
+ EPC->callSPSWrapperAsync<SPSSignature, SendResultT, ArgTs...>(
+ std::forward<SendResultT>(SendResult), WrapperFnAddr, Args...);
}
/// Run a wrapper function using SPS to serialize the arguments and
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
new file mode 100644
index 0000000000000..20a47846927a4
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
@@ -0,0 +1,90 @@
+//===- EPCGenericMemoryAccess.h - Generic EPC MemoryAccess impl -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements ExecutorProcessControl::MemoryAccess by making calls to
+// ExecutorProcessControl::callWrapperAsync.
+//
+// This simplifies the implementaton of new ExecutorProcessControl instances,
+// as this implementation will always work (at the cost of some performance
+// overhead for the calls).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESS_H
+#define LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESS_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+
+namespace llvm {
+namespace orc {
+
+class EPCGenericMemoryAccess : public ExecutorProcessControl::MemoryAccess {
+public:
+ /// Function addresses for memory access.
+ struct FuncAddrs {
+ ExecutorAddress WriteUInt8s;
+ ExecutorAddress WriteUInt16s;
+ ExecutorAddress WriteUInt32s;
+ ExecutorAddress WriteUInt64s;
+ ExecutorAddress WriteBuffers;
+ };
+
+ /// Create an EPCGenericMemoryAccess instance from a given set of
+ /// function addrs.
+ EPCGenericMemoryAccess(ExecutorProcessControl &EPC, FuncAddrs FAs)
+ : EPC(EPC), FAs(FAs) {}
+
+ /// Create using the standard memory access function names from the ORC
+ /// runtime.
+ static Expected<std::unique_ptr<EPCGenericMemoryAccess>>
+ CreateUsingOrcRTFuncs(ExecutionSession &ES, JITDylib &OrcRuntimeJD);
+
+ void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ using namespace shared;
+ EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessUInt8Write>)>(
+ std::move(OnWriteComplete), FAs.WriteUInt8s.getValue(), Ws);
+ }
+
+ void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ using namespace shared;
+ EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessUInt16Write>)>(
+ std::move(OnWriteComplete), FAs.WriteUInt16s.getValue(), Ws);
+ }
+
+ void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ using namespace shared;
+ EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessUInt32Write>)>(
+ std::move(OnWriteComplete), FAs.WriteUInt32s.getValue(), Ws);
+ }
+
+ void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ using namespace shared;
+ EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessUInt64Write>)>(
+ std::move(OnWriteComplete), FAs.WriteUInt64s.getValue(), Ws);
+ }
+
+ void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
+ WriteResultFn OnWriteComplete) override {
+ using namespace shared;
+ EPC.callSPSWrapperAsync<void(SPSSequence<SPSMemoryAccessBufferWrite>)>(
+ std::move(OnWriteComplete), FAs.WriteBuffers.getValue(), Ws);
+ }
+
+private:
+ ExecutorProcessControl &EPC;
+ FuncAddrs FAs;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
index a98ff46b22220..9b00369311c95 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
@@ -168,8 +168,7 @@ class ExecutorProcessControl {
/// The result of the lookup is a 2-dimentional array of target addresses
/// that correspond to the lookup order. If a required symbol is not
/// found then this method will return an error. If a weakly referenced
- /// symbol is not found then it be assigned a '0' value in the result.
- /// that correspond to the lookup order.
+ /// symbol is not found then it be assigned a '0' value.
virtual Expected<std::vector<tpctypes::LookupResult>>
lookupSymbols(ArrayRef<LookupRequest> Request) = 0;
@@ -190,6 +189,22 @@ class ExecutorProcessControl {
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) = 0;
+ /// Run a wrapper function using SPS to serialize the arguments and
+ /// deserialize the results.
+ template <typename SPSSignature, typename SendResultT, typename... ArgTs>
+ void callSPSWrapperAsync(SendResultT &&SendResult,
+ JITTargetAddress WrapperFnAddr,
+ const ArgTs &...Args) {
+ shared::WrapperFunction<SPSSignature>::callAsync(
+ [this,
+ WrapperFnAddr](ExecutorProcessControl::SendResultFunction SendResult,
+ const char *ArgData, size_t ArgSize) {
+ callWrapperAsync(std::move(SendResult), WrapperFnAddr,
+ ArrayRef<char>(ArgData, ArgSize));
+ },
+ std::move(SendResult), Args...);
+ }
+
/// Disconnect from the target process.
///
/// This should be called after the JIT session is shut down.
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h b/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
index c100005afc1e1..181d735468c63 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
@@ -61,7 +61,8 @@ Error lookupAndRecordAddrs(
/// weak.
Error lookupAndRecordAddrs(
ExecutorProcessControl &EPC, tpctypes::DylibHandle H,
- std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs);
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
+ SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol);
} // End namespace orc
} // End namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h
index 854f1098d5af5..ea86304728466 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h
@@ -289,6 +289,13 @@ class TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>> {
}
};
+/// Trivial ArrayRef<T> -> SPSSequence<SPSElementTagT> serialization.
+template <typename SPSElementTagT, typename T>
+class TrivialSPSSequenceSerialization<SPSElementTagT, ArrayRef<T>> {
+public:
+ static constexpr bool available = true;
+};
+
/// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size
/// followed by a for-earch loop over the elements of the sequence to serialize
/// each of them.
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
index a44bcd4c80648..fe9b7b1e56f80 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
@@ -62,6 +62,62 @@ using DylibHandle = JITTargetAddress;
using LookupResult = std::vector<JITTargetAddress>;
} // end namespace tpctypes
+
+namespace shared {
+
+template <typename T>
+using SPSMemoryAccessUIntWrite = SPSTuple<SPSExecutorAddress, T>;
+
+using SPSMemoryAccessUInt8Write = SPSMemoryAccessUIntWrite<uint8_t>;
+using SPSMemoryAccessUInt16Write = SPSMemoryAccessUIntWrite<uint16_t>;
+using SPSMemoryAccessUInt32Write = SPSMemoryAccessUIntWrite<uint32_t>;
+using SPSMemoryAccessUInt64Write = SPSMemoryAccessUIntWrite<uint64_t>;
+
+using SPSMemoryAccessBufferWrite =
+ SPSTuple<SPSExecutorAddress, SPSSequence<char>>;
+
+template <typename T>
+class SPSSerializationTraits<SPSMemoryAccessUIntWrite<T>,
+ tpctypes::UIntWrite<T>> {
+public:
+ static size_t size(const tpctypes::UIntWrite<T> &W) {
+ return SPSTuple<SPSExecutorAddress, T>::AsArgList::size(W.Address, W.Value);
+ }
+
+ static bool serialize(SPSOutputBuffer &OB, const tpctypes::UIntWrite<T> &W) {
+ return SPSTuple<SPSExecutorAddress, T>::AsArgList::serialize(OB, W.Address,
+ W.Value);
+ }
+
+ static bool deserialize(SPSInputBuffer &IB, tpctypes::UIntWrite<T> &W) {
+ return SPSTuple<SPSExecutorAddress, T>::AsArgList::deserialize(
+ IB, W.Address, W.Value);
+ }
+};
+
+template <>
+class SPSSerializationTraits<SPSMemoryAccessBufferWrite,
+ tpctypes::BufferWrite> {
+public:
+ static size_t size(const tpctypes::BufferWrite &W) {
+ return SPSTuple<SPSExecutorAddress, SPSSequence<char>>::AsArgList::size(
+ W.Address, W.Buffer);
+ }
+
+ static bool serialize(SPSOutputBuffer &OB, const tpctypes::BufferWrite &W) {
+ return SPSTuple<SPSExecutorAddress,
+ SPSSequence<char>>::AsArgList ::serialize(OB, W.Address,
+ W.Buffer);
+ }
+
+ static bool deserialize(SPSInputBuffer &IB, tpctypes::BufferWrite &W) {
+ return SPSTuple<SPSExecutorAddress,
+ SPSSequence<char>>::AsArgList ::deserialize(IB, W.Address,
+ W.Buffer);
+ }
+};
+
+} // end namespace shared
} // end namespace orc
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h
index d1d7d540b7ce3..3154bf68271fe 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h
@@ -486,7 +486,7 @@ class WrapperFunction<SPSRetTagT(SPSTagTs...)> {
}
auto SendSerializedResult = [SDR = std::move(SendDeserializedResult)](
- WrapperFunctionResult R) {
+ WrapperFunctionResult R) mutable {
RetT RetVal = detail::ResultDeserializer<SPSRetTagT, RetT>::makeValue();
detail::ResultDeserializer<SPSRetTagT, RetT>::makeSafe(RetVal);
@@ -554,8 +554,10 @@ class WrapperFunction<void(SPSTagTs...)>
const ArgTs &...Args) {
WrapperFunction<SPSEmpty(SPSTagTs...)>::callAsync(
Caller,
- [SDR = std::move(SendDeserializedResult)](
- Error SerializeErr, SPSEmpty E) { SDR(std::move(SerializeErr)); },
+ [SDR = std::move(SendDeserializedResult)](Error SerializeErr,
+ SPSEmpty E) mutable {
+ SDR(std::move(SerializeErr));
+ },
Args...);
}
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 6dc12dac7daf1..fb697814fc062 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -7,6 +7,7 @@ add_llvm_component_library(LLVMOrcJIT
EPCDynamicLibrarySearchGenerator.cpp
EPCDebugObjectRegistrar.cpp
EPCEHFrameRegistrar.cpp
+ EPCGenericMemoryAccess.cpp
EPCIndirectionUtils.cpp
ExecutionUtils.cpp
IndirectionUtils.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccess.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccess.cpp
new file mode 100644
index 0000000000000..319909fed7837
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccess.cpp
@@ -0,0 +1,44 @@
+//===----- EPCGenericMemoryAccess.cpp - Generic EPC MemoryAccess impl -----===//
+//
+// 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/EPCGenericMemoryAccess.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+
+namespace llvm {
+namespace orc {
+
+/// Create from a ExecutorProcessControl instance.
+Expected<std::unique_ptr<EPCGenericMemoryAccess>>
+EPCGenericMemoryAccess::CreateUsingOrcRTFuncs(ExecutionSession &ES,
+ JITDylib &OrcRuntimeJD) {
+
+ StringRef GlobalPrefix = "";
+ if (ES.getExecutorProcessControl().getTargetTriple().isOSBinFormatMachO())
+ GlobalPrefix = "_";
+
+ FuncAddrs FAs;
+ if (auto Err = lookupAndRecordAddrs(
+ ES, LookupKind::Static, makeJITDylibSearchOrder(&OrcRuntimeJD),
+ {{ES.intern((GlobalPrefix + "__orc_rt_write_uint8s_wrapper").str()),
+ &FAs.WriteUInt8s},
+ {ES.intern((GlobalPrefix + "__orc_rt_write_uint16s_wrapper").str()),
+ &FAs.WriteUInt16s},
+ {ES.intern((GlobalPrefix + "__orc_rt_write_uint32s_wrapper").str()),
+ &FAs.WriteUInt32s},
+ {ES.intern((GlobalPrefix + "__orc_rt_write_uint64s_wrapper").str()),
+ &FAs.WriteUInt64s},
+ {ES.intern((GlobalPrefix + "__orc_rt_write_buffers_wrapper").str()),
+ &FAs.WriteBuffers}}))
+ return std::move(Err);
+
+ return std::make_unique<EPCGenericMemoryAccess>(
+ ES.getExecutorProcessControl(), FAs);
+}
+
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 8f7097af7a8cc..79c16cbe0597e 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -17,6 +17,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(OrcJITTests
CoreAPIsTest.cpp
ExecutionSessionWrapperFunctionCallsTest.cpp
+ EPCGenericMemoryAccessTest.cpp
IndirectionUtilsTest.cpp
JITTargetMachineBuilderTest.cpp
LazyCallThroughAndReexportsTest.cpp
diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
new file mode 100644
index 0000000000000..f5209d66fc1d2
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
@@ -0,0 +1,98 @@
+//===- EPCGenericMemoryAccessTest.cpp -- Tests for EPCGenericMemoryAccess -===//
+//
+// 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 "OrcTestCommon.h"
+
+#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
+#include "llvm/Testing/Support/Error.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::shared;
+
+namespace {
+
+template <typename WriteT, typename SPSWriteT>
+llvm::orc::shared::detail::CWrapperFunctionResult
+testWriteUInts(const char *ArgData, size_t ArgSize) {
+ return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle(
+ ArgData, ArgSize,
+ [](std::vector<WriteT> Ws) {
+ for (auto &W : Ws)
+ *jitTargetAddressToPointer<decltype(W.Value) *>(W.Address) =
+ W.Value;
+ })
+ .release();
+}
+
+llvm::orc::shared::detail::CWrapperFunctionResult
+testWriteBuffers(const char *ArgData, size_t ArgSize) {
+ return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle(
+ ArgData, ArgSize,
+ [](std::vector<tpctypes::BufferWrite> Ws) {
+ for (auto &W : Ws)
+ memcpy(jitTargetAddressToPointer<char *>(W.Address),
+ W.Buffer.data(), W.Buffer.size());
+ })
+ .release();
+}
+
+TEST(EPCGenericMemoryAccessTest, MemWrites) {
+ auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
+
+ EPCGenericMemoryAccess::FuncAddrs FAs;
+ FAs.WriteUInt8s = ExecutorAddress::fromPtr(
+ &testWriteUInts<tpctypes::UInt8Write, SPSMemoryAccessUInt8Write>);
+ FAs.WriteUInt16s = ExecutorAddress::fromPtr(
+ &testWriteUInts<tpctypes::UInt16Write, SPSMemoryAccessUInt16Write>);
+ FAs.WriteUInt32s = ExecutorAddress::fromPtr(
+ &testWriteUInts<tpctypes::UInt32Write, SPSMemoryAccessUInt32Write>);
+ FAs.WriteUInt64s = ExecutorAddress::fromPtr(
+ &testWriteUInts<tpctypes::UInt64Write, SPSMemoryAccessUInt64Write>);
+ FAs.WriteBuffers = ExecutorAddress::fromPtr(&testWriteBuffers);
+
+ auto MemAccess = std::make_unique<EPCGenericMemoryAccess>(*SelfEPC, FAs);
+
+ uint8_t Test_UInt8_1 = 0;
+ uint8_t Test_UInt8_2 = 0;
+ uint16_t Test_UInt16 = 0;
+ uint32_t Test_UInt32 = 0;
+ uint64_t Test_UInt64 = 0;
+ char Test_Buffer[21];
+
+ auto Err1 = MemAccess->writeUInt8s(
+ {{pointerToJITTargetAddress(&Test_UInt8_1), 1},
+ {pointerToJITTargetAddress(&Test_UInt8_2), 0xFE}});
+
+ EXPECT_THAT_ERROR(std::move(Err1), Succeeded());
+ EXPECT_EQ(Test_UInt8_1, 1U);
+ EXPECT_EQ(Test_UInt8_2, 0xFE);
+
+ auto Err2 =
+ MemAccess->writeUInt16s({{pointerToJITTargetAddress(&Test_UInt16), 1}});
+ EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
+ EXPECT_EQ(Test_UInt16, 1U);
+
+ auto Err3 =
+ MemAccess->writeUInt32s({{pointerToJITTargetAddress(&Test_UInt32), 1}});
+ EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
+ EXPECT_EQ(Test_UInt32, 1U);
+
+ auto Err4 =
+ MemAccess->writeUInt64s({{pointerToJITTargetAddress(&Test_UInt64), 1}});
+ EXPECT_THAT_ERROR(std::move(Err4), Succeeded());
+ EXPECT_EQ(Test_UInt64, 1U);
+
+ StringRef TestMsg("test-message");
+ auto Err5 = MemAccess->writeBuffers(
+ {{pointerToJITTargetAddress(&Test_Buffer), TestMsg}});
+ EXPECT_THAT_ERROR(std::move(Err5), Succeeded());
+ EXPECT_EQ(StringRef(Test_Buffer, TestMsg.size()), TestMsg);
+}
+
+} // namespace
More information about the llvm-commits
mailing list