Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
BitmaskEnum.h
Go to the documentation of this file.
1//===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- C++ -*-===//
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#ifndef LLVM_ADT_BITMASKENUM_H
10#define LLVM_ADT_BITMASKENUM_H
11
12#include <cassert>
13#include <type_traits>
14#include <utility>
15
16#include "llvm/ADT/STLForwardCompat.h"
17#include "llvm/Support/MathExtras.h"
18
19/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
20/// perform bitwise operations on it without putting static_cast everywhere.
21///
22/// \code
23/// enum MyEnum {
24/// E1 = 1, E2 = 2, E3 = 4, E4 = 8,
25/// LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
26/// };
27///
28/// void Foo() {
29/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
30/// }
31/// \endcode
32///
33/// Normally when you do a bitwise operation on an enum value, you get back an
34/// instance of the underlying type (e.g. int). But using this macro, bitwise
35/// ops on your enum will return you back instances of the enum. This is
36/// particularly useful for enums which represent a combination of flags.
37///
38/// The parameter to LLVM_MARK_AS_BITMASK_ENUM should be the largest individual
39/// value in your enum.
40///
41/// All of the enum's values must be non-negative.
42#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue) \
43 LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
44
45/// LLVM_DECLARE_ENUM_AS_BITMASK can be used to declare an enum type as a bit
46/// set, so that bitwise operation on such enum does not require static_cast.
47///
48/// \code
49/// enum MyEnum { E1 = 1, E2 = 2, E3 = 4, E4 = 8 };
50/// LLVM_DECLARE_ENUM_AS_BITMASK(MyEnum, E4);
51///
52/// void Foo() {
53/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // No static_cast
54/// }
55/// \endcode
56///
57/// The second parameter to LLVM_DECLARE_ENUM_AS_BITMASK specifies the largest
58/// bit value of the enum type.
59///
60/// LLVM_DECLARE_ENUM_AS_BITMASK should be used in llvm namespace.
61///
62/// This a non-intrusive alternative for LLVM_MARK_AS_BITMASK_ENUM. It allows
63/// declaring more than one non-scoped enumerations as bitmask types in the same
64/// scope. Otherwise it provides the same functionality as
65/// LLVM_MARK_AS_BITMASK_ENUM.
66#define LLVM_DECLARE_ENUM_AS_BITMASK(Enum, LargestValue) \
67 template <> struct is_bitmask_enum<Enum> : std::true_type {}; \
68 template <> struct largest_bitmask_enum_bit<Enum> { \
69 static constexpr std::underlying_type_t<Enum> value = LargestValue; \
70 }
71
72/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used
73/// by LLVM_MARK_AS_BITMASK_ENUM into the current namespace.
74///
75/// Suppose you have an enum foo::bar::MyEnum. Before using
76/// LLVM_MARK_AS_BITMASK_ENUM on MyEnum, you must put
77/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() somewhere inside namespace foo or
78/// namespace foo::bar. This allows the relevant operator overloads to be found
79/// by ADL.
80///
81/// You don't need to use this macro in namespace llvm; it's done at the bottom
82/// of this file.
83#define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() \
84 using ::llvm::BitmaskEnumDetail::operator~; \
85 using ::llvm::BitmaskEnumDetail::operator|; \
86 using ::llvm::BitmaskEnumDetail::operator&; \
87 using ::llvm::BitmaskEnumDetail::operator^; \
88 using ::llvm::BitmaskEnumDetail::operator<<; \
89 using ::llvm::BitmaskEnumDetail::operator>>; \
90 using ::llvm::BitmaskEnumDetail::operator|=; \
91 using ::llvm::BitmaskEnumDetail::operator&=; \
92 using ::llvm::BitmaskEnumDetail::operator^=; \
93 using ::llvm::BitmaskEnumDetail::operator<<=; \
94 using ::llvm::BitmaskEnumDetail::operator>>=; \
95/* Force a semicolon at the end of this macro. */ \
96 using ::llvm::BitmaskEnumDetail::any
97
98namespacellvm {
99
100/// Traits class to determine whether an enum has a
101/// LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
102template <typename E,typename Enable =void>
103structis_bitmask_enum : std::false_type {};
104
105template <typename E>
106structis_bitmask_enum<
107E,std::enable_if_t<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >= 0>>
108 : std::true_type {};
109
110/// Trait class to determine bitmask enumeration largest bit.
111template <typename E,typename Enable =void>structlargest_bitmask_enum_bit;
112
113template <typename E>
114structlargest_bitmask_enum_bit<
115E,std::enable_if_t<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >= 0>> {
116usingUnderlyingTy = std::underlying_type_t<E>;
117staticconstexprUnderlyingTyvalue =
118static_cast<UnderlyingTy>(E::LLVM_BITMASK_LARGEST_ENUMERATOR);
119};
120
121namespaceBitmaskEnumDetail {
122
123/// Get a bitmask with 1s in all places up to the high-order bit of E's largest
124/// value.
125template <typename E>constexpr std::underlying_type_t<E>Mask() {
126// On overflow, NextPowerOf2 returns zero with the type uint64_t, so
127// subtracting 1 gives us the mask with all bits set, like we want.
128returnNextPowerOf2(largest_bitmask_enum_bit<E>::value) - 1;
129}
130
131/// Check that Val is in range for E, and return Val cast to E's underlying
132/// type.
133template <typename E>constexpr std::underlying_type_t<E>Underlying(E Val) {
134auto U =llvm::to_underlying(Val);
135assert(U >= 0 &&"Negative enum values are not allowed.");
136assert(U <= Mask<E>() &&"Enum value too large (or largest val too small?)");
137return U;
138}
139
140constexprunsignedbitWidth(uint64_tValue) {
141returnValue ? 1 +bitWidth(Value >> 1) : 0;
142}
143
144template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
145constexprboolany(E Val) {
146return Val !=static_cast<E>(0);
147}
148
149template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
150constexprEoperator~(E Val) {
151returnstatic_cast<E>(~Underlying(Val) & Mask<E>());
152}
153
154template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
155constexprEoperator|(ELHS,ERHS) {
156returnstatic_cast<E>(Underlying(LHS) |Underlying(RHS));
157}
158
159template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
160constexprEoperator&(ELHS,ERHS) {
161returnstatic_cast<E>(Underlying(LHS) &Underlying(RHS));
162}
163
164template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
165constexprEoperator^(ELHS,ERHS) {
166returnstatic_cast<E>(Underlying(LHS) ^Underlying(RHS));
167}
168
169template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
170constexprEoperator<<(ELHS,ERHS) {
171returnstatic_cast<E>(Underlying(LHS) <<Underlying(RHS));
172}
173
174template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
175constexprEoperator>>(ELHS,ERHS) {
176returnstatic_cast<E>(Underlying(LHS) >>Underlying(RHS));
177}
178
179// |=, &=, and ^= return a reference to LHS, to match the behavior of the
180// operators on builtin types.
181
182template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
183E &operator|=(E &LHS,ERHS) {
184LHS =LHS |RHS;
185returnLHS;
186}
187
188template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
189E &operator&=(E &LHS,ERHS) {
190LHS =LHS &RHS;
191returnLHS;
192}
193
194template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
195E &operator^=(E &LHS,ERHS) {
196LHS =LHS ^RHS;
197returnLHS;
198}
199
200template <typename e, typename = std::enable_if_t<is_bitmask_enum<e>::value>>
201e &operator<<=(e &lhs, e rhs) {
202 lhs = lhs << rhs;
203return lhs;
204}
205
206template <typename e, typename = std::enable_if_t<is_bitmask_enum<e>::value>>
207e &operator>>=(e &lhs, e rhs) {
208 lhs = lhs >> rhs;
209return lhs;
210}
211
212}// namespace BitmaskEnumDetail
213
214// Enable bitmask enums in namespace ::llvm and all nested namespaces.
215LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
216template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
217constexprunsignedBitWidth =BitmaskEnumDetail::bitWidth(
218uint64_t{llvm::to_underlying(E::LLVM_BITMASK_LARGEST_ENUMERATOR)});
219
220}// namespace llvm
221
222#endif
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
value
Given that RA is a live value
Definition:DeadArgumentElimination.cpp:716
MathExtras.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
STLForwardCompat.h
This file contains library features backported from future STL versions.
RHS
Value * RHS
Definition:X86PartialReduction.cpp:74
LHS
Value * LHS
Definition:X86PartialReduction.cpp:73
llvm::Value
LLVM Value Representation.
Definition:Value.h:74
uint64_t
llvm::BitmaskEnumDetail::operator>>=
e & operator>>=(e &lhs, e rhs)
Definition:BitmaskEnum.h:207
llvm::BitmaskEnumDetail::operator>>
constexpr E operator>>(E LHS, E RHS)
Definition:BitmaskEnum.h:175
llvm::BitmaskEnumDetail::operator^
constexpr E operator^(E LHS, E RHS)
Definition:BitmaskEnum.h:165
llvm::BitmaskEnumDetail::any
constexpr bool any(E Val)
Definition:BitmaskEnum.h:145
llvm::BitmaskEnumDetail::operator~
constexpr E operator~(E Val)
Definition:BitmaskEnum.h:150
llvm::BitmaskEnumDetail::bitWidth
constexpr unsigned bitWidth(uint64_t Value)
Definition:BitmaskEnum.h:140
llvm::BitmaskEnumDetail::Underlying
constexpr std::underlying_type_t< E > Underlying(E Val)
Check that Val is in range for E, and return Val cast to E's underlying type.
Definition:BitmaskEnum.h:133
llvm::BitmaskEnumDetail::Mask
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition:BitmaskEnum.h:125
llvm::BitmaskEnumDetail::operator^=
E & operator^=(E &LHS, E RHS)
Definition:BitmaskEnum.h:195
llvm::BitmaskEnumDetail::operator&=
E & operator&=(E &LHS, E RHS)
Definition:BitmaskEnum.h:189
llvm::BitmaskEnumDetail::operator&
constexpr E operator&(E LHS, E RHS)
Definition:BitmaskEnum.h:160
llvm::BitmaskEnumDetail::operator<<=
e & operator<<=(e &lhs, e rhs)
Definition:BitmaskEnum.h:201
llvm::BitmaskEnumDetail::operator<<
constexpr E operator<<(E LHS, E RHS)
Definition:BitmaskEnum.h:170
llvm::BitmaskEnumDetail::operator|=
E & operator|=(E &LHS, E RHS)
Definition:BitmaskEnum.h:183
llvm::BitmaskEnumDetail::operator|
constexpr E operator|(E LHS, E RHS)
Definition:BitmaskEnum.h:155
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
llvm::to_underlying
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
Definition:STLForwardCompat.h:66
llvm::BitWidth
constexpr unsigned BitWidth
Definition:BitmaskEnum.h:217
llvm::NextPowerOf2
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition:MathExtras.h:383
std
Implement std::hash so that hash_code can be used in STL containers.
Definition:BitVector.h:858
llvm::is_bitmask_enum
Traits class to determine whether an enum has a LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
Definition:BitmaskEnum.h:103
llvm::largest_bitmask_enum_bit< E, std::enable_if_t< sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >=0 >::UnderlyingTy
std::underlying_type_t< E > UnderlyingTy
Definition:BitmaskEnum.h:116
llvm::largest_bitmask_enum_bit
Trait class to determine bitmask enumeration largest bit.
Definition:BitmaskEnum.h:111

Generated on Thu Jul 17 2025 03:52:02 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp