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
13namespace LIBC_NAMESPACE {
14
15using UINT = uintptr_t;
16
17// Converts an offset into a pointer.
18const void *forge(size_t offset) {
19 return reinterpret_cast<const void *>(offset);
20}
21
22TEST(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
30TEST(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
38TEST(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
46TEST(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(offset: I, p1, p2, count&: 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
60TEST(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, count&: 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, count&: 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
87TEST(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
100TEST(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

source code of libc/test/src/string/memory_utils/utils_test.cpp