// // Copyright 2002 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #ifndef COMPILER_TRANSLATOR_COMMON_H_ #define COMPILER_TRANSLATOR_COMMON_H_ #include #include #include #include #include #include #include #include "common/angleutils.h" #include "common/debug.h" #include "common/third_party/smhasher/src/PMurHash.h" #include "compiler/translator/PoolAlloc.h" namespace sh { struct TSourceLoc { int first_file; int first_line; int last_file; int last_line; }; constexpr TSourceLoc kNoSourceLoc{-1, -1, -1, -1}; // // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // #define POOL_ALLOCATOR_NEW_DELETE \ void *operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ void *operator new(size_t, void *_Where) { return (_Where); } \ void operator delete(void *) {} \ void operator delete(void *, void *) {} \ void *operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ void *operator new[](size_t, void *_Where) { return (_Where); } \ void operator delete[](void *) {} \ void operator delete[](void *, void *) {} // // Pool version of string. // typedef pool_allocator TStringAllocator; typedef std::basic_string, TStringAllocator> TString; typedef std::basic_ostringstream, TStringAllocator> TStringStream; // // Persistent memory. Should only be used for strings that survive across compiles. // using TPersistString = std::string; using TPersistStringStream = std::ostringstream; // // Pool allocator versions of vectors, lists, and maps // template class TVector : public std::vector> { public: POOL_ALLOCATOR_NEW_DELETE typedef typename std::vector>::size_type size_type; TVector() : std::vector>() {} TVector(const pool_allocator &a) : std::vector>(a) {} TVector(size_type i) : std::vector>(i) {} TVector(size_type i, const T &value) : std::vector>(i, value) {} template TVector(InputIt first, InputIt last) : std::vector>(first, last) {} TVector(std::initializer_list init) : std::vector>(init) {} }; template , class CMP = std::equal_to> class TUnorderedMap : public std::unordered_map>> { public: POOL_ALLOCATOR_NEW_DELETE typedef pool_allocator> tAllocator; TUnorderedMap() : std::unordered_map() {} // use correct two-stage name lookup supported in gcc 3.4 and above TUnorderedMap(const tAllocator &a) : std::unordered_map( std::unordered_map::key_compare(), a) {} }; template > class TMap : public std::map>> { public: POOL_ALLOCATOR_NEW_DELETE typedef pool_allocator> tAllocator; TMap() : std::map() {} // use correct two-stage name lookup supported in gcc 3.4 and above TMap(const tAllocator &a) : std::map(std::map::key_compare(), a) {} }; // Basic implementation of C++20's span for use with pool-allocated containers (TVector) or static // arrays. This is used by the array sizes member of TType to allow arrayed types to be // constexpr-constructed. // See the reference for std::span here: https://en.cppreference.com/w/cpp/container/span template class TSpan { public: typedef size_t size_type; constexpr TSpan() {} constexpr TSpan(T *ptr, size_type size) : mData(ptr), mSize(size) {} constexpr TSpan(const TSpan &that) : mData(that.mData), mSize(that.mSize) {} constexpr TSpan &operator=(const TSpan &that) { mData = that.mData; mSize = that.mSize; return *this; } // Note: the pointer is taken out of the TVector because TVector's memory is pool allocated, // so the memory will live on even if the TVector is destroyed. template TSpan(const TVector &vec) : mData(vec.data()), mSize(vec.size()) {} template TSpan &operator=(const TVector &vec) { mData = vec.data(); mSize = vec.size(); return *this; } constexpr bool operator==(const TSpan &that) const { if (mSize != that.mSize) { return false; } if (mData == that.mData) { return true; } for (size_type index = 0; index < mSize; ++index) { if (mData[index] != that.mData[index]) { return false; } } return true; } constexpr bool operator!=(const TSpan &that) const { return !(*this == that); } constexpr T *data() const { return mData; } constexpr size_type size() const { return mSize; } constexpr bool empty() const { return mSize == 0; } constexpr T &operator[](size_type index) const { return mData[index]; } constexpr T &front() const { return mData[0]; } constexpr T &back() const { return mData[mSize - 1]; } constexpr T *begin() const { return mData; } constexpr T *end() const { return mData + mSize; } constexpr std::reverse_iterator rbegin() const { return std::make_reverse_iterator(end()); } constexpr std::reverse_iterator rend() const { return std::make_reverse_iterator(begin()); } constexpr TSpan first(size_type count) const { ASSERT(count <= mSize); return count == 0 ? TSpan() : TSpan(mData, count); } constexpr TSpan last(size_type count) const { ASSERT(count <= mSize); return count == 0 ? TSpan() : TSpan(mData + mSize - count, count); } constexpr TSpan subspan(size_type offset, size_type count) const { ASSERT(offset + count <= mSize); return count == 0 ? TSpan() : TSpan(mData + offset, count); } private: T *mData = nullptr; size_t mSize = 0; }; // Integer to TString conversion template inline TString str(T i) { ASSERT(std::numeric_limits::is_integer); char buffer[((8 * sizeof(T)) / 3) + 3]; const char *formatStr = std::numeric_limits::is_signed ? "%d" : "%u"; snprintf(buffer, sizeof(buffer), formatStr, i); return buffer; } // Allocate a char array in the global memory pool. str must be a null terminated string. strLength // is the length without the null terminator. inline const char *AllocatePoolCharArray(const char *str, size_t strLength) { size_t requiredSize = strLength + 1; char *buffer = static_cast(GetGlobalPoolAllocator()->allocate(requiredSize)); memcpy(buffer, str, requiredSize); ASSERT(buffer[strLength] == '\0'); return buffer; } // Initialize a new stream which must be imbued with the classic locale template T InitializeStream() { T stream; stream.imbue(std::locale::classic()); return stream; } } // namespace sh namespace std { template <> struct hash { size_t operator()(const sh::TString &s) const { return angle::PMurHash32(0, s.data(), static_cast(s.length())); } }; } // namespace std #endif // COMPILER_TRANSLATOR_COMMON_H_