[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / ExecutionEngine / Orc / MemoryMapperTest.cpp
blob57a9fac77d84c87e658d5f024e420549e32b5c8c
1 //===------------------------ MemoryMapperTest.cpp ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
10 #include "llvm/Support/Process.h"
11 #include "llvm/Testing/Support/Error.h"
12 #include "gtest/gtest.h"
14 using namespace llvm;
15 using namespace llvm::orc;
16 using namespace llvm::orc::shared;
18 namespace {
20 Expected<ExecutorAddrRange> reserve(MemoryMapper &M, size_t NumBytes) {
21 std::promise<MSVCPExpected<ExecutorAddrRange>> P;
22 auto F = P.get_future();
23 M.reserve(NumBytes, [&](auto R) { P.set_value(std::move(R)); });
24 return F.get();
27 Expected<ExecutorAddr> initialize(MemoryMapper &M,
28 MemoryMapper::AllocInfo &AI) {
29 std::promise<MSVCPExpected<ExecutorAddr>> P;
30 auto F = P.get_future();
31 M.initialize(AI, [&](auto R) { P.set_value(std::move(R)); });
32 return F.get();
35 Error deinitialize(MemoryMapper &M,
36 const std::vector<ExecutorAddr> &Allocations) {
37 std::promise<MSVCPError> P;
38 auto F = P.get_future();
39 M.deinitialize(Allocations, [&](auto R) { P.set_value(std::move(R)); });
40 return F.get();
43 Error release(MemoryMapper &M, const std::vector<ExecutorAddr> &Reservations) {
44 std::promise<MSVCPError> P;
45 auto F = P.get_future();
46 M.release(Reservations, [&](auto R) { P.set_value(std::move(R)); });
47 return F.get();
50 // A basic function to be used as both initializer/deinitializer
51 orc::shared::CWrapperFunctionResult incrementWrapper(const char *ArgData,
52 size_t ArgSize) {
53 return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
54 ArgData, ArgSize,
55 [](ExecutorAddr A) -> Error {
56 *A.toPtr<int *>() += 1;
57 return Error::success();
59 .release();
62 TEST(MemoryMapperTest, InitializeDeinitialize) {
63 // These counters are used to track how many times the initializer and
64 // deinitializer functions are called
65 int InitializeCounter = 0;
66 int DeinitializeCounter = 0;
68 std::unique_ptr<MemoryMapper> Mapper =
69 cantFail(InProcessMemoryMapper::Create());
71 // We will do two separate allocations
72 auto PageSize = Mapper->getPageSize();
73 auto TotalSize = PageSize * 2;
75 // Reserve address space
76 auto Mem1 = reserve(*Mapper, TotalSize);
77 EXPECT_THAT_ERROR(Mem1.takeError(), Succeeded());
79 // Test string for memory transfer
80 std::string HW = "Hello, world!";
83 // Provide working memory
84 char *WA1 = Mapper->prepare(Mem1->Start, HW.size() + 1);
85 std::strcpy(static_cast<char *>(WA1), HW.c_str());
88 // A structure to be passed to initialize
89 MemoryMapper::AllocInfo Alloc1;
91 MemoryMapper::AllocInfo::SegInfo Seg1;
92 Seg1.Offset = 0;
93 Seg1.ContentSize = HW.size();
94 Seg1.ZeroFillSize = PageSize - Seg1.ContentSize;
95 Seg1.Prot = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
97 Alloc1.MappingBase = Mem1->Start;
98 Alloc1.Segments.push_back(Seg1);
99 Alloc1.Actions.push_back(
100 {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
101 ExecutorAddr::fromPtr(incrementWrapper),
102 ExecutorAddr::fromPtr(&InitializeCounter))),
103 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
104 ExecutorAddr::fromPtr(incrementWrapper),
105 ExecutorAddr::fromPtr(&DeinitializeCounter)))});
109 char *WA2 = Mapper->prepare(Mem1->Start + PageSize, HW.size() + 1);
110 std::strcpy(static_cast<char *>(WA2), HW.c_str());
113 MemoryMapper::AllocInfo Alloc2;
115 MemoryMapper::AllocInfo::SegInfo Seg2;
116 Seg2.Offset = PageSize;
117 Seg2.ContentSize = HW.size();
118 Seg2.ZeroFillSize = PageSize - Seg2.ContentSize;
119 Seg2.Prot = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
121 Alloc2.MappingBase = Mem1->Start;
122 Alloc2.Segments.push_back(Seg2);
123 Alloc2.Actions.push_back(
124 {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
125 ExecutorAddr::fromPtr(incrementWrapper),
126 ExecutorAddr::fromPtr(&InitializeCounter))),
127 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
128 ExecutorAddr::fromPtr(incrementWrapper),
129 ExecutorAddr::fromPtr(&DeinitializeCounter)))});
132 EXPECT_EQ(InitializeCounter, 0);
133 EXPECT_EQ(DeinitializeCounter, 0);
135 // Set memory protections and run initializers
136 auto Init1 = initialize(*Mapper, Alloc1);
137 EXPECT_THAT_ERROR(Init1.takeError(), Succeeded());
138 EXPECT_EQ(HW, std::string(static_cast<char *>(Init1->toPtr<char *>())));
140 EXPECT_EQ(InitializeCounter, 1);
141 EXPECT_EQ(DeinitializeCounter, 0);
143 auto Init2 = initialize(*Mapper, Alloc2);
144 EXPECT_THAT_ERROR(Init2.takeError(), Succeeded());
145 EXPECT_EQ(HW, std::string(static_cast<char *>(Init2->toPtr<char *>())));
147 EXPECT_EQ(InitializeCounter, 2);
148 EXPECT_EQ(DeinitializeCounter, 0);
150 // Explicit deinitialization of first allocation
151 std::vector<ExecutorAddr> DeinitAddr = {*Init1};
152 EXPECT_THAT_ERROR(deinitialize(*Mapper, DeinitAddr), Succeeded());
154 EXPECT_EQ(InitializeCounter, 2);
155 EXPECT_EQ(DeinitializeCounter, 1);
157 // Test explicit release
159 auto Mem2 = reserve(*Mapper, PageSize);
160 EXPECT_THAT_ERROR(Mem2.takeError(), Succeeded());
162 char *WA = Mapper->prepare(Mem2->Start, HW.size() + 1);
163 std::strcpy(static_cast<char *>(WA), HW.c_str());
165 MemoryMapper::AllocInfo Alloc3;
167 MemoryMapper::AllocInfo::SegInfo Seg3;
168 Seg3.Offset = 0;
169 Seg3.ContentSize = HW.size();
170 Seg3.ZeroFillSize = PageSize - Seg3.ContentSize;
171 Seg3.Prot = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
173 Alloc3.MappingBase = Mem2->Start;
174 Alloc3.Segments.push_back(Seg3);
175 Alloc3.Actions.push_back(
176 {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
177 ExecutorAddr::fromPtr(incrementWrapper),
178 ExecutorAddr::fromPtr(&InitializeCounter))),
179 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
180 ExecutorAddr::fromPtr(incrementWrapper),
181 ExecutorAddr::fromPtr(&DeinitializeCounter)))});
183 auto Init3 = initialize(*Mapper, Alloc3);
184 EXPECT_THAT_ERROR(Init3.takeError(), Succeeded());
185 EXPECT_EQ(HW, std::string(static_cast<char *>(Init3->toPtr<char *>())));
187 EXPECT_EQ(InitializeCounter, 3);
188 EXPECT_EQ(DeinitializeCounter, 1);
190 std::vector<ExecutorAddr> ReleaseAddrs = {Mem2->Start};
191 EXPECT_THAT_ERROR(release(*Mapper, ReleaseAddrs), Succeeded());
193 EXPECT_EQ(InitializeCounter, 3);
194 EXPECT_EQ(DeinitializeCounter, 2);
198 // Implicit deinitialization by the destructor
199 EXPECT_EQ(InitializeCounter, 3);
200 EXPECT_EQ(DeinitializeCounter, 3);
203 } // namespace