LLVM 18.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 "DemangleConfig.h"
20
21#include <array>
22#include <cassert>
23#include <cstdint>
24#include <cstdlib>
25#include <cstring>
26#include <limits>
27#include <string_view>
28
30
31// Stream that AST nodes write their string representation into after the AST
32// has been parsed.
34 char *Buffer = nullptr;
35 size_t CurrentPosition = 0;
36 size_t BufferCapacity = 0;
37
38 // Ensure there are at least N more positions in the buffer.
39 void grow(size_t N) {
40 size_t Need = N + CurrentPosition;
41 if (Need > BufferCapacity) {
42 // Reduce the number of reallocations, with a bit of hysteresis. The
43 // number here is chosen so the first allocation will more-than-likely not
44 // allocate more than 1K.
45 Need += 1024 - 32;
46 BufferCapacity *= 2;
47 if (BufferCapacity < Need)
48 BufferCapacity = Need;
49 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
50 if (Buffer == nullptr)
51 std::abort();
52 }
53 }
54
55 OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
56 std::array<char, 21> Temp;
57 char *TempPtr = Temp.data() + Temp.size();
58
59 // Output at least one character.
60 do {
61 *--TempPtr = char('0' + N % 10);
62 N /= 10;
63 } while (N);
64
65 // Add negative sign.
66 if (isNeg)
67 *--TempPtr = '-';
68
69 return operator+=(
70 std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
71 }
72
73public:
74 OutputBuffer(char *StartBuf, size_t Size)
75 : Buffer(StartBuf), BufferCapacity(Size) {}
76 OutputBuffer(char *StartBuf, size_t *SizePtr)
77 : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
78 OutputBuffer() = default;
79 // Non-copyable
80 OutputBuffer(const OutputBuffer &) = delete;
82
83 operator std::string_view() const {
84 return std::string_view(Buffer, CurrentPosition);
85 }
86
87 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
88 /// into the pack that we're currently printing.
89 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
90 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
91
92 /// When zero, we're printing template args and '>' needs to be parenthesized.
93 /// Use a counter so we can simply increment inside parentheses.
94 unsigned GtIsGt = 1;
95
96 bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
97
98 void printOpen(char Open = '(') {
99 GtIsGt++;
100 *this += Open;
101 }
102 void printClose(char Close = ')') {
103 GtIsGt--;
104 *this += Close;
105 }
106
107 OutputBuffer &operator+=(std::string_view R) {
108 if (size_t Size = R.size()) {
109 grow(Size);
110 std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
111 CurrentPosition += Size;
112 }
113 return *this;
114 }
115
117 grow(1);
118 Buffer[CurrentPosition++] = C;
119 return *this;
120 }
121
122 OutputBuffer &prepend(std::string_view R) {
123 size_t Size = R.size();
124
125 grow(Size);
126 std::memmove(Buffer + Size, Buffer, CurrentPosition);
127 std::memcpy(Buffer, &*R.begin(), Size);
128 CurrentPosition += Size;
129
130 return *this;
131 }
132
133 OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
134
135 OutputBuffer &operator<<(char C) { return (*this += C); }
136
138 return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
139 }
140
141 OutputBuffer &operator<<(unsigned long long N) {
142 return writeUnsigned(N, false);
143 }
144
146 return this->operator<<(static_cast<long long>(N));
147 }
148
149 OutputBuffer &operator<<(unsigned long N) {
150 return this->operator<<(static_cast<unsigned long long>(N));
151 }
152
154 return this->operator<<(static_cast<long long>(N));
155 }
156
157 OutputBuffer &operator<<(unsigned int N) {
158 return this->operator<<(static_cast<unsigned long long>(N));
159 }
160
161 void insert(size_t Pos, const char *S, size_t N) {
162 assert(Pos <= CurrentPosition);
163 if (N == 0)
164 return;
165 grow(N);
166 std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
167 std::memcpy(Buffer + Pos, S, N);
168 CurrentPosition += N;
169 }
170
171 size_t getCurrentPosition() const { return CurrentPosition; }
172 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
173
174 char back() const {
175 assert(CurrentPosition);
176 return Buffer[CurrentPosition - 1];
177 }
178
179 bool empty() const { return CurrentPosition == 0; }
180
181 char *getBuffer() { return Buffer; }
182 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
183 size_t getBufferCapacity() const { return BufferCapacity; }
184};
185
186template <class T> class ScopedOverride {
187 T &Loc;
188 T Original;
189
190public:
191 ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
192
193 ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
194 Loc_ = std::move(NewVal);
195 }
196 ~ScopedOverride() { Loc = std::move(Original); }
197
200};
201
203
204#endif
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static bool isNeg(Value *V)
Returns true if the operation is a negation of V, and it works for both integers and floats.
#define DEMANGLE_NAMESPACE_END
#define DEMANGLE_NAMESPACE_BEGIN
uint64_t Size
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
char * getBufferEnd()
Definition: Utility.h:182
OutputBuffer & operator<<(unsigned long long N)
Definition: Utility.h:141
OutputBuffer()=default
OutputBuffer(const OutputBuffer &)=delete
size_t getBufferCapacity() const
Definition: Utility.h:183
OutputBuffer & operator+=(std::string_view R)
Definition: Utility.h:107
bool empty() const
Definition: Utility.h:179
OutputBuffer(char *StartBuf, size_t Size)
Definition: Utility.h:74
unsigned GtIsGt
When zero, we're printing template args and '>' needs to be parenthesized.
Definition: Utility.h:94
OutputBuffer(char *StartBuf, size_t *SizePtr)
Definition: Utility.h:76
OutputBuffer & operator<<(char C)
Definition: Utility.h:135
char back() const
Definition: Utility.h:174
OutputBuffer & operator=(const OutputBuffer &)=delete
OutputBuffer & prepend(std::string_view R)
Definition: Utility.h:122
char * getBuffer()
Definition: Utility.h:181
unsigned CurrentPackMax
Definition: Utility.h:90
OutputBuffer & operator<<(std::string_view R)
Definition: Utility.h:133
unsigned CurrentPackIndex
If a ParameterPackExpansion (or similar type) is encountered, the offset into the pack that we're cur...
Definition: Utility.h:89
OutputBuffer & operator<<(long N)
Definition: Utility.h:145
OutputBuffer & operator<<(int N)
Definition: Utility.h:153
OutputBuffer & operator<<(long long N)
Definition: Utility.h:137
void printClose(char Close=')')
Definition: Utility.h:102
void setCurrentPosition(size_t NewPos)
Definition: Utility.h:172
bool isGtInsideTemplateArgs() const
Definition: Utility.h:96
OutputBuffer & operator+=(char C)
Definition: Utility.h:116
size_t getCurrentPosition() const
Definition: Utility.h:171
void printOpen(char Open='(')
Definition: Utility.h:98
void insert(size_t Pos, const char *S, size_t N)
Definition: Utility.h:161
OutputBuffer & operator<<(unsigned long N)
Definition: Utility.h:149
OutputBuffer & operator<<(unsigned int N)
Definition: Utility.h:157
ScopedOverride(T &Loc_, T NewVal)
Definition: Utility.h:193
ScopedOverride(T &Loc_)
Definition: Utility.h:191
ScopedOverride & operator=(const ScopedOverride &)=delete
ScopedOverride(const ScopedOverride &)=delete
#define N