//===- llvm/ADT/PointerSumType.h --------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_POINTERSUMTYPE_H #define LLVM_ADT_POINTERSUMTYPE_H #include "llvm/ADT/bit.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> #include <cstdint> #include <type_traits> namespace llvm { /// A compile time pair of an integer tag and the pointer-like type which it /// indexes within a sum type. Also allows the user to specify a particular /// traits class for pointer types with custom behavior such as over-aligned /// allocation. template <uintptr_t N, typename PointerArgT, typename TraitsArgT = PointerLikeTypeTraits<PointerArgT>> struct PointerSumTypeMember { enum { Tag = N }; using PointerT = PointerArgT; using TraitsT = TraitsArgT; }; namespace detail { template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper; } // end namespace detail /// A sum type over pointer-like types. /// /// This is a normal tagged union across pointer-like types that uses the low /// bits of the pointers to store the tag. /// /// Each member of the sum type is specified by passing a \c /// PointerSumTypeMember specialization in the variadic member argument list. /// This allows the user to control the particular tag value associated with /// a particular type, use the same type for multiple different tags, and /// customize the pointer-like traits used for a particular member. Note that /// these *must* be specializations of \c PointerSumTypeMember, no other type /// will suffice, even if it provides a compatible interface. /// /// This type implements all of the comparison operators and even hash table /// support by comparing the underlying storage of the pointer values. It /// doesn't support delegating to particular members for comparisons. /// /// It also default constructs to a zero tag with a null pointer, whatever that /// would be. This means that the zero value for the tag type is significant /// and may be desirable to set to a state that is particularly desirable to /// default construct. /// /// Having a supported zero-valued tag also enables getting the address of a /// pointer stored with that tag provided it is stored in its natural bit /// representation. This works because in the case of a zero-valued tag, the /// pointer's value is directly stored into this object and we can expose the /// address of that internal storage. This is especially useful when building an /// `ArrayRef` of a single pointer stored in a sum type. /// /// There is no support for constructing or accessing with a dynamic tag as /// that would fundamentally violate the type safety provided by the sum type. template <typename TagT, typename... MemberTs> class PointerSumType { … }; namespace detail { /// A helper template for implementing \c PointerSumType. It provides fast /// compile-time lookup of the member from a particular tag value, along with /// useful constants and compile time checking infrastructure.. template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper : MemberTs... { … }; } // end namespace detail // Teach DenseMap how to use PointerSumTypes as keys. DenseMapInfo<PointerSumType<TagT, MemberTs...>>; } // end namespace llvm #endif // LLVM_ADT_POINTERSUMTYPE_H