LLVM  16.0.0git
Utility.h
Go to the documentation of this file.
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 
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.
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 
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 
112  grow(1);
113  Buffer[CurrentPosition++] = C;
114  return *this;
115  }
116 
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 
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 
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 
198 
199 #endif
OutputBuffer::operator+=
OutputBuffer & operator+=(StringView R)
Definition: Utility.h:102
ScopedOverride::ScopedOverride
ScopedOverride(T &Loc_)
Definition: Utility.h:186
OutputBuffer::getBufferCapacity
size_t getBufferCapacity() const
Definition: Utility.h:178
ScopedOverride::ScopedOverride
ScopedOverride(T &Loc_, T NewVal)
Definition: Utility.h:188
OutputBuffer::CurrentPackMax
unsigned CurrentPackMax
Definition: Utility.h:85
OutputBuffer::OutputBuffer
OutputBuffer(char *StartBuf, size_t *SizePtr)
Definition: Utility.h:73
ScopedOverride::operator=
ScopedOverride & operator=(const ScopedOverride &)=delete
OutputBuffer::GtIsGt
unsigned GtIsGt
When zero, we're printing template args and '>' needs to be parenthesized.
Definition: Utility.h:89
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::max
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:337
OutputBuffer::back
char back() const
Definition: Utility.h:169
OutputBuffer::operator=
OutputBuffer & operator=(const OutputBuffer &)=delete
OutputBuffer::operator<<
OutputBuffer & operator<<(int N)
Definition: Utility.h:148
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:265
OutputBuffer::insert
void insert(size_t Pos, const char *S, size_t N)
Definition: Utility.h:156
OutputBuffer::printClose
void printClose(char Close=')')
Definition: Utility.h:97
OutputBuffer::getBuffer
char * getBuffer()
Definition: Utility.h:176
OutputBuffer::empty
bool empty() const
Definition: Utility.h:174
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned long N)
Definition: Utility.h:144
OutputBuffer::operator+=
OutputBuffer & operator+=(char C)
Definition: Utility.h:111
OutputBuffer::prepend
OutputBuffer & prepend(StringView R)
Definition: Utility.h:117
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned int N)
Definition: Utility.h:152
OutputBuffer::operator<<
OutputBuffer & operator<<(long N)
Definition: Utility.h:140
OutputBuffer::setCurrentPosition
void setCurrentPosition(size_t NewPos)
Definition: Utility.h:167
StringView.h
DEMANGLE_NAMESPACE_END
#define DEMANGLE_NAMESPACE_END
Definition: DemangleConfig.h:90
OutputBuffer::operator<<
OutputBuffer & operator<<(long long N)
Definition: Utility.h:132
uint64_t
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
OutputBuffer::getCurrentPosition
size_t getCurrentPosition() const
Definition: Utility.h:166
OutputBuffer::getBufferEnd
char * getBufferEnd()
Definition: Utility.h:177
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OutputBuffer::operator<<
OutputBuffer & operator<<(char C)
Definition: Utility.h:130
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
ScopedOverride::~ScopedOverride
~ScopedOverride()
Definition: Utility.h:191
OutputBuffer::CurrentPackIndex
unsigned CurrentPackIndex
If a ParameterPackExpansion (or similar type) is encountered, the offset into the pack that we're cur...
Definition: Utility.h:84
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned long long N)
Definition: Utility.h:136
OutputBuffer::OutputBuffer
OutputBuffer()=default
OutputBuffer::isGtInsideTemplateArgs
bool isGtInsideTemplateArgs() const
Definition: Utility.h:91
OutputBuffer::operator<<
OutputBuffer & operator<<(StringView R)
Definition: Utility.h:128
DEMANGLE_NAMESPACE_BEGIN
#define DEMANGLE_NAMESPACE_BEGIN
Definition: DemangleConfig.h:89
OutputBuffer::OutputBuffer
OutputBuffer(char *StartBuf, size_t Size)
Definition: Utility.h:71
OutputBuffer
Definition: Utility.h:31
N
#define N
StringView
Definition: StringView.h:25
InlinePriorityMode::Size
@ Size
llvm::abs
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition: APFloat.h:1297
OutputBuffer::printOpen
void printOpen(char Open='(')
Definition: Utility.h:93
ScopedOverride
Definition: Utility.h:181