File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ADT_POINTERSUMTYPE_H
0010 #define LLVM_ADT_POINTERSUMTYPE_H
0011
0012 #include "llvm/ADT/bit.h"
0013 #include "llvm/ADT/DenseMapInfo.h"
0014 #include "llvm/Support/PointerLikeTypeTraits.h"
0015 #include <cassert>
0016 #include <cstdint>
0017 #include <type_traits>
0018
0019 namespace llvm {
0020
0021
0022
0023
0024
0025 template <uintptr_t N, typename PointerArgT,
0026 typename TraitsArgT = PointerLikeTypeTraits<PointerArgT>>
0027 struct PointerSumTypeMember {
0028 enum { Tag = N };
0029 using PointerT = PointerArgT;
0030 using TraitsT = TraitsArgT;
0031 };
0032
0033 namespace detail {
0034
0035 template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper;
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 template <typename TagT, typename... MemberTs> class PointerSumType {
0071 using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>;
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 union StorageT {
0083
0084
0085
0086 StorageT() : Value(0) {}
0087
0088 uintptr_t Value;
0089
0090 typename HelperT::template Lookup<HelperT::MinTag>::PointerT MinTagPointer;
0091 };
0092
0093 StorageT Storage;
0094
0095 public:
0096 constexpr PointerSumType() = default;
0097
0098
0099 template <TagT N>
0100 void set(typename HelperT::template Lookup<N>::PointerT Pointer) {
0101 void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer);
0102 assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 &&
0103 "Pointer is insufficiently aligned to store the discriminant!");
0104 Storage.Value = reinterpret_cast<uintptr_t>(V) | N;
0105 }
0106
0107
0108 template <TagT N>
0109 static PointerSumType
0110 create(typename HelperT::template Lookup<N>::PointerT Pointer) {
0111 PointerSumType Result;
0112 Result.set<N>(Pointer);
0113 return Result;
0114 }
0115
0116
0117 void clear() { set<HelperT::MinTag>(nullptr); }
0118
0119 TagT getTag() const {
0120 return static_cast<TagT>(getOpaqueValue() & HelperT::TagMask);
0121 }
0122
0123 template <TagT N> bool is() const { return N == getTag(); }
0124
0125 template <TagT N> typename HelperT::template Lookup<N>::PointerT get() const {
0126 void *P = is<N>() ? getVoidPtr() : nullptr;
0127 return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(P);
0128 }
0129
0130 template <TagT N>
0131 typename HelperT::template Lookup<N>::PointerT cast() const {
0132 assert(is<N>() && "This instance has a different active member.");
0133 return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(
0134 getVoidPtr());
0135 }
0136
0137
0138
0139
0140 typename HelperT::template Lookup<HelperT::MinTag>::PointerT const *
0141 getAddrOfZeroTagPointer() const {
0142 return const_cast<PointerSumType *>(this)->getAddrOfZeroTagPointer();
0143 }
0144
0145
0146
0147
0148 typename HelperT::template Lookup<HelperT::MinTag>::PointerT *
0149 getAddrOfZeroTagPointer() {
0150 static_assert(HelperT::MinTag == 0, "Non-zero minimum tag value!");
0151 assert(is<HelperT::MinTag>() && "The active tag is not zero!");
0152
0153 auto InitialPtr = get<HelperT::MinTag>();
0154
0155
0156
0157 Storage.MinTagPointer = InitialPtr;
0158
0159
0160 assert(InitialPtr == get<HelperT::MinTag>() &&
0161 "Switching to typed storage changed the pointer returned!");
0162
0163 return &Storage.MinTagPointer;
0164 }
0165
0166 explicit operator bool() const {
0167 return getOpaqueValue() & HelperT::PointerMask;
0168 }
0169 bool operator==(const PointerSumType &R) const {
0170 return getOpaqueValue() == R.getOpaqueValue();
0171 }
0172 bool operator!=(const PointerSumType &R) const {
0173 return getOpaqueValue() != R.getOpaqueValue();
0174 }
0175 bool operator<(const PointerSumType &R) const {
0176 return getOpaqueValue() < R.getOpaqueValue();
0177 }
0178 bool operator>(const PointerSumType &R) const {
0179 return getOpaqueValue() > R.getOpaqueValue();
0180 }
0181 bool operator<=(const PointerSumType &R) const {
0182 return getOpaqueValue() <= R.getOpaqueValue();
0183 }
0184 bool operator>=(const PointerSumType &R) const {
0185 return getOpaqueValue() >= R.getOpaqueValue();
0186 }
0187
0188 uintptr_t getOpaqueValue() const {
0189
0190
0191 return bit_cast<uintptr_t>(Storage);
0192 }
0193
0194 protected:
0195 void *getVoidPtr() const {
0196 return reinterpret_cast<void *>(getOpaqueValue() & HelperT::PointerMask);
0197 }
0198 };
0199
0200 namespace detail {
0201
0202
0203
0204
0205 template <typename TagT, typename... MemberTs>
0206 struct PointerSumTypeHelper : MemberTs... {
0207
0208
0209
0210
0211
0212 template <TagT N, typename PointerT, typename TraitsT>
0213 static PointerSumTypeMember<N, PointerT, TraitsT>
0214 LookupOverload(PointerSumTypeMember<N, PointerT, TraitsT> *);
0215 template <TagT N> static void LookupOverload(...);
0216 template <TagT N> struct Lookup {
0217
0218 using MemberT = decltype(
0219 LookupOverload<N>(static_cast<PointerSumTypeHelper *>(nullptr)));
0220
0221
0222 using PointerT = typename MemberT::PointerT;
0223
0224
0225 using TraitsT = typename MemberT::TraitsT;
0226 };
0227
0228
0229
0230
0231 template <uintptr_t V, uintptr_t... Vs>
0232 struct Min : std::integral_constant<
0233 uintptr_t, (V < Min<Vs...>::value ? V : Min<Vs...>::value)> {
0234 };
0235 template <uintptr_t V>
0236 struct Min<V> : std::integral_constant<uintptr_t, V> {};
0237 enum { NumTagBits = Min<MemberTs::TraitsT::NumLowBitsAvailable...>::value };
0238
0239
0240 constexpr static TagT MinTag =
0241 static_cast<TagT>(Min<MemberTs::Tag...>::value);
0242 enum : uint64_t {
0243 PointerMask = static_cast<uint64_t>(-1) << NumTagBits,
0244 TagMask = ~PointerMask
0245 };
0246
0247
0248
0249 template <typename MemberT, typename... InnerMemberTs>
0250 struct Checker : Checker<InnerMemberTs...> {
0251 static_assert(MemberT::Tag < (1 << NumTagBits),
0252 "This discriminant value requires too many bits!");
0253 };
0254 template <typename MemberT> struct Checker<MemberT> : std::true_type {
0255 static_assert(MemberT::Tag < (1 << NumTagBits),
0256 "This discriminant value requires too many bits!");
0257 };
0258 static_assert(Checker<MemberTs...>::value,
0259 "Each member must pass the checker.");
0260 };
0261
0262 }
0263
0264
0265 template <typename TagT, typename... MemberTs>
0266 struct DenseMapInfo<PointerSumType<TagT, MemberTs...>> {
0267 using SumType = PointerSumType<TagT, MemberTs...>;
0268 using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>;
0269 enum { SomeTag = HelperT::MinTag };
0270 using SomePointerT =
0271 typename HelperT::template Lookup<HelperT::MinTag>::PointerT;
0272 using SomePointerInfo = DenseMapInfo<SomePointerT>;
0273
0274 static inline SumType getEmptyKey() {
0275 return SumType::template create<SomeTag>(SomePointerInfo::getEmptyKey());
0276 }
0277
0278 static inline SumType getTombstoneKey() {
0279 return SumType::template create<SomeTag>(
0280 SomePointerInfo::getTombstoneKey());
0281 }
0282
0283 static unsigned getHashValue(const SumType &Arg) {
0284 uintptr_t OpaqueValue = Arg.getOpaqueValue();
0285 return DenseMapInfo<uintptr_t>::getHashValue(OpaqueValue);
0286 }
0287
0288 static bool isEqual(const SumType &LHS, const SumType &RHS) {
0289 return LHS == RHS;
0290 }
0291 };
0292
0293 }
0294
0295 #endif