1 //===-- Unittests for memory_utils ----------------------------------------===// 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 //===----------------------------------------------------------------------===// 8 9 #include "src/__support/CPP/array.h" 10 #include "src/string/memory_utils/utils.h" 11 #include "test/UnitTest/Test.h" 12 13 namespace __llvm_libc { 14 15 TEST(LlvmLibcUtilsTest, IsPowerOfTwoOrZero) { 16 static const cpp::array<bool, 65> kExpectedValues{ 17 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 0-15 18 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 19 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 20 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63 21 1 // 64 22 }; 23 for (size_t i = 0; i < kExpectedValues.size(); ++i) 24 EXPECT_EQ(is_power2_or_zero(i), kExpectedValues[i]); 25 } 26 27 TEST(LlvmLibcUtilsTest, IsPowerOfTwo) { 28 static const cpp::array<bool, 65> kExpectedValues{ 29 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 0-15 30 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 31 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63 33 1 // 64 34 }; 35 for (size_t i = 0; i < kExpectedValues.size(); ++i) 36 EXPECT_EQ(is_power2(i), kExpectedValues[i]); 37 } 38 39 TEST(LlvmLibcUtilsTest, Log2) { 40 static const cpp::array<size_t, 65> kExpectedValues{ 41 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 0-15 42 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16-31 43 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 32-47 44 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 48-63 45 6 // 64 46 }; 47 for (size_t i = 0; i < kExpectedValues.size(); ++i) 48 EXPECT_EQ(log2s(i), kExpectedValues[i]); 49 } 50 51 TEST(LlvmLibcUtilsTest, LEPowerOf2) { 52 static const cpp::array<size_t, 65> kExpectedValues{ 53 0, 1, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, // 0-15 54 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, // 16-31 55 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 32-47 56 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 48-63 57 64 // 64 58 }; 59 for (size_t i = 0; i < kExpectedValues.size(); ++i) 60 EXPECT_EQ(le_power2(i), kExpectedValues[i]); 61 } 62 63 TEST(LlvmLibcUtilsTest, GEPowerOf2) { 64 static const cpp::array<size_t, 66> kExpectedValues{ 65 0, 1, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, // 0-15 66 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 16-31 67 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, // 32-47 68 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, // 48-63 69 64, 128 // 64-65 70 }; 71 for (size_t i = 0; i < kExpectedValues.size(); ++i) 72 EXPECT_EQ(ge_power2(i), kExpectedValues[i]); 73 } 74 75 using UINT = uintptr_t; 76 77 // Converts an offset into a pointer. 78 const void *forge(size_t offset) { 79 return reinterpret_cast<const void *>(offset); 80 } 81 82 TEST(LlvmLibcUtilsTest, DistanceToNextAligned) { 83 EXPECT_EQ(distance_to_next_aligned<16>(forge(0)), UINT(16)); 84 EXPECT_EQ(distance_to_next_aligned<16>(forge(1)), UINT(15)); 85 EXPECT_EQ(distance_to_next_aligned<16>(forge(16)), UINT(16)); 86 EXPECT_EQ(distance_to_next_aligned<16>(forge(15)), UINT(1)); 87 EXPECT_EQ(distance_to_next_aligned<32>(forge(16)), UINT(16)); 88 } 89 90 TEST(LlvmLibcUtilsTest, DistanceToAlignUp) { 91 EXPECT_EQ(distance_to_align_up<16>(forge(0)), UINT(0)); 92 EXPECT_EQ(distance_to_align_up<16>(forge(1)), UINT(15)); 93 EXPECT_EQ(distance_to_align_up<16>(forge(16)), UINT(0)); 94 EXPECT_EQ(distance_to_align_up<16>(forge(15)), UINT(1)); 95 EXPECT_EQ(distance_to_align_up<32>(forge(16)), UINT(16)); 96 } 97 98 TEST(LlvmLibcUtilsTest, DistanceToAlignDown) { 99 EXPECT_EQ(distance_to_align_down<16>(forge(0)), UINT(0)); 100 EXPECT_EQ(distance_to_align_down<16>(forge(1)), UINT(1)); 101 EXPECT_EQ(distance_to_align_down<16>(forge(16)), UINT(0)); 102 EXPECT_EQ(distance_to_align_down<16>(forge(15)), UINT(15)); 103 EXPECT_EQ(distance_to_align_down<32>(forge(16)), UINT(16)); 104 } 105 106 TEST(LlvmLibcUtilsTest, Adjust2) { 107 char a, b; 108 const size_t base_size = 10; 109 for (ptrdiff_t I = -2; I < 2; ++I) { 110 auto *p1 = &a; 111 auto *p2 = &b; 112 size_t size = base_size; 113 adjust(I, p1, p2, size); 114 EXPECT_EQ(intptr_t(p1), intptr_t(&a + I)); 115 EXPECT_EQ(intptr_t(p2), intptr_t(&b + I)); 116 EXPECT_EQ(size, base_size - I); 117 } 118 } 119 120 TEST(LlvmLibcUtilsTest, Align2) { 121 char a, b; 122 const size_t base_size = 10; 123 { 124 auto *p1 = &a; 125 auto *p2 = &b; 126 size_t size = base_size; 127 align_to_next_boundary<128, Arg::P1>(p1, p2, size); 128 EXPECT_TRUE(uintptr_t(p1) % 128 == 0); 129 EXPECT_GT(p1, &a); 130 EXPECT_GT(p2, &b); 131 EXPECT_EQ(size_t(p1 - &a), base_size - size); 132 EXPECT_EQ(size_t(p2 - &b), base_size - size); 133 } 134 { 135 auto *p1 = &a; 136 auto *p2 = &b; 137 size_t size = base_size; 138 align_to_next_boundary<128, Arg::P2>(p1, p2, size); 139 EXPECT_TRUE(uintptr_t(p2) % 128 == 0); 140 EXPECT_GT(p1, &a); 141 EXPECT_GT(p2, &b); 142 EXPECT_EQ(size_t(p1 - &a), base_size - size); 143 EXPECT_EQ(size_t(p2 - &b), base_size - size); 144 } 145 } 146 147 TEST(LlvmLibcUtilsTest, DisjointBuffers) { 148 char buf[3]; 149 const char *const a = buf + 0; 150 const char *const b = buf + 1; 151 EXPECT_TRUE(is_disjoint(a, b, 0)); 152 EXPECT_TRUE(is_disjoint(a, b, 1)); 153 EXPECT_FALSE(is_disjoint(a, b, 2)); 154 155 EXPECT_TRUE(is_disjoint(b, a, 0)); 156 EXPECT_TRUE(is_disjoint(b, a, 1)); 157 EXPECT_FALSE(is_disjoint(b, a, 2)); 158 } 159 160 TEST(LlvmLibcUtilsTest, LoadStoreAligned) { 161 const uint64_t init = 0xDEAD'C0DE'BEEF'F00D; 162 CPtr const src = reinterpret_cast<CPtr>(&init); 163 uint64_t store; 164 Ptr const dst = reinterpret_cast<Ptr>(&store); 165 166 using LoadFun = uint64_t (*)(CPtr); 167 using StoreFun = void (*)(uint64_t, Ptr); 168 169 { 170 LoadFun ld = load_aligned<uint64_t, uint64_t>; 171 StoreFun st = store_aligned<uint64_t, uint64_t>; 172 const uint64_t loaded = ld(src); 173 EXPECT_EQ(init, loaded); 174 store = 0; 175 st(init, dst); 176 EXPECT_EQ(init, store); 177 } 178 179 { 180 LoadFun ld = load_aligned<uint64_t, uint32_t, uint32_t>; 181 StoreFun st = store_aligned<uint64_t, uint32_t, uint32_t>; 182 const uint64_t loaded = ld(src); 183 EXPECT_EQ(init, loaded); 184 store = 0; 185 st(init, dst); 186 EXPECT_EQ(init, store); 187 } 188 189 { 190 LoadFun ld = load_aligned<uint64_t, uint32_t, uint16_t, uint8_t, uint8_t>; 191 StoreFun st = store_aligned<uint64_t, uint32_t, uint16_t, uint8_t, uint8_t>; 192 const uint64_t loaded = ld(src); 193 EXPECT_EQ(init, loaded); 194 store = 0; 195 st(init, dst); 196 EXPECT_EQ(init, store); 197 } 198 } 199 200 } // namespace __llvm_libc 201