summaryrefslogtreecommitdiff
path: root/externals/demangle/llvm/Demangle/Utility.h
diff options
context:
space:
mode:
Diffstat (limited to 'externals/demangle/llvm/Demangle/Utility.h')
-rw-r--r--externals/demangle/llvm/Demangle/Utility.h208
1 files changed, 111 insertions, 97 deletions
diff --git a/externals/demangle/llvm/Demangle/Utility.h b/externals/demangle/llvm/Demangle/Utility.h
index 50d05c6b1..30dfbfc8d 100644
--- a/externals/demangle/llvm/Demangle/Utility.h
+++ b/externals/demangle/llvm/Demangle/Utility.h
@@ -1,5 +1,5 @@
1//===--- Utility.h ----------------------------------------------*- C++ -*-===// 1//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
2// 2// Do not edit! See README.txt.
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 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. 4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-FileCopyrightText: Part of the LLVM Project 5// SPDX-FileCopyrightText: Part of the LLVM Project
@@ -7,70 +7,83 @@
7// 7//
8//===----------------------------------------------------------------------===// 8//===----------------------------------------------------------------------===//
9// 9//
10// Provide some utility classes for use in the demangler(s). 10// Provide some utility classes for use in the demangler.
11// There are two copies of this file in the source tree. The one in libcxxabi
12// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
13// the copy. See README.txt for more details.
11// 14//
12//===----------------------------------------------------------------------===// 15//===----------------------------------------------------------------------===//
13 16
14#ifndef DEMANGLE_UTILITY_H 17#ifndef DEMANGLE_UTILITY_H
15#define DEMANGLE_UTILITY_H 18#define DEMANGLE_UTILITY_H
16 19
17#include "StringView.h" 20#include "DemangleConfig.h"
21
22#include <array>
23#include <cassert>
18#include <cstdint> 24#include <cstdint>
19#include <cstdlib> 25#include <cstdlib>
20#include <cstring> 26#include <cstring>
21#include <iterator> 27#include <exception>
22#include <limits> 28#include <limits>
29#include <string_view>
23 30
24DEMANGLE_NAMESPACE_BEGIN 31DEMANGLE_NAMESPACE_BEGIN
25 32
26// Stream that AST nodes write their string representation into after the AST 33// Stream that AST nodes write their string representation into after the AST
27// has been parsed. 34// has been parsed.
28class OutputStream { 35class OutputBuffer {
29 char *Buffer; 36 char *Buffer = nullptr;
30 size_t CurrentPosition; 37 size_t CurrentPosition = 0;
31 size_t BufferCapacity; 38 size_t BufferCapacity = 0;
32 39
33 // Ensure there is at least n more positions in buffer. 40 // Ensure there are at least N more positions in the buffer.
34 void grow(size_t N) { 41 void grow(size_t N) {
35 if (N + CurrentPosition >= BufferCapacity) { 42 size_t Need = N + CurrentPosition;
43 if (Need > BufferCapacity) {
44 // Reduce the number of reallocations, with a bit of hysteresis. The
45 // number here is chosen so the first allocation will more-than-likely not
46 // allocate more than 1K.
47 Need += 1024 - 32;
36 BufferCapacity *= 2; 48 BufferCapacity *= 2;
37 if (BufferCapacity < N + CurrentPosition) 49 if (BufferCapacity < Need)
38 BufferCapacity = N + CurrentPosition; 50 BufferCapacity = Need;
39 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity)); 51 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
40 if (Buffer == nullptr) 52 if (Buffer == nullptr)
41 std::terminate(); 53 std::terminate();
42 } 54 }
43 } 55 }
44 56
45 void writeUnsigned(uint64_t N, bool isNeg = false) { 57 OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
46 // Handle special case... 58 std::array<char, 21> Temp;
47 if (N == 0) { 59 char *TempPtr = Temp.data() + Temp.size();
48 *this << '0';
49 return;
50 }
51
52 char Temp[21];
53 char *TempPtr = std::end(Temp);
54 60
55 while (N) { 61 // Output at least one character.
56 *--TempPtr = '0' + char(N % 10); 62 do {
63 *--TempPtr = char('0' + N % 10);
57 N /= 10; 64 N /= 10;
58 } 65 } while (N);
59 66
60 // Add negative sign... 67 // Add negative sign.
61 if (isNeg) 68 if (isNeg)
62 *--TempPtr = '-'; 69 *--TempPtr = '-';
63 this->operator<<(StringView(TempPtr, std::end(Temp))); 70
71 return operator+=(
72 std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
64 } 73 }
65 74
66public: 75public:
67 OutputStream(char *StartBuf, size_t Size) 76 OutputBuffer(char *StartBuf, size_t Size)
68 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {} 77 : Buffer(StartBuf), BufferCapacity(Size) {}
69 OutputStream() = default; 78 OutputBuffer(char *StartBuf, size_t *SizePtr)
70 void reset(char *Buffer_, size_t BufferCapacity_) { 79 : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
71 CurrentPosition = 0; 80 OutputBuffer() = default;
72 Buffer = Buffer_; 81 // Non-copyable
73 BufferCapacity = BufferCapacity_; 82 OutputBuffer(const OutputBuffer &) = delete;
83 OutputBuffer &operator=(const OutputBuffer &) = delete;
84
85 operator std::string_view() const {
86 return std::string_view(Buffer, CurrentPosition);
74 } 87 }
75 88
76 /// If a ParameterPackExpansion (or similar type) is encountered, the offset 89 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
@@ -78,115 +91,116 @@ public:
78 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); 91 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
79 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max(); 92 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
80 93
81 OutputStream &operator+=(StringView R) { 94 /// When zero, we're printing template args and '>' needs to be parenthesized.
82 size_t Size = R.size(); 95 /// Use a counter so we can simply increment inside parentheses.
83 if (Size == 0) 96 unsigned GtIsGt = 1;
84 return *this; 97
85 grow(Size); 98 bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
86 std::memmove(Buffer + CurrentPosition, R.begin(), Size); 99
87 CurrentPosition += Size; 100 void printOpen(char Open = '(') {
101 GtIsGt++;
102 *this += Open;
103 }
104 void printClose(char Close = ')') {
105 GtIsGt--;
106 *this += Close;
107 }
108
109 OutputBuffer &operator+=(std::string_view R) {
110 if (size_t Size = R.size()) {
111 grow(Size);
112 std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
113 CurrentPosition += Size;
114 }
88 return *this; 115 return *this;
89 } 116 }
90 117
91 OutputStream &operator+=(char C) { 118 OutputBuffer &operator+=(char C) {
92 grow(1); 119 grow(1);
93 Buffer[CurrentPosition++] = C; 120 Buffer[CurrentPosition++] = C;
94 return *this; 121 return *this;
95 } 122 }
96 123
97 OutputStream &operator<<(StringView R) { return (*this += R); } 124 OutputBuffer &prepend(std::string_view R) {
125 size_t Size = R.size();
98 126
99 OutputStream &operator<<(char C) { return (*this += C); } 127 grow(Size);
128 std::memmove(Buffer + Size, Buffer, CurrentPosition);
129 std::memcpy(Buffer, &*R.begin(), Size);
130 CurrentPosition += Size;
100 131
101 OutputStream &operator<<(long long N) {
102 if (N < 0)
103 writeUnsigned(static_cast<unsigned long long>(-N), true);
104 else
105 writeUnsigned(static_cast<unsigned long long>(N));
106 return *this; 132 return *this;
107 } 133 }
108 134
109 OutputStream &operator<<(unsigned long long N) { 135 OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
110 writeUnsigned(N, false); 136
111 return *this; 137 OutputBuffer &operator<<(char C) { return (*this += C); }
138
139 OutputBuffer &operator<<(long long N) {
140 return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
112 } 141 }
113 142
114 OutputStream &operator<<(long N) { 143 OutputBuffer &operator<<(unsigned long long N) {
144 return writeUnsigned(N, false);
145 }
146
147 OutputBuffer &operator<<(long N) {
115 return this->operator<<(static_cast<long long>(N)); 148 return this->operator<<(static_cast<long long>(N));
116 } 149 }
117 150
118 OutputStream &operator<<(unsigned long N) { 151 OutputBuffer &operator<<(unsigned long N) {
119 return this->operator<<(static_cast<unsigned long long>(N)); 152 return this->operator<<(static_cast<unsigned long long>(N));
120 } 153 }
121 154
122 OutputStream &operator<<(int N) { 155 OutputBuffer &operator<<(int N) {
123 return this->operator<<(static_cast<long long>(N)); 156 return this->operator<<(static_cast<long long>(N));
124 } 157 }
125 158
126 OutputStream &operator<<(unsigned int N) { 159 OutputBuffer &operator<<(unsigned int N) {
127 return this->operator<<(static_cast<unsigned long long>(N)); 160 return this->operator<<(static_cast<unsigned long long>(N));
128 } 161 }
129 162
163 void insert(size_t Pos, const char *S, size_t N) {
164 assert(Pos <= CurrentPosition);
165 if (N == 0)
166 return;
167 grow(N);
168 std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
169 std::memcpy(Buffer + Pos, S, N);
170 CurrentPosition += N;
171 }
172
130 size_t getCurrentPosition() const { return CurrentPosition; } 173 size_t getCurrentPosition() const { return CurrentPosition; }
131 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } 174 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
132 175
133 char back() const { 176 char back() const {
134 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0'; 177 assert(CurrentPosition);
178 return Buffer[CurrentPosition - 1];
135 } 179 }
136 180
137 bool empty() const { return CurrentPosition == 0; } 181 bool empty() const { return CurrentPosition == 0; }
138 182
139 char *getBuffer() { return Buffer; } 183 char *getBuffer() { return Buffer; }
140 char *getBufferEnd() { return Buffer + CurrentPosition - 1; } 184 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
141 size_t getBufferCapacity() { return BufferCapacity; } 185 size_t getBufferCapacity() const { return BufferCapacity; }
142}; 186};
143 187
144template <class T> class SwapAndRestore { 188template <class T> class ScopedOverride {
145 T &Restore; 189 T &Loc;
146 T OriginalValue; 190 T Original;
147 bool ShouldRestore = true;
148 191
149public: 192public:
150 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {} 193 ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
151
152 SwapAndRestore(T &Restore_, T NewVal)
153 : Restore(Restore_), OriginalValue(Restore) {
154 Restore = std::move(NewVal);
155 }
156 ~SwapAndRestore() {
157 if (ShouldRestore)
158 Restore = std::move(OriginalValue);
159 }
160 194
161 void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; } 195 ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
162 196 Loc_ = std::move(NewVal);
163 void restoreNow(bool Force) {
164 if (!Force && !ShouldRestore)
165 return;
166
167 Restore = std::move(OriginalValue);
168 ShouldRestore = false;
169 } 197 }
198 ~ScopedOverride() { Loc = std::move(Original); }
170 199
171 SwapAndRestore(const SwapAndRestore &) = delete; 200 ScopedOverride(const ScopedOverride &) = delete;
172 SwapAndRestore &operator=(const SwapAndRestore &) = delete; 201 ScopedOverride &operator=(const ScopedOverride &) = delete;
173}; 202};
174 203
175inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
176 size_t InitSize) {
177 size_t BufferSize;
178 if (Buf == nullptr) {
179 Buf = static_cast<char *>(std::malloc(InitSize));
180 if (Buf == nullptr)
181 return false;
182 BufferSize = InitSize;
183 } else
184 BufferSize = *N;
185
186 S.reset(Buf, BufferSize);
187 return true;
188}
189
190DEMANGLE_NAMESPACE_END 204DEMANGLE_NAMESPACE_END
191 205
192#endif 206#endif