Utility.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
  7. // Do not edit! See README.txt.
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Provide some utility classes for use in the demangler.
  15. // There are two copies of this file in the source tree. The one in libcxxabi
  16. // is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
  17. // the copy. See README.txt for more details.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #ifndef DEMANGLE_UTILITY_H
  21. #define DEMANGLE_UTILITY_H
  22. #include "StringView.h"
  23. #include <array>
  24. #include <cstdint>
  25. #include <cstdlib>
  26. #include <cstring>
  27. #include <exception>
  28. #include <limits>
  29. DEMANGLE_NAMESPACE_BEGIN
  30. // Stream that AST nodes write their string representation into after the AST
  31. // has been parsed.
  32. class OutputBuffer {
  33. char *Buffer = nullptr;
  34. size_t CurrentPosition = 0;
  35. size_t BufferCapacity = 0;
  36. // Ensure there are at least N more positions in the buffer.
  37. void grow(size_t N) {
  38. size_t Need = N + CurrentPosition;
  39. if (Need > BufferCapacity) {
  40. // Reduce the number of reallocations, with a bit of hysteresis. The
  41. // number here is chosen so the first allocation will more-than-likely not
  42. // allocate more than 1K.
  43. Need += 1024 - 32;
  44. BufferCapacity *= 2;
  45. if (BufferCapacity < Need)
  46. BufferCapacity = Need;
  47. Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
  48. if (Buffer == nullptr)
  49. std::terminate();
  50. }
  51. }
  52. OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
  53. std::array<char, 21> Temp;
  54. char *TempPtr = Temp.data() + Temp.size();
  55. // Output at least one character.
  56. do {
  57. *--TempPtr = char('0' + N % 10);
  58. N /= 10;
  59. } while (N);
  60. // Add negative sign.
  61. if (isNeg)
  62. *--TempPtr = '-';
  63. return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
  64. }
  65. public:
  66. OutputBuffer(char *StartBuf, size_t Size)
  67. : Buffer(StartBuf), BufferCapacity(Size) {}
  68. OutputBuffer(char *StartBuf, size_t *SizePtr)
  69. : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
  70. OutputBuffer() = default;
  71. // Non-copyable
  72. OutputBuffer(const OutputBuffer &) = delete;
  73. OutputBuffer &operator=(const OutputBuffer &) = delete;
  74. operator StringView() const { return StringView(Buffer, CurrentPosition); }
  75. /// If a ParameterPackExpansion (or similar type) is encountered, the offset
  76. /// into the pack that we're currently printing.
  77. unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
  78. unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
  79. /// When zero, we're printing template args and '>' needs to be parenthesized.
  80. /// Use a counter so we can simply increment inside parentheses.
  81. unsigned GtIsGt = 1;
  82. bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
  83. void printOpen(char Open = '(') {
  84. GtIsGt++;
  85. *this += Open;
  86. }
  87. void printClose(char Close = ')') {
  88. GtIsGt--;
  89. *this += Close;
  90. }
  91. OutputBuffer &operator+=(StringView R) {
  92. if (size_t Size = R.size()) {
  93. grow(Size);
  94. std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
  95. CurrentPosition += Size;
  96. }
  97. return *this;
  98. }
  99. OutputBuffer &operator+=(char C) {
  100. grow(1);
  101. Buffer[CurrentPosition++] = C;
  102. return *this;
  103. }
  104. OutputBuffer &prepend(StringView R) {
  105. size_t Size = R.size();
  106. grow(Size);
  107. std::memmove(Buffer + Size, Buffer, CurrentPosition);
  108. std::memcpy(Buffer, R.begin(), Size);
  109. CurrentPosition += Size;
  110. return *this;
  111. }
  112. OutputBuffer &operator<<(StringView R) { return (*this += R); }
  113. OutputBuffer &operator<<(char C) { return (*this += C); }
  114. OutputBuffer &operator<<(long long N) {
  115. return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
  116. }
  117. OutputBuffer &operator<<(unsigned long long N) {
  118. return writeUnsigned(N, false);
  119. }
  120. OutputBuffer &operator<<(long N) {
  121. return this->operator<<(static_cast<long long>(N));
  122. }
  123. OutputBuffer &operator<<(unsigned long N) {
  124. return this->operator<<(static_cast<unsigned long long>(N));
  125. }
  126. OutputBuffer &operator<<(int N) {
  127. return this->operator<<(static_cast<long long>(N));
  128. }
  129. OutputBuffer &operator<<(unsigned int N) {
  130. return this->operator<<(static_cast<unsigned long long>(N));
  131. }
  132. void insert(size_t Pos, const char *S, size_t N) {
  133. assert(Pos <= CurrentPosition);
  134. if (N == 0)
  135. return;
  136. grow(N);
  137. std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
  138. std::memcpy(Buffer + Pos, S, N);
  139. CurrentPosition += N;
  140. }
  141. size_t getCurrentPosition() const { return CurrentPosition; }
  142. void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
  143. char back() const {
  144. assert(CurrentPosition);
  145. return Buffer[CurrentPosition - 1];
  146. }
  147. bool empty() const { return CurrentPosition == 0; }
  148. char *getBuffer() { return Buffer; }
  149. char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
  150. size_t getBufferCapacity() const { return BufferCapacity; }
  151. };
  152. template <class T> class ScopedOverride {
  153. T &Loc;
  154. T Original;
  155. public:
  156. ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
  157. ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
  158. Loc_ = std::move(NewVal);
  159. }
  160. ~ScopedOverride() { Loc = std::move(Original); }
  161. ScopedOverride(const ScopedOverride &) = delete;
  162. ScopedOverride &operator=(const ScopedOverride &) = delete;
  163. };
  164. DEMANGLE_NAMESPACE_END
  165. #endif
  166. #ifdef __GNUC__
  167. #pragma GCC diagnostic pop
  168. #endif