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