257 lines · cpp
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-exception6//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>(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 67TEST(BitfieldsTest, FirstBit) {68 uint8_t Storage = 0;69 using FirstBit = Bitfield::Element<bool, 0, 1>;70 // Set true71 Bitfield::set<FirstBit>(Storage, true);72 EXPECT_EQ(Bitfield::get<FirstBit>(Storage), true);73 EXPECT_EQ(Storage, 0x1ULL);74 // Set false75 Bitfield::set<FirstBit>(Storage, 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 true84 Bitfield::set<SecondBit>(Storage, true);85 EXPECT_EQ(Bitfield::get<SecondBit>(Storage), true);86 EXPECT_EQ(Storage, 0x2ULL);87 // Set false88 Bitfield::set<SecondBit>(Storage, 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 true97 Bitfield::set<LastBit>(Storage, true);98 EXPECT_EQ(Bitfield::get<LastBit>(Storage), true);99 EXPECT_EQ(Storage, 0x80ULL);100 // Set false101 Bitfield::set<LastBit>(Storage, 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 true110 Bitfield::set<LastBit>(Storage, true);111 EXPECT_EQ(Bitfield::get<LastBit>(Storage), true);112 EXPECT_EQ(Storage, 0x8000000000000000ULL);113 // Set false114 Bitfield::set<LastBit>(Storage, 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>(Storage, 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>(Storage, 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>(Storage, -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>(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 175TEST(BitfieldsTest, isOverlapping) {176 // 01234567177 // 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:1197 using B = Bitfield::Element<unsigned, 1, 4>; // Next Bit:5198 using C = Bitfield::Element<unsigned, 5, 3>; // Next Bit:8199 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>(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 216TEST(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_DEATH226 227TEST(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 235TEST(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 243TEST(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 out of range");251 EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, -3), "value is out of range");252}253 254#endif255 256} // namespace257