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
12using namespace llvm;
13
14namespace {
15
16TEST(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>(Packed&: Storage, Value: 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>(Packed&: Storage, Value: 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>(Packed&: Storage, Value: 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>(Packed&: Storage, Value: -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
67TEST(BitfieldsTest, FirstBit) {
68 uint8_t Storage = 0;
69 using FirstBit = Bitfield::Element<bool, 0, 1>;
70 // Set true
71 Bitfield::set<FirstBit>(Packed&: Storage, Value: true);
72 EXPECT_EQ(Bitfield::get<FirstBit>(Storage), true);
73 EXPECT_EQ(Storage, 0x1ULL);
74 // Set false
75 Bitfield::set<FirstBit>(Packed&: Storage, Value: false);
76 EXPECT_EQ(Bitfield::get<FirstBit>(Storage), false);
77 EXPECT_EQ(Storage, 0x0ULL);
78}
79
80TEST(BitfieldsTest, SecondBit) {
81 uint8_t Storage = 0;
82 using SecondBit = Bitfield::Element<bool, 1, 1>;
83 // Set true
84 Bitfield::set<SecondBit>(Packed&: Storage, Value: true);
85 EXPECT_EQ(Bitfield::get<SecondBit>(Storage), true);
86 EXPECT_EQ(Storage, 0x2ULL);
87 // Set false
88 Bitfield::set<SecondBit>(Packed&: Storage, Value: false);
89 EXPECT_EQ(Bitfield::get<SecondBit>(Storage), false);
90 EXPECT_EQ(Storage, 0x0ULL);
91}
92
93TEST(BitfieldsTest, LastBit) {
94 uint8_t Storage = 0;
95 using LastBit = Bitfield::Element<bool, 7, 1>;
96 // Set true
97 Bitfield::set<LastBit>(Packed&: Storage, Value: true);
98 EXPECT_EQ(Bitfield::get<LastBit>(Storage), true);
99 EXPECT_EQ(Storage, 0x80ULL);
100 // Set false
101 Bitfield::set<LastBit>(Packed&: Storage, Value: false);
102 EXPECT_EQ(Bitfield::get<LastBit>(Storage), false);
103 EXPECT_EQ(Storage, 0x0ULL);
104}
105
106TEST(BitfieldsTest, LastBitUint64) {
107 uint64_t Storage = 0;
108 using LastBit = Bitfield::Element<bool, 63, 1>;
109 // Set true
110 Bitfield::set<LastBit>(Packed&: Storage, Value: true);
111 EXPECT_EQ(Bitfield::get<LastBit>(Storage), true);
112 EXPECT_EQ(Storage, 0x8000000000000000ULL);
113 // Set false
114 Bitfield::set<LastBit>(Packed&: Storage, Value: false);
115 EXPECT_EQ(Bitfield::get<LastBit>(Storage), false);
116 EXPECT_EQ(Storage, 0x0ULL);
117}
118
119TEST(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>(Packed&: Storage, Value: Two);
126 EXPECT_EQ(Bitfield::get<OrderingField>(Storage), Two);
127 EXPECT_EQ(Storage, 0b00000100);
128 // value 2 in ^^
129}
130
131TEST(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>(Packed&: Storage, Value: Enum::Two);
138 EXPECT_EQ(Bitfield::get<OrderingField>(Storage), Enum::Two);
139 EXPECT_EQ(Storage, 0b00000100);
140 // value 2 in ^^
141}
142
143TEST(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>(Packed&: Storage, Value: -1);
150 EXPECT_EQ(Bitfield::get<SignedField>(Storage), -1);
151 EXPECT_EQ(Storage, 0b00000010);
152 // value 1 in ^
153}
154
155TEST(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>(Packed&: Storage, Value: 1);
162 EXPECT_EQ(Bitfield::get<SignedField>(Storage), 1);
163 EXPECT_EQ(Storage, 0b00000010);
164 // value 1 in ^^
165 Bitfield::set<SignedField>(Packed&: Storage, Value: -1);
166 EXPECT_EQ(Bitfield::get<SignedField>(Storage), -1);
167 EXPECT_EQ(Storage, 0b00000110);
168 // value -1 in ^^
169 Bitfield::set<SignedField>(Packed&: Storage, Value: -2);
170 EXPECT_EQ(Bitfield::get<SignedField>(Storage), -2);
171 EXPECT_EQ(Storage, 0b00000100);
172 // value -2 in ^^
173}
174
175TEST(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
195TEST(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
207TEST(BitfieldsTest, FullUint64) {
208 uint64_t Storage = 0;
209 using Value = Bitfield::Element<uint64_t, 0, 64>;
210 Bitfield::set<Value>(Packed&: Storage, Value: -1ULL);
211 EXPECT_EQ(Bitfield::get<Value>(Storage), -1ULL);
212 Bitfield::set<Value>(Packed&: Storage, Value: 0ULL);
213 EXPECT_EQ(Bitfield::get<Value>(Storage), 0ULL);
214}
215
216TEST(BitfieldsTest, FullInt64) {
217 uint64_t Storage = 0;
218 using Value = Bitfield::Element<int64_t, 0, 64>;
219 Bitfield::set<Value>(Packed&: Storage, Value: -1);
220 EXPECT_EQ(Bitfield::get<Value>(Storage), -1);
221 Bitfield::set<Value>(Packed&: Storage, Value: 0);
222 EXPECT_EQ(Bitfield::get<Value>(Storage), 0);
223}
224
225#ifdef EXPECT_DEBUG_DEATH
226
227TEST(BitfieldsTest, ValueTooBigBool) {
228 uint64_t Storage = 0;
229 using A = Bitfield::Element<unsigned, 0, 1>;
230 Bitfield::set<A>(Packed&: Storage, Value: true);
231 Bitfield::set<A>(Packed&: Storage, Value: false);
232 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, 2), "value is too big");
233}
234
235TEST(BitfieldsTest, ValueTooBigInt) {
236 uint64_t Storage = 0;
237 using A = Bitfield::Element<unsigned, 0, 2>;
238 Bitfield::set<A>(Packed&: Storage, Value: 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
243TEST(BitfieldsTest, ValueTooBigBounded) {
244 uint8_t Storage = 0;
245 using A = Bitfield::Element<int, 1, 2>;
246 Bitfield::set<A>(Packed&: Storage, Value: 1);
247 Bitfield::set<A>(Packed&: Storage, Value: 0);
248 Bitfield::set<A>(Packed&: Storage, Value: -1);
249 Bitfield::set<A>(Packed&: Storage, Value: -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

source code of llvm/unittests/ADT/BitFieldsTest.cpp