File indexing completed on 2026-05-10 08:43:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 #ifndef LLVM_ADT_BITFIELDS_H
0080 #define LLVM_ADT_BITFIELDS_H
0081
0082 #include <cassert>
0083 #include <climits> // CHAR_BIT
0084 #include <cstddef> // size_t
0085 #include <cstdint> // uintXX_t
0086 #include <limits> // numeric_limits
0087 #include <type_traits>
0088
0089 namespace llvm {
0090
0091 namespace bitfields_details {
0092
0093
0094 template <typename T, unsigned Bits> struct BitPatterns {
0095
0096
0097
0098
0099 using Unsigned = std::make_unsigned_t<T>;
0100 static_assert(sizeof(Unsigned) == sizeof(T), "Types must have same size");
0101
0102 static constexpr unsigned TypeBits = sizeof(Unsigned) * CHAR_BIT;
0103 static_assert(TypeBits >= Bits, "n-bit must fit in T");
0104
0105
0106 static constexpr Unsigned AllZeros = Unsigned(0);
0107 static constexpr Unsigned AllOnes = ~Unsigned(0);
0108 static constexpr Unsigned Umin = AllZeros;
0109 static constexpr Unsigned Umax = AllOnes >> (TypeBits - Bits);
0110 static constexpr Unsigned SignBitMask = Unsigned(1) << (Bits - 1);
0111 static constexpr Unsigned Smax = Umax >> 1U;
0112 static constexpr Unsigned Smin = ~Smax;
0113 static constexpr Unsigned SignExtend = Unsigned(Smin << 1U);
0114 };
0115
0116
0117
0118
0119
0120 template <typename T, unsigned Bits, bool = std::is_unsigned<T>::value>
0121 struct Compressor {
0122 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
0123 using BP = BitPatterns<T, Bits>;
0124
0125 static T pack(T UserValue, T UserMaxValue) {
0126 assert(UserValue <= UserMaxValue && "value is too big");
0127 assert(UserValue <= BP::Umax && "value is too big");
0128 return UserValue;
0129 }
0130
0131 static T unpack(T StorageValue) { return StorageValue; }
0132 };
0133
0134 template <typename T, unsigned Bits> struct Compressor<T, Bits, false> {
0135 static_assert(std::is_signed<T>::value, "T must be signed");
0136 using BP = BitPatterns<T, Bits>;
0137
0138 static T pack(T UserValue, T UserMaxValue) {
0139 assert(UserValue <= UserMaxValue && "value is too big");
0140 assert(UserValue <= T(BP::Smax) && "value is too big");
0141 assert(UserValue >= T(BP::Smin) && "value is too small");
0142 if (UserValue < 0)
0143 UserValue &= ~BP::SignExtend;
0144 return UserValue;
0145 }
0146
0147 static T unpack(T StorageValue) {
0148 if (StorageValue >= T(BP::SignBitMask))
0149 StorageValue |= BP::SignExtend;
0150 return StorageValue;
0151 }
0152 };
0153
0154
0155
0156 template <typename Bitfield, typename StorageType> struct Impl {
0157 static_assert(std::is_unsigned<StorageType>::value,
0158 "Storage must be unsigned");
0159 using IntegerType = typename Bitfield::IntegerType;
0160 using C = Compressor<IntegerType, Bitfield::Bits>;
0161 using BP = BitPatterns<StorageType, Bitfield::Bits>;
0162
0163 static constexpr size_t StorageBits = sizeof(StorageType) * CHAR_BIT;
0164 static_assert(Bitfield::FirstBit <= StorageBits, "Data must fit in mask");
0165 static_assert(Bitfield::LastBit <= StorageBits, "Data must fit in mask");
0166 static constexpr StorageType Mask = BP::Umax << Bitfield::Shift;
0167
0168
0169
0170 static void update(StorageType &Packed, IntegerType UserValue) {
0171 const StorageType StorageValue = C::pack(UserValue, Bitfield::UserMaxValue);
0172 Packed &= ~Mask;
0173 Packed |= StorageValue << Bitfield::Shift;
0174 }
0175
0176
0177
0178 static IntegerType extract(StorageType Packed) {
0179 const StorageType StorageValue = (Packed & Mask) >> Bitfield::Shift;
0180 return C::unpack(StorageValue);
0181 }
0182
0183
0184
0185 static StorageType test(StorageType Packed) { return Packed & Mask; }
0186 };
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 template <typename T, bool = std::is_enum<T>::value>
0197 struct ResolveUnderlyingType {
0198 using type = std::underlying_type_t<T>;
0199 };
0200 template <typename T> struct ResolveUnderlyingType<T, false> {
0201 using type = T;
0202 };
0203 template <> struct ResolveUnderlyingType<bool, false> {
0204
0205
0206 using type = std::conditional_t<sizeof(bool) == 1, uint8_t, void>;
0207 };
0208
0209 }
0210
0211
0212 struct Bitfield {
0213
0214
0215
0216
0217
0218
0219 template <typename T, unsigned Offset, unsigned Size,
0220 T MaxValue = std::is_enum<T>::value
0221 ? T(0)
0222 : std::numeric_limits<T>::max()>
0223 struct Element {
0224 using Type = T;
0225 using IntegerType =
0226 typename bitfields_details::ResolveUnderlyingType<T>::type;
0227 static constexpr unsigned Shift = Offset;
0228 static constexpr unsigned Bits = Size;
0229 static constexpr unsigned FirstBit = Offset;
0230 static constexpr unsigned LastBit = Shift + Bits - 1;
0231 static constexpr unsigned NextBit = Shift + Bits;
0232
0233 private:
0234 template <typename, typename> friend struct bitfields_details::Impl;
0235
0236 static_assert(Bits > 0, "Bits must be non zero");
0237 static constexpr size_t TypeBits = sizeof(IntegerType) * CHAR_BIT;
0238 static_assert(Bits <= TypeBits, "Bits may not be greater than T size");
0239 static_assert(!std::is_enum<T>::value || MaxValue != T(0),
0240 "Enum Bitfields must provide a MaxValue");
0241 static_assert(!std::is_enum<T>::value ||
0242 std::is_unsigned<IntegerType>::value,
0243 "Enum must be unsigned");
0244 static_assert(std::is_integral<IntegerType>::value &&
0245 std::numeric_limits<IntegerType>::is_integer,
0246 "IntegerType must be an integer type");
0247
0248 static constexpr IntegerType UserMaxValue =
0249 static_cast<IntegerType>(MaxValue);
0250 };
0251
0252
0253 template <typename Bitfield, typename StorageType>
0254 static typename Bitfield::Type get(StorageType Packed) {
0255 using I = bitfields_details::Impl<Bitfield, StorageType>;
0256 return static_cast<typename Bitfield::Type>(I::extract(Packed));
0257 }
0258
0259
0260
0261 template <typename Bitfield, typename StorageType>
0262 static StorageType test(StorageType Packed) {
0263 using I = bitfields_details::Impl<Bitfield, StorageType>;
0264 return I::test(Packed);
0265 }
0266
0267
0268
0269 template <typename Bitfield, typename StorageType>
0270 static void set(StorageType &Packed, typename Bitfield::Type Value) {
0271 using I = bitfields_details::Impl<Bitfield, StorageType>;
0272 I::update(Packed, static_cast<typename Bitfield::IntegerType>(Value));
0273 }
0274
0275
0276 template <typename A, typename B> static constexpr bool isOverlapping() {
0277 return A::LastBit >= B::FirstBit && B::LastBit >= A::FirstBit;
0278 }
0279
0280 template <typename A> static constexpr bool areContiguous() { return true; }
0281 template <typename A, typename B, typename... Others>
0282 static constexpr bool areContiguous() {
0283 return A::NextBit == B::FirstBit && areContiguous<B, Others...>();
0284 }
0285 };
0286
0287 }
0288
0289 #endif