LLVM 17.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.
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
70public:
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;
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.
84 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
85 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
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
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
181template <class T> class ScopedOverride {
182 T &Loc;
183 T Original;
184
185public:
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
195};
196
198
199#endif
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define DEMANGLE_NAMESPACE_END
#define DEMANGLE_NAMESPACE_BEGIN
uint64_t Size
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
char * getBufferEnd()
Definition: Utility.h:177
OutputBuffer & operator<<(unsigned long long N)
Definition: Utility.h:136
OutputBuffer()=default
OutputBuffer(const OutputBuffer &)=delete
OutputBuffer & operator+=(StringView R)
Definition: Utility.h:102
size_t getBufferCapacity() const
Definition: Utility.h:178
bool empty() const
Definition: Utility.h:174
OutputBuffer & operator<<(StringView R)
Definition: Utility.h:128
OutputBuffer & prepend(StringView R)
Definition: Utility.h:117
OutputBuffer(char *StartBuf, size_t Size)
Definition: Utility.h:71
unsigned GtIsGt
When zero, we're printing template args and '>' needs to be parenthesized.
Definition: Utility.h:89
OutputBuffer(char *StartBuf, size_t *SizePtr)
Definition: Utility.h:73
OutputBuffer & operator<<(char C)
Definition: Utility.h:130
char back() const
Definition: Utility.h:169
OutputBuffer & operator=(const OutputBuffer &)=delete
char * getBuffer()
Definition: Utility.h:176
unsigned CurrentPackMax
Definition: Utility.h:85
unsigned CurrentPackIndex
If a ParameterPackExpansion (or similar type) is encountered, the offset into the pack that we're cur...
Definition: Utility.h:84
OutputBuffer & operator<<(long N)
Definition: Utility.h:140
OutputBuffer & operator<<(int N)
Definition: Utility.h:148
OutputBuffer & operator<<(long long N)
Definition: Utility.h:132
void printClose(char Close=')')
Definition: Utility.h:97
void setCurrentPosition(size_t NewPos)
Definition: Utility.h:167
bool isGtInsideTemplateArgs() const
Definition: Utility.h:91
OutputBuffer & operator+=(char C)
Definition: Utility.h:111
size_t getCurrentPosition() const
Definition: Utility.h:166
void printOpen(char Open='(')
Definition: Utility.h:93
void insert(size_t Pos, const char *S, size_t N)
Definition: Utility.h:156
OutputBuffer & operator<<(unsigned long N)
Definition: Utility.h:144
OutputBuffer & operator<<(unsigned int N)
Definition: Utility.h:152
ScopedOverride(T &Loc_, T NewVal)
Definition: Utility.h:188
ScopedOverride(T &Loc_)
Definition: Utility.h:186
ScopedOverride & operator=(const ScopedOverride &)=delete
ScopedOverride(const ScopedOverride &)=delete
#define N