1 //===- llvm/unittests/ADT/BitFieldsTest.cpp - BitFields unit 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/ADT/Bitfields.h" 10 #include "gtest/gtest.h" 11 12 using namespace llvm; 13 14 namespace { 15 16 TEST(BitfieldsTest, Example) { 17 uint8_t Storage = 0; 18 19 // Store and retrieve a single bit as bool. 20 using Bool = Bitfield::Element<bool, 0, 1>; 21 Bitfield::set<Bool>(Storage, true); 22 EXPECT_EQ(Storage, 0b00000001); 23 // ^ 24 EXPECT_EQ(Bitfield::get<Bool>(Storage), true); 25 26 // Store and retrieve a 2 bit typed enum. 27 // Note: enum underlying type must be unsigned. 28 enum class SuitEnum : uint8_t { CLUBS, DIAMONDS, HEARTS, SPADES }; 29 // Note: enum maximum value needs to be passed in as last parameter. 30 using Suit = Bitfield::Element<SuitEnum, 1, 2, SuitEnum::SPADES>; 31 Bitfield::set<Suit>(Storage, SuitEnum::HEARTS); 32 EXPECT_EQ(Storage, 0b00000101); 33 // ^^ 34 EXPECT_EQ(Bitfield::get<Suit>(Storage), SuitEnum::HEARTS); 35 36 // Store and retrieve a 5 bit value as unsigned. 37 using Value = Bitfield::Element<unsigned, 3, 5>; 38 Bitfield::set<Value>(Storage, 10); 39 EXPECT_EQ(Storage, 0b01010101); 40 // ^^^^^ 41 EXPECT_EQ(Bitfield::get<Value>(Storage), 10U); 42 43 // Interpret the same 5 bit value as signed. 44 using SignedValue = Bitfield::Element<int, 3, 5>; 45 Bitfield::set<SignedValue>(Storage, -2); 46 EXPECT_EQ(Storage, 0b11110101); 47 // ^^^^^ 48 EXPECT_EQ(Bitfield::get<SignedValue>(Storage), -2); 49 50 // Ability to efficiently test if a field is non zero. 51 EXPECT_TRUE(Bitfield::test<Value>(Storage)); 52 53 // Alter Storage changes value. 54 Storage = 0; 55 EXPECT_EQ(Bitfield::get<Bool>(Storage), false); 56 EXPECT_EQ(Bitfield::get<Suit>(Storage), SuitEnum::CLUBS); 57 EXPECT_EQ(Bitfield::get<Value>(Storage), 0U); 58 EXPECT_EQ(Bitfield::get<SignedValue>(Storage), 0); 59 60 Storage = 255; 61 EXPECT_EQ(Bitfield::get<Bool>(Storage), true); 62 EXPECT_EQ(Bitfield::get<Suit>(Storage), SuitEnum::SPADES); 63 EXPECT_EQ(Bitfield::get<Value>(Storage), 31U); 64 EXPECT_EQ(Bitfield::get<SignedValue>(Storage), -1); 65 } 66 67 TEST(BitfieldsTest, FirstBit) { 68 uint8_t Storage = 0; 69 using FirstBit = Bitfield::Element<bool, 0, 1>; 70 // Set true 71 Bitfield::set<FirstBit>(Storage, true); 72 EXPECT_EQ(Bitfield::get<FirstBit>(Storage), true); 73 EXPECT_EQ(Storage, 0x1ULL); 74 // Set false 75 Bitfield::set<FirstBit>(Storage, false); 76 EXPECT_EQ(Bitfield::get<FirstBit>(Storage), false); 77 EXPECT_EQ(Storage, 0x0ULL); 78 } 79 80 TEST(BitfieldsTest, SecondBit) { 81 uint8_t Storage = 0; 82 using SecondBit = Bitfield::Element<bool, 1, 1>; 83 // Set true 84 Bitfield::set<SecondBit>(Storage, true); 85 EXPECT_EQ(Bitfield::get<SecondBit>(Storage), true); 86 EXPECT_EQ(Storage, 0x2ULL); 87 // Set false 88 Bitfield::set<SecondBit>(Storage, false); 89 EXPECT_EQ(Bitfield::get<SecondBit>(Storage), false); 90 EXPECT_EQ(Storage, 0x0ULL); 91 } 92 93 TEST(BitfieldsTest, LastBit) { 94 uint8_t Storage = 0; 95 using LastBit = Bitfield::Element<bool, 7, 1>; 96 // Set true 97 Bitfield::set<LastBit>(Storage, true); 98 EXPECT_EQ(Bitfield::get<LastBit>(Storage), true); 99 EXPECT_EQ(Storage, 0x80ULL); 100 // Set false 101 Bitfield::set<LastBit>(Storage, false); 102 EXPECT_EQ(Bitfield::get<LastBit>(Storage), false); 103 EXPECT_EQ(Storage, 0x0ULL); 104 } 105 106 TEST(BitfieldsTest, LastBitUint64) { 107 uint64_t Storage = 0; 108 using LastBit = Bitfield::Element<bool, 63, 1>; 109 // Set true 110 Bitfield::set<LastBit>(Storage, true); 111 EXPECT_EQ(Bitfield::get<LastBit>(Storage), true); 112 EXPECT_EQ(Storage, 0x8000000000000000ULL); 113 // Set false 114 Bitfield::set<LastBit>(Storage, false); 115 EXPECT_EQ(Bitfield::get<LastBit>(Storage), false); 116 EXPECT_EQ(Storage, 0x0ULL); 117 } 118 119 TEST(BitfieldsTest, Enum) { 120 enum Enum : unsigned { Zero = 0, Two = 2, LAST = Two }; 121 122 uint8_t Storage = 0; 123 using OrderingField = Bitfield::Element<Enum, 1, 2, LAST>; 124 EXPECT_EQ(Bitfield::get<OrderingField>(Storage), Zero); 125 Bitfield::set<OrderingField>(Storage, Two); 126 EXPECT_EQ(Bitfield::get<OrderingField>(Storage), Two); 127 EXPECT_EQ(Storage, 0b00000100); 128 // value 2 in ^^ 129 } 130 131 TEST(BitfieldsTest, EnumClass) { 132 enum class Enum : unsigned { Zero = 0, Two = 2, LAST = Two }; 133 134 uint8_t Storage = 0; 135 using OrderingField = Bitfield::Element<Enum, 1, 2, Enum::LAST>; 136 EXPECT_EQ(Bitfield::get<OrderingField>(Storage), Enum::Zero); 137 Bitfield::set<OrderingField>(Storage, Enum::Two); 138 EXPECT_EQ(Bitfield::get<OrderingField>(Storage), Enum::Two); 139 EXPECT_EQ(Storage, 0b00000100); 140 // value 2 in ^^ 141 } 142 143 TEST(BitfieldsTest, OneBitSigned) { 144 uint8_t Storage = 0; 145 using SignedField = Bitfield::Element<int, 1, 1>; 146 EXPECT_EQ(Bitfield::get<SignedField>(Storage), 0); 147 EXPECT_EQ(Storage, 0b00000000); 148 // value 0 in ^ 149 Bitfield::set<SignedField>(Storage, -1); 150 EXPECT_EQ(Bitfield::get<SignedField>(Storage), -1); 151 EXPECT_EQ(Storage, 0b00000010); 152 // value 1 in ^ 153 } 154 155 TEST(BitfieldsTest, TwoBitSigned) { 156 uint8_t Storage = 0; 157 using SignedField = Bitfield::Element<int, 1, 2>; 158 EXPECT_EQ(Bitfield::get<SignedField>(Storage), 0); 159 EXPECT_EQ(Storage, 0b00000000); 160 // value 0 in ^^ 161 Bitfield::set<SignedField>(Storage, 1); 162 EXPECT_EQ(Bitfield::get<SignedField>(Storage), 1); 163 EXPECT_EQ(Storage, 0b00000010); 164 // value 1 in ^^ 165 Bitfield::set<SignedField>(Storage, -1); 166 EXPECT_EQ(Bitfield::get<SignedField>(Storage), -1); 167 EXPECT_EQ(Storage, 0b00000110); 168 // value -1 in ^^ 169 Bitfield::set<SignedField>(Storage, -2); 170 EXPECT_EQ(Bitfield::get<SignedField>(Storage), -2); 171 EXPECT_EQ(Storage, 0b00000100); 172 // value -2 in ^^ 173 } 174 175 TEST(BitfieldsTest, isOverlapping) { 176 // 01234567 177 // A: -------- 178 // B: --- 179 // C: --- 180 // D: --- 181 using A = Bitfield::Element<unsigned, 0, 8>; 182 using B = Bitfield::Element<unsigned, 3, 3>; 183 using C = Bitfield::Element<unsigned, 1, 3>; 184 using D = Bitfield::Element<unsigned, 4, 3>; 185 EXPECT_TRUE((Bitfield::isOverlapping<A, B>())); 186 EXPECT_TRUE((Bitfield::isOverlapping<A, C>())); 187 EXPECT_TRUE((Bitfield::isOverlapping<A, B>())); 188 EXPECT_TRUE((Bitfield::isOverlapping<A, D>())); 189 190 EXPECT_TRUE((Bitfield::isOverlapping<B, C>())); 191 EXPECT_TRUE((Bitfield::isOverlapping<B, D>())); 192 EXPECT_FALSE((Bitfield::isOverlapping<C, D>())); 193 } 194 195 TEST(BitfieldsTest, areContiguous) { 196 using A = Bitfield::Element<unsigned, 0, 1>; // Next Bit:1 197 using B = Bitfield::Element<unsigned, 1, 4>; // Next Bit:5 198 using C = Bitfield::Element<unsigned, 5, 3>; // Next Bit:8 199 EXPECT_TRUE((Bitfield::areContiguous<A, B>())); 200 EXPECT_TRUE((Bitfield::areContiguous<A, B, C>())); 201 202 EXPECT_FALSE((Bitfield::areContiguous<A, C>())); 203 EXPECT_FALSE((Bitfield::areContiguous<A, A>())); 204 EXPECT_FALSE((Bitfield::areContiguous<B, A>())); 205 } 206 207 TEST(BitfieldsTest, FullUint64) { 208 uint64_t Storage = 0; 209 using Value = Bitfield::Element<uint64_t, 0, 64>; 210 Bitfield::set<Value>(Storage, -1ULL); 211 EXPECT_EQ(Bitfield::get<Value>(Storage), -1ULL); 212 Bitfield::set<Value>(Storage, 0ULL); 213 EXPECT_EQ(Bitfield::get<Value>(Storage), 0ULL); 214 } 215 216 TEST(BitfieldsTest, FullInt64) { 217 uint64_t Storage = 0; 218 using Value = Bitfield::Element<int64_t, 0, 64>; 219 Bitfield::set<Value>(Storage, -1); 220 EXPECT_EQ(Bitfield::get<Value>(Storage), -1); 221 Bitfield::set<Value>(Storage, 0); 222 EXPECT_EQ(Bitfield::get<Value>(Storage), 0); 223 } 224 225 #ifdef EXPECT_DEBUG_DEATH 226 227 TEST(BitfieldsTest, ValueTooBigBool) { 228 uint64_t Storage = 0; 229 using A = Bitfield::Element<unsigned, 0, 1>; 230 Bitfield::set<A>(Storage, true); 231 Bitfield::set<A>(Storage, false); 232 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, 2), "value is too big"); 233 } 234 235 TEST(BitfieldsTest, ValueTooBigInt) { 236 uint64_t Storage = 0; 237 using A = Bitfield::Element<unsigned, 0, 2>; 238 Bitfield::set<A>(Storage, 3); 239 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, 4), "value is too big"); 240 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, -1), "value is too big"); 241 } 242 243 TEST(BitfieldsTest, ValueTooBigBounded) { 244 uint8_t Storage = 0; 245 using A = Bitfield::Element<int, 1, 2>; 246 Bitfield::set<A>(Storage, 1); 247 Bitfield::set<A>(Storage, 0); 248 Bitfield::set<A>(Storage, -1); 249 Bitfield::set<A>(Storage, -2); 250 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, 2), "value is too big"); 251 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, -3), "value is too small"); 252 } 253 254 #endif 255 256 } // namespace 257