]> git.proxmox.com Git - rustc.git/blob - src/llvm/unittests/Support/MemoryTest.cpp
Imported Upstream version 1.0.0+dfsg1
[rustc.git] / src / llvm / unittests / Support / MemoryTest.cpp
1 //===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Support/Memory.h"
11 #include "llvm/Support/Process.h"
12 #include "gtest/gtest.h"
13 #include <cstdlib>
14
15 using namespace llvm;
16 using namespace sys;
17
18 namespace {
19
20 class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
21 public:
22 MappedMemoryTest() {
23 Flags = GetParam();
24 PageSize = sys::Process::getPageSize();
25 }
26
27 protected:
28 // Adds RW flags to permit testing of the resulting memory
29 unsigned getTestableEquivalent(unsigned RequestedFlags) {
30 switch (RequestedFlags) {
31 case Memory::MF_READ:
32 case Memory::MF_WRITE:
33 case Memory::MF_READ|Memory::MF_WRITE:
34 return Memory::MF_READ|Memory::MF_WRITE;
35 case Memory::MF_READ|Memory::MF_EXEC:
36 case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
37 case Memory::MF_EXEC:
38 return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
39 }
40 // Default in case values are added to the enum, as required by some compilers
41 return Memory::MF_READ|Memory::MF_WRITE;
42 }
43
44 // Returns true if the memory blocks overlap
45 bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
46 if (M1.base() == M2.base())
47 return true;
48
49 if (M1.base() > M2.base())
50 return (unsigned char *)M2.base() + M2.size() > M1.base();
51
52 return (unsigned char *)M1.base() + M1.size() > M2.base();
53 }
54
55 unsigned Flags;
56 size_t PageSize;
57 };
58
59 TEST_P(MappedMemoryTest, AllocAndRelease) {
60 std::error_code EC;
61 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
62 EXPECT_EQ(std::error_code(), EC);
63
64 EXPECT_NE((void*)nullptr, M1.base());
65 EXPECT_LE(sizeof(int), M1.size());
66
67 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
68 }
69
70 TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
71 std::error_code EC;
72 MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
73 EXPECT_EQ(std::error_code(), EC);
74 MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC);
75 EXPECT_EQ(std::error_code(), EC);
76 MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC);
77 EXPECT_EQ(std::error_code(), EC);
78
79 EXPECT_NE((void*)nullptr, M1.base());
80 EXPECT_LE(16U, M1.size());
81 EXPECT_NE((void*)nullptr, M2.base());
82 EXPECT_LE(64U, M2.size());
83 EXPECT_NE((void*)nullptr, M3.base());
84 EXPECT_LE(32U, M3.size());
85
86 EXPECT_FALSE(doesOverlap(M1, M2));
87 EXPECT_FALSE(doesOverlap(M2, M3));
88 EXPECT_FALSE(doesOverlap(M1, M3));
89
90 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
91 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
92 MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
93 EXPECT_EQ(std::error_code(), EC);
94 EXPECT_NE((void*)nullptr, M4.base());
95 EXPECT_LE(16U, M4.size());
96 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
97 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
98 }
99
100 TEST_P(MappedMemoryTest, BasicWrite) {
101 // This test applies only to readable and writeable combinations
102 if (Flags &&
103 !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
104 return;
105
106 std::error_code EC;
107 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
108 EXPECT_EQ(std::error_code(), EC);
109
110 EXPECT_NE((void*)nullptr, M1.base());
111 EXPECT_LE(sizeof(int), M1.size());
112
113 int *a = (int*)M1.base();
114 *a = 1;
115 EXPECT_EQ(1, *a);
116
117 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
118 }
119
120 TEST_P(MappedMemoryTest, MultipleWrite) {
121 // This test applies only to readable and writeable combinations
122 if (Flags &&
123 !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
124 return;
125 std::error_code EC;
126 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,
127 EC);
128 EXPECT_EQ(std::error_code(), EC);
129 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
130 EC);
131 EXPECT_EQ(std::error_code(), EC);
132 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
133 EC);
134 EXPECT_EQ(std::error_code(), EC);
135
136 EXPECT_FALSE(doesOverlap(M1, M2));
137 EXPECT_FALSE(doesOverlap(M2, M3));
138 EXPECT_FALSE(doesOverlap(M1, M3));
139
140 EXPECT_NE((void*)nullptr, M1.base());
141 EXPECT_LE(1U * sizeof(int), M1.size());
142 EXPECT_NE((void*)nullptr, M2.base());
143 EXPECT_LE(8U * sizeof(int), M2.size());
144 EXPECT_NE((void*)nullptr, M3.base());
145 EXPECT_LE(4U * sizeof(int), M3.size());
146
147 int *x = (int*)M1.base();
148 *x = 1;
149
150 int *y = (int*)M2.base();
151 for (int i = 0; i < 8; i++) {
152 y[i] = i;
153 }
154
155 int *z = (int*)M3.base();
156 *z = 42;
157
158 EXPECT_EQ(1, *x);
159 EXPECT_EQ(7, y[7]);
160 EXPECT_EQ(42, *z);
161
162 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
163 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
164
165 MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr,
166 Flags, EC);
167 EXPECT_EQ(std::error_code(), EC);
168 EXPECT_NE((void*)nullptr, M4.base());
169 EXPECT_LE(64U * sizeof(int), M4.size());
170 x = (int*)M4.base();
171 *x = 4;
172 EXPECT_EQ(4, *x);
173 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
174
175 // Verify that M2 remains unaffected by other activity
176 for (int i = 0; i < 8; i++) {
177 EXPECT_EQ(i, y[i]);
178 }
179 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
180 }
181
182 TEST_P(MappedMemoryTest, EnabledWrite) {
183 std::error_code EC;
184 MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags,
185 EC);
186 EXPECT_EQ(std::error_code(), EC);
187 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
188 EC);
189 EXPECT_EQ(std::error_code(), EC);
190 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
191 EC);
192 EXPECT_EQ(std::error_code(), EC);
193
194 EXPECT_NE((void*)nullptr, M1.base());
195 EXPECT_LE(2U * sizeof(int), M1.size());
196 EXPECT_NE((void*)nullptr, M2.base());
197 EXPECT_LE(8U * sizeof(int), M2.size());
198 EXPECT_NE((void*)nullptr, M3.base());
199 EXPECT_LE(4U * sizeof(int), M3.size());
200
201 EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
202 EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
203 EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
204
205 EXPECT_FALSE(doesOverlap(M1, M2));
206 EXPECT_FALSE(doesOverlap(M2, M3));
207 EXPECT_FALSE(doesOverlap(M1, M3));
208
209 int *x = (int*)M1.base();
210 *x = 1;
211 int *y = (int*)M2.base();
212 for (unsigned int i = 0; i < 8; i++) {
213 y[i] = i;
214 }
215 int *z = (int*)M3.base();
216 *z = 42;
217
218 EXPECT_EQ(1, *x);
219 EXPECT_EQ(7, y[7]);
220 EXPECT_EQ(42, *z);
221
222 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
223 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
224 EXPECT_EQ(6, y[6]);
225
226 MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
227 EXPECT_EQ(std::error_code(), EC);
228 EXPECT_NE((void*)nullptr, M4.base());
229 EXPECT_LE(16U, M4.size());
230 EXPECT_EQ(std::error_code(),
231 Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
232 x = (int*)M4.base();
233 *x = 4;
234 EXPECT_EQ(4, *x);
235 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
236 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
237 }
238
239 TEST_P(MappedMemoryTest, SuccessiveNear) {
240 std::error_code EC;
241 MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
242 EXPECT_EQ(std::error_code(), EC);
243 MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
244 EXPECT_EQ(std::error_code(), EC);
245 MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
246 EXPECT_EQ(std::error_code(), EC);
247
248 EXPECT_NE((void*)nullptr, M1.base());
249 EXPECT_LE(16U, M1.size());
250 EXPECT_NE((void*)nullptr, M2.base());
251 EXPECT_LE(64U, M2.size());
252 EXPECT_NE((void*)nullptr, M3.base());
253 EXPECT_LE(32U, M3.size());
254
255 EXPECT_FALSE(doesOverlap(M1, M2));
256 EXPECT_FALSE(doesOverlap(M2, M3));
257 EXPECT_FALSE(doesOverlap(M1, M3));
258
259 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
260 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
261 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
262 }
263
264 TEST_P(MappedMemoryTest, DuplicateNear) {
265 std::error_code EC;
266 MemoryBlock Near((void*)(3*PageSize), 16);
267 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
268 EXPECT_EQ(std::error_code(), EC);
269 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
270 EXPECT_EQ(std::error_code(), EC);
271 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
272 EXPECT_EQ(std::error_code(), EC);
273
274 EXPECT_NE((void*)nullptr, M1.base());
275 EXPECT_LE(16U, M1.size());
276 EXPECT_NE((void*)nullptr, M2.base());
277 EXPECT_LE(64U, M2.size());
278 EXPECT_NE((void*)nullptr, M3.base());
279 EXPECT_LE(32U, M3.size());
280
281 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
282 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
283 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
284 }
285
286 TEST_P(MappedMemoryTest, ZeroNear) {
287 std::error_code EC;
288 MemoryBlock Near(nullptr, 0);
289 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
290 EXPECT_EQ(std::error_code(), EC);
291 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
292 EXPECT_EQ(std::error_code(), EC);
293 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
294 EXPECT_EQ(std::error_code(), EC);
295
296 EXPECT_NE((void*)nullptr, M1.base());
297 EXPECT_LE(16U, M1.size());
298 EXPECT_NE((void*)nullptr, M2.base());
299 EXPECT_LE(64U, M2.size());
300 EXPECT_NE((void*)nullptr, M3.base());
301 EXPECT_LE(32U, M3.size());
302
303 EXPECT_FALSE(doesOverlap(M1, M2));
304 EXPECT_FALSE(doesOverlap(M2, M3));
305 EXPECT_FALSE(doesOverlap(M1, M3));
306
307 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
308 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
309 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
310 }
311
312 TEST_P(MappedMemoryTest, ZeroSizeNear) {
313 std::error_code EC;
314 MemoryBlock Near((void*)(4*PageSize), 0);
315 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
316 EXPECT_EQ(std::error_code(), EC);
317 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
318 EXPECT_EQ(std::error_code(), EC);
319 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
320 EXPECT_EQ(std::error_code(), EC);
321
322 EXPECT_NE((void*)nullptr, M1.base());
323 EXPECT_LE(16U, M1.size());
324 EXPECT_NE((void*)nullptr, M2.base());
325 EXPECT_LE(64U, M2.size());
326 EXPECT_NE((void*)nullptr, M3.base());
327 EXPECT_LE(32U, M3.size());
328
329 EXPECT_FALSE(doesOverlap(M1, M2));
330 EXPECT_FALSE(doesOverlap(M2, M3));
331 EXPECT_FALSE(doesOverlap(M1, M3));
332
333 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
334 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
335 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
336 }
337
338 TEST_P(MappedMemoryTest, UnalignedNear) {
339 std::error_code EC;
340 MemoryBlock Near((void*)(2*PageSize+5), 0);
341 MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
342 EXPECT_EQ(std::error_code(), EC);
343
344 EXPECT_NE((void*)nullptr, M1.base());
345 EXPECT_LE(sizeof(int), M1.size());
346
347 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
348 }
349
350 // Note that Memory::MF_WRITE is not supported exclusively across
351 // operating systems and architectures and can imply MF_READ|MF_WRITE
352 unsigned MemoryFlags[] = {
353 Memory::MF_READ,
354 Memory::MF_WRITE,
355 Memory::MF_READ|Memory::MF_WRITE,
356 Memory::MF_EXEC,
357 Memory::MF_READ|Memory::MF_EXEC,
358 Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
359 };
360
361 INSTANTIATE_TEST_CASE_P(AllocationTests,
362 MappedMemoryTest,
363 ::testing::ValuesIn(MemoryFlags));
364
365 } // anonymous namespace