[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / unittests / ADT / BitFieldsTest.cpp
blob3062d5d7f293c3e9a6b076e6258daf7777ddd204
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 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/Bitfields.h"
10 #include "gtest/gtest.h"
12 using namespace llvm;
14 namespace {
16 TEST(BitfieldsTest, Example) {
17 uint8_t Storage = 0;
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);
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);
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);
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);
50 // Ability to efficiently test if a field is non zero.
51 EXPECT_TRUE(Bitfield::test<Value>(Storage));
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);
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);
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);
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);
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);
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);
119 TEST(BitfieldsTest, Enum) {
120 enum Enum : unsigned { Zero = 0, Two = 2, LAST = Two };
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 ^^
131 TEST(BitfieldsTest, EnumClass) {
132 enum class Enum : unsigned { Zero = 0, Two = 2, LAST = Two };
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 ^^
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 ^
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 ^^
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>()));
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) {
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");
254 #endif
256 } // namespace