Home | History | Annotate | Download | only in ADT
      1 //===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines DenseMapInfo traits for DenseMap.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_ADT_DENSEMAPINFO_H
     15 #define LLVM_ADT_DENSEMAPINFO_H
     16 
     17 #include "llvm/ADT/ArrayRef.h"
     18 #include "llvm/ADT/Hashing.h"
     19 #include "llvm/ADT/StringRef.h"
     20 #include "llvm/Support/PointerLikeTypeTraits.h"
     21 #include <cassert>
     22 #include <cstddef>
     23 #include <cstdint>
     24 #include <utility>
     25 
     26 namespace llvm {
     27 
     28 template<typename T>
     29 struct DenseMapInfo {
     30   //static inline T getEmptyKey();
     31   //static inline T getTombstoneKey();
     32   //static unsigned getHashValue(const T &Val);
     33   //static bool isEqual(const T &LHS, const T &RHS);
     34 };
     35 
     36 // Provide DenseMapInfo for all pointers.
     37 template<typename T>
     38 struct DenseMapInfo<T*> {
     39   static inline T* getEmptyKey() {
     40     uintptr_t Val = static_cast<uintptr_t>(-1);
     41     Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
     42     return reinterpret_cast<T*>(Val);
     43   }
     44 
     45   static inline T* getTombstoneKey() {
     46     uintptr_t Val = static_cast<uintptr_t>(-2);
     47     Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
     48     return reinterpret_cast<T*>(Val);
     49   }
     50 
     51   static unsigned getHashValue(const T *PtrVal) {
     52     return (unsigned((uintptr_t)PtrVal) >> 4) ^
     53            (unsigned((uintptr_t)PtrVal) >> 9);
     54   }
     55 
     56   static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
     57 };
     58 
     59 // Provide DenseMapInfo for chars.
     60 template<> struct DenseMapInfo<char> {
     61   static inline char getEmptyKey() { return ~0; }
     62   static inline char getTombstoneKey() { return ~0 - 1; }
     63   static unsigned getHashValue(const char& Val) { return Val * 37U; }
     64 
     65   static bool isEqual(const char &LHS, const char &RHS) {
     66     return LHS == RHS;
     67   }
     68 };
     69 
     70 // Provide DenseMapInfo for unsigned shorts.
     71 template <> struct DenseMapInfo<unsigned short> {
     72   static inline unsigned short getEmptyKey() { return 0xFFFF; }
     73   static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
     74   static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
     75 
     76   static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
     77     return LHS == RHS;
     78   }
     79 };
     80 
     81 // Provide DenseMapInfo for unsigned ints.
     82 template<> struct DenseMapInfo<unsigned> {
     83   static inline unsigned getEmptyKey() { return ~0U; }
     84   static inline unsigned getTombstoneKey() { return ~0U - 1; }
     85   static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
     86 
     87   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
     88     return LHS == RHS;
     89   }
     90 };
     91 
     92 // Provide DenseMapInfo for unsigned longs.
     93 template<> struct DenseMapInfo<unsigned long> {
     94   static inline unsigned long getEmptyKey() { return ~0UL; }
     95   static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
     96 
     97   static unsigned getHashValue(const unsigned long& Val) {
     98     return (unsigned)(Val * 37UL);
     99   }
    100 
    101   static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
    102     return LHS == RHS;
    103   }
    104 };
    105 
    106 // Provide DenseMapInfo for unsigned long longs.
    107 template<> struct DenseMapInfo<unsigned long long> {
    108   static inline unsigned long long getEmptyKey() { return ~0ULL; }
    109   static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
    110 
    111   static unsigned getHashValue(const unsigned long long& Val) {
    112     return (unsigned)(Val * 37ULL);
    113   }
    114 
    115   static bool isEqual(const unsigned long long& LHS,
    116                       const unsigned long long& RHS) {
    117     return LHS == RHS;
    118   }
    119 };
    120 
    121 // Provide DenseMapInfo for shorts.
    122 template <> struct DenseMapInfo<short> {
    123   static inline short getEmptyKey() { return 0x7FFF; }
    124   static inline short getTombstoneKey() { return -0x7FFF - 1; }
    125   static unsigned getHashValue(const short &Val) { return Val * 37U; }
    126   static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
    127 };
    128 
    129 // Provide DenseMapInfo for ints.
    130 template<> struct DenseMapInfo<int> {
    131   static inline int getEmptyKey() { return 0x7fffffff; }
    132   static inline int getTombstoneKey() { return -0x7fffffff - 1; }
    133   static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
    134 
    135   static bool isEqual(const int& LHS, const int& RHS) {
    136     return LHS == RHS;
    137   }
    138 };
    139 
    140 // Provide DenseMapInfo for longs.
    141 template<> struct DenseMapInfo<long> {
    142   static inline long getEmptyKey() {
    143     return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
    144   }
    145 
    146   static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
    147 
    148   static unsigned getHashValue(const long& Val) {
    149     return (unsigned)(Val * 37UL);
    150   }
    151 
    152   static bool isEqual(const long& LHS, const long& RHS) {
    153     return LHS == RHS;
    154   }
    155 };
    156 
    157 // Provide DenseMapInfo for long longs.
    158 template<> struct DenseMapInfo<long long> {
    159   static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
    160   static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
    161 
    162   static unsigned getHashValue(const long long& Val) {
    163     return (unsigned)(Val * 37ULL);
    164   }
    165 
    166   static bool isEqual(const long long& LHS,
    167                       const long long& RHS) {
    168     return LHS == RHS;
    169   }
    170 };
    171 
    172 // Provide DenseMapInfo for all pairs whose members have info.
    173 template<typename T, typename U>
    174 struct DenseMapInfo<std::pair<T, U>> {
    175   using Pair = std::pair<T, U>;
    176   using FirstInfo = DenseMapInfo<T>;
    177   using SecondInfo = DenseMapInfo<U>;
    178 
    179   static inline Pair getEmptyKey() {
    180     return std::make_pair(FirstInfo::getEmptyKey(),
    181                           SecondInfo::getEmptyKey());
    182   }
    183 
    184   static inline Pair getTombstoneKey() {
    185     return std::make_pair(FirstInfo::getTombstoneKey(),
    186                           SecondInfo::getTombstoneKey());
    187   }
    188 
    189   static unsigned getHashValue(const Pair& PairVal) {
    190     uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
    191           | (uint64_t)SecondInfo::getHashValue(PairVal.second);
    192     key += ~(key << 32);
    193     key ^= (key >> 22);
    194     key += ~(key << 13);
    195     key ^= (key >> 8);
    196     key += (key << 3);
    197     key ^= (key >> 15);
    198     key += ~(key << 27);
    199     key ^= (key >> 31);
    200     return (unsigned)key;
    201   }
    202 
    203   static bool isEqual(const Pair &LHS, const Pair &RHS) {
    204     return FirstInfo::isEqual(LHS.first, RHS.first) &&
    205            SecondInfo::isEqual(LHS.second, RHS.second);
    206   }
    207 };
    208 
    209 // Provide DenseMapInfo for StringRefs.
    210 template <> struct DenseMapInfo<StringRef> {
    211   static inline StringRef getEmptyKey() {
    212     return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
    213                      0);
    214   }
    215 
    216   static inline StringRef getTombstoneKey() {
    217     return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
    218                      0);
    219   }
    220 
    221   static unsigned getHashValue(StringRef Val) {
    222     assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
    223     assert(Val.data() != getTombstoneKey().data() &&
    224            "Cannot hash the tombstone key!");
    225     return (unsigned)(hash_value(Val));
    226   }
    227 
    228   static bool isEqual(StringRef LHS, StringRef RHS) {
    229     if (RHS.data() == getEmptyKey().data())
    230       return LHS.data() == getEmptyKey().data();
    231     if (RHS.data() == getTombstoneKey().data())
    232       return LHS.data() == getTombstoneKey().data();
    233     return LHS == RHS;
    234   }
    235 };
    236 
    237 // Provide DenseMapInfo for ArrayRefs.
    238 template <typename T> struct DenseMapInfo<ArrayRef<T>> {
    239   static inline ArrayRef<T> getEmptyKey() {
    240     return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
    241                        size_t(0));
    242   }
    243 
    244   static inline ArrayRef<T> getTombstoneKey() {
    245     return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
    246                        size_t(0));
    247   }
    248 
    249   static unsigned getHashValue(ArrayRef<T> Val) {
    250     assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
    251     assert(Val.data() != getTombstoneKey().data() &&
    252            "Cannot hash the tombstone key!");
    253     return (unsigned)(hash_value(Val));
    254   }
    255 
    256   static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
    257     if (RHS.data() == getEmptyKey().data())
    258       return LHS.data() == getEmptyKey().data();
    259     if (RHS.data() == getTombstoneKey().data())
    260       return LHS.data() == getTombstoneKey().data();
    261     return LHS == RHS;
    262   }
    263 };
    264 
    265 } // end namespace llvm
    266 
    267 #endif // LLVM_ADT_DENSEMAPINFO_H
    268