File indexing completed on 2026-05-10 08:43:03
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ADT_BITMASKENUM_H
0010 #define LLVM_ADT_BITMASKENUM_H
0011
0012 #include <cassert>
0013 #include <type_traits>
0014 #include <utility>
0015
0016 #include "llvm/ADT/STLForwardCompat.h"
0017 #include "llvm/Support/MathExtras.h"
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 #define LLVM_MARK_AS_BITMASK_ENUM(LargestValue) \
0043 LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 #define LLVM_DECLARE_ENUM_AS_BITMASK(Enum, LargestValue) \
0067 template <> struct is_bitmask_enum<Enum> : std::true_type {}; \
0068 template <> struct largest_bitmask_enum_bit<Enum> { \
0069 static constexpr std::underlying_type_t<Enum> value = LargestValue; \
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 #define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() \
0084 using ::llvm::BitmaskEnumDetail::operator~; \
0085 using ::llvm::BitmaskEnumDetail::operator|; \
0086 using ::llvm::BitmaskEnumDetail::operator&; \
0087 using ::llvm::BitmaskEnumDetail::operator^; \
0088 using ::llvm::BitmaskEnumDetail::operator<<; \
0089 using ::llvm::BitmaskEnumDetail::operator>>; \
0090 using ::llvm::BitmaskEnumDetail::operator|=; \
0091 using ::llvm::BitmaskEnumDetail::operator&=; \
0092 using ::llvm::BitmaskEnumDetail::operator^=; \
0093 using ::llvm::BitmaskEnumDetail::operator<<=; \
0094 using ::llvm::BitmaskEnumDetail::operator>>=; \
0095 \
0096 using ::llvm::BitmaskEnumDetail::any
0097
0098 namespace llvm {
0099
0100
0101
0102 template <typename E, typename Enable = void>
0103 struct is_bitmask_enum : std::false_type {};
0104
0105 template <typename E>
0106 struct is_bitmask_enum<
0107 E, std::enable_if_t<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >= 0>>
0108 : std::true_type {};
0109
0110
0111 template <typename E, typename Enable = void> struct largest_bitmask_enum_bit;
0112
0113 template <typename E>
0114 struct largest_bitmask_enum_bit<
0115 E, std::enable_if_t<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >= 0>> {
0116 using UnderlyingTy = std::underlying_type_t<E>;
0117 static constexpr UnderlyingTy value =
0118 static_cast<UnderlyingTy>(E::LLVM_BITMASK_LARGEST_ENUMERATOR);
0119 };
0120
0121 namespace BitmaskEnumDetail {
0122
0123
0124
0125 template <typename E> constexpr std::underlying_type_t<E> Mask() {
0126
0127
0128 return NextPowerOf2(largest_bitmask_enum_bit<E>::value) - 1;
0129 }
0130
0131
0132
0133 template <typename E> constexpr std::underlying_type_t<E> Underlying(E Val) {
0134 auto U = llvm::to_underlying(Val);
0135 assert(U >= 0 && "Negative enum values are not allowed.");
0136 assert(U <= Mask<E>() && "Enum value too large (or largest val too small?)");
0137 return U;
0138 }
0139
0140 constexpr unsigned bitWidth(uint64_t Value) {
0141 return Value ? 1 + bitWidth(Value >> 1) : 0;
0142 }
0143
0144 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0145 constexpr bool any(E Val) {
0146 return Val != static_cast<E>(0);
0147 }
0148
0149 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0150 constexpr E operator~(E Val) {
0151 return static_cast<E>(~Underlying(Val) & Mask<E>());
0152 }
0153
0154 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0155 constexpr E operator|(E LHS, E RHS) {
0156 return static_cast<E>(Underlying(LHS) | Underlying(RHS));
0157 }
0158
0159 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0160 constexpr E operator&(E LHS, E RHS) {
0161 return static_cast<E>(Underlying(LHS) & Underlying(RHS));
0162 }
0163
0164 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0165 constexpr E operator^(E LHS, E RHS) {
0166 return static_cast<E>(Underlying(LHS) ^ Underlying(RHS));
0167 }
0168
0169 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0170 constexpr E operator<<(E LHS, E RHS) {
0171 return static_cast<E>(Underlying(LHS) << Underlying(RHS));
0172 }
0173
0174 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0175 constexpr E operator>>(E LHS, E RHS) {
0176 return static_cast<E>(Underlying(LHS) >> Underlying(RHS));
0177 }
0178
0179
0180
0181
0182 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0183 E &operator|=(E &LHS, E RHS) {
0184 LHS = LHS | RHS;
0185 return LHS;
0186 }
0187
0188 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0189 E &operator&=(E &LHS, E RHS) {
0190 LHS = LHS & RHS;
0191 return LHS;
0192 }
0193
0194 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0195 E &operator^=(E &LHS, E RHS) {
0196 LHS = LHS ^ RHS;
0197 return LHS;
0198 }
0199
0200 template <typename e, typename = std::enable_if_t<is_bitmask_enum<e>::value>>
0201 e &operator<<=(e &lhs, e rhs) {
0202 lhs = lhs << rhs;
0203 return lhs;
0204 }
0205
0206 template <typename e, typename = std::enable_if_t<is_bitmask_enum<e>::value>>
0207 e &operator>>=(e &lhs, e rhs) {
0208 lhs = lhs >> rhs;
0209 return lhs;
0210 }
0211
0212 }
0213
0214
0215 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
0216 template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
0217 constexpr unsigned BitWidth = BitmaskEnumDetail::bitWidth(
0218 uint64_t{llvm::to_underlying(E::LLVM_BITMASK_LARGEST_ENUMERATOR)});
0219
0220 }
0221
0222 #endif