xref: /llvm-project/libc/test/src/string/memory_utils/utils_test.cpp (revision 1d894788305c624c700ae332742886823554560e)
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