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
|