xref: /llvm-project/llvm/unittests/Support/AlignmentTest.cpp (revision 2fa744e631cbabe583da010ec56560edbc7a5384)
1ac486919SGuillaume Chatelet //=== - llvm/unittest/Support/Alignment.cpp - Alignment utility tests -----===//
2ac486919SGuillaume Chatelet //
3ac486919SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ac486919SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information.
5ac486919SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ac486919SGuillaume Chatelet //
7ac486919SGuillaume Chatelet //===----------------------------------------------------------------------===//
8ac486919SGuillaume Chatelet 
9ac486919SGuillaume Chatelet #include "llvm/Support/Alignment.h"
10aba43035SDmitri Gribenko #include "llvm/ADT/STLExtras.h"
11ac486919SGuillaume Chatelet #include "gtest/gtest.h"
12ac486919SGuillaume Chatelet 
13ac486919SGuillaume Chatelet #include <vector>
14ac486919SGuillaume Chatelet 
151c013ca1SSimon Pilgrim #ifdef _MSC_VER
161c013ca1SSimon Pilgrim // Disable warnings about potential divide by 0.
171c013ca1SSimon Pilgrim #pragma warning(push)
181c013ca1SSimon Pilgrim #pragma warning(disable : 4723)
191c013ca1SSimon Pilgrim #endif
201c013ca1SSimon Pilgrim 
21ac486919SGuillaume Chatelet using namespace llvm;
22ac486919SGuillaume Chatelet 
23ac486919SGuillaume Chatelet namespace {
24ac486919SGuillaume Chatelet 
TEST(AlignmentTest,AlignOfConstant)25415df89eSGuillaume Chatelet TEST(AlignmentTest, AlignOfConstant) {
26415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Of<uint8_t>(), Align(alignof(uint8_t)));
27415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Of<uint16_t>(), Align(alignof(uint16_t)));
28415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Of<uint32_t>(), Align(alignof(uint32_t)));
29415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Of<uint64_t>(), Align(alignof(uint64_t)));
30415df89eSGuillaume Chatelet }
31415df89eSGuillaume Chatelet 
TEST(AlignmentTest,AlignConstant)32415df89eSGuillaume Chatelet TEST(AlignmentTest, AlignConstant) {
33415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<1>(), Align(1));
34415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<2>(), Align(2));
35415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<4>(), Align(4));
36415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<8>(), Align(8));
37415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<16>(), Align(16));
38415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<32>(), Align(32));
39415df89eSGuillaume Chatelet   EXPECT_EQ(Align::Constant<64>(), Align(64));
40415df89eSGuillaume Chatelet }
41415df89eSGuillaume Chatelet 
TEST(AlignmentTest,AlignConstexprConstant)42415df89eSGuillaume Chatelet TEST(AlignmentTest, AlignConstexprConstant) {
43415df89eSGuillaume Chatelet   constexpr Align kConstantAlign = Align::Of<uint64_t>();
44da68fd8fSGuillaume Chatelet   EXPECT_EQ(Align(alignof(uint64_t)), kConstantAlign);
45415df89eSGuillaume Chatelet }
46415df89eSGuillaume Chatelet 
getValidAlignments()47ac486919SGuillaume Chatelet std::vector<uint64_t> getValidAlignments() {
48ac486919SGuillaume Chatelet   std::vector<uint64_t> Out;
49ac486919SGuillaume Chatelet   for (size_t Shift = 0; Shift < 64; ++Shift)
50ac486919SGuillaume Chatelet     Out.push_back(1ULL << Shift);
51ac486919SGuillaume Chatelet   return Out;
52ac486919SGuillaume Chatelet }
53ac486919SGuillaume Chatelet 
TEST(AlignmentTest,AlignDefaultCTor)549803db8cSGuillaume Chatelet TEST(AlignmentTest, AlignDefaultCTor) { EXPECT_EQ(Align().value(), 1ULL); }
55ac486919SGuillaume Chatelet 
TEST(AlignmentTest,MaybeAlignDefaultCTor)56d152e50cSKazu Hirata TEST(AlignmentTest, MaybeAlignDefaultCTor) { EXPECT_FALSE(MaybeAlign()); }
57ac486919SGuillaume Chatelet 
TEST(AlignmentTest,ValidCTors)5810dd2965SGuillaume Chatelet TEST(AlignmentTest, ValidCTors) {
5941dfc69dSGuillaume Chatelet   for (uint64_t Value : getValidAlignments()) {
60ac486919SGuillaume Chatelet     EXPECT_EQ(Align(Value).value(), Value);
61ac486919SGuillaume Chatelet     EXPECT_EQ((*MaybeAlign(Value)).value(), Value);
62ac486919SGuillaume Chatelet   }
63ac486919SGuillaume Chatelet }
64ac486919SGuillaume Chatelet 
TEST(AlignmentTest,CheckMaybeAlignHasValue)6510dd2965SGuillaume Chatelet TEST(AlignmentTest, CheckMaybeAlignHasValue) {
66ac486919SGuillaume Chatelet   EXPECT_TRUE(MaybeAlign(1));
673361a364SKazu Hirata   EXPECT_TRUE(MaybeAlign(1).has_value());
68ac486919SGuillaume Chatelet   EXPECT_FALSE(MaybeAlign(0));
693361a364SKazu Hirata   EXPECT_FALSE(MaybeAlign(0).has_value());
70ac486919SGuillaume Chatelet   EXPECT_FALSE(MaybeAlign());
713361a364SKazu Hirata   EXPECT_FALSE(MaybeAlign().has_value());
72ac486919SGuillaume Chatelet }
73ac486919SGuillaume Chatelet 
TEST(AlignmentTest,Division)7410dd2965SGuillaume Chatelet TEST(AlignmentTest, Division) {
7541dfc69dSGuillaume Chatelet   for (uint64_t Value : getValidAlignments()) {
7610dd2965SGuillaume Chatelet     if (Value > 1) {
7703036061SGuillaume Chatelet       EXPECT_EQ(Align(Value).previous(), Value / 2);
78ac486919SGuillaume Chatelet     }
79ac486919SGuillaume Chatelet   }
80ac486919SGuillaume Chatelet }
81ac486919SGuillaume Chatelet 
TEST(AlignmentTest,AlignTo)8210dd2965SGuillaume Chatelet TEST(AlignmentTest, AlignTo) {
83ac486919SGuillaume Chatelet   struct {
84ac486919SGuillaume Chatelet     uint64_t alignment;
85ac486919SGuillaume Chatelet     uint64_t offset;
86ac486919SGuillaume Chatelet     uint64_t rounded;
87ce56e1a1SGuillaume Chatelet     const void *forgedAddr() const {
88ce56e1a1SGuillaume Chatelet       //  A value of any integral or enumeration type can be converted to a
89ce56e1a1SGuillaume Chatelet       //  pointer type.
90ce56e1a1SGuillaume Chatelet       return reinterpret_cast<const void *>(offset);
91ce56e1a1SGuillaume Chatelet     }
92ac486919SGuillaume Chatelet   } kTests[] = {
93d3cf49e9SGuillaume Chatelet       // Align
949803db8cSGuillaume Chatelet       {1, 0, 0}, {1, 1, 1},   {1, 5, 5}, {2, 0, 0}, {2, 1, 2}, {2, 2, 2},
959803db8cSGuillaume Chatelet       {2, 7, 8}, {2, 16, 16}, {4, 0, 0}, {4, 1, 4}, {4, 4, 4}, {4, 6, 8},
96ac486919SGuillaume Chatelet   };
97ac486919SGuillaume Chatelet   for (const auto &T : kTests) {
98d3cf49e9SGuillaume Chatelet     Align A = Align(T.alignment);
99ac486919SGuillaume Chatelet     EXPECT_EQ(alignTo(T.offset, A), T.rounded);
100d3cf49e9SGuillaume Chatelet     EXPECT_EQ(alignAddr(T.forgedAddr(), A), T.rounded);
101ac486919SGuillaume Chatelet   }
102383650c7SBill Wendling }
103ac486919SGuillaume Chatelet 
TEST(AlignmentTest,AlignToWithSkew)104a060a178SGuillaume Chatelet TEST(AlignmentTest, AlignToWithSkew) {
105a060a178SGuillaume Chatelet   EXPECT_EQ(alignTo(5, Align(8), 0), alignTo(5, Align(8)));
106a060a178SGuillaume Chatelet   EXPECT_EQ(alignTo(5, Align(8), 7), 7U);
107a060a178SGuillaume Chatelet   EXPECT_EQ(alignTo(17, Align(8), 1), 17U);
108a060a178SGuillaume Chatelet   EXPECT_EQ(alignTo(~0LL, Align(8), 3), 3U);
109a060a178SGuillaume Chatelet }
110a060a178SGuillaume Chatelet 
TEST(AlignmentTest,Log2)11110dd2965SGuillaume Chatelet TEST(AlignmentTest, Log2) {
11241dfc69dSGuillaume Chatelet   for (uint64_t Value : getValidAlignments()) {
113ac486919SGuillaume Chatelet     EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));
114ac486919SGuillaume Chatelet   }
115ac486919SGuillaume Chatelet }
116ac486919SGuillaume Chatelet 
TEST(AlignmentTest,Encode_Decode)11710dd2965SGuillaume Chatelet TEST(AlignmentTest, Encode_Decode) {
11841dfc69dSGuillaume Chatelet   for (uint64_t Value : getValidAlignments()) {
119ac486919SGuillaume Chatelet     {
120ac486919SGuillaume Chatelet       Align Actual(Value);
121d152e50cSKazu Hirata       Align Expected = *decodeMaybeAlign(encode(Actual));
122ac486919SGuillaume Chatelet       EXPECT_EQ(Expected, Actual);
123ac486919SGuillaume Chatelet     }
124ac486919SGuillaume Chatelet     {
125ac486919SGuillaume Chatelet       MaybeAlign Actual(Value);
126ac486919SGuillaume Chatelet       MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
127ac486919SGuillaume Chatelet       EXPECT_EQ(Expected, Actual);
128ac486919SGuillaume Chatelet     }
129ac486919SGuillaume Chatelet   }
130ac486919SGuillaume Chatelet   MaybeAlign Actual(0);
131ac486919SGuillaume Chatelet   MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
132ac486919SGuillaume Chatelet   EXPECT_EQ(Expected, Actual);
133ac486919SGuillaume Chatelet }
134ac486919SGuillaume Chatelet 
TEST(AlignmentTest,isAligned_isAddrAligned)135ce56e1a1SGuillaume Chatelet TEST(AlignmentTest, isAligned_isAddrAligned) {
136ac486919SGuillaume Chatelet   struct {
137ac486919SGuillaume Chatelet     uint64_t alignment;
138ac486919SGuillaume Chatelet     uint64_t offset;
139ac486919SGuillaume Chatelet     bool isAligned;
140ce56e1a1SGuillaume Chatelet     const void *forgedAddr() const {
141ce56e1a1SGuillaume Chatelet       //  A value of any integral or enumeration type can be converted to a
142ce56e1a1SGuillaume Chatelet       //  pointer type.
143ce56e1a1SGuillaume Chatelet       return reinterpret_cast<const void *>(offset);
144ce56e1a1SGuillaume Chatelet     }
145ac486919SGuillaume Chatelet   } kTests[] = {
146ac486919SGuillaume Chatelet       {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},
147ac486919SGuillaume Chatelet       {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},
148ac486919SGuillaume Chatelet       {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},
149ac486919SGuillaume Chatelet   };
150ac486919SGuillaume Chatelet   for (const auto &T : kTests) {
151ac486919SGuillaume Chatelet     MaybeAlign A(T.alignment);
152ac486919SGuillaume Chatelet     // Test Align
153383650c7SBill Wendling     if (A) {
154*2fa744e6SFangrui Song       EXPECT_EQ(isAligned(*A, T.offset), T.isAligned);
155*2fa744e6SFangrui Song       EXPECT_EQ(isAddrAligned(*A, T.forgedAddr()), T.isAligned);
156ac486919SGuillaume Chatelet     }
157ac486919SGuillaume Chatelet   }
158383650c7SBill Wendling }
159ac486919SGuillaume Chatelet 
TEST(AlignmentTest,offsetToAlignment)160ce56e1a1SGuillaume Chatelet TEST(AlignmentTest, offsetToAlignment) {
161ce56e1a1SGuillaume Chatelet   struct {
162ce56e1a1SGuillaume Chatelet     uint64_t alignment;
163ce56e1a1SGuillaume Chatelet     uint64_t offset;
164ce56e1a1SGuillaume Chatelet     uint64_t alignedOffset;
165ce56e1a1SGuillaume Chatelet     const void *forgedAddr() const {
166ce56e1a1SGuillaume Chatelet       //  A value of any integral or enumeration type can be converted to a
167ce56e1a1SGuillaume Chatelet       //  pointer type.
168ce56e1a1SGuillaume Chatelet       return reinterpret_cast<const void *>(offset);
169ce56e1a1SGuillaume Chatelet     }
170ce56e1a1SGuillaume Chatelet   } kTests[] = {
171ce56e1a1SGuillaume Chatelet       {1, 0, 0}, {1, 1, 0},  {1, 5, 0}, {2, 0, 0}, {2, 1, 1}, {2, 2, 0},
172ce56e1a1SGuillaume Chatelet       {2, 7, 1}, {2, 16, 0}, {4, 0, 0}, {4, 1, 3}, {4, 4, 0}, {4, 6, 2},
173ce56e1a1SGuillaume Chatelet   };
174ce56e1a1SGuillaume Chatelet   for (const auto &T : kTests) {
175ce56e1a1SGuillaume Chatelet     const Align A(T.alignment);
176ce56e1a1SGuillaume Chatelet     EXPECT_EQ(offsetToAlignment(T.offset, A), T.alignedOffset);
177ce56e1a1SGuillaume Chatelet     EXPECT_EQ(offsetToAlignedAddr(T.forgedAddr(), A), T.alignedOffset);
178ce56e1a1SGuillaume Chatelet   }
179ce56e1a1SGuillaume Chatelet }
180ce56e1a1SGuillaume Chatelet 
TEST(AlignmentTest,AlignComparisons)18110dd2965SGuillaume Chatelet TEST(AlignmentTest, AlignComparisons) {
182c87581c4SGuillaume Chatelet   std::vector<uint64_t> ValidAlignments = getValidAlignments();
183aba43035SDmitri Gribenko   llvm::sort(ValidAlignments);
184ac486919SGuillaume Chatelet   for (size_t I = 1; I < ValidAlignments.size(); ++I) {
185ac486919SGuillaume Chatelet     assert(I >= 1);
186ac486919SGuillaume Chatelet     const Align A(ValidAlignments[I - 1]);
187ac486919SGuillaume Chatelet     const Align B(ValidAlignments[I]);
188ac486919SGuillaume Chatelet     EXPECT_EQ(A, A);
189ac486919SGuillaume Chatelet     EXPECT_NE(A, B);
190ac486919SGuillaume Chatelet     EXPECT_LT(A, B);
191ac486919SGuillaume Chatelet     EXPECT_GT(B, A);
192ac486919SGuillaume Chatelet     EXPECT_LE(A, B);
193ac486919SGuillaume Chatelet     EXPECT_GE(B, A);
194ac486919SGuillaume Chatelet     EXPECT_LE(A, A);
195ac486919SGuillaume Chatelet     EXPECT_GE(A, A);
196ac486919SGuillaume Chatelet 
197ac486919SGuillaume Chatelet     EXPECT_EQ(A, A.value());
198ac486919SGuillaume Chatelet     EXPECT_NE(A, B.value());
199ac486919SGuillaume Chatelet     EXPECT_LT(A, B.value());
200ac486919SGuillaume Chatelet     EXPECT_GT(B, A.value());
201ac486919SGuillaume Chatelet     EXPECT_LE(A, B.value());
202ac486919SGuillaume Chatelet     EXPECT_GE(B, A.value());
203ac486919SGuillaume Chatelet     EXPECT_LE(A, A.value());
204ac486919SGuillaume Chatelet     EXPECT_GE(A, A.value());
205ac486919SGuillaume Chatelet 
206ac486919SGuillaume Chatelet     EXPECT_EQ(std::max(A, B), B);
207ac486919SGuillaume Chatelet     EXPECT_EQ(std::min(A, B), A);
208ac486919SGuillaume Chatelet 
209ac486919SGuillaume Chatelet     const MaybeAlign MA(ValidAlignments[I - 1]);
210ac486919SGuillaume Chatelet     const MaybeAlign MB(ValidAlignments[I]);
211ac486919SGuillaume Chatelet     EXPECT_EQ(MA, MA);
212ac486919SGuillaume Chatelet     EXPECT_NE(MA, MB);
213ac486919SGuillaume Chatelet 
214ac486919SGuillaume Chatelet     EXPECT_EQ(std::max(A, B), B);
215ac486919SGuillaume Chatelet     EXPECT_EQ(std::min(A, B), A);
216ac486919SGuillaume Chatelet   }
217ac486919SGuillaume Chatelet }
218ac486919SGuillaume Chatelet 
TEST(AlignmentTest,AssumeAligned)21910dd2965SGuillaume Chatelet TEST(AlignmentTest, AssumeAligned) {
220ac486919SGuillaume Chatelet   EXPECT_EQ(assumeAligned(0), Align(1));
221ac486919SGuillaume Chatelet   EXPECT_EQ(assumeAligned(0), Align());
222ac486919SGuillaume Chatelet   EXPECT_EQ(assumeAligned(1), Align(1));
223ac486919SGuillaume Chatelet   EXPECT_EQ(assumeAligned(1), Align());
224ac486919SGuillaume Chatelet }
225ac486919SGuillaume Chatelet 
22610dd2965SGuillaume Chatelet // Death tests reply on assert which is disabled in release mode.
22710dd2965SGuillaume Chatelet #ifndef NDEBUG
22810dd2965SGuillaume Chatelet 
22910dd2965SGuillaume Chatelet // We use a subset of valid alignments for DEATH_TESTs as they are particularly
23010dd2965SGuillaume Chatelet // slow.
getValidAlignmentsForDeathTest()23110dd2965SGuillaume Chatelet std::vector<uint64_t> getValidAlignmentsForDeathTest() {
23210dd2965SGuillaume Chatelet   return {1, 1ULL << 31, 1ULL << 63};
23310dd2965SGuillaume Chatelet }
23410dd2965SGuillaume Chatelet 
getNonPowerOfTwo()23510dd2965SGuillaume Chatelet std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }
23610dd2965SGuillaume Chatelet 
TEST(AlignmentDeathTest,InvalidCTors)23710dd2965SGuillaume Chatelet TEST(AlignmentDeathTest, InvalidCTors) {
23810dd2965SGuillaume Chatelet   EXPECT_DEATH((Align(0)), "Value must not be 0");
23941dfc69dSGuillaume Chatelet   for (uint64_t Value : getNonPowerOfTwo()) {
24010dd2965SGuillaume Chatelet     EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");
24139652137SGuillaume Chatelet     EXPECT_DEATH((MaybeAlign(Value)),
24239652137SGuillaume Chatelet                  "Alignment is neither 0 nor a power of 2");
24310dd2965SGuillaume Chatelet   }
24410dd2965SGuillaume Chatelet }
24510dd2965SGuillaume Chatelet 
TEST(AlignmentDeathTest,ComparisonsWithZero)24610dd2965SGuillaume Chatelet TEST(AlignmentDeathTest, ComparisonsWithZero) {
24741dfc69dSGuillaume Chatelet   for (uint64_t Value : getValidAlignmentsForDeathTest()) {
248ac486919SGuillaume Chatelet     EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");
249ac486919SGuillaume Chatelet     EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");
250ac486919SGuillaume Chatelet     EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");
251ac486919SGuillaume Chatelet     EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");
252ac486919SGuillaume Chatelet     EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");
253ac486919SGuillaume Chatelet     EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");
254ac486919SGuillaume Chatelet   }
255ac486919SGuillaume Chatelet }
256ac486919SGuillaume Chatelet 
TEST(AlignmentDeathTest,AlignAddr)257ce56e1a1SGuillaume Chatelet TEST(AlignmentDeathTest, AlignAddr) {
258ce56e1a1SGuillaume Chatelet   const void *const unaligned_high_ptr =
259ce56e1a1SGuillaume Chatelet       reinterpret_cast<const void *>(std::numeric_limits<uintptr_t>::max() - 1);
260ce56e1a1SGuillaume Chatelet   EXPECT_DEATH(alignAddr(unaligned_high_ptr, Align(16)), "Overflow");
261ce56e1a1SGuillaume Chatelet }
262ce56e1a1SGuillaume Chatelet 
26310dd2965SGuillaume Chatelet #endif // NDEBUG
26410dd2965SGuillaume Chatelet 
265ac486919SGuillaume Chatelet } // end anonymous namespace
2661c013ca1SSimon Pilgrim 
2671c013ca1SSimon Pilgrim #ifdef _MSC_VER
2681c013ca1SSimon Pilgrim #pragma warning(pop)
2691c013ca1SSimon Pilgrim #endif
270