• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(BitfieldsTest,Example)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 
TEST(BitfieldsTest,FirstBit)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 
TEST(BitfieldsTest,SecondBit)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 
TEST(BitfieldsTest,LastBit)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 
TEST(BitfieldsTest,LastBitUint64)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 
TEST(BitfieldsTest,Enum)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 
TEST(BitfieldsTest,EnumClass)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 
TEST(BitfieldsTest,OneBitSigned)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 
TEST(BitfieldsTest,TwoBitSigned)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 
TEST(BitfieldsTest,isOverlapping)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 
TEST(BitfieldsTest,areContiguous)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 
TEST(BitfieldsTest,FullUint64)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 
TEST(BitfieldsTest,FullInt64)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 
TEST(BitfieldsTest,ValueTooBigBool)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 
TEST(BitfieldsTest,ValueTooBigInt)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 
TEST(BitfieldsTest,ValueTooBigBounded)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