//===- 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( const_cast(CI.at(Name)))); } SimpleSymbolTable CI; }; TEST_F(MemoryAccessSPSCITest, Registration) { EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint8s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint16s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint32s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint64s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_pointers")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_buffers")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint8s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint16s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint32s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint64s")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_pointers")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_buffers")); EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_strings")); } TEST_F(MemoryAccessSPSCITest, WriteUInt8s) { uint8_t X = 0, Y = 0; using SPSSig = void(SPSSequence>); std::vector> Writes = { {ExecutorAddr::fromPtr(&X), 42}, {ExecutorAddr::fromPtr(&Y), 255}}; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_write_uint8s"), [](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>); std::vector> Writes = { {ExecutorAddr::fromPtr(&X), 1000}, {ExecutorAddr::fromPtr(&Y), 65535}}; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_write_uint16s"), [](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>); std::vector> Writes = { {ExecutorAddr::fromPtr(&X), 100000}, {ExecutorAddr::fromPtr(&Y), 0xdeadbeef}}; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_write_uint32s"), [](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>); std::vector> Writes = { {ExecutorAddr::fromPtr(&X), 0x0102030405060708ULL}, {ExecutorAddr::fromPtr(&Y), 0xdeadbeefcafef00dULL}}; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_write_uint64s"), [](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>); std::vector> Writes = { {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&A)}, {ExecutorAddr::fromPtr(&Y), ExecutorAddr::fromPtr(&B)}}; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_write_pointers"), [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes)); EXPECT_EQ(X, static_cast(&A)); EXPECT_EQ(Y, static_cast(&B)); } TEST_F(MemoryAccessSPSCITest, WriteBuffers) { char Buf[8] = {}; char Content[] = "hello"; using SPSSig = void(SPSSequence>>); std::vector>> Writes = { {ExecutorAddr::fromPtr(Buf), span(Content, sizeof(Content))}}; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_write_buffers"), [](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(SPSSequence); std::vector Addrs = {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&Y)}; std::vector Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_uint8s"), [&](Expected> 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(SPSSequence); std::vector Addrs = {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&Y)}; std::vector Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_uint16s"), [&](Expected> 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(SPSSequence); std::vector Addrs = {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&Y)}; std::vector Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_uint32s"), [&](Expected> 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(SPSSequence); std::vector Addrs = {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&Y)}; std::vector Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_uint64s"), [&](Expected> 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(SPSSequence); std::vector Addrs = {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&Y)}; std::vector Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_pointers"), [&](Expected> R) { Result = cantFail(std::move(R)); }, std::move(Addrs)); ASSERT_EQ(Result.size(), 2U); EXPECT_EQ(Result[0], static_cast(&A)); EXPECT_EQ(Result[1], static_cast(&B)); } TEST_F(MemoryAccessSPSCITest, ReadBuffers) { const char Src[] = "hello world"; using SPSSig = SPSSequence>( SPSSequence>); std::vector> Reads = { {ExecutorAddr::fromPtr(Src), 5}, // "hello" {ExecutorAddr::fromPtr(Src + 6), 5}}; // "world" std::vector> Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_buffers"), [&](Expected>> R) { Result = cantFail(std::move(R)); }, std::move(Reads)); ASSERT_EQ(Result.size(), 2U); EXPECT_EQ(Result[0], (std::vector{'h', 'e', 'l', 'l', 'o'})); EXPECT_EQ(Result[1], (std::vector{'w', 'o', 'r', 'l', 'd'})); } TEST_F(MemoryAccessSPSCITest, ReadStrings) { const char *Str1 = "hello"; const char *Str2 = "world"; using SPSSig = SPSSequence(SPSSequence); std::vector Addrs = {ExecutorAddr::fromPtr(Str1), ExecutorAddr::fromPtr(Str2)}; std::vector Result; SPSWrapperFunction::call( caller("orc_rt_ci_sps_mem_read_strings"), [&](Expected> R) { Result = cantFail(std::move(R)); }, std::move(Addrs)); ASSERT_EQ(Result.size(), 2U); EXPECT_EQ(Result[0], "hello"); EXPECT_EQ(Result[1], "world"); }