[llvm] [orc-rt] Add MemoryAccess SPS controller interface. (PR #195252)
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Fri May 1 04:13:10 PDT 2026
https://github.com/lhames created https://github.com/llvm/llvm-project/pull/195252
Adds SPS wrappers for reading and writing primitive types (uint8 through uint64), pointers, byte buffers, and C strings in executor memory. This CI is designed to support the LLVM EPCGenericMemoryAccess class, though the plumbing to connect the two remains to be done.
Includes unit tests for all read and write operations.
>From 15b64dc348a45c842182bacf61de56346aa4e31c Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Fri, 1 May 2026 17:15:39 +1000
Subject: [PATCH] [orc-rt] Add MemoryAccess SPS controller interface.
Adds SPS wrappers for reading and writing primitive types (uint8 through
uint64), pointers, byte buffers, and C strings in executor memory. This
CI is designed to support the LLVM EPCGenericMemoryAccess class, though
the plumbing to connect the two remains to be done.
Includes unit tests for all read and write operations.
---
orc-rt/include/CMakeLists.txt | 1 +
.../include/orc-rt/sps-ci/MemoryAccessSPSCI.h | 25 ++
orc-rt/lib/executor/CMakeLists.txt | 1 +
.../lib/executor/sps-ci/MemoryAccessSPSCI.cpp | 154 +++++++++++
orc-rt/unittests/CMakeLists.txt | 1 +
orc-rt/unittests/MemoryAccessSPSCITest.cpp | 251 ++++++++++++++++++
6 files changed, 433 insertions(+)
create mode 100644 orc-rt/include/orc-rt/sps-ci/MemoryAccessSPSCI.h
create mode 100644 orc-rt/lib/executor/sps-ci/MemoryAccessSPSCI.cpp
create mode 100644 orc-rt/unittests/MemoryAccessSPSCITest.cpp
diff --git a/orc-rt/include/CMakeLists.txt b/orc-rt/include/CMakeLists.txt
index 25788ac1be463..d1f60dd793c38 100644
--- a/orc-rt/include/CMakeLists.txt
+++ b/orc-rt/include/CMakeLists.txt
@@ -26,6 +26,7 @@ set(ORC_RT_HEADERS
orc-rt/SimplePackedSerialization.h
orc-rt/SPSAllocAction.h
orc-rt/sps-ci/AllSPSCI.h
+ orc-rt/sps-ci/MemoryAccessSPSCI.h
orc-rt/sps-ci/NativeDylibManagerSPSCI.h
orc-rt/sps-ci/SimpleNativeMemoryMapSPSCI.h
orc-rt/SPSMemoryFlags.h
diff --git a/orc-rt/include/orc-rt/sps-ci/MemoryAccessSPSCI.h b/orc-rt/include/orc-rt/sps-ci/MemoryAccessSPSCI.h
new file mode 100644
index 0000000000000..59229738294c5
--- /dev/null
+++ b/orc-rt/include/orc-rt/sps-ci/MemoryAccessSPSCI.h
@@ -0,0 +1,25 @@
+//===-- MemoryAccessSPSCI.h -- MemoryAccess SPS CI --*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// SPS Controller Interface registration for MemoryAccess.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ORC_RT_SPS_CI_MEMORYACCESSSPSCI_H
+#define ORC_RT_SPS_CI_MEMORYACCESSSPSCI_H
+
+#include "orc-rt/SimpleSymbolTable.h"
+
+namespace orc_rt::sps_ci {
+
+/// Add the MemoryAccess SPS interface to the controller interface.
+Error addMemoryAccess(SimpleSymbolTable &ST);
+
+} // namespace orc_rt::sps_ci
+
+#endif // ORC_RT_SPS_CI_MEMORYACCESSSPSCI_H
diff --git a/orc-rt/lib/executor/CMakeLists.txt b/orc-rt/lib/executor/CMakeLists.txt
index d999316f63dc7..6ef1ed79c6359 100644
--- a/orc-rt/lib/executor/CMakeLists.txt
+++ b/orc-rt/lib/executor/CMakeLists.txt
@@ -13,6 +13,7 @@ set(files
TaskDispatcher.cpp
ThreadPoolTaskDispatcher.cpp
sps-ci/AllSPSCI.cpp
+ sps-ci/MemoryAccessSPSCI.cpp
sps-ci/NativeDylibManagerSPSCI.cpp
sps-ci/SimpleNativeMemoryMapSPSCI.cpp
)
diff --git a/orc-rt/lib/executor/sps-ci/MemoryAccessSPSCI.cpp b/orc-rt/lib/executor/sps-ci/MemoryAccessSPSCI.cpp
new file mode 100644
index 0000000000000..85484a4d43e46
--- /dev/null
+++ b/orc-rt/lib/executor/sps-ci/MemoryAccessSPSCI.cpp
@@ -0,0 +1,154 @@
+//===- MemoryAccessSPSCI.cpp ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// SPS Controller Interface implementation for MemoryAccess.
+//
+//===----------------------------------------------------------------------===//
+
+#include "orc-rt/sps-ci/MemoryAccessSPSCI.h"
+#include "orc-rt/SPSWrapperFunction.h"
+#include "orc-rt/move_only_function.h"
+
+#include <cstring>
+#include <vector>
+
+using namespace orc_rt;
+
+namespace {
+
+template <typename T>
+void writePrimitives(move_only_function<void()> &&OnComplete,
+ std::vector<std::pair<T *, T>> Writes) {
+ for (auto &[Ptr, Value] : Writes)
+ *Ptr = Value;
+ OnComplete();
+}
+
+void writeBuffers(move_only_function<void()> &&OnComplete,
+ std::vector<std::pair<char *, std::vector<char>>> Writes) {
+ for (auto &[Ptr, Value] : Writes)
+ memcpy(Ptr, Value.data(), Value.size());
+ OnComplete();
+}
+
+template <typename T>
+void readPrimitives(move_only_function<void(std::vector<T>)> &&OnComplete,
+ std::vector<const T *> Reads) {
+ std::vector<T> Values;
+ Values.reserve(Reads.size());
+ for (auto *Ptr : Reads)
+ Values.push_back(*Ptr);
+ OnComplete(std::move(Values));
+}
+
+void readBuffers(
+ move_only_function<void(std::vector<std::vector<char>>)> &&OnComplete,
+ std::vector<std::pair<const char *, uint64_t>> Reads) {
+
+ std::vector<std::vector<char>> Values;
+ Values.reserve(Reads.size());
+ for (auto &[Ptr, Size] : Reads) {
+ Values.push_back({});
+ Values.back().resize(Size);
+ memcpy(Values.back().data(), Ptr, Size);
+ }
+ OnComplete(std::move(Values));
+}
+
+void readStrings(
+ move_only_function<void(std::vector<std::string>)> &&OnComplete,
+ std::vector<const char *> Reads) {
+ std::vector<std::string> Values;
+ Values.reserve(Reads.size());
+ for (auto *Ptr : Reads) {
+ Values.push_back({});
+ while (*Ptr != '\0')
+ Values.back().push_back(*Ptr++);
+ }
+ OnComplete(std::move(Values));
+}
+
+} // anonymous namespace
+namespace orc_rt::sps_ci {
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_write_uint8s_sps_wrapper,
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, uint8_t>>),
+ writePrimitives<uint8_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_write_uint16s_sps_wrapper,
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, uint16_t>>),
+ writePrimitives<uint16_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_write_uint32s_sps_wrapper,
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, uint32_t>>),
+ writePrimitives<uint32_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_write_uint64s_sps_wrapper,
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>),
+ writePrimitives<uint64_t>);
+
+ORC_RT_SPS_WRAPPER(
+ orc_rt_sps_ci_mem_write_pointers_sps_wrapper,
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr>>),
+ writePrimitives<void *>);
+
+ORC_RT_SPS_WRAPPER(
+ orc_rt_sps_ci_mem_write_buffers_sps_wrapper,
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSSequence<char>>>),
+ writeBuffers);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_uint8s_sps_wrapper,
+ SPSSequence<uint8_t>(SPSSequence<SPSExecutorAddr>),
+ readPrimitives<uint8_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_uint16s_sps_wrapper,
+ SPSSequence<uint16_t>(SPSSequence<SPSExecutorAddr>),
+ readPrimitives<uint16_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_uint32s_sps_wrapper,
+ SPSSequence<uint32_t>(SPSSequence<SPSExecutorAddr>),
+ readPrimitives<uint32_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_uint64s_sps_wrapper,
+ SPSSequence<uint64_t>(SPSSequence<SPSExecutorAddr>),
+ readPrimitives<uint64_t>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_pointers_sps_wrapper,
+ SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>),
+ readPrimitives<void *>);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_buffers_sps_wrapper,
+ SPSSequence<SPSSequence<char>>(
+ SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>),
+ readBuffers);
+
+ORC_RT_SPS_WRAPPER(orc_rt_sps_ci_mem_read_strings_sps_wrapper,
+ SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>),
+ readStrings);
+
+static std::pair<const char *, const void *>
+ orc_rt_sps_ci_MemoryAccess_sps_interface[] = {
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_write_uint8s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_write_uint16s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_write_uint32s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_write_uint64s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_write_pointers_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_write_buffers_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_uint8s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_uint16s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_uint32s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_uint64s_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_pointers_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_buffers_sps_wrapper),
+ ORC_RT_SYMTAB_PAIR(orc_rt_sps_ci_mem_read_strings_sps_wrapper)};
+
+Error addMemoryAccess(SimpleSymbolTable &ST) {
+ return ST.addUnique(orc_rt_sps_ci_MemoryAccess_sps_interface);
+}
+
+} // namespace orc_rt::sps_ci
diff --git a/orc-rt/unittests/CMakeLists.txt b/orc-rt/unittests/CMakeLists.txt
index fec95ce450ea1..571e7f1444838 100644
--- a/orc-rt/unittests/CMakeLists.txt
+++ b/orc-rt/unittests/CMakeLists.txt
@@ -27,6 +27,7 @@ add_orc_rt_unittest(CoreTests
IntervalSetTest.cpp
LockedAccessTest.cpp
MathTest.cpp
+ MemoryAccessSPSCITest.cpp
MemoryFlagsTest.cpp
NativeDylibManagerTest.cpp
NativeDylibManagerSPSCITest.cpp
diff --git a/orc-rt/unittests/MemoryAccessSPSCITest.cpp b/orc-rt/unittests/MemoryAccessSPSCITest.cpp
new file mode 100644
index 0000000000000..285f532f7315f
--- /dev/null
+++ b/orc-rt/unittests/MemoryAccessSPSCITest.cpp
@@ -0,0 +1,251 @@
+//===- MemoryAccessSPSCITest.cpp ------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests for MemoryAccess's SPS Controller Interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "orc-rt/sps-ci/MemoryAccessSPSCI.h"
+#include "orc-rt/SPSWrapperFunction.h"
+#include "orc-rt/SimpleSymbolTable.h"
+
+#include "DirectCaller.h"
+#include "gtest/gtest.h"
+
+using namespace orc_rt;
+
+class MemoryAccessSPSCITest : public ::testing::Test {
+protected:
+ void SetUp() override { cantFail(sps_ci::addMemoryAccess(CI)); }
+
+ DirectCaller caller(const char *Name) {
+ return DirectCaller(nullptr, reinterpret_cast<orc_rt_WrapperFunction>(
+ const_cast<void *>(CI.at(Name))));
+ }
+
+ SimpleSymbolTable CI;
+};
+
+TEST_F(MemoryAccessSPSCITest, Registration) {
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_write_uint8s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_write_uint16s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_write_uint32s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_write_uint64s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_write_pointers_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_write_buffers_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_uint8s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_uint16s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_uint32s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_uint64s_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_pointers_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_buffers_sps_wrapper"));
+ EXPECT_TRUE(CI.count("orc_rt_sps_ci_mem_read_strings_sps_wrapper"));
+}
+
+TEST_F(MemoryAccessSPSCITest, WriteUInt8s) {
+ uint8_t X = 0, Y = 0;
+ using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint8_t>>);
+ std::vector<std::pair<ExecutorAddr, uint8_t>> Writes = {
+ {ExecutorAddr::fromPtr(&X), 42}, {ExecutorAddr::fromPtr(&Y), 255}};
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_write_uint8s_sps_wrapper"),
+ [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
+ EXPECT_EQ(X, 42U);
+ EXPECT_EQ(Y, 255U);
+}
+
+TEST_F(MemoryAccessSPSCITest, WriteUInt16s) {
+ uint16_t X = 0, Y = 0;
+ using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint16_t>>);
+ std::vector<std::pair<ExecutorAddr, uint16_t>> Writes = {
+ {ExecutorAddr::fromPtr(&X), 1000}, {ExecutorAddr::fromPtr(&Y), 65535}};
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_write_uint16s_sps_wrapper"),
+ [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
+ EXPECT_EQ(X, 1000U);
+ EXPECT_EQ(Y, 65535U);
+}
+
+TEST_F(MemoryAccessSPSCITest, WriteUInt32s) {
+ uint32_t X = 0, Y = 0;
+ using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint32_t>>);
+ std::vector<std::pair<ExecutorAddr, uint32_t>> Writes = {
+ {ExecutorAddr::fromPtr(&X), 100000},
+ {ExecutorAddr::fromPtr(&Y), 0xdeadbeef}};
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_write_uint32s_sps_wrapper"),
+ [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
+ EXPECT_EQ(X, 100000U);
+ EXPECT_EQ(Y, 0xdeadbeefU);
+}
+
+TEST_F(MemoryAccessSPSCITest, WriteUInt64s) {
+ uint64_t X = 0, Y = 0;
+ using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>);
+ std::vector<std::pair<ExecutorAddr, uint64_t>> Writes = {
+ {ExecutorAddr::fromPtr(&X), 0x0102030405060708ULL},
+ {ExecutorAddr::fromPtr(&Y), 0xdeadbeefcafef00dULL}};
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_write_uint64s_sps_wrapper"),
+ [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
+ EXPECT_EQ(X, 0x0102030405060708ULL);
+ EXPECT_EQ(Y, 0xdeadbeefcafef00dULL);
+}
+
+TEST_F(MemoryAccessSPSCITest, WritePointers) {
+ void *X = nullptr, *Y = nullptr;
+ int A = 1, B = 2;
+ using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr>>);
+ std::vector<std::pair<ExecutorAddr, ExecutorAddr>> Writes = {
+ {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&A)},
+ {ExecutorAddr::fromPtr(&Y), ExecutorAddr::fromPtr(&B)}};
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_write_pointers_sps_wrapper"),
+ [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
+ EXPECT_EQ(X, static_cast<void *>(&A));
+ EXPECT_EQ(Y, static_cast<void *>(&B));
+}
+
+TEST_F(MemoryAccessSPSCITest, WriteBuffers) {
+ char Buf[8] = {};
+ char Content[] = "hello";
+ using SPSSig =
+ void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSSequence<char>>>);
+ std::vector<std::pair<ExecutorAddr, span<char>>> Writes = {
+ {ExecutorAddr::fromPtr(Buf), span<char>(Content, sizeof(Content))}};
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_write_buffers_sps_wrapper"),
+ [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
+ EXPECT_EQ(Buf[0], 'h');
+ EXPECT_EQ(Buf[1], 'e');
+ EXPECT_EQ(Buf[2], 'l');
+ EXPECT_EQ(Buf[3], 'l');
+ EXPECT_EQ(Buf[4], 'o');
+ EXPECT_EQ(Buf[5], '\0');
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadUInt8s) {
+ uint8_t X = 42, Y = 255;
+ using SPSSig = SPSSequence<uint8_t>(SPSSequence<SPSExecutorAddr>);
+ std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
+ ExecutorAddr::fromPtr(&Y)};
+ std::vector<uint8_t> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_uint8s_sps_wrapper"),
+ [&](Expected<std::vector<uint8_t>> R) {
+ Result = cantFail(std::move(R));
+ },
+ std::move(Addrs));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], 42U);
+ EXPECT_EQ(Result[1], 255U);
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadUInt16s) {
+ uint16_t X = 1000, Y = 65535;
+ using SPSSig = SPSSequence<uint16_t>(SPSSequence<SPSExecutorAddr>);
+ std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
+ ExecutorAddr::fromPtr(&Y)};
+ std::vector<uint16_t> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_uint16s_sps_wrapper"),
+ [&](Expected<std::vector<uint16_t>> R) {
+ Result = cantFail(std::move(R));
+ },
+ std::move(Addrs));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], 1000U);
+ EXPECT_EQ(Result[1], 65535U);
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadUInt32s) {
+ uint32_t X = 100000, Y = 0xdeadbeef;
+ using SPSSig = SPSSequence<uint32_t>(SPSSequence<SPSExecutorAddr>);
+ std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
+ ExecutorAddr::fromPtr(&Y)};
+ std::vector<uint32_t> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_uint32s_sps_wrapper"),
+ [&](Expected<std::vector<uint32_t>> R) {
+ Result = cantFail(std::move(R));
+ },
+ std::move(Addrs));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], 100000U);
+ EXPECT_EQ(Result[1], 0xdeadbeefU);
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadUInt64s) {
+ uint64_t X = 0x0102030405060708ULL, Y = 0xdeadbeefcafebabeULL;
+ using SPSSig = SPSSequence<uint64_t>(SPSSequence<SPSExecutorAddr>);
+ std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
+ ExecutorAddr::fromPtr(&Y)};
+ std::vector<uint64_t> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_uint64s_sps_wrapper"),
+ [&](Expected<std::vector<uint64_t>> R) {
+ Result = cantFail(std::move(R));
+ },
+ std::move(Addrs));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], 0x0102030405060708ULL);
+ EXPECT_EQ(Result[1], 0xdeadbeefcafebabeULL);
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadPointers) {
+ int A = 1, B = 2;
+ void *X = &A, *Y = &B;
+ using SPSSig = SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>);
+ std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
+ ExecutorAddr::fromPtr(&Y)};
+ std::vector<void *> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_pointers_sps_wrapper"),
+ [&](Expected<std::vector<void *>> R) { Result = cantFail(std::move(R)); },
+ std::move(Addrs));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], static_cast<void *>(&A));
+ EXPECT_EQ(Result[1], static_cast<void *>(&B));
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadBuffers) {
+ const char Src[] = "hello world";
+ using SPSSig = SPSSequence<SPSSequence<char>>(
+ SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>);
+ std::vector<std::pair<ExecutorAddr, uint64_t>> Reads = {
+ {ExecutorAddr::fromPtr(Src), 5}, // "hello"
+ {ExecutorAddr::fromPtr(Src + 6), 5}}; // "world"
+ std::vector<std::vector<char>> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_buffers_sps_wrapper"),
+ [&](Expected<std::vector<std::vector<char>>> R) {
+ Result = cantFail(std::move(R));
+ },
+ std::move(Reads));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], (std::vector<char>{'h', 'e', 'l', 'l', 'o'}));
+ EXPECT_EQ(Result[1], (std::vector<char>{'w', 'o', 'r', 'l', 'd'}));
+}
+
+TEST_F(MemoryAccessSPSCITest, ReadStrings) {
+ const char *Str1 = "hello";
+ const char *Str2 = "world";
+ using SPSSig = SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>);
+ std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(Str1),
+ ExecutorAddr::fromPtr(Str2)};
+ std::vector<std::string> Result;
+ SPSWrapperFunction<SPSSig>::call(
+ caller("orc_rt_sps_ci_mem_read_strings_sps_wrapper"),
+ [&](Expected<std::vector<std::string>> R) {
+ Result = cantFail(std::move(R));
+ },
+ std::move(Addrs));
+ ASSERT_EQ(Result.size(), 2U);
+ EXPECT_EQ(Result[0], "hello");
+ EXPECT_EQ(Result[1], "world");
+}
More information about the llvm-commits
mailing list