Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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