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 "llvm/ADT/STLExtras.h" 11 #include "gtest/gtest.h" 12 13 #include <vector> 14 15 #ifdef _MSC_VER 16 // Disable warnings about potential divide by 0. 17 #pragma warning(push) 18 #pragma warning(disable : 4723) 19 #endif 20 21 using namespace llvm; 22 23 namespace { 24 25 TEST(AlignmentTest, AlignOfConstant) { 26 EXPECT_EQ(Align::Of<uint8_t>(), Align(alignof(uint8_t))); 27 EXPECT_EQ(Align::Of<uint16_t>(), Align(alignof(uint16_t))); 28 EXPECT_EQ(Align::Of<uint32_t>(), Align(alignof(uint32_t))); 29 EXPECT_EQ(Align::Of<uint64_t>(), Align(alignof(uint64_t))); 30 } 31 32 TEST(AlignmentTest, AlignConstant) { 33 EXPECT_EQ(Align::Constant<1>(), Align(1)); 34 EXPECT_EQ(Align::Constant<2>(), Align(2)); 35 EXPECT_EQ(Align::Constant<4>(), Align(4)); 36 EXPECT_EQ(Align::Constant<8>(), Align(8)); 37 EXPECT_EQ(Align::Constant<16>(), Align(16)); 38 EXPECT_EQ(Align::Constant<32>(), Align(32)); 39 EXPECT_EQ(Align::Constant<64>(), Align(64)); 40 } 41 42 TEST(AlignmentTest, AlignConstexprConstant) { 43 constexpr Align kConstantAlign = Align::Of<uint64_t>(); 44 EXPECT_EQ(Align(alignof(uint64_t)), kConstantAlign); 45 } 46 47 std::vector<uint64_t> getValidAlignments() { 48 std::vector<uint64_t> Out; 49 for (size_t Shift = 0; Shift < 64; ++Shift) 50 Out.push_back(1ULL << Shift); 51 return Out; 52 } 53 54 TEST(AlignmentTest, AlignDefaultCTor) { EXPECT_EQ(Align().value(), 1ULL); } 55 56 TEST(AlignmentTest, MaybeAlignDefaultCTor) { EXPECT_FALSE(MaybeAlign()); } 57 58 TEST(AlignmentTest, ValidCTors) { 59 for (uint64_t Value : getValidAlignments()) { 60 EXPECT_EQ(Align(Value).value(), Value); 61 EXPECT_EQ((*MaybeAlign(Value)).value(), Value); 62 } 63 } 64 65 TEST(AlignmentTest, CheckMaybeAlignHasValue) { 66 EXPECT_TRUE(MaybeAlign(1)); 67 EXPECT_TRUE(MaybeAlign(1).has_value()); 68 EXPECT_FALSE(MaybeAlign(0)); 69 EXPECT_FALSE(MaybeAlign(0).has_value()); 70 EXPECT_FALSE(MaybeAlign()); 71 EXPECT_FALSE(MaybeAlign().has_value()); 72 } 73 74 TEST(AlignmentTest, Division) { 75 for (uint64_t Value : getValidAlignments()) { 76 if (Value > 1) { 77 EXPECT_EQ(Align(Value).previous(), Value / 2); 78 } 79 } 80 } 81 82 TEST(AlignmentTest, AlignTo) { 83 struct { 84 uint64_t alignment; 85 uint64_t offset; 86 uint64_t rounded; 87 const void *forgedAddr() const { 88 // A value of any integral or enumeration type can be converted to a 89 // pointer type. 90 return reinterpret_cast<const void *>(offset); 91 } 92 } kTests[] = { 93 // Align 94 {1, 0, 0}, {1, 1, 1}, {1, 5, 5}, {2, 0, 0}, {2, 1, 2}, {2, 2, 2}, 95 {2, 7, 8}, {2, 16, 16}, {4, 0, 0}, {4, 1, 4}, {4, 4, 4}, {4, 6, 8}, 96 }; 97 for (const auto &T : kTests) { 98 Align A = Align(T.alignment); 99 EXPECT_EQ(alignTo(T.offset, A), T.rounded); 100 EXPECT_EQ(alignAddr(T.forgedAddr(), A), T.rounded); 101 } 102 } 103 104 TEST(AlignmentTest, AlignToWithSkew) { 105 EXPECT_EQ(alignTo(5, Align(8), 0), alignTo(5, Align(8))); 106 EXPECT_EQ(alignTo(5, Align(8), 7), 7U); 107 EXPECT_EQ(alignTo(17, Align(8), 1), 17U); 108 EXPECT_EQ(alignTo(~0LL, Align(8), 3), 3U); 109 } 110 111 TEST(AlignmentTest, Log2) { 112 for (uint64_t Value : getValidAlignments()) { 113 EXPECT_EQ(Log2(Align(Value)), Log2_64(Value)); 114 } 115 } 116 117 TEST(AlignmentTest, Encode_Decode) { 118 for (uint64_t Value : getValidAlignments()) { 119 { 120 Align Actual(Value); 121 Align Expected = *decodeMaybeAlign(encode(Actual)); 122 EXPECT_EQ(Expected, Actual); 123 } 124 { 125 MaybeAlign Actual(Value); 126 MaybeAlign Expected = decodeMaybeAlign(encode(Actual)); 127 EXPECT_EQ(Expected, Actual); 128 } 129 } 130 MaybeAlign Actual(0); 131 MaybeAlign Expected = decodeMaybeAlign(encode(Actual)); 132 EXPECT_EQ(Expected, Actual); 133 } 134 135 TEST(AlignmentTest, isAligned_isAddrAligned) { 136 struct { 137 uint64_t alignment; 138 uint64_t offset; 139 bool isAligned; 140 const void *forgedAddr() const { 141 // A value of any integral or enumeration type can be converted to a 142 // pointer type. 143 return reinterpret_cast<const void *>(offset); 144 } 145 } kTests[] = { 146 {1, 0, true}, {1, 1, true}, {1, 5, true}, {2, 0, true}, 147 {2, 1, false}, {2, 2, true}, {2, 7, false}, {2, 16, true}, 148 {4, 0, true}, {4, 1, false}, {4, 4, true}, {4, 6, false}, 149 }; 150 for (const auto &T : kTests) { 151 MaybeAlign A(T.alignment); 152 // Test Align 153 if (A) { 154 EXPECT_EQ(isAligned(A.value(), T.offset), T.isAligned); 155 EXPECT_EQ(isAddrAligned(A.value(), T.forgedAddr()), T.isAligned); 156 } 157 } 158 } 159 160 TEST(AlignmentTest, offsetToAlignment) { 161 struct { 162 uint64_t alignment; 163 uint64_t offset; 164 uint64_t alignedOffset; 165 const void *forgedAddr() const { 166 // A value of any integral or enumeration type can be converted to a 167 // pointer type. 168 return reinterpret_cast<const void *>(offset); 169 } 170 } kTests[] = { 171 {1, 0, 0}, {1, 1, 0}, {1, 5, 0}, {2, 0, 0}, {2, 1, 1}, {2, 2, 0}, 172 {2, 7, 1}, {2, 16, 0}, {4, 0, 0}, {4, 1, 3}, {4, 4, 0}, {4, 6, 2}, 173 }; 174 for (const auto &T : kTests) { 175 const Align A(T.alignment); 176 EXPECT_EQ(offsetToAlignment(T.offset, A), T.alignedOffset); 177 EXPECT_EQ(offsetToAlignedAddr(T.forgedAddr(), A), T.alignedOffset); 178 } 179 } 180 181 TEST(AlignmentTest, AlignComparisons) { 182 std::vector<uint64_t> ValidAlignments = getValidAlignments(); 183 llvm::sort(ValidAlignments); 184 for (size_t I = 1; I < ValidAlignments.size(); ++I) { 185 assert(I >= 1); 186 const Align A(ValidAlignments[I - 1]); 187 const Align B(ValidAlignments[I]); 188 EXPECT_EQ(A, A); 189 EXPECT_NE(A, B); 190 EXPECT_LT(A, B); 191 EXPECT_GT(B, A); 192 EXPECT_LE(A, B); 193 EXPECT_GE(B, A); 194 EXPECT_LE(A, A); 195 EXPECT_GE(A, A); 196 197 EXPECT_EQ(A, A.value()); 198 EXPECT_NE(A, B.value()); 199 EXPECT_LT(A, B.value()); 200 EXPECT_GT(B, A.value()); 201 EXPECT_LE(A, B.value()); 202 EXPECT_GE(B, A.value()); 203 EXPECT_LE(A, A.value()); 204 EXPECT_GE(A, A.value()); 205 206 EXPECT_EQ(std::max(A, B), B); 207 EXPECT_EQ(std::min(A, B), A); 208 209 const MaybeAlign MA(ValidAlignments[I - 1]); 210 const MaybeAlign MB(ValidAlignments[I]); 211 EXPECT_EQ(MA, MA); 212 EXPECT_NE(MA, MB); 213 214 EXPECT_EQ(std::max(A, B), B); 215 EXPECT_EQ(std::min(A, B), A); 216 } 217 } 218 219 TEST(AlignmentTest, AssumeAligned) { 220 EXPECT_EQ(assumeAligned(0), Align(1)); 221 EXPECT_EQ(assumeAligned(0), Align()); 222 EXPECT_EQ(assumeAligned(1), Align(1)); 223 EXPECT_EQ(assumeAligned(1), Align()); 224 } 225 226 // Death tests reply on assert which is disabled in release mode. 227 #ifndef NDEBUG 228 229 // We use a subset of valid alignments for DEATH_TESTs as they are particularly 230 // slow. 231 std::vector<uint64_t> getValidAlignmentsForDeathTest() { 232 return {1, 1ULL << 31, 1ULL << 63}; 233 } 234 235 std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; } 236 237 TEST(AlignmentDeathTest, InvalidCTors) { 238 EXPECT_DEATH((Align(0)), "Value must not be 0"); 239 for (uint64_t Value : getNonPowerOfTwo()) { 240 EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2"); 241 EXPECT_DEATH((MaybeAlign(Value)), 242 "Alignment is neither 0 nor a power of 2"); 243 } 244 } 245 246 TEST(AlignmentDeathTest, ComparisonsWithZero) { 247 for (uint64_t Value : getValidAlignmentsForDeathTest()) { 248 EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined"); 249 EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined"); 250 EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined"); 251 EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined"); 252 EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined"); 253 EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined"); 254 } 255 } 256 257 TEST(AlignmentDeathTest, AlignAddr) { 258 const void *const unaligned_high_ptr = 259 reinterpret_cast<const void *>(std::numeric_limits<uintptr_t>::max() - 1); 260 EXPECT_DEATH(alignAddr(unaligned_high_ptr, Align(16)), "Overflow"); 261 } 262 263 #endif // NDEBUG 264 265 } // end anonymous namespace 266 267 #ifdef _MSC_VER 268 #pragma warning(pop) 269 #endif 270