WaymarkingTest.cpp
3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//===- llvm/unittest/IR/WaymarkTest.cpp - Waymarking unit tests -----------===//
//
// 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/ADT/Waymarking.h"
#include "gtest/gtest.h"
using namespace llvm;
static const int N = 100;
// Get the Waymarking Tag of the pointer.
static int tag(int *P) {
return static_cast<int>(reinterpret_cast<uintptr_t>(P) &
uintptr_t(alignof(int *) - 1));
}
// Get the actual pointer, by stripping the Waymarking Tag.
static int *ref(int *P) {
return reinterpret_cast<int *>(reinterpret_cast<uintptr_t>(P) &
~uintptr_t(alignof(int *) - 1));
}
static int **createArray(int Len) {
int **A = new int *[Len];
for (int I = 0; I < Len; ++I)
A[I] = new int(I);
return A;
}
static void freeArray(int **A, int Len) {
for (int I = 0; I < Len; ++I)
delete ref(A[I]);
delete[] A;
}
// Verify the values stored in the array are as expected, and did not change due
// to fillWaymarks.
static void verifyArrayValues(int **A, int Begin, int End) {
for (int I = Begin; I < End; ++I)
EXPECT_EQ(I, *ref(A[I]));
}
static void verifyArrayValues(int **A, int Len) {
verifyArrayValues(A, 0, Len);
}
// Verify that we can follow the waymarks to the array's head from each element
// of the array.
static void verifyFollowWaymarks(int **A, int Len) {
for (int I = 0; I < Len; ++I) {
int **P = followWaymarks(A + I);
EXPECT_EQ(A, P);
}
}
namespace {
// Test filling and following the waymarks of a single array.
TEST(WaymarkingTest, SingleHead) {
const int N2 = 2 * N;
int **volatile A = createArray(N2);
// Fill the first half of the array with waymarks.
fillWaymarks(A, A + N, 0);
verifyArrayValues(A, N2);
verifyFollowWaymarks(A, N);
// Fill the rest of the waymarks (continuing from where we stopped).
fillWaymarks(A + N, A + N2, N);
verifyArrayValues(A, N2);
verifyFollowWaymarks(A, N);
freeArray(A, N2);
}
// Test filling and following the waymarks of an array split into several
// different sections of waymarks (treated just like separate arrays).
TEST(WaymarkingTest, MultiHead) {
const int N2 = 2 * N;
const int N3 = 3 * N;
int **volatile A = createArray(N3);
// Separate the array into 3 sections of waymarks.
fillWaymarks(A, A + N, 0);
fillWaymarks(A + N, A + N2, 0);
fillWaymarks(A + N2, A + N3, 0);
verifyArrayValues(A, N3);
verifyFollowWaymarks(A, N);
verifyFollowWaymarks(A + N, N2 - N);
verifyFollowWaymarks(A + N2, N3 - N2);
freeArray(A, N3);
}
// Test reseting (value and tag of) elements inside an array of waymarks.
TEST(WaymarkingTest, Reset) {
int **volatile A = createArray(N);
fillWaymarks(A, A + N, 0);
verifyArrayValues(A, N);
const int N2 = N / 2;
const int N3 = N / 3;
const int N4 = N / 4;
// Reset specific elements and check that the tag remains the same.
int T2 = tag(A[N2]);
delete ref(A[N2]);
A[N2] = new int(N2);
fillWaymarks(A + N2, A + N2 + 1, N2);
verifyArrayValues(A, N2, N2 + 1);
EXPECT_EQ(T2, tag(A[N2]));
int T3 = tag(A[N3]);
delete ref(A[N3]);
A[N3] = new int(N3);
fillWaymarks(A + N3, A + N3 + 1, N3);
verifyArrayValues(A, N3, N3 + 1);
EXPECT_EQ(T3, tag(A[N3]));
int T4 = tag(A[N4]);
delete ref(A[N4]);
A[N4] = new int(N4);
fillWaymarks(A + N4, A + N4 + 1, N4);
verifyArrayValues(A, N4, N4 + 1);
EXPECT_EQ(T4, tag(A[N4]));
verifyArrayValues(A, N);
verifyFollowWaymarks(A, N);
freeArray(A, N);
}
} // end anonymous namespace