Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- llvm/ADT/PointerEmbeddedInt.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_POINTEREMBEDDEDINT_H
0010 #define LLVM_ADT_POINTEREMBEDDEDINT_H
0011 
0012 #include "llvm/ADT/DenseMapInfo.h"
0013 #include "llvm/Support/MathExtras.h"
0014 #include "llvm/Support/PointerLikeTypeTraits.h"
0015 #include <cassert>
0016 #include <climits>
0017 #include <cstdint>
0018 #include <type_traits>
0019 
0020 namespace llvm {
0021 
0022 /// Utility to embed an integer into a pointer-like type. This is specifically
0023 /// intended to allow embedding integers where fewer bits are required than
0024 /// exist in a pointer, and the integer can participate in abstractions along
0025 /// side other pointer-like types. For example it can be placed into a \c
0026 /// PointerSumType or \c PointerUnion.
0027 ///
0028 /// Note that much like pointers, an integer value of zero has special utility
0029 /// due to boolean conversions. For example, a non-null value can be tested for
0030 /// in the above abstractions without testing the particular active member.
0031 /// Also, the default constructed value zero initializes the integer.
0032 template <typename IntT, int Bits = sizeof(IntT) * CHAR_BIT>
0033 class PointerEmbeddedInt {
0034   uintptr_t Value = 0;
0035 
0036   // Note: This '<' is correct; using '<=' would result in some shifts
0037   // overflowing their storage types.
0038   static_assert(Bits < sizeof(uintptr_t) * CHAR_BIT,
0039                 "Cannot embed more bits than we have in a pointer!");
0040 
0041   enum : uintptr_t {
0042     // We shift as many zeros into the value as we can while preserving the
0043     // number of bits desired for the integer.
0044     Shift = sizeof(uintptr_t) * CHAR_BIT - Bits,
0045 
0046     // We also want to be able to mask out the preserved bits for asserts.
0047     Mask = static_cast<uintptr_t>(-1) << Bits
0048   };
0049 
0050   struct RawValueTag {
0051     explicit RawValueTag() = default;
0052   };
0053 
0054   friend struct PointerLikeTypeTraits<PointerEmbeddedInt>;
0055 
0056   explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {}
0057 
0058 public:
0059   PointerEmbeddedInt() = default;
0060 
0061   PointerEmbeddedInt(IntT I) { *this = I; }
0062 
0063   PointerEmbeddedInt &operator=(IntT I) {
0064     assert((std::is_signed<IntT>::value ? isInt<Bits>(I) : isUInt<Bits>(I)) &&
0065            "Integer has bits outside those preserved!");
0066     Value = static_cast<uintptr_t>(I) << Shift;
0067     return *this;
0068   }
0069 
0070   // Note that this implicit conversion additionally allows all of the basic
0071   // comparison operators to work transparently, etc.
0072   operator IntT() const {
0073     if (std::is_signed<IntT>::value)
0074       return static_cast<IntT>(static_cast<intptr_t>(Value) >> Shift);
0075     return static_cast<IntT>(Value >> Shift);
0076   }
0077 };
0078 
0079 // Provide pointer like traits to support use with pointer unions and sum
0080 // types.
0081 template <typename IntT, int Bits>
0082 struct PointerLikeTypeTraits<PointerEmbeddedInt<IntT, Bits>> {
0083   using T = PointerEmbeddedInt<IntT, Bits>;
0084 
0085   static inline void *getAsVoidPointer(const T &P) {
0086     return reinterpret_cast<void *>(P.Value);
0087   }
0088 
0089   static inline T getFromVoidPointer(void *P) {
0090     return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
0091   }
0092 
0093   static inline T getFromVoidPointer(const void *P) {
0094     return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
0095   }
0096 
0097   static constexpr int NumLowBitsAvailable = T::Shift;
0098 };
0099 
0100 // Teach DenseMap how to use PointerEmbeddedInt objects as keys if the Int type
0101 // itself can be a key.
0102 template <typename IntT, int Bits>
0103 struct DenseMapInfo<PointerEmbeddedInt<IntT, Bits>> {
0104   using T = PointerEmbeddedInt<IntT, Bits>;
0105   using IntInfo = DenseMapInfo<IntT>;
0106 
0107   static inline T getEmptyKey() { return IntInfo::getEmptyKey(); }
0108   static inline T getTombstoneKey() { return IntInfo::getTombstoneKey(); }
0109 
0110   static unsigned getHashValue(const T &Arg) {
0111     return IntInfo::getHashValue(Arg);
0112   }
0113 
0114   static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; }
0115 };
0116 
0117 } // end namespace llvm
0118 
0119 #endif // LLVM_ADT_POINTEREMBEDDEDINT_H