Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:03

0001 //===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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 /// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
0020 /// perform bitwise operations on it without putting static_cast everywhere.
0021 ///
0022 /// \code
0023 ///   enum MyEnum {
0024 ///     E1 = 1, E2 = 2, E3 = 4, E4 = 8,
0025 ///     LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
0026 ///   };
0027 ///
0028 ///   void Foo() {
0029 ///     MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
0030 ///   }
0031 /// \endcode
0032 ///
0033 /// Normally when you do a bitwise operation on an enum value, you get back an
0034 /// instance of the underlying type (e.g. int).  But using this macro, bitwise
0035 /// ops on your enum will return you back instances of the enum.  This is
0036 /// particularly useful for enums which represent a combination of flags.
0037 ///
0038 /// The parameter to LLVM_MARK_AS_BITMASK_ENUM should be the largest individual
0039 /// value in your enum.
0040 ///
0041 /// All of the enum's values must be non-negative.
0042 #define LLVM_MARK_AS_BITMASK_ENUM(LargestValue)                                \
0043   LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
0044 
0045 /// LLVM_DECLARE_ENUM_AS_BITMASK can be used to declare an enum type as a bit
0046 /// set, so that bitwise operation on such enum does not require static_cast.
0047 ///
0048 /// \code
0049 ///   enum MyEnum { E1 = 1, E2 = 2, E3 = 4, E4 = 8 };
0050 ///   LLVM_DECLARE_ENUM_AS_BITMASK(MyEnum, E4);
0051 ///
0052 ///   void Foo() {
0053 ///     MyEnum A = (E1 | E2) & E3 ^ ~E4; // No static_cast
0054 ///   }
0055 /// \endcode
0056 ///
0057 /// The second parameter to LLVM_DECLARE_ENUM_AS_BITMASK specifies the largest
0058 /// bit value of the enum type.
0059 ///
0060 /// LLVM_DECLARE_ENUM_AS_BITMASK should be used in llvm namespace.
0061 ///
0062 /// This a non-intrusive alternative for LLVM_MARK_AS_BITMASK_ENUM. It allows
0063 /// declaring more than one non-scoped enumerations as bitmask types in the same
0064 /// scope. Otherwise it provides the same functionality as
0065 /// LLVM_MARK_AS_BITMASK_ENUM.
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 /// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used
0073 /// by LLVM_MARK_AS_BITMASK_ENUM into the current namespace.
0074 ///
0075 /// Suppose you have an enum foo::bar::MyEnum.  Before using
0076 /// LLVM_MARK_AS_BITMASK_ENUM on MyEnum, you must put
0077 /// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() somewhere inside namespace foo or
0078 /// namespace foo::bar.  This allows the relevant operator overloads to be found
0079 /// by ADL.
0080 ///
0081 /// You don't need to use this macro in namespace llvm; it's done at the bottom
0082 /// of this file.
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   /* Force a semicolon at the end of this macro. */                            \
0096   using ::llvm::BitmaskEnumDetail::any
0097 
0098 namespace llvm {
0099 
0100 /// Traits class to determine whether an enum has a
0101 /// LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
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 /// Trait class to determine bitmask enumeration largest bit.
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 /// Get a bitmask with 1s in all places up to the high-order bit of E's largest
0124 /// value.
0125 template <typename E> constexpr std::underlying_type_t<E> Mask() {
0126   // On overflow, NextPowerOf2 returns zero with the type uint64_t, so
0127   // subtracting 1 gives us the mask with all bits set, like we want.
0128   return NextPowerOf2(largest_bitmask_enum_bit<E>::value) - 1;
0129 }
0130 
0131 /// Check that Val is in range for E, and return Val cast to E's underlying
0132 /// type.
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 // |=, &=, and ^= return a reference to LHS, to match the behavior of the
0180 // operators on builtin types.
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 } // namespace BitmaskEnumDetail
0213 
0214 // Enable bitmask enums in namespace ::llvm and all nested namespaces.
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 } // namespace llvm
0221 
0222 #endif