llvm.org GIT mirror llvm / 937d2c0
[LLVMDemangle] Move some utility classes to header files. In a followup I'm looking to add a Microsoft demangler. Doing so needs a lot of the same utility classes and feature test macros which are already implemented in ItaniumDemangle.cpp. So move all of these things into header files so that they can be re-used by a new demangler. Differential Revision: https://reviews.llvm.org/D49399 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337217 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 3 months ago
5 changed file(s) with 257 addition(s) and 198 deletion(s). Raw diff Collapse all Expand all
0 add_llvm_library(LLVMDemangle
11 ItaniumDemangle.cpp
2
3 ADDITIONAL_HEADER_DIRS
4 "${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"
25 )
0 //===--- Compiler.h ---------------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //
8 // This file contains a variety of feature test macros copied from
9 // include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take
10 // a dependency on LLVMSupport.
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_DEMANGLE_COMPILER_H
14 #define LLVM_DEMANGLE_COMPILER_H
15
16 #ifdef _MSC_VER
17 // snprintf is implemented in VS 2015
18 #if _MSC_VER < 1900
19 #define snprintf _snprintf_s
20 #endif
21 #endif
22
23 #ifndef __has_feature
24 #define __has_feature(x) 0
25 #endif
26
27 #ifndef __has_cpp_attribute
28 #define __has_cpp_attribute(x) 0
29 #endif
30
31 #ifndef __has_attribute
32 #define __has_attribute(x) 0
33 #endif
34
35 #ifndef __has_builtin
36 #define __has_builtin(x) 0
37 #endif
38
39 #ifndef LLVM_GNUC_PREREQ
40 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
41 #define LLVM_GNUC_PREREQ(maj, min, patch) \
42 ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
43 ((maj) << 20) + ((min) << 10) + (patch))
44 #elif defined(__GNUC__) && defined(__GNUC_MINOR__)
45 #define LLVM_GNUC_PREREQ(maj, min, patch) \
46 ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
47 #else
48 #define LLVM_GNUC_PREREQ(maj, min, patch) 0
49 #endif
50 #endif
51
52 #if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
53 #define LLVM_ATTRIBUTE_USED __attribute__((__used__))
54 #else
55 #define LLVM_ATTRIBUTE_USED
56 #endif
57
58 #if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
59 #define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
60 #elif defined(_MSC_VER)
61 #define LLVM_BUILTIN_UNREACHABLE __assume(false)
62 #endif
63
64 #if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
65 #define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
66 #elif defined(_MSC_VER)
67 #define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
68 #else
69 #define LLVM_ATTRIBUTE_NOINLINE
70 #endif
71
72 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
73 #define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
74 #else
75 #define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
76 #endif
77
78 #if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
79 #define LLVM_FALLTHROUGH [[fallthrough]]
80 #elif __has_cpp_attribute(gnu::fallthrough)
81 #define LLVM_FALLTHROUGH [[gnu::fallthrough]]
82 #elif !__cplusplus
83 // Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
84 // error when __has_cpp_attribute is given a scoped attribute in C mode.
85 #define LLVM_FALLTHROUGH
86 #elif __has_cpp_attribute(clang::fallthrough)
87 #define LLVM_FALLTHROUGH [[clang::fallthrough]]
88 #else
89 #define LLVM_FALLTHROUGH
90 #endif
91
92 #endif
1010 // file does not yet support:
1111 // - C++ modules TS
1212
13 #include "Compiler.h"
14 #include "StringView.h"
15 #include "Utility.h"
1316 #include "llvm/Demangle/Demangle.h"
1417
15 #include
1618 #include
1719 #include
1820 #include
2123 #include
2224 #include
2325
24 #ifdef _MSC_VER
25 // snprintf is implemented in VS 2015
26 #if _MSC_VER < 1900
27 #define snprintf _snprintf_s
28 #endif
29 #endif
30
31 // A variety of feature test macros copied from include/llvm/Support/Compiler.h
32 #ifndef __has_feature
33 #define __has_feature(x) 0
34 #endif
35
36 #ifndef __has_cpp_attribute
37 #define __has_cpp_attribute(x) 0
38 #endif
39
40 #ifndef __has_attribute
41 #define __has_attribute(x) 0
42 #endif
43
44 #ifndef __has_builtin
45 #define __has_builtin(x) 0
46 #endif
47
48 #ifndef LLVM_GNUC_PREREQ
49 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
50 #define LLVM_GNUC_PREREQ(maj, min, patch) \
51 ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
52 ((maj) << 20) + ((min) << 10) + (patch))
53 #elif defined(__GNUC__) && defined(__GNUC_MINOR__)
54 #define LLVM_GNUC_PREREQ(maj, min, patch) \
55 ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
56 #else
57 #define LLVM_GNUC_PREREQ(maj, min, patch) 0
58 #endif
59 #endif
60
61 #if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
62 #define LLVM_ATTRIBUTE_USED __attribute__((__used__))
63 #else
64 #define LLVM_ATTRIBUTE_USED
65 #endif
66
67 #if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
68 #define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
69 #elif defined(_MSC_VER)
70 #define LLVM_BUILTIN_UNREACHABLE __assume(false)
71 #endif
72
73 #if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
74 #define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
75 #elif defined(_MSC_VER)
76 #define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
77 #else
78 #define LLVM_ATTRIBUTE_NOINLINE
79 #endif
80
81 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
82 #define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
83 #else
84 #define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
85 #endif
86
87 #if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
88 #define LLVM_FALLTHROUGH [[fallthrough]]
89 #elif __has_cpp_attribute(gnu::fallthrough)
90 #define LLVM_FALLTHROUGH [[gnu::fallthrough]]
91 #elif !__cplusplus
92 // Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
93 // error when __has_cpp_attribute is given a scoped attribute in C mode.
94 #define LLVM_FALLTHROUGH
95 #elif __has_cpp_attribute(clang::fallthrough)
96 #define LLVM_FALLTHROUGH [[clang::fallthrough]]
97 #else
98 #define LLVM_FALLTHROUGH
99 #endif
10026
10127 namespace {
10228
103 class StringView {
104 const char *First;
105 const char *Last;
106
107 public:
108 template
109 StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
110 StringView(const char *First_, const char *Last_) : First(First_), Last(Last_) {}
111 StringView() : First(nullptr), Last(nullptr) {}
112
113 StringView substr(size_t From, size_t To) {
114 if (To >= size())
115 To = size() - 1;
116 if (From >= size())
117 From = size() - 1;
118 return StringView(First + From, First + To);
119 }
120
121 StringView dropFront(size_t N) const {
122 if (N >= size())
123 N = size() - 1;
124 return StringView(First + N, Last);
125 }
126
127 bool startsWith(StringView Str) const {
128 if (Str.size() > size())
129 return false;
130 return std::equal(Str.begin(), Str.end(), begin());
131 }
132
133 const char &operator[](size_t Idx) const { return *(begin() + Idx); }
134
135 const char *begin() const { return First; }
136 const char *end() const { return Last; }
137 size_t size() const { return static_cast(Last - First); }
138 bool empty() const { return First == Last; }
139 };
140
141 bool operator==(const StringView &LHS, const StringView &RHS) {
142 return LHS.size() == RHS.size() &&
143 std::equal(LHS.begin(), LHS.end(), RHS.begin());
144 }
145
146 // Stream that AST nodes write their string representation into after the AST
147 // has been parsed.
148 class OutputStream {
149 char *Buffer;
150 size_t CurrentPosition;
151 size_t BufferCapacity;
152
153 // Ensure there is at least n more positions in buffer.
154 void grow(size_t N) {
155 if (N + CurrentPosition >= BufferCapacity) {
156 BufferCapacity *= 2;
157 if (BufferCapacity < N + CurrentPosition)
158 BufferCapacity = N + CurrentPosition;
159 Buffer = static_cast(std::realloc(Buffer, BufferCapacity));
160 }
161 }
162
163 public:
164 OutputStream(char *StartBuf, size_t Size)
165 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
166 OutputStream() = default;
167 void reset(char *Buffer_, size_t BufferCapacity_) {
168 CurrentPosition = 0;
169 Buffer = Buffer_;
170 BufferCapacity = BufferCapacity_;
171 }
172
173 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
174 /// into the pack that we're currently printing.
175 unsigned CurrentPackIndex = std::numeric_limits::max();
176 unsigned CurrentPackMax = std::numeric_limits::max();
177
178 OutputStream &operator+=(StringView R) {
179 size_t Size = R.size();
180 if (Size == 0)
181 return *this;
182 grow(Size);
183 memmove(Buffer + CurrentPosition, R.begin(), Size);
184 CurrentPosition += Size;
185 return *this;
186 }
187
188 OutputStream &operator+=(char C) {
189 grow(1);
190 Buffer[CurrentPosition++] = C;
191 return *this;
192 }
193
194 size_t getCurrentPosition() const { return CurrentPosition; }
195 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
196
197 char back() const {
198 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
199 }
200
201 bool empty() const { return CurrentPosition == 0; }
202
203 char *getBuffer() { return Buffer; }
204 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
205 size_t getBufferCapacity() { return BufferCapacity; }
206 };
207
208 template
209 class SwapAndRestore {
210 T &Restore;
211 T OriginalValue;
212 public:
213 SwapAndRestore(T& Restore_, T NewVal)
214 : Restore(Restore_), OriginalValue(Restore) {
215 Restore = std::move(NewVal);
216 }
217 ~SwapAndRestore() { Restore = std::move(OriginalValue); }
218
219 SwapAndRestore(const SwapAndRestore &) = delete;
220 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
221 };
22229
22330 // Base class of all AST nodes. The AST is built by the parser, then is
22431 // traversed by the printLeft/Right functions to produce a demangled string.
29862793 //
29872794 // extension ::= srN [] * E
29882795 // ::= [gs] # x or (with "gs") ::x
2989 // ::= [gs] sr + E
2796 // ::= [gs] sr + E
29902797 // # A::x, N::y, A::z; "gs" means leading "::"
29912798 // ::= sr # T::x / decltype(p)::x
29922799 // extension ::= sr
30362843 return SoFar;
30372844 }
30382845
3039 // [gs] sr + E
2846 // [gs] sr + E
30402847 if (std::isdigit(look())) {
30412848 do {
30422849 Node *Qual = parseSimpleId();
0 //===--- StringView.h -------------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //
8 // This file contains a limited version of LLVM's StringView class. It is
9 // copied here so that LLVMDemangle need not take a dependency on LLVMSupport.
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_DEMANGLE_STRINGVIEW_H
13 #define LLVM_DEMANGLE_STRINGVIEW_H
14
15 #include
16
17 class StringView {
18 const char *First;
19 const char *Last;
20
21 public:
22 template
23 StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
24 StringView(const char *First_, const char *Last_)
25 : First(First_), Last(Last_) {}
26 StringView() : First(nullptr), Last(nullptr) {}
27
28 StringView substr(size_t From, size_t To) {
29 if (To >= size())
30 To = size() - 1;
31 if (From >= size())
32 From = size() - 1;
33 return StringView(First + From, First + To);
34 }
35
36 StringView dropFront(size_t N) const {
37 if (N >= size())
38 N = size() - 1;
39 return StringView(First + N, Last);
40 }
41
42 bool startsWith(StringView Str) const {
43 if (Str.size() > size())
44 return false;
45 return std::equal(Str.begin(), Str.end(), begin());
46 }
47
48 const char &operator[](size_t Idx) const { return *(begin() + Idx); }
49
50 const char *begin() const { return First; }
51 const char *end() const { return Last; }
52 size_t size() const { return static_cast(Last - First); }
53 bool empty() const { return First == Last; }
54 };
55
56 inline bool operator==(const StringView &LHS, const StringView &RHS) {
57 return LHS.size() == RHS.size() &&
58 std::equal(LHS.begin(), LHS.end(), RHS.begin());
59 }
60
61 #endif
0 //===--- Utility.h ----------------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //
8 // This file contains several utility classes used by the demangle library.
9 //===----------------------------------------------------------------------===//
10
11 #ifndef LLVM_DEMANGLE_UTILITY_H
12 #define LLVM_DEMANGLE_UTILITY_H
13
14 #include
15
16 // Stream that AST nodes write their string representation into after the AST
17 // has been parsed.
18 class OutputStream {
19 char *Buffer;
20 size_t CurrentPosition;
21 size_t BufferCapacity;
22
23 // Ensure there is at least n more positions in buffer.
24 void grow(size_t N) {
25 if (N + CurrentPosition >= BufferCapacity) {
26 BufferCapacity *= 2;
27 if (BufferCapacity < N + CurrentPosition)
28 BufferCapacity = N + CurrentPosition;
29 Buffer = static_cast(std::realloc(Buffer, BufferCapacity));
30 }
31 }
32
33 public:
34 OutputStream(char *StartBuf, size_t Size)
35 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
36 OutputStream() = default;
37 void reset(char *Buffer_, size_t BufferCapacity_) {
38 CurrentPosition = 0;
39 Buffer = Buffer_;
40 BufferCapacity = BufferCapacity_;
41 }
42
43 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
44 /// into the pack that we're currently printing.
45 unsigned CurrentPackIndex = std::numeric_limits::max();
46 unsigned CurrentPackMax = std::numeric_limits::max();
47
48 OutputStream &operator+=(StringView R) {
49 size_t Size = R.size();
50 if (Size == 0)
51 return *this;
52 grow(Size);
53 std::memmove(Buffer + CurrentPosition, R.begin(), Size);
54 CurrentPosition += Size;
55 return *this;
56 }
57
58 OutputStream &operator+=(char C) {
59 grow(1);
60 Buffer[CurrentPosition++] = C;
61 return *this;
62 }
63
64 size_t getCurrentPosition() const { return CurrentPosition; }
65 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
66
67 char back() const {
68 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
69 }
70
71 bool empty() const { return CurrentPosition == 0; }
72
73 char *getBuffer() { return Buffer; }
74 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
75 size_t getBufferCapacity() { return BufferCapacity; }
76 };
77
78 template class SwapAndRestore {
79 T &Restore;
80 T OriginalValue;
81
82 public:
83 SwapAndRestore(T &Restore_, T NewVal)
84 : Restore(Restore_), OriginalValue(Restore) {
85 Restore = std::move(NewVal);
86 }
87 ~SwapAndRestore() { Restore = std::move(OriginalValue); }
88
89 SwapAndRestore(const SwapAndRestore &) = delete;
90 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
91 };
92
93 #endif