Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:48

0001 //===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
0002 //       Do not edit! See README.txt.
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Provide some utility classes for use in the demangler.
0010 // There are two copies of this file in the source tree.  The one in libcxxabi
0011 // is the original and the one in llvm is the copy.  Use cp-to-llvm.sh to update
0012 // the copy.  See README.txt for more details.
0013 //
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef DEMANGLE_UTILITY_H
0017 #define DEMANGLE_UTILITY_H
0018 
0019 #include "DemangleConfig.h"
0020 
0021 #include <array>
0022 #include <cstdint>
0023 #include <cstdlib>
0024 #include <cstring>
0025 #include <limits>
0026 #include <string_view>
0027 
0028 DEMANGLE_NAMESPACE_BEGIN
0029 
0030 // Stream that AST nodes write their string representation into after the AST
0031 // has been parsed.
0032 class OutputBuffer {
0033   char *Buffer = nullptr;
0034   size_t CurrentPosition = 0;
0035   size_t BufferCapacity = 0;
0036 
0037   // Ensure there are at least N more positions in the buffer.
0038   void grow(size_t N) {
0039     size_t Need = N + CurrentPosition;
0040     if (Need > BufferCapacity) {
0041       // Reduce the number of reallocations, with a bit of hysteresis. The
0042       // number here is chosen so the first allocation will more-than-likely not
0043       // allocate more than 1K.
0044       Need += 1024 - 32;
0045       BufferCapacity *= 2;
0046       if (BufferCapacity < Need)
0047         BufferCapacity = Need;
0048       Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
0049       if (Buffer == nullptr)
0050         std::abort();
0051     }
0052   }
0053 
0054   OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
0055     std::array<char, 21> Temp;
0056     char *TempPtr = Temp.data() + Temp.size();
0057 
0058     // Output at least one character.
0059     do {
0060       *--TempPtr = char('0' + N % 10);
0061       N /= 10;
0062     } while (N);
0063 
0064     // Add negative sign.
0065     if (isNeg)
0066       *--TempPtr = '-';
0067 
0068     return operator+=(
0069         std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
0070   }
0071 
0072 public:
0073   OutputBuffer(char *StartBuf, size_t Size)
0074       : Buffer(StartBuf), BufferCapacity(Size) {}
0075   OutputBuffer(char *StartBuf, size_t *SizePtr)
0076       : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
0077   OutputBuffer() = default;
0078   // Non-copyable
0079   OutputBuffer(const OutputBuffer &) = delete;
0080   OutputBuffer &operator=(const OutputBuffer &) = delete;
0081 
0082   operator std::string_view() const {
0083     return std::string_view(Buffer, CurrentPosition);
0084   }
0085 
0086   /// If a ParameterPackExpansion (or similar type) is encountered, the offset
0087   /// into the pack that we're currently printing.
0088   unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
0089   unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
0090 
0091   /// When zero, we're printing template args and '>' needs to be parenthesized.
0092   /// Use a counter so we can simply increment inside parentheses.
0093   unsigned GtIsGt = 1;
0094 
0095   bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
0096 
0097   void printOpen(char Open = '(') {
0098     GtIsGt++;
0099     *this += Open;
0100   }
0101   void printClose(char Close = ')') {
0102     GtIsGt--;
0103     *this += Close;
0104   }
0105 
0106   OutputBuffer &operator+=(std::string_view R) {
0107     if (size_t Size = R.size()) {
0108       grow(Size);
0109       std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
0110       CurrentPosition += Size;
0111     }
0112     return *this;
0113   }
0114 
0115   OutputBuffer &operator+=(char C) {
0116     grow(1);
0117     Buffer[CurrentPosition++] = C;
0118     return *this;
0119   }
0120 
0121   OutputBuffer &prepend(std::string_view R) {
0122     size_t Size = R.size();
0123 
0124     grow(Size);
0125     std::memmove(Buffer + Size, Buffer, CurrentPosition);
0126     std::memcpy(Buffer, &*R.begin(), Size);
0127     CurrentPosition += Size;
0128 
0129     return *this;
0130   }
0131 
0132   OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
0133 
0134   OutputBuffer &operator<<(char C) { return (*this += C); }
0135 
0136   OutputBuffer &operator<<(long long N) {
0137     return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
0138   }
0139 
0140   OutputBuffer &operator<<(unsigned long long N) {
0141     return writeUnsigned(N, false);
0142   }
0143 
0144   OutputBuffer &operator<<(long N) {
0145     return this->operator<<(static_cast<long long>(N));
0146   }
0147 
0148   OutputBuffer &operator<<(unsigned long N) {
0149     return this->operator<<(static_cast<unsigned long long>(N));
0150   }
0151 
0152   OutputBuffer &operator<<(int N) {
0153     return this->operator<<(static_cast<long long>(N));
0154   }
0155 
0156   OutputBuffer &operator<<(unsigned int N) {
0157     return this->operator<<(static_cast<unsigned long long>(N));
0158   }
0159 
0160   void insert(size_t Pos, const char *S, size_t N) {
0161     DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
0162     if (N == 0)
0163       return;
0164     grow(N);
0165     std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
0166     std::memcpy(Buffer + Pos, S, N);
0167     CurrentPosition += N;
0168   }
0169 
0170   size_t getCurrentPosition() const { return CurrentPosition; }
0171   void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
0172 
0173   char back() const {
0174     DEMANGLE_ASSERT(CurrentPosition, "");
0175     return Buffer[CurrentPosition - 1];
0176   }
0177 
0178   bool empty() const { return CurrentPosition == 0; }
0179 
0180   char *getBuffer() { return Buffer; }
0181   char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
0182   size_t getBufferCapacity() const { return BufferCapacity; }
0183 };
0184 
0185 template <class T> class ScopedOverride {
0186   T &Loc;
0187   T Original;
0188 
0189 public:
0190   ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
0191 
0192   ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
0193     Loc_ = std::move(NewVal);
0194   }
0195   ~ScopedOverride() { Loc = std::move(Original); }
0196 
0197   ScopedOverride(const ScopedOverride &) = delete;
0198   ScopedOverride &operator=(const ScopedOverride &) = delete;
0199 };
0200 
0201 DEMANGLE_NAMESPACE_END
0202 
0203 #endif