| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | //===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
 | 
					
						
							|  |  |  | //       Do not edit! See README.txt.
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
					
						
							|  |  |  | // See https://llvm.org/LICENSE.txt for license information.
 | 
					
						
							| 
									
										
										
										
											2023-01-21 06:19:43 +00:00
										 |  |  | // SPDX-FileCopyrightText: Part of the LLVM Project
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //===----------------------------------------------------------------------===//
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | // Provide some utility classes for use in the demangler.
 | 
					
						
							|  |  |  | // There are two copies of this file in the source tree.  The one in libcxxabi
 | 
					
						
							|  |  |  | // is the original and the one in llvm is the copy.  Use cp-to-llvm.sh to update
 | 
					
						
							|  |  |  | // the copy.  See README.txt for more details.
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | //
 | 
					
						
							|  |  |  | //===----------------------------------------------------------------------===//
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef DEMANGLE_UTILITY_H
 | 
					
						
							|  |  |  | #define DEMANGLE_UTILITY_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | #include "DemangleConfig.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <array>
 | 
					
						
							|  |  |  | #include <cassert>
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | #include <cstdint>
 | 
					
						
							|  |  |  | #include <cstdlib>
 | 
					
						
							|  |  |  | #include <cstring>
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | #include <exception>
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | #include <limits>
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | #include <string_view>
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | DEMANGLE_NAMESPACE_BEGIN | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Stream that AST nodes write their string representation into after the AST
 | 
					
						
							|  |  |  | // has been parsed.
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | class OutputBuffer { | 
					
						
							|  |  |  |   char *Buffer = nullptr; | 
					
						
							|  |  |  |   size_t CurrentPosition = 0; | 
					
						
							|  |  |  |   size_t BufferCapacity = 0; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   // Ensure there are at least N more positions in the buffer.
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   void grow(size_t N) { | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |     size_t Need = N + CurrentPosition; | 
					
						
							|  |  |  |     if (Need > BufferCapacity) { | 
					
						
							|  |  |  |       // Reduce the number of reallocations, with a bit of hysteresis. The
 | 
					
						
							|  |  |  |       // number here is chosen so the first allocation will more-than-likely not
 | 
					
						
							|  |  |  |       // allocate more than 1K.
 | 
					
						
							|  |  |  |       Need += 1024 - 32; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |       BufferCapacity *= 2; | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |       if (BufferCapacity < Need) | 
					
						
							|  |  |  |         BufferCapacity = Need; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |       Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity)); | 
					
						
							|  |  |  |       if (Buffer == nullptr) | 
					
						
							|  |  |  |         std::terminate(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) { | 
					
						
							|  |  |  |     std::array<char, 21> Temp; | 
					
						
							|  |  |  |     char *TempPtr = Temp.data() + Temp.size(); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |     // Output at least one character.
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |       *--TempPtr = char('0' + N % 10); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |       N /= 10; | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |     } while (N); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |     // Add negative sign.
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     if (isNeg) | 
					
						
							|  |  |  |       *--TempPtr = '-'; | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return operator+=( | 
					
						
							|  |  |  |         std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr)); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer(char *StartBuf, size_t Size) | 
					
						
							|  |  |  |       : Buffer(StartBuf), BufferCapacity(Size) {} | 
					
						
							|  |  |  |   OutputBuffer(char *StartBuf, size_t *SizePtr) | 
					
						
							|  |  |  |       : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {} | 
					
						
							|  |  |  |   OutputBuffer() = default; | 
					
						
							|  |  |  |   // Non-copyable
 | 
					
						
							|  |  |  |   OutputBuffer(const OutputBuffer &) = delete; | 
					
						
							|  |  |  |   OutputBuffer &operator=(const OutputBuffer &) = delete; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   operator std::string_view() const { | 
					
						
							|  |  |  |     return std::string_view(Buffer, CurrentPosition); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// If a ParameterPackExpansion (or similar type) is encountered, the offset
 | 
					
						
							|  |  |  |   /// into the pack that we're currently printing.
 | 
					
						
							|  |  |  |   unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); | 
					
						
							|  |  |  |   unsigned CurrentPackMax = std::numeric_limits<unsigned>::max(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   /// When zero, we're printing template args and '>' needs to be parenthesized.
 | 
					
						
							|  |  |  |   /// Use a counter so we can simply increment inside parentheses.
 | 
					
						
							|  |  |  |   unsigned GtIsGt = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool isGtInsideTemplateArgs() const { return GtIsGt == 0; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void printOpen(char Open = '(') { | 
					
						
							|  |  |  |     GtIsGt++; | 
					
						
							|  |  |  |     *this += Open; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void printClose(char Close = ')') { | 
					
						
							|  |  |  |     GtIsGt--; | 
					
						
							|  |  |  |     *this += Close; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OutputBuffer &operator+=(std::string_view R) { | 
					
						
							|  |  |  |     if (size_t Size = R.size()) { | 
					
						
							|  |  |  |       grow(Size); | 
					
						
							|  |  |  |       std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size); | 
					
						
							|  |  |  |       CurrentPosition += Size; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     return *this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &operator+=(char C) { | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     grow(1); | 
					
						
							|  |  |  |     Buffer[CurrentPosition++] = C; | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &prepend(std::string_view R) { | 
					
						
							|  |  |  |     size_t Size = R.size(); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |     grow(Size); | 
					
						
							|  |  |  |     std::memmove(Buffer + Size, Buffer, CurrentPosition); | 
					
						
							|  |  |  |     std::memcpy(Buffer, &*R.begin(), Size); | 
					
						
							|  |  |  |     CurrentPosition += Size; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &operator<<(std::string_view R) { return (*this += R); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OutputBuffer &operator<<(char C) { return (*this += C); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OutputBuffer &operator<<(long long N) { | 
					
						
							|  |  |  |     return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &operator<<(unsigned long long N) { | 
					
						
							|  |  |  |     return writeUnsigned(N, false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OutputBuffer &operator<<(long N) { | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     return this->operator<<(static_cast<long long>(N)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &operator<<(unsigned long N) { | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     return this->operator<<(static_cast<unsigned long long>(N)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &operator<<(int N) { | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     return this->operator<<(static_cast<long long>(N)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   OutputBuffer &operator<<(unsigned int N) { | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |     return this->operator<<(static_cast<unsigned long long>(N)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   void insert(size_t Pos, const char *S, size_t N) { | 
					
						
							|  |  |  |     assert(Pos <= CurrentPosition); | 
					
						
							|  |  |  |     if (N == 0) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     grow(N); | 
					
						
							|  |  |  |     std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); | 
					
						
							|  |  |  |     std::memcpy(Buffer + Pos, S, N); | 
					
						
							|  |  |  |     CurrentPosition += N; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   size_t getCurrentPosition() const { return CurrentPosition; } | 
					
						
							|  |  |  |   void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   char back() const { | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |     assert(CurrentPosition); | 
					
						
							|  |  |  |     return Buffer[CurrentPosition - 1]; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool empty() const { return CurrentPosition == 0; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   char *getBuffer() { return Buffer; } | 
					
						
							|  |  |  |   char *getBufferEnd() { return Buffer + CurrentPosition - 1; } | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   size_t getBufferCapacity() const { return BufferCapacity; } | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  | template <class T> class ScopedOverride { | 
					
						
							|  |  |  |   T &Loc; | 
					
						
							|  |  |  |   T Original; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {} | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) { | 
					
						
							|  |  |  |     Loc_ = std::move(NewVal); | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   ~ScopedOverride() { Loc = std::move(Original); } | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:39:37 -04:00
										 |  |  |   ScopedOverride(const ScopedOverride &) = delete; | 
					
						
							|  |  |  |   ScopedOverride &operator=(const ScopedOverride &) = delete; | 
					
						
							| 
									
										
										
										
											2023-01-13 21:06:13 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEMANGLE_NAMESPACE_END | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |