Common.h (8057B)
1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #ifndef COMPILER_TRANSLATOR_COMMON_H_ 8 #define COMPILER_TRANSLATOR_COMMON_H_ 9 10 #include <stdio.h> 11 #include <limits> 12 #include <map> 13 #include <sstream> 14 #include <string> 15 #include <unordered_map> 16 #include <vector> 17 18 #include "common/angleutils.h" 19 #include "common/debug.h" 20 #include "common/third_party/smhasher/src/PMurHash.h" 21 #include "compiler/translator/PoolAlloc.h" 22 23 namespace sh 24 { 25 26 struct TSourceLoc 27 { 28 int first_file; 29 int first_line; 30 int last_file; 31 int last_line; 32 }; 33 34 constexpr TSourceLoc kNoSourceLoc{-1, -1, -1, -1}; 35 36 // 37 // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. 38 // 39 #define POOL_ALLOCATOR_NEW_DELETE \ 40 void *operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ 41 void *operator new(size_t, void *_Where) { return (_Where); } \ 42 void operator delete(void *) {} \ 43 void operator delete(void *, void *) {} \ 44 void *operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ 45 void *operator new[](size_t, void *_Where) { return (_Where); } \ 46 void operator delete[](void *) {} \ 47 void operator delete[](void *, void *) {} 48 49 // 50 // Pool version of string. 51 // 52 typedef pool_allocator<char> TStringAllocator; 53 typedef std::basic_string<char, std::char_traits<char>, TStringAllocator> TString; 54 typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; 55 56 // 57 // Persistent memory. Should only be used for strings that survive across compiles. 58 // 59 using TPersistString = std::string; 60 using TPersistStringStream = std::ostringstream; 61 62 // 63 // Pool allocator versions of vectors, lists, and maps 64 // 65 template <class T> 66 class TVector : public std::vector<T, pool_allocator<T>> 67 { 68 public: 69 POOL_ALLOCATOR_NEW_DELETE 70 71 typedef typename std::vector<T, pool_allocator<T>>::size_type size_type; 72 TVector() : std::vector<T, pool_allocator<T>>() {} 73 TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {} 74 TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {} 75 TVector(size_type i, const T &value) : std::vector<T, pool_allocator<T>>(i, value) {} 76 template <typename InputIt> 77 TVector(InputIt first, InputIt last) : std::vector<T, pool_allocator<T>>(first, last) 78 {} 79 TVector(std::initializer_list<T> init) : std::vector<T, pool_allocator<T>>(init) {} 80 }; 81 82 template <class K, class D, class H = std::hash<K>, class CMP = std::equal_to<K>> 83 class TUnorderedMap : public std::unordered_map<K, D, H, CMP, pool_allocator<std::pair<const K, D>>> 84 { 85 public: 86 POOL_ALLOCATOR_NEW_DELETE 87 typedef pool_allocator<std::pair<const K, D>> tAllocator; 88 89 TUnorderedMap() : std::unordered_map<K, D, H, CMP, tAllocator>() {} 90 // use correct two-stage name lookup supported in gcc 3.4 and above 91 TUnorderedMap(const tAllocator &a) 92 : std::unordered_map<K, D, H, CMP, tAllocator>( 93 std::unordered_map<K, D, H, CMP, tAllocator>::key_compare(), 94 a) 95 {} 96 }; 97 98 template <class K, class D, class CMP = std::less<K>> 99 class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>> 100 { 101 public: 102 POOL_ALLOCATOR_NEW_DELETE 103 typedef pool_allocator<std::pair<const K, D>> tAllocator; 104 105 TMap() : std::map<K, D, CMP, tAllocator>() {} 106 // use correct two-stage name lookup supported in gcc 3.4 and above 107 TMap(const tAllocator &a) 108 : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) 109 {} 110 }; 111 112 // Basic implementation of C++20's span for use with pool-allocated containers (TVector) or static 113 // arrays. This is used by the array sizes member of TType to allow arrayed types to be 114 // constexpr-constructed. 115 // See the reference for std::span here: https://en.cppreference.com/w/cpp/container/span 116 template <typename T> 117 class TSpan 118 { 119 public: 120 typedef size_t size_type; 121 122 constexpr TSpan() {} 123 constexpr TSpan(T *ptr, size_type size) : mData(ptr), mSize(size) {} 124 125 constexpr TSpan(const TSpan &that) : mData(that.mData), mSize(that.mSize) {} 126 constexpr TSpan &operator=(const TSpan &that) 127 { 128 mData = that.mData; 129 mSize = that.mSize; 130 return *this; 131 } 132 133 // Note: the pointer is taken out of the TVector because TVector's memory is pool allocated, 134 // so the memory will live on even if the TVector is destroyed. 135 template <typename S> 136 TSpan(const TVector<S> &vec) : mData(vec.data()), mSize(vec.size()) 137 {} 138 template <typename S> 139 TSpan &operator=(const TVector<S> &vec) 140 { 141 mData = vec.data(); 142 mSize = vec.size(); 143 return *this; 144 } 145 146 constexpr bool operator==(const TSpan &that) const 147 { 148 if (mSize != that.mSize) 149 { 150 return false; 151 } 152 153 if (mData == that.mData) 154 { 155 return true; 156 } 157 158 for (size_type index = 0; index < mSize; ++index) 159 { 160 if (mData[index] != that.mData[index]) 161 { 162 return false; 163 } 164 } 165 166 return true; 167 } 168 constexpr bool operator!=(const TSpan &that) const { return !(*this == that); } 169 170 constexpr T *data() const { return mData; } 171 constexpr size_type size() const { return mSize; } 172 constexpr bool empty() const { return mSize == 0; } 173 174 constexpr T &operator[](size_type index) const { return mData[index]; } 175 constexpr T &front() const { return mData[0]; } 176 constexpr T &back() const { return mData[mSize - 1]; } 177 178 constexpr T *begin() const { return mData; } 179 constexpr T *end() const { return mData + mSize; } 180 181 constexpr std::reverse_iterator<T *> rbegin() const 182 { 183 return std::make_reverse_iterator(end()); 184 } 185 constexpr std::reverse_iterator<T *> rend() const 186 { 187 return std::make_reverse_iterator(begin()); 188 } 189 190 constexpr TSpan first(size_type count) const 191 { 192 ASSERT(count <= mSize); 193 return count == 0 ? TSpan() : TSpan(mData, count); 194 } 195 constexpr TSpan last(size_type count) const 196 { 197 ASSERT(count <= mSize); 198 return count == 0 ? TSpan() : TSpan(mData + mSize - count, count); 199 } 200 constexpr TSpan subspan(size_type offset, size_type count) const 201 { 202 ASSERT(offset + count <= mSize); 203 return count == 0 ? TSpan() : TSpan(mData + offset, count); 204 } 205 206 private: 207 T *mData = nullptr; 208 size_t mSize = 0; 209 }; 210 211 // Integer to TString conversion 212 template <typename T> 213 inline TString str(T i) 214 { 215 ASSERT(std::numeric_limits<T>::is_integer); 216 char buffer[((8 * sizeof(T)) / 3) + 3]; 217 const char *formatStr = std::numeric_limits<T>::is_signed ? "%d" : "%u"; 218 snprintf(buffer, sizeof(buffer), formatStr, i); 219 return buffer; 220 } 221 222 // Allocate a char array in the global memory pool. str must be a null terminated string. strLength 223 // is the length without the null terminator. 224 inline const char *AllocatePoolCharArray(const char *str, size_t strLength) 225 { 226 size_t requiredSize = strLength + 1; 227 char *buffer = static_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize)); 228 memcpy(buffer, str, requiredSize); 229 ASSERT(buffer[strLength] == '\0'); 230 return buffer; 231 } 232 233 // Initialize a new stream which must be imbued with the classic locale 234 template <typename T> 235 T InitializeStream() 236 { 237 T stream; 238 stream.imbue(std::locale::classic()); 239 return stream; 240 } 241 242 } // namespace sh 243 244 namespace std 245 { 246 template <> 247 struct hash<sh::TString> 248 { 249 size_t operator()(const sh::TString &s) const 250 { 251 return angle::PMurHash32(0, s.data(), static_cast<int>(s.length())); 252 } 253 }; 254 } // namespace std 255 256 #endif // COMPILER_TRANSLATOR_COMMON_H_