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 LLVM_DEMANGLE_UTILITY_H
17 #define LLVM_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), CurrentPosition(0), BufferCapacity(Size) {}
73  OutputBuffer() = default;
74  // Non-copyable
75  OutputBuffer(const OutputBuffer &) = delete;
76  OutputBuffer &operator=(const OutputBuffer &) = delete;
77 
78  operator StringView() const { return StringView(Buffer, CurrentPosition); }
79 
80  void reset(char *Buffer_, size_t BufferCapacity_) {
81  CurrentPosition = 0;
82  Buffer = Buffer_;
83  BufferCapacity = BufferCapacity_;
84  }
85 
86  /// If a ParameterPackExpansion (or similar type) is encountered, the offset
87  /// into the pack that we're currently printing.
90 
91  /// When zero, we're printing template args and '>' needs to be parenthesized.
92  /// Use a counter so we can simply increment inside parentheses.
93  unsigned GtIsGt = 1;
94 
95  bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
96 
97  void printOpen(char Open = '(') {
98  GtIsGt++;
99  *this += Open;
100  }
101  void printClose(char Close = ')') {
102  GtIsGt--;
103  *this += Close;
104  }
105 
107  if (size_t Size = R.size()) {
108  grow(Size);
109  std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
110  CurrentPosition += Size;
111  }
112  return *this;
113  }
114 
116  grow(1);
117  Buffer[CurrentPosition++] = C;
118  return *this;
119  }
120 
122  size_t Size = R.size();
123 
124  grow(Size);
125  std::memmove(Buffer + Size, Buffer, CurrentPosition);
126  std::memcpy(Buffer, R.begin(), Size);
127  CurrentPosition += Size;
128 
129  return *this;
130  }
131 
132  OutputBuffer &operator<<(StringView R) { return (*this += R); }
133 
134  OutputBuffer &operator<<(char C) { return (*this += C); }
135 
136  OutputBuffer &operator<<(long long N) {
137  return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
138  }
139 
140  OutputBuffer &operator<<(unsigned long long N) {
141  return writeUnsigned(N, false);
142  }
143 
145  return this->operator<<(static_cast<long long>(N));
146  }
147 
148  OutputBuffer &operator<<(unsigned long N) {
149  return this->operator<<(static_cast<unsigned long long>(N));
150  }
151 
153  return this->operator<<(static_cast<long long>(N));
154  }
155 
156  OutputBuffer &operator<<(unsigned int N) {
157  return this->operator<<(static_cast<unsigned long long>(N));
158  }
159 
160  void insert(size_t Pos, const char *S, size_t N) {
161  assert(Pos <= CurrentPosition);
162  if (N == 0)
163  return;
164  grow(N);
165  std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
166  std::memcpy(Buffer + Pos, S, N);
167  CurrentPosition += N;
168  }
169 
170  size_t getCurrentPosition() const { return CurrentPosition; }
171  void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
172 
173  char back() const {
174  assert(CurrentPosition);
175  return Buffer[CurrentPosition - 1];
176  }
177 
178  bool empty() const { return CurrentPosition == 0; }
179 
180  char *getBuffer() { return Buffer; }
181  char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
182  size_t getBufferCapacity() const { return BufferCapacity; }
183 };
184 
185 template <class T> class ScopedOverride {
186  T &Loc;
187  T Original;
188 
189 public:
190  ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
191 
192  ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
193  Loc_ = std::move(NewVal);
194  }
195  ~ScopedOverride() { Loc = std::move(Original); }
196 
197  ScopedOverride(const ScopedOverride &) = delete;
198  ScopedOverride &operator=(const ScopedOverride &) = delete;
199 };
200 
201 inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
202  size_t InitSize) {
203  size_t BufferSize;
204  if (Buf == nullptr) {
205  Buf = static_cast<char *>(std::malloc(InitSize));
206  if (Buf == nullptr)
207  return false;
208  BufferSize = InitSize;
209  } else
210  BufferSize = *N;
211 
212  OB.reset(Buf, BufferSize);
213  return true;
214 }
215 
217 
218 #endif
OutputBuffer::operator+=
OutputBuffer & operator+=(StringView R)
Definition: Utility.h:106
ScopedOverride::ScopedOverride
ScopedOverride(T &Loc_)
Definition: Utility.h:190
OutputBuffer::getBufferCapacity
size_t getBufferCapacity() const
Definition: Utility.h:182
ScopedOverride::ScopedOverride
ScopedOverride(T &Loc_, T NewVal)
Definition: Utility.h:192
OutputBuffer::CurrentPackMax
unsigned CurrentPackMax
Definition: Utility.h:89
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:93
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:173
OutputBuffer::operator=
OutputBuffer & operator=(const OutputBuffer &)=delete
OutputBuffer::operator<<
OutputBuffer & operator<<(int N)
Definition: Utility.h:152
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:265
OutputBuffer::insert
void insert(size_t Pos, const char *S, size_t N)
Definition: Utility.h:160
OutputBuffer::printClose
void printClose(char Close=')')
Definition: Utility.h:101
OutputBuffer::getBuffer
char * getBuffer()
Definition: Utility.h:180
llvm::X86II::OB
@ OB
Definition: X86BaseInfo.h:801
OutputBuffer::empty
bool empty() const
Definition: Utility.h:178
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned long N)
Definition: Utility.h:148
OutputBuffer::operator+=
OutputBuffer & operator+=(char C)
Definition: Utility.h:115
OutputBuffer::prepend
OutputBuffer & prepend(StringView R)
Definition: Utility.h:121
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
OutputBuffer::reset
void reset(char *Buffer_, size_t BufferCapacity_)
Definition: Utility.h:80
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned int N)
Definition: Utility.h:156
OutputBuffer::operator<<
OutputBuffer & operator<<(long N)
Definition: Utility.h:144
OutputBuffer::setCurrentPosition
void setCurrentPosition(size_t NewPos)
Definition: Utility.h:171
StringView.h
DEMANGLE_NAMESPACE_END
#define DEMANGLE_NAMESPACE_END
Definition: DemangleConfig.h:90
OutputBuffer::operator<<
OutputBuffer & operator<<(long long N)
Definition: Utility.h:136
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:170
OutputBuffer::getBufferEnd
char * getBufferEnd()
Definition: Utility.h:181
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OutputBuffer::operator<<
OutputBuffer & operator<<(char C)
Definition: Utility.h:134
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:195
OutputBuffer::CurrentPackIndex
unsigned CurrentPackIndex
If a ParameterPackExpansion (or similar type) is encountered, the offset into the pack that we're cur...
Definition: Utility.h:88
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:140
OutputBuffer::OutputBuffer
OutputBuffer()=default
OutputBuffer::isGtInsideTemplateArgs
bool isGtInsideTemplateArgs() const
Definition: Utility.h:95
initializeOutputBuffer
bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB, size_t InitSize)
Definition: Utility.h:201
OutputBuffer::operator<<
OutputBuffer & operator<<(StringView R)
Definition: Utility.h:132
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:1282
OutputBuffer::printOpen
void printOpen(char Open='(')
Definition: Utility.h:97
ScopedOverride
Definition: Utility.h:185