xref: /llvm-project/llvm/unittests/Support/AlignmentTest.cpp (revision da68fd8f81602f388b4a603518fede7fcafd3bc1)
1 //=== - llvm/unittest/Support/Alignment.cpp - Alignment utility 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/Alignment.h"
10 #include "gtest/gtest.h"
11 
12 #include <vector>
13 
14 #ifdef _MSC_VER
15 // Disable warnings about potential divide by 0.
16 #pragma warning(push)
17 #pragma warning(disable : 4723)
18 #endif
19 
20 using namespace llvm;
21 
22 namespace {
23 
24 TEST(AlignmentTest, AlignOfConstant) {
25   EXPECT_EQ(Align::Of<uint8_t>(), Align(alignof(uint8_t)));
26   EXPECT_EQ(Align::Of<uint16_t>(), Align(alignof(uint16_t)));
27   EXPECT_EQ(Align::Of<uint32_t>(), Align(alignof(uint32_t)));
28   EXPECT_EQ(Align::Of<uint64_t>(), Align(alignof(uint64_t)));
29 }
30 
31 TEST(AlignmentTest, AlignConstant) {
32   EXPECT_EQ(Align::Constant<1>(), Align(1));
33   EXPECT_EQ(Align::Constant<2>(), Align(2));
34   EXPECT_EQ(Align::Constant<4>(), Align(4));
35   EXPECT_EQ(Align::Constant<8>(), Align(8));
36   EXPECT_EQ(Align::Constant<16>(), Align(16));
37   EXPECT_EQ(Align::Constant<32>(), Align(32));
38   EXPECT_EQ(Align::Constant<64>(), Align(64));
39 }
40 
41 TEST(AlignmentTest, AlignConstexprConstant) {
42   constexpr Align kConstantAlign = Align::Of<uint64_t>();
43   EXPECT_EQ(Align(alignof(uint64_t)), kConstantAlign);
44 }
45 
46 std::vector<uint64_t> getValidAlignments() {
47   std::vector<uint64_t> Out;
48   for (size_t Shift = 0; Shift < 64; ++Shift)
49     Out.push_back(1ULL << Shift);
50   return Out;
51 }
52 
53 TEST(AlignmentTest, AlignDefaultCTor) {
54   EXPECT_EQ(Align().value(), 1ULL);
55   EXPECT_EQ(Align::None().value(), 1ULL);
56 }
57 
58 TEST(AlignmentTest, MaybeAlignDefaultCTor) {
59   EXPECT_FALSE(MaybeAlign().hasValue());
60 }
61 
62 TEST(AlignmentTest, ValidCTors) {
63   for (uint64_t Value : getValidAlignments()) {
64     EXPECT_EQ(Align(Value).value(), Value);
65     EXPECT_EQ((*MaybeAlign(Value)).value(), Value);
66   }
67 }
68 
69 TEST(AlignmentTest, CheckMaybeAlignHasValue) {
70   EXPECT_TRUE(MaybeAlign(1));
71   EXPECT_TRUE(MaybeAlign(1).hasValue());
72   EXPECT_FALSE(MaybeAlign(0));
73   EXPECT_FALSE(MaybeAlign(0).hasValue());
74   EXPECT_FALSE(MaybeAlign());
75   EXPECT_FALSE(MaybeAlign().hasValue());
76 }
77 
78 TEST(AlignmentTest, Division) {
79   for (uint64_t Value : getValidAlignments()) {
80     if (Value > 1) {
81       EXPECT_EQ(Align(Value) / 2, Value / 2);
82       EXPECT_EQ(MaybeAlign(Value) / 2, Value / 2);
83     }
84   }
85   EXPECT_EQ(MaybeAlign(0) / 2, MaybeAlign(0));
86 }
87 
88 TEST(AlignmentTest, AlignTo) {
89   struct {
90     uint64_t alignment;
91     uint64_t offset;
92     uint64_t rounded;
93     const void *forgedAddr() const {
94       //  A value of any integral or enumeration type can be converted to a
95       //  pointer type.
96       return reinterpret_cast<const void *>(offset);
97     }
98   } kTests[] = {
99       // MaybeAlign
100       {0, 0, 0},
101       {0, 1, 1},
102       {0, 5, 5},
103       // MaybeAlign / Align
104       {1, 0, 0},
105       {1, 1, 1},
106       {1, 5, 5},
107       {2, 0, 0},
108       {2, 1, 2},
109       {2, 2, 2},
110       {2, 7, 8},
111       {2, 16, 16},
112       {4, 0, 0},
113       {4, 1, 4},
114       {4, 4, 4},
115       {4, 6, 8},
116   };
117   for (const auto &T : kTests) {
118     MaybeAlign A(T.alignment);
119     // Test MaybeAlign
120     EXPECT_EQ(alignTo(T.offset, A), T.rounded);
121     // Test Align
122     if (A) {
123       EXPECT_EQ(alignTo(T.offset, A.getValue()), T.rounded);
124       EXPECT_EQ(alignAddr(T.forgedAddr(), A.getValue()), T.rounded);
125     }
126   }
127 }
128 
129 TEST(AlignmentTest, Log2) {
130   for (uint64_t Value : getValidAlignments()) {
131     EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));
132     EXPECT_EQ(Log2(MaybeAlign(Value)), Log2_64(Value));
133   }
134 }
135 
136 TEST(AlignmentTest, MinAlign) {
137   struct {
138     uint64_t A;
139     uint64_t B;
140     uint64_t MinAlign;
141   } kTests[] = {
142       // MaybeAlign
143       {0, 0, 0},
144       {0, 8, 8},
145       {2, 0, 2},
146       // MaybeAlign / Align
147       {1, 2, 1},
148       {8, 4, 4},
149   };
150   for (const auto &T : kTests) {
151     EXPECT_EQ(commonAlignment(MaybeAlign(T.A), MaybeAlign(T.B)), T.MinAlign);
152     EXPECT_EQ(MinAlign(T.A, T.B), T.MinAlign);
153     if (T.A) {
154       EXPECT_EQ(commonAlignment(Align(T.A), MaybeAlign(T.B)), T.MinAlign);
155     }
156     if (T.B) {
157       EXPECT_EQ(commonAlignment(MaybeAlign(T.A), Align(T.B)), T.MinAlign);
158     }
159     if (T.A && T.B) {
160       EXPECT_EQ(commonAlignment(Align(T.A), Align(T.B)), T.MinAlign);
161     }
162   }
163 }
164 
165 TEST(AlignmentTest, Encode_Decode) {
166   for (uint64_t Value : getValidAlignments()) {
167     {
168       Align Actual(Value);
169       Align Expected = decodeMaybeAlign(encode(Actual)).getValue();
170       EXPECT_EQ(Expected, Actual);
171     }
172     {
173       MaybeAlign Actual(Value);
174       MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
175       EXPECT_EQ(Expected, Actual);
176     }
177   }
178   MaybeAlign Actual(0);
179   MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
180   EXPECT_EQ(Expected, Actual);
181 }
182 
183 TEST(AlignmentTest, isAligned_isAddrAligned) {
184   struct {
185     uint64_t alignment;
186     uint64_t offset;
187     bool isAligned;
188     const void *forgedAddr() const {
189       //  A value of any integral or enumeration type can be converted to a
190       //  pointer type.
191       return reinterpret_cast<const void *>(offset);
192     }
193   } kTests[] = {
194       {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},
195       {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},
196       {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},
197   };
198   for (const auto &T : kTests) {
199     MaybeAlign A(T.alignment);
200     // Test MaybeAlign
201     EXPECT_EQ(isAligned(A, T.offset), T.isAligned);
202     // Test Align
203     if (A) {
204       EXPECT_EQ(isAligned(A.getValue(), T.offset), T.isAligned);
205       EXPECT_EQ(isAddrAligned(A.getValue(), T.forgedAddr()), T.isAligned);
206     }
207   }
208 }
209 
210 TEST(AlignmentTest, offsetToAlignment) {
211   struct {
212     uint64_t alignment;
213     uint64_t offset;
214     uint64_t alignedOffset;
215     const void *forgedAddr() const {
216       //  A value of any integral or enumeration type can be converted to a
217       //  pointer type.
218       return reinterpret_cast<const void *>(offset);
219     }
220   } kTests[] = {
221       {1, 0, 0}, {1, 1, 0},  {1, 5, 0}, {2, 0, 0}, {2, 1, 1}, {2, 2, 0},
222       {2, 7, 1}, {2, 16, 0}, {4, 0, 0}, {4, 1, 3}, {4, 4, 0}, {4, 6, 2},
223   };
224   for (const auto &T : kTests) {
225     const Align A(T.alignment);
226     EXPECT_EQ(offsetToAlignment(T.offset, A), T.alignedOffset);
227     EXPECT_EQ(offsetToAlignedAddr(T.forgedAddr(), A), T.alignedOffset);
228   }
229 }
230 
231 TEST(AlignmentTest, AlignComparisons) {
232   std::vector<uint64_t> ValidAlignments = getValidAlignments();
233   std::sort(ValidAlignments.begin(), ValidAlignments.end());
234   for (size_t I = 1; I < ValidAlignments.size(); ++I) {
235     assert(I >= 1);
236     const Align A(ValidAlignments[I - 1]);
237     const Align B(ValidAlignments[I]);
238     EXPECT_EQ(A, A);
239     EXPECT_NE(A, B);
240     EXPECT_LT(A, B);
241     EXPECT_GT(B, A);
242     EXPECT_LE(A, B);
243     EXPECT_GE(B, A);
244     EXPECT_LE(A, A);
245     EXPECT_GE(A, A);
246 
247     EXPECT_EQ(A, A.value());
248     EXPECT_NE(A, B.value());
249     EXPECT_LT(A, B.value());
250     EXPECT_GT(B, A.value());
251     EXPECT_LE(A, B.value());
252     EXPECT_GE(B, A.value());
253     EXPECT_LE(A, A.value());
254     EXPECT_GE(A, A.value());
255 
256     EXPECT_EQ(std::max(A, B), B);
257     EXPECT_EQ(std::min(A, B), A);
258 
259     const MaybeAlign MA(ValidAlignments[I - 1]);
260     const MaybeAlign MB(ValidAlignments[I]);
261     EXPECT_EQ(MA, MA);
262     EXPECT_NE(MA, MB);
263     EXPECT_LT(MA, MB);
264     EXPECT_GT(MB, MA);
265     EXPECT_LE(MA, MB);
266     EXPECT_GE(MB, MA);
267     EXPECT_LE(MA, MA);
268     EXPECT_GE(MA, MA);
269 
270     EXPECT_EQ(MA, MA ? (*MA).value() : 0);
271     EXPECT_NE(MA, MB ? (*MB).value() : 0);
272     EXPECT_LT(MA, MB ? (*MB).value() : 0);
273     EXPECT_GT(MB, MA ? (*MA).value() : 0);
274     EXPECT_LE(MA, MB ? (*MB).value() : 0);
275     EXPECT_GE(MB, MA ? (*MA).value() : 0);
276     EXPECT_LE(MA, MA ? (*MA).value() : 0);
277     EXPECT_GE(MA, MA ? (*MA).value() : 0);
278 
279     EXPECT_EQ(std::max(A, B), B);
280     EXPECT_EQ(std::min(A, B), A);
281   }
282 }
283 
284 TEST(AlignmentTest, Max) {
285   // We introduce std::max here to test ADL.
286   using std::max;
287 
288   // Uses llvm::max.
289   EXPECT_EQ(max(MaybeAlign(), Align(2)), Align(2));
290   EXPECT_EQ(max(Align(2), MaybeAlign()), Align(2));
291 
292   EXPECT_EQ(max(MaybeAlign(1), Align(2)), Align(2));
293   EXPECT_EQ(max(Align(2), MaybeAlign(1)), Align(2));
294 
295   EXPECT_EQ(max(MaybeAlign(2), Align(2)), Align(2));
296   EXPECT_EQ(max(Align(2), MaybeAlign(2)), Align(2));
297 
298   EXPECT_EQ(max(MaybeAlign(4), Align(2)), Align(4));
299   EXPECT_EQ(max(Align(2), MaybeAlign(4)), Align(4));
300 
301   // Uses std::max.
302   EXPECT_EQ(max(Align(2), Align(4)), Align(4));
303   EXPECT_EQ(max(MaybeAlign(2), MaybeAlign(4)), MaybeAlign(4));
304   EXPECT_EQ(max(MaybeAlign(), MaybeAlign()), MaybeAlign());
305 }
306 
307 TEST(AlignmentTest, AssumeAligned) {
308   EXPECT_EQ(assumeAligned(0), Align(1));
309   EXPECT_EQ(assumeAligned(0), Align());
310   EXPECT_EQ(assumeAligned(1), Align(1));
311   EXPECT_EQ(assumeAligned(1), Align());
312 }
313 
314 // Death tests reply on assert which is disabled in release mode.
315 #ifndef NDEBUG
316 
317 // We use a subset of valid alignments for DEATH_TESTs as they are particularly
318 // slow.
319 std::vector<uint64_t> getValidAlignmentsForDeathTest() {
320   return {1, 1ULL << 31, 1ULL << 63};
321 }
322 
323 std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }
324 
325 TEST(AlignmentDeathTest, Log2) {
326   EXPECT_DEATH(Log2(MaybeAlign(0)), ".* should be defined");
327 }
328 
329 TEST(AlignmentDeathTest, CantConvertUnsetMaybe) {
330   EXPECT_DEATH((MaybeAlign(0).getValue()), ".*");
331 }
332 
333 TEST(AlignmentDeathTest, Division) {
334   EXPECT_DEATH(Align(1) / 2, "Can't halve byte alignment");
335   EXPECT_DEATH(MaybeAlign(1) / 2, "Can't halve byte alignment");
336 
337   EXPECT_DEATH(Align(8) / 0, "Divisor must be positive and a power of 2");
338   EXPECT_DEATH(Align(8) / 3, "Divisor must be positive and a power of 2");
339 }
340 
341 TEST(AlignmentDeathTest, InvalidCTors) {
342   EXPECT_DEATH((Align(0)), "Value must not be 0");
343   for (uint64_t Value : getNonPowerOfTwo()) {
344     EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");
345     EXPECT_DEATH((MaybeAlign(Value)),
346                  "Alignment is neither 0 nor a power of 2");
347   }
348 }
349 
350 TEST(AlignmentDeathTest, ComparisonsWithZero) {
351   for (uint64_t Value : getValidAlignmentsForDeathTest()) {
352     EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");
353     EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");
354     EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");
355     EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");
356     EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");
357     EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");
358   }
359 }
360 
361 TEST(AlignmentDeathTest, CompareMaybeAlignToZero) {
362   for (uint64_t Value : getValidAlignmentsForDeathTest()) {
363     // MaybeAlign is allowed to be == or != 0
364     (void)(MaybeAlign(Value) == 0);
365     (void)(MaybeAlign(Value) != 0);
366     EXPECT_DEATH((void)(MaybeAlign(Value) >= 0), ".* should be defined");
367     EXPECT_DEATH((void)(MaybeAlign(Value) <= 0), ".* should be defined");
368     EXPECT_DEATH((void)(MaybeAlign(Value) > 0), ".* should be defined");
369     EXPECT_DEATH((void)(MaybeAlign(Value) < 0), ".* should be defined");
370   }
371 }
372 
373 TEST(AlignmentDeathTest, CompareAlignToUndefMaybeAlign) {
374   for (uint64_t Value : getValidAlignmentsForDeathTest()) {
375     EXPECT_DEATH((void)(Align(Value) == MaybeAlign(0)), ".* should be defined");
376     EXPECT_DEATH((void)(Align(Value) != MaybeAlign(0)), ".* should be defined");
377     EXPECT_DEATH((void)(Align(Value) >= MaybeAlign(0)), ".* should be defined");
378     EXPECT_DEATH((void)(Align(Value) <= MaybeAlign(0)), ".* should be defined");
379     EXPECT_DEATH((void)(Align(Value) > MaybeAlign(0)), ".* should be defined");
380     EXPECT_DEATH((void)(Align(Value) < MaybeAlign(0)), ".* should be defined");
381   }
382 }
383 
384 TEST(AlignmentDeathTest, AlignAddr) {
385   const void *const unaligned_high_ptr =
386       reinterpret_cast<const void *>(std::numeric_limits<uintptr_t>::max() - 1);
387   EXPECT_DEATH(alignAddr(unaligned_high_ptr, Align(16)), "Overflow");
388 }
389 
390 #endif // NDEBUG
391 
392 } // end anonymous namespace
393 
394 #ifdef _MSC_VER
395 #pragma warning(pop)
396 #endif
397