1 | //===- unittests/Support/EndianTest.cpp - Endian.h tests ------------------===// |
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 "llvm/Support/Endian.h" |
10 | #include "llvm/Support/DataTypes.h" |
11 | #include "gtest/gtest.h" |
12 | #include <cstdlib> |
13 | #include <ctime> |
14 | using namespace llvm; |
15 | using namespace support; |
16 | |
17 | #undef max |
18 | |
19 | namespace { |
20 | |
21 | TEST(Endian, Read) { |
22 | // These are 5 bytes so we can be sure at least one of the reads is unaligned. |
23 | unsigned char bigval[] = {0x00, 0x01, 0x02, 0x03, 0x04}; |
24 | unsigned char littleval[] = {0x00, 0x04, 0x03, 0x02, 0x01}; |
25 | int32_t BigAsHost = 0x00010203; |
26 | EXPECT_EQ(BigAsHost, |
27 | (endian::read<int32_t, llvm::endianness::big, unaligned>(bigval))); |
28 | int32_t LittleAsHost = 0x02030400; |
29 | EXPECT_EQ( |
30 | LittleAsHost, |
31 | (endian::read<int32_t, llvm::endianness::little, unaligned>(littleval))); |
32 | |
33 | EXPECT_EQ( |
34 | (endian::read<int32_t, llvm::endianness::big, unaligned>(bigval + 1)), |
35 | (endian::read<int32_t, llvm::endianness::little, unaligned>(littleval + |
36 | 1))); |
37 | } |
38 | |
39 | TEST(Endian, WriteNext) { |
40 | unsigned char bigval[] = {0x00, 0x00}, *p = bigval; |
41 | endian::writeNext<int16_t, llvm::endianness::big>(memory&: p, value: short(0xaabb)); |
42 | EXPECT_EQ(bigval[0], 0xaa); |
43 | EXPECT_EQ(bigval[1], 0xbb); |
44 | EXPECT_EQ(p, bigval + 2); |
45 | |
46 | char littleval[8] = {}, *q = littleval; |
47 | endian::writeNext<uint32_t, llvm::endianness::little>(memory&: q, value: 0x44556677); |
48 | EXPECT_EQ(littleval[0], 0x77); |
49 | EXPECT_EQ(littleval[1], 0x66); |
50 | EXPECT_EQ(littleval[2], 0x55); |
51 | EXPECT_EQ(littleval[3], 0x44); |
52 | EXPECT_EQ(q, littleval + 4); |
53 | |
54 | endian::writeNext<uint32_t>(memory&: q, value: 0x11223344, endian: llvm::endianness::little); |
55 | EXPECT_EQ(littleval[4], 0x44); |
56 | EXPECT_EQ(littleval[5], 0x33); |
57 | EXPECT_EQ(littleval[6], 0x22); |
58 | EXPECT_EQ(littleval[7], 0x11); |
59 | EXPECT_EQ(q, littleval + 8); |
60 | } |
61 | |
62 | TEST(Endian, ReadBitAligned) { |
63 | // Simple test to make sure we properly pull out the 0x0 word. |
64 | unsigned char littleval[] = {0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff}; |
65 | unsigned char bigval[] = {0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0}; |
66 | EXPECT_EQ( |
67 | (endian::readAtBitAlignment<int, llvm::endianness::little, unaligned>( |
68 | &littleval[0], 6)), |
69 | 0x0); |
70 | EXPECT_EQ((endian::readAtBitAlignment<int, llvm::endianness::big, unaligned>( |
71 | &bigval[0], 6)), |
72 | 0x0); |
73 | // Test to make sure that signed right shift of 0xf0000000 is masked |
74 | // properly. |
75 | unsigned char littleval2[] = {0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00}; |
76 | unsigned char bigval2[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
77 | EXPECT_EQ( |
78 | (endian::readAtBitAlignment<int, llvm::endianness::little, unaligned>( |
79 | &littleval2[0], 4)), |
80 | 0x0f000000); |
81 | EXPECT_EQ((endian::readAtBitAlignment<int, llvm::endianness::big, unaligned>( |
82 | &bigval2[0], 4)), |
83 | 0x0f000000); |
84 | // Test to make sure left shift of start bit doesn't overflow. |
85 | EXPECT_EQ( |
86 | (endian::readAtBitAlignment<int, llvm::endianness::little, unaligned>( |
87 | &littleval2[0], 1)), |
88 | 0x78000000); |
89 | EXPECT_EQ((endian::readAtBitAlignment<int, llvm::endianness::big, unaligned>( |
90 | &bigval2[0], 1)), |
91 | 0x78000000); |
92 | // Test to make sure 64-bit int doesn't overflow. |
93 | unsigned char littleval3[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, |
94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
95 | unsigned char bigval3[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
96 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
97 | EXPECT_EQ( |
98 | (endian::readAtBitAlignment<int64_t, llvm::endianness::little, unaligned>( |
99 | &littleval3[0], 4)), |
100 | 0x0f00000000000000); |
101 | EXPECT_EQ( |
102 | (endian::readAtBitAlignment<int64_t, llvm::endianness::big, unaligned>( |
103 | &bigval3[0], 4)), |
104 | 0x0f00000000000000); |
105 | } |
106 | |
107 | TEST(Endian, WriteBitAligned) { |
108 | // This test ensures that signed right shift of 0xffffaa is masked |
109 | // properly. |
110 | unsigned char bigval[8] = {0x00}; |
111 | endian::writeAtBitAlignment<int32_t, llvm::endianness::big, unaligned>( |
112 | memory: bigval, value: (int)0xffffaaaa, startBit: 4); |
113 | EXPECT_EQ(bigval[0], 0xff); |
114 | EXPECT_EQ(bigval[1], 0xfa); |
115 | EXPECT_EQ(bigval[2], 0xaa); |
116 | EXPECT_EQ(bigval[3], 0xa0); |
117 | EXPECT_EQ(bigval[4], 0x00); |
118 | EXPECT_EQ(bigval[5], 0x00); |
119 | EXPECT_EQ(bigval[6], 0x00); |
120 | EXPECT_EQ(bigval[7], 0x0f); |
121 | |
122 | unsigned char littleval[8] = {0x00}; |
123 | endian::writeAtBitAlignment<int32_t, llvm::endianness::little, unaligned>( |
124 | memory: littleval, value: (int)0xffffaaaa, startBit: 4); |
125 | EXPECT_EQ(littleval[0], 0xa0); |
126 | EXPECT_EQ(littleval[1], 0xaa); |
127 | EXPECT_EQ(littleval[2], 0xfa); |
128 | EXPECT_EQ(littleval[3], 0xff); |
129 | EXPECT_EQ(littleval[4], 0x0f); |
130 | EXPECT_EQ(littleval[5], 0x00); |
131 | EXPECT_EQ(littleval[6], 0x00); |
132 | EXPECT_EQ(littleval[7], 0x00); |
133 | |
134 | // This test makes sure 1<<31 doesn't overflow. |
135 | // Test to make sure left shift of start bit doesn't overflow. |
136 | unsigned char bigval2[8] = {0x00}; |
137 | endian::writeAtBitAlignment<int32_t, llvm::endianness::big, unaligned>( |
138 | memory: bigval2, value: (int)0xffffffff, startBit: 1); |
139 | EXPECT_EQ(bigval2[0], 0xff); |
140 | EXPECT_EQ(bigval2[1], 0xff); |
141 | EXPECT_EQ(bigval2[2], 0xff); |
142 | EXPECT_EQ(bigval2[3], 0xfe); |
143 | EXPECT_EQ(bigval2[4], 0x00); |
144 | EXPECT_EQ(bigval2[5], 0x00); |
145 | EXPECT_EQ(bigval2[6], 0x00); |
146 | EXPECT_EQ(bigval2[7], 0x01); |
147 | |
148 | unsigned char littleval2[8] = {0x00}; |
149 | endian::writeAtBitAlignment<int32_t, llvm::endianness::little, unaligned>( |
150 | memory: littleval2, value: (int)0xffffffff, startBit: 1); |
151 | EXPECT_EQ(littleval2[0], 0xfe); |
152 | EXPECT_EQ(littleval2[1], 0xff); |
153 | EXPECT_EQ(littleval2[2], 0xff); |
154 | EXPECT_EQ(littleval2[3], 0xff); |
155 | EXPECT_EQ(littleval2[4], 0x01); |
156 | EXPECT_EQ(littleval2[5], 0x00); |
157 | EXPECT_EQ(littleval2[6], 0x00); |
158 | EXPECT_EQ(littleval2[7], 0x00); |
159 | |
160 | // Test to make sure 64-bit int doesn't overflow. |
161 | unsigned char bigval64[16] = {0x00}; |
162 | endian::writeAtBitAlignment<int64_t, llvm::endianness::big, unaligned>( |
163 | memory: bigval64, value: (int64_t)0xffffffffffffffff, startBit: 1); |
164 | EXPECT_EQ(bigval64[0], 0xff); |
165 | EXPECT_EQ(bigval64[1], 0xff); |
166 | EXPECT_EQ(bigval64[2], 0xff); |
167 | EXPECT_EQ(bigval64[3], 0xff); |
168 | EXPECT_EQ(bigval64[4], 0xff); |
169 | EXPECT_EQ(bigval64[5], 0xff); |
170 | EXPECT_EQ(bigval64[6], 0xff); |
171 | EXPECT_EQ(bigval64[7], 0xfe); |
172 | EXPECT_EQ(bigval64[8], 0x00); |
173 | EXPECT_EQ(bigval64[9], 0x00); |
174 | EXPECT_EQ(bigval64[10], 0x00); |
175 | EXPECT_EQ(bigval64[11], 0x00); |
176 | EXPECT_EQ(bigval64[12], 0x00); |
177 | EXPECT_EQ(bigval64[13], 0x00); |
178 | EXPECT_EQ(bigval64[14], 0x00); |
179 | EXPECT_EQ(bigval64[15], 0x01); |
180 | |
181 | unsigned char littleval64[16] = {0x00}; |
182 | endian::writeAtBitAlignment<int64_t, llvm::endianness::little, unaligned>( |
183 | memory: littleval64, value: (int64_t)0xffffffffffffffff, startBit: 1); |
184 | EXPECT_EQ(littleval64[0], 0xfe); |
185 | EXPECT_EQ(littleval64[1], 0xff); |
186 | EXPECT_EQ(littleval64[2], 0xff); |
187 | EXPECT_EQ(littleval64[3], 0xff); |
188 | EXPECT_EQ(littleval64[4], 0xff); |
189 | EXPECT_EQ(littleval64[5], 0xff); |
190 | EXPECT_EQ(littleval64[6], 0xff); |
191 | EXPECT_EQ(littleval64[7], 0xff); |
192 | EXPECT_EQ(littleval64[8], 0x01); |
193 | EXPECT_EQ(littleval64[9], 0x00); |
194 | EXPECT_EQ(littleval64[10], 0x00); |
195 | EXPECT_EQ(littleval64[11], 0x00); |
196 | EXPECT_EQ(littleval64[12], 0x00); |
197 | EXPECT_EQ(littleval64[13], 0x00); |
198 | EXPECT_EQ(littleval64[14], 0x00); |
199 | EXPECT_EQ(littleval64[15], 0x00); |
200 | } |
201 | |
202 | TEST(Endian, Write) { |
203 | unsigned char data[5]; |
204 | endian::write<int32_t, llvm::endianness::big, unaligned>(memory: data, value: -1362446643); |
205 | EXPECT_EQ(data[0], 0xAE); |
206 | EXPECT_EQ(data[1], 0xCA); |
207 | EXPECT_EQ(data[2], 0xB6); |
208 | EXPECT_EQ(data[3], 0xCD); |
209 | endian::write<int32_t, llvm::endianness::big, unaligned>(memory: data + 1, |
210 | value: -1362446643); |
211 | EXPECT_EQ(data[1], 0xAE); |
212 | EXPECT_EQ(data[2], 0xCA); |
213 | EXPECT_EQ(data[3], 0xB6); |
214 | EXPECT_EQ(data[4], 0xCD); |
215 | |
216 | endian::write<int32_t, llvm::endianness::little, unaligned>(memory: data, |
217 | value: -1362446643); |
218 | EXPECT_EQ(data[0], 0xCD); |
219 | EXPECT_EQ(data[1], 0xB6); |
220 | EXPECT_EQ(data[2], 0xCA); |
221 | EXPECT_EQ(data[3], 0xAE); |
222 | endian::write<int32_t, llvm::endianness::little, unaligned>(memory: data + 1, |
223 | value: -1362446643); |
224 | EXPECT_EQ(data[1], 0xCD); |
225 | EXPECT_EQ(data[2], 0xB6); |
226 | EXPECT_EQ(data[3], 0xCA); |
227 | EXPECT_EQ(data[4], 0xAE); |
228 | } |
229 | |
230 | TEST(Endian, PackedEndianSpecificIntegral) { |
231 | // These are 5 bytes so we can be sure at least one of the reads is unaligned. |
232 | unsigned char big[] = {0x00, 0x01, 0x02, 0x03, 0x04}; |
233 | unsigned char little[] = {0x00, 0x04, 0x03, 0x02, 0x01}; |
234 | big32_t *big_val = |
235 | reinterpret_cast<big32_t *>(big + 1); |
236 | little32_t *little_val = |
237 | reinterpret_cast<little32_t *>(little + 1); |
238 | |
239 | EXPECT_EQ(*big_val, *little_val); |
240 | } |
241 | |
242 | TEST(Endian, PacketEndianSpecificIntegralAsEnum) { |
243 | enum class Test : uint16_t { ONETWO = 0x0102, TWOONE = 0x0201 }; |
244 | unsigned char bytes[] = {0x01, 0x02}; |
245 | using LittleTest = little_t<Test>; |
246 | using BigTest = big_t<Test>; |
247 | EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes)); |
248 | EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes)); |
249 | } |
250 | |
251 | } // end anon namespace |
252 | |