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 LIBC_NAMESPACE { 14 15 using UINT = uintptr_t; 16 17 // Converts an offset into a pointer. 18 const void *forge(size_t offset) { 19 return reinterpret_cast<const void *>(offset); 20 } 21 22 TEST(LlvmLibcUtilsTest, DistanceToNextAligned) { 23 EXPECT_EQ(distance_to_next_aligned<16>(forge(0)), UINT(16)); 24 EXPECT_EQ(distance_to_next_aligned<16>(forge(1)), UINT(15)); 25 EXPECT_EQ(distance_to_next_aligned<16>(forge(16)), UINT(16)); 26 EXPECT_EQ(distance_to_next_aligned<16>(forge(15)), UINT(1)); 27 EXPECT_EQ(distance_to_next_aligned<32>(forge(16)), UINT(16)); 28 } 29 30 TEST(LlvmLibcUtilsTest, DistanceToAlignUp) { 31 EXPECT_EQ(distance_to_align_up<16>(forge(0)), UINT(0)); 32 EXPECT_EQ(distance_to_align_up<16>(forge(1)), UINT(15)); 33 EXPECT_EQ(distance_to_align_up<16>(forge(16)), UINT(0)); 34 EXPECT_EQ(distance_to_align_up<16>(forge(15)), UINT(1)); 35 EXPECT_EQ(distance_to_align_up<32>(forge(16)), UINT(16)); 36 } 37 38 TEST(LlvmLibcUtilsTest, DistanceToAlignDown) { 39 EXPECT_EQ(distance_to_align_down<16>(forge(0)), UINT(0)); 40 EXPECT_EQ(distance_to_align_down<16>(forge(1)), UINT(1)); 41 EXPECT_EQ(distance_to_align_down<16>(forge(16)), UINT(0)); 42 EXPECT_EQ(distance_to_align_down<16>(forge(15)), UINT(15)); 43 EXPECT_EQ(distance_to_align_down<32>(forge(16)), UINT(16)); 44 } 45 46 TEST(LlvmLibcUtilsTest, Adjust2) { 47 char a, b; 48 const size_t base_size = 10; 49 for (ptrdiff_t I = -2; I < 2; ++I) { 50 auto *p1 = &a; 51 auto *p2 = &b; 52 size_t size = base_size; 53 adjust(I, p1, p2, size); 54 EXPECT_EQ(intptr_t(p1), intptr_t(&a + I)); 55 EXPECT_EQ(intptr_t(p2), intptr_t(&b + I)); 56 EXPECT_EQ(size, base_size - I); 57 } 58 } 59 60 TEST(LlvmLibcUtilsTest, Align2) { 61 char a, b; 62 const size_t base_size = 10; 63 { 64 auto *p1 = &a; 65 auto *p2 = &b; 66 size_t size = base_size; 67 align_to_next_boundary<128, Arg::P1>(p1, p2, size); 68 EXPECT_TRUE(uintptr_t(p1) % 128 == 0); 69 EXPECT_GT(p1, &a); 70 EXPECT_GT(p2, &b); 71 EXPECT_EQ(size_t(p1 - &a), base_size - size); 72 EXPECT_EQ(size_t(p2 - &b), base_size - size); 73 } 74 { 75 auto *p1 = &a; 76 auto *p2 = &b; 77 size_t size = base_size; 78 align_to_next_boundary<128, Arg::P2>(p1, p2, size); 79 EXPECT_TRUE(uintptr_t(p2) % 128 == 0); 80 EXPECT_GT(p1, &a); 81 EXPECT_GT(p2, &b); 82 EXPECT_EQ(size_t(p1 - &a), base_size - size); 83 EXPECT_EQ(size_t(p2 - &b), base_size - size); 84 } 85 } 86 87 TEST(LlvmLibcUtilsTest, DisjointBuffers) { 88 char buf[3]; 89 const char *const a = buf + 0; 90 const char *const b = buf + 1; 91 EXPECT_TRUE(is_disjoint(a, b, 0)); 92 EXPECT_TRUE(is_disjoint(a, b, 1)); 93 EXPECT_FALSE(is_disjoint(a, b, 2)); 94 95 EXPECT_TRUE(is_disjoint(b, a, 0)); 96 EXPECT_TRUE(is_disjoint(b, a, 1)); 97 EXPECT_FALSE(is_disjoint(b, a, 2)); 98 } 99 100 TEST(LlvmLibcUtilsTest, LoadStoreAligned) { 101 const uint64_t init = 0xDEAD'C0DE'BEEF'F00D; 102 CPtr const src = reinterpret_cast<CPtr>(&init); 103 uint64_t store; 104 Ptr const dst = reinterpret_cast<Ptr>(&store); 105 106 using LoadFun = uint64_t (*)(CPtr); 107 using StoreFun = void (*)(uint64_t, Ptr); 108 109 { 110 LoadFun ld = load_aligned<uint64_t, uint64_t>; 111 StoreFun st = store_aligned<uint64_t, uint64_t>; 112 const uint64_t loaded = ld(src); 113 EXPECT_EQ(init, loaded); 114 store = 0; 115 st(init, dst); 116 EXPECT_EQ(init, store); 117 } 118 119 { 120 LoadFun ld = load_aligned<uint64_t, uint32_t, uint32_t>; 121 StoreFun st = store_aligned<uint64_t, uint32_t, uint32_t>; 122 const uint64_t loaded = ld(src); 123 EXPECT_EQ(init, loaded); 124 store = 0; 125 st(init, dst); 126 EXPECT_EQ(init, store); 127 } 128 129 { 130 LoadFun ld = load_aligned<uint64_t, uint32_t, uint16_t, uint8_t, uint8_t>; 131 StoreFun st = store_aligned<uint64_t, uint32_t, uint16_t, uint8_t, uint8_t>; 132 const uint64_t loaded = ld(src); 133 EXPECT_EQ(init, loaded); 134 store = 0; 135 st(init, dst); 136 EXPECT_EQ(init, store); 137 } 138 } 139 140 } // namespace LIBC_NAMESPACE 141