1 //===- llvm/unittests/ADT/BitFieldsTest.cpp - BitFields unit tests --------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/Bitfields.h"
10 #include "gtest/gtest.h"
16 TEST(BitfieldsTest
, Example
) {
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);
24 EXPECT_EQ(Bitfield::get
<Bool
>(Storage
), true);
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);
34 EXPECT_EQ(Bitfield::get
<Suit
>(Storage
), SuitEnum::HEARTS
);
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);
41 EXPECT_EQ(Bitfield::get
<Value
>(Storage
), 10U);
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);
48 EXPECT_EQ(Bitfield::get
<SignedValue
>(Storage
), -2);
50 // Ability to efficiently test if a field is non zero.
51 EXPECT_TRUE(Bitfield::test
<Value
>(Storage
));
53 // Alter Storage changes value.
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);
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);
67 TEST(BitfieldsTest
, FirstBit
) {
69 using FirstBit
= Bitfield::Element
<bool, 0, 1>;
71 Bitfield::set
<FirstBit
>(Storage
, true);
72 EXPECT_EQ(Bitfield::get
<FirstBit
>(Storage
), true);
73 EXPECT_EQ(Storage
, 0x1ULL
);
75 Bitfield::set
<FirstBit
>(Storage
, false);
76 EXPECT_EQ(Bitfield::get
<FirstBit
>(Storage
), false);
77 EXPECT_EQ(Storage
, 0x0ULL
);
80 TEST(BitfieldsTest
, SecondBit
) {
82 using SecondBit
= Bitfield::Element
<bool, 1, 1>;
84 Bitfield::set
<SecondBit
>(Storage
, true);
85 EXPECT_EQ(Bitfield::get
<SecondBit
>(Storage
), true);
86 EXPECT_EQ(Storage
, 0x2ULL
);
88 Bitfield::set
<SecondBit
>(Storage
, false);
89 EXPECT_EQ(Bitfield::get
<SecondBit
>(Storage
), false);
90 EXPECT_EQ(Storage
, 0x0ULL
);
93 TEST(BitfieldsTest
, LastBit
) {
95 using LastBit
= Bitfield::Element
<bool, 7, 1>;
97 Bitfield::set
<LastBit
>(Storage
, true);
98 EXPECT_EQ(Bitfield::get
<LastBit
>(Storage
), true);
99 EXPECT_EQ(Storage
, 0x80ULL
);
101 Bitfield::set
<LastBit
>(Storage
, false);
102 EXPECT_EQ(Bitfield::get
<LastBit
>(Storage
), false);
103 EXPECT_EQ(Storage
, 0x0ULL
);
106 TEST(BitfieldsTest
, LastBitUint64
) {
107 uint64_t Storage
= 0;
108 using LastBit
= Bitfield::Element
<bool, 63, 1>;
110 Bitfield::set
<LastBit
>(Storage
, true);
111 EXPECT_EQ(Bitfield::get
<LastBit
>(Storage
), true);
112 EXPECT_EQ(Storage
, 0x8000000000000000ULL
);
114 Bitfield::set
<LastBit
>(Storage
, false);
115 EXPECT_EQ(Bitfield::get
<LastBit
>(Storage
), false);
116 EXPECT_EQ(Storage
, 0x0ULL
);
119 TEST(BitfieldsTest
, Enum
) {
120 enum Enum
: unsigned { Zero
= 0, Two
= 2, LAST
= Two
};
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);
131 TEST(BitfieldsTest
, EnumClass
) {
132 enum class Enum
: unsigned { Zero
= 0, Two
= 2, LAST
= Two
};
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);
143 TEST(BitfieldsTest
, OneBitSigned
) {
145 using SignedField
= Bitfield::Element
<int, 1, 1>;
146 EXPECT_EQ(Bitfield::get
<SignedField
>(Storage
), 0);
147 EXPECT_EQ(Storage
, 0b00000000);
149 Bitfield::set
<SignedField
>(Storage
, -1);
150 EXPECT_EQ(Bitfield::get
<SignedField
>(Storage
), -1);
151 EXPECT_EQ(Storage
, 0b00000010);
155 TEST(BitfieldsTest
, TwoBitSigned
) {
157 using SignedField
= Bitfield::Element
<int, 1, 2>;
158 EXPECT_EQ(Bitfield::get
<SignedField
>(Storage
), 0);
159 EXPECT_EQ(Storage
, 0b00000000);
161 Bitfield::set
<SignedField
>(Storage
, 1);
162 EXPECT_EQ(Bitfield::get
<SignedField
>(Storage
), 1);
163 EXPECT_EQ(Storage
, 0b00000010);
165 Bitfield::set
<SignedField
>(Storage
, -1);
166 EXPECT_EQ(Bitfield::get
<SignedField
>(Storage
), -1);
167 EXPECT_EQ(Storage
, 0b00000110);
169 Bitfield::set
<SignedField
>(Storage
, -2);
170 EXPECT_EQ(Bitfield::get
<SignedField
>(Storage
), -2);
171 EXPECT_EQ(Storage
, 0b00000100);
175 TEST(BitfieldsTest
, isOverlapping
) {
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
>()));
190 EXPECT_TRUE((Bitfield::isOverlapping
<B
, C
>()));
191 EXPECT_TRUE((Bitfield::isOverlapping
<B
, D
>()));
192 EXPECT_FALSE((Bitfield::isOverlapping
<C
, D
>()));
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
>()));
202 EXPECT_FALSE((Bitfield::areContiguous
<A
, C
>()));
203 EXPECT_FALSE((Bitfield::areContiguous
<A
, A
>()));
204 EXPECT_FALSE((Bitfield::areContiguous
<B
, A
>()));
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);
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);
225 #ifdef EXPECT_DEBUG_DEATH
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");
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");
243 TEST(BitfieldsTest
, ValueTooBigBounded
) {
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");