LLVM  14.0.0git
Utility.h
Go to the documentation of this file.
1 //===--- Utility.h ----------------------------------------------*- C++ -*-===//
2 //
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(s).
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef DEMANGLE_UTILITY_H
14 #define DEMANGLE_UTILITY_H
15 
16 #include "StringView.h"
17 #include <array>
18 #include <cstdint>
19 #include <cstdlib>
20 #include <cstring>
21 #include <exception>
22 #include <limits>
23 
25 
26 // Stream that AST nodes write their string representation into after the AST
27 // has been parsed.
28 class OutputBuffer {
29  char *Buffer = nullptr;
30  size_t CurrentPosition = 0;
31  size_t BufferCapacity = 0;
32 
33  // Ensure there is at least n more positions in buffer.
34  void grow(size_t N) {
35  if (N + CurrentPosition >= BufferCapacity) {
36  BufferCapacity *= 2;
37  if (BufferCapacity < N + CurrentPosition)
38  BufferCapacity = N + CurrentPosition;
39  Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
40  if (Buffer == nullptr)
41  std::terminate();
42  }
43  }
44 
45  void writeUnsigned(uint64_t N, bool isNeg = false) {
46  // Handle special case...
47  if (N == 0) {
48  *this << '0';
49  return;
50  }
51 
52  std::array<char, 21> Temp;
53  char *TempPtr = Temp.data() + Temp.size();
54 
55  while (N) {
56  *--TempPtr = char('0' + N % 10);
57  N /= 10;
58  }
59 
60  // Add negative sign...
61  if (isNeg)
62  *--TempPtr = '-';
63  this->operator<<(StringView(TempPtr, Temp.data() + Temp.size()));
64  }
65 
66 public:
67  OutputBuffer(char *StartBuf, size_t Size)
68  : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
69  OutputBuffer() = default;
70  void reset(char *Buffer_, size_t BufferCapacity_) {
71  CurrentPosition = 0;
72  Buffer = Buffer_;
73  BufferCapacity = BufferCapacity_;
74  }
75 
76  /// If a ParameterPackExpansion (or similar type) is encountered, the offset
77  /// into the pack that we're currently printing.
80 
82  size_t Size = R.size();
83  if (Size == 0)
84  return *this;
85  grow(Size);
86  std::memmove(Buffer + CurrentPosition, R.begin(), Size);
87  CurrentPosition += Size;
88  return *this;
89  }
90 
92  grow(1);
93  Buffer[CurrentPosition++] = C;
94  return *this;
95  }
96 
97  OutputBuffer &operator<<(StringView R) { return (*this += R); }
98 
100  size_t Size = R.size();
101 
102  grow(Size);
103  std::memmove(Buffer + Size, Buffer, CurrentPosition);
104  std::memcpy(Buffer, R.begin(), Size);
105  CurrentPosition += Size;
106 
107  return *this;
108  }
109 
110  OutputBuffer &operator<<(char C) { return (*this += C); }
111 
112  OutputBuffer &operator<<(long long N) {
113  if (N < 0)
114  writeUnsigned(static_cast<unsigned long long>(-N), true);
115  else
116  writeUnsigned(static_cast<unsigned long long>(N));
117  return *this;
118  }
119 
120  OutputBuffer &operator<<(unsigned long long N) {
121  writeUnsigned(N, false);
122  return *this;
123  }
124 
126  return this->operator<<(static_cast<long long>(N));
127  }
128 
129  OutputBuffer &operator<<(unsigned long N) {
130  return this->operator<<(static_cast<unsigned long long>(N));
131  }
132 
134  return this->operator<<(static_cast<long long>(N));
135  }
136 
137  OutputBuffer &operator<<(unsigned int N) {
138  return this->operator<<(static_cast<unsigned long long>(N));
139  }
140 
141  void insert(size_t Pos, const char *S, size_t N) {
142  assert(Pos <= CurrentPosition);
143  if (N == 0)
144  return;
145  grow(N);
146  std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
147  std::memcpy(Buffer + Pos, S, N);
148  CurrentPosition += N;
149  }
150 
151  size_t getCurrentPosition() const { return CurrentPosition; }
152  void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
153 
154  char back() const {
155  return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
156  }
157 
158  bool empty() const { return CurrentPosition == 0; }
159 
160  char *getBuffer() { return Buffer; }
161  char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
162  size_t getBufferCapacity() const { return BufferCapacity; }
163 };
164 
165 template <class T> class SwapAndRestore {
166  T &Restore;
167  T OriginalValue;
168  bool ShouldRestore = true;
169 
170 public:
171  SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
172 
173  SwapAndRestore(T &Restore_, T NewVal)
174  : Restore(Restore_), OriginalValue(Restore) {
175  Restore = std::move(NewVal);
176  }
178  if (ShouldRestore)
179  Restore = std::move(OriginalValue);
180  }
181 
182  void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
183 
184  void restoreNow(bool Force) {
185  if (!Force && !ShouldRestore)
186  return;
187 
188  Restore = std::move(OriginalValue);
189  ShouldRestore = false;
190  }
191 
192  SwapAndRestore(const SwapAndRestore &) = delete;
193  SwapAndRestore &operator=(const SwapAndRestore &) = delete;
194 };
195 
196 inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
197  size_t InitSize) {
198  size_t BufferSize;
199  if (Buf == nullptr) {
200  Buf = static_cast<char *>(std::malloc(InitSize));
201  if (Buf == nullptr)
202  return false;
203  BufferSize = InitSize;
204  } else
205  BufferSize = *N;
206 
207  OB.reset(Buf, BufferSize);
208  return true;
209 }
210 
212 
213 #endif
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
OutputBuffer::operator+=
OutputBuffer & operator+=(StringView R)
Definition: Utility.h:81
SwapAndRestore
Definition: Utility.h:165
OutputBuffer::getBufferCapacity
size_t getBufferCapacity() const
Definition: Utility.h:162
OutputBuffer::CurrentPackMax
unsigned CurrentPackMax
Definition: Utility.h:79
SwapAndRestore::operator=
SwapAndRestore & operator=(const SwapAndRestore &)=delete
T
#define T
Definition: Mips16ISelLowering.cpp:341
OutputBuffer::back
char back() const
Definition: Utility.h:154
OutputBuffer::operator<<
OutputBuffer & operator<<(int N)
Definition: Utility.h:133
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:207
OutputBuffer::insert
void insert(size_t Pos, const char *S, size_t N)
Definition: Utility.h:141
OutputBuffer::getBuffer
char * getBuffer()
Definition: Utility.h:160
OutputBuffer::empty
bool empty() const
Definition: Utility.h:158
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned long N)
Definition: Utility.h:129
OutputBuffer::operator+=
OutputBuffer & operator+=(char C)
Definition: Utility.h:91
llvm::X86II::OB
@ OB
Definition: X86BaseInfo.h:801
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
SwapAndRestore::SwapAndRestore
SwapAndRestore(T &Restore_, T NewVal)
Definition: Utility.h:173
OutputBuffer::reset
void reset(char *Buffer_, size_t BufferCapacity_)
Definition: Utility.h:70
OutputBuffer::operator<<
OutputBuffer & operator<<(unsigned int N)
Definition: Utility.h:137
SwapAndRestore::~SwapAndRestore
~SwapAndRestore()
Definition: Utility.h:177
OutputBuffer::operator<<
OutputBuffer & operator<<(long N)
Definition: Utility.h:125
OutputBuffer::setCurrentPosition
void setCurrentPosition(size_t NewPos)
Definition: Utility.h:152
StringView.h
OutputBuffer::prepend
OutputBuffer prepend(StringView R)
Definition: Utility.h:99
DEMANGLE_NAMESPACE_END
#define DEMANGLE_NAMESPACE_END
Definition: DemangleConfig.h:90
OutputBuffer::operator<<
OutputBuffer & operator<<(long long N)
Definition: Utility.h:112
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:151
SwapAndRestore::restoreNow
void restoreNow(bool Force)
Definition: Utility.h:184
OutputBuffer::getBufferEnd
char * getBufferEnd()
Definition: Utility.h:161
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SwapAndRestore::shouldRestore
void shouldRestore(bool ShouldRestore_)
Definition: Utility.h:182
OutputBuffer::operator<<
OutputBuffer & operator<<(char C)
Definition: Utility.h:110
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(<
OutputBuffer::CurrentPackIndex
unsigned CurrentPackIndex
If a ParameterPackExpansion (or similar type) is encountered, the offset into the pack that we're cur...
Definition: Utility.h:78
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:120
OutputBuffer::OutputBuffer
OutputBuffer()=default
SwapAndRestore::SwapAndRestore
SwapAndRestore(T &Restore_)
Definition: Utility.h:171
initializeOutputBuffer
bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB, size_t InitSize)
Definition: Utility.h:196
OutputBuffer::operator<<
OutputBuffer & operator<<(StringView R)
Definition: Utility.h:97
DEMANGLE_NAMESPACE_BEGIN
#define DEMANGLE_NAMESPACE_BEGIN
Definition: DemangleConfig.h:89
OutputBuffer::OutputBuffer
OutputBuffer(char *StartBuf, size_t Size)
Definition: Utility.h:67
OutputBuffer
Definition: Utility.h:28
N
#define N
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
StringView
Definition: StringView.h:22