9 #ifndef LLVM_ADT_POINTERSUMTYPE_H
10 #define LLVM_ADT_POINTERSUMTYPE_H
17 #include <type_traits>
25 template <uintptr_t
N,
typename PointerArgT,
26 typename TraitsArgT = PointerLikeTypeTraits<PointerArgT>>
86 StorageT() :
Value(0) {}
90 typename HelperT::template Lookup<HelperT::MinTag>::PointerT MinTagPointer;
100 void set(
typename HelperT::template Lookup<N>::PointerT Pointer) {
101 void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer);
103 "Pointer is insufficiently aligned to store the discriminant!");
104 Storage.Value =
reinterpret_cast<uintptr_t
>(V) |
N;
110 create(
typename HelperT::template Lookup<N>::PointerT Pointer) {
112 Result.set<
N>(Pointer);
117 void clear() { set<HelperT::MinTag>(
nullptr); }
123 template <TagT N>
bool is()
const {
return N ==
getTag(); }
125 template <TagT N>
typename HelperT::template Lookup<N>::PointerT
get()
const {
127 return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(
P);
131 typename HelperT::template Lookup<N>::PointerT
cast()
const {
132 assert(is<N>() &&
"This instance has a different active member.");
133 return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(
140 typename HelperT::template Lookup<HelperT::MinTag>::PointerT
const *
148 typename HelperT::template Lookup<HelperT::MinTag>::PointerT *
151 assert(is<HelperT::MinTag>() &&
"The active tag is not zero!");
153 auto InitialPtr = get<HelperT::MinTag>();
157 Storage.MinTagPointer = InitialPtr;
160 assert(InitialPtr == get<HelperT::MinTag>() &&
161 "Switching to typed storage changed the pointer returned!");
163 return &Storage.MinTagPointer;
166 explicit operator bool()
const {
191 return bit_cast<uintptr_t>(Storage);
205 template <
typename TagT,
typename... MemberTs>
206 struct PointerSumTypeHelper : MemberTs... {
212 template <TagT N,
typename Po
interT,
typename TraitsT>
213 static PointerSumTypeMember<N, PointerT, TraitsT>
231 template <uintptr_t V, uintptr_t... Vs>
232 struct Min : std::integral_constant<
233 uintptr_t, (V < Min<Vs...>::value ? V : Min<Vs...>::value)> {
235 template <uintptr_t V>
236 struct Min<V> : std::integral_constant<uintptr_t, V> {};
237 enum { NumTagBits = Min<MemberTs::TraitsT::NumLowBitsAvailable...>::value };
240 constexpr static TagT MinTag =
241 static_cast<TagT>(Min<MemberTs::Tag...>::value);
243 PointerMask = static_cast<uint64_t>(-1) << NumTagBits,
244 TagMask = ~PointerMask
249 template <typename MemberT, typename... InnerMemberTs>
250 struct Checker : Checker<InnerMemberTs...> {
251 static_assert(MemberT::Tag < (1 << NumTagBits),
252 "This discriminant value requires too many bits!");
254 template <typename MemberT> struct Checker<MemberT> : std::true_type {
255 static_assert(MemberT::Tag < (1 << NumTagBits),
256 "This discriminant value requires too many bits!");
258 static_assert(Checker<MemberTs...>::value,
259 "Each member must pass the checker.");
265 template <typename TagT, typename... MemberTs>
266 struct DenseMapInfo<PointerSumType<TagT, MemberTs...>> {
267 using SumType = PointerSumType<TagT, MemberTs...>;
268 using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>;
269 enum { SomeTag = HelperT::MinTag };
271 typename HelperT::template Lookup<HelperT::MinTag>::PointerT;
272 using SomePointerInfo = DenseMapInfo<SomePointerT>;
274 static inline SumType getEmptyKey() {
275 return SumType::template create<SomeTag>(SomePointerInfo::getEmptyKey());
278 static inline SumType getTombstoneKey() {
279 return SumType::template create<SomeTag>(
280 SomePointerInfo::getTombstoneKey());
283 static unsigned getHashValue(const SumType &Arg) {
284 uintptr_t OpaqueValue = Arg.getOpaqueValue();
285 return DenseMapInfo<uintptr_t>::getHashValue(OpaqueValue);
288 static bool isEqual(const SumType &LHS, const SumType &RHS) {