source: src/SymTab/Demangle.cc@ 0589e83

Last change on this file since 0589e83 was 0589e83, checked in by Andrew Beach <ajbeach@…>, 2 years ago

The demangler now uses the compiler's genType. The only difference I can find is that the demangler genType wrote functions ': RET_TYPE' instead of the C style. If this or a different change turns out to be imported it will have to be replicated post-translation.

  • Property mode set to 100644
File size: 12.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Demangle.cc -- Convert a mangled name into a human readable name.
8//
9// Author : Rob Schluntz
10// Created On : Thu Jul 19 12:52:41 2018
11// Last Modified By : Andrew Beach
12// Last Modified On : Mon Nov 6 15:59:00 2023
13// Update Count : 12
14//
15
16#include <algorithm>
17#include <sstream>
18
19#include "CodeGen/GenType.h"
20#include "CodeGen/OperatorTable.h"
21#include "Common/PassVisitor.h"
22#include "Common/utility.h" // isPrefix
23#include "Mangler.h"
24#include "SynTree/Type.h"
25#include "SynTree/Declaration.h"
26
27#define DEBUG
28#ifdef DEBUG
29#define PRINT(x) x
30#else
31#define PRINT(x) {}
32#endif
33
34namespace SymTab {
35 namespace Mangler {
36 namespace {
37 struct StringView {
38 private:
39 std::string str;
40 size_t idx = 0;
41 // typedef Type * (StringView::*parser)(Type::Qualifiers);
42 typedef std::function<Type * (Type::Qualifiers)> parser;
43 std::vector<std::pair<std::string, parser>> parsers;
44 public:
45 StringView(const std::string & str);
46
47 bool done() const { return idx >= str.size(); }
48 char cur() const { assert(! done()); return str[idx]; }
49
50 bool expect(char ch) { return str[idx++] == ch; }
51 void next(size_t inc = 1) { idx += inc; }
52
53 /// determines if `pref` is a prefix of `str`
54 bool isPrefix(const std::string & pref);
55 bool extractNumber(size_t & out);
56 bool extractName(std::string & out);
57 bool stripMangleName(std::string & name);
58
59 Type * parseFunction(Type::Qualifiers tq);
60 Type * parseTuple(Type::Qualifiers tq);
61 Type * parseVoid(Type::Qualifiers tq);
62 Type * parsePointer(Type::Qualifiers tq);
63 Type * parseArray(Type::Qualifiers tq);
64 Type * parseStruct(Type::Qualifiers tq);
65 Type * parseUnion(Type::Qualifiers tq);
66 Type * parseEnum(Type::Qualifiers tq);
67 Type * parseType(Type::Qualifiers tq);
68
69 Type * parseType();
70 bool parse(std::string & name, Type *& type);
71 };
72
73 StringView::StringView(const std::string & str) : str(str) {
74 // basic types
75 for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
76 parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
77 PRINT( std::cerr << "basic type: " << k << std::endl; )
78 return new BasicType(tq, (BasicType::Kind)k);
79 });
80 }
81 // type variable types
82 for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
83 static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
84 static_assert(
85 sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
86 "Each type variable kind should have a demangle name prefix"
87 );
88 parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
89 PRINT( std::cerr << "type variable type: " << k << std::endl; )
90 size_t N;
91 if (! extractNumber(N)) return nullptr;
92 return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
93 });
94 }
95 // everything else
96 parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
97 parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
98 parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
99 parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
100 parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
101 parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
102 parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
103 parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
104 parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
105 parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
106 parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
107 }
108
109 bool StringView::extractNumber(size_t & out) {
110 std::stringstream numss;
111 if (idx >= str.size()) return false;
112 while (isdigit(str[idx])) {
113 numss << str[idx];
114 ++idx;
115 if (idx == str.size()) break;
116 }
117 if (! (numss >> out)) return false;
118 PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
119 return true;
120 }
121
122 bool StringView::extractName(std::string & out) {
123 size_t len;
124 if (! extractNumber(len)) return false;
125 if (idx+len > str.size()) return false;
126 out = str.substr(idx, len);
127 idx += len;
128 PRINT( std::cerr << "extractName success: " << out << std::endl; )
129 return true;
130 }
131
132 bool StringView::isPrefix(const std::string & pref) {
133 // if ( pref.size() > str.size()-idx ) return false;
134 // auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
135 // if (its.first == pref.end()) {
136 // idx += pref.size();
137 // return true;
138 // }
139
140 // This update is untested because there are no tests for this code.
141 if ( ::isPrefix( str, pref, idx ) ) {
142 idx += pref.size();
143 return true;
144 }
145 return false;
146 }
147
148 // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
149 bool StringView::stripMangleName(std::string & name) {
150 PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
151 if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
152 if ( ! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back() ) ) return false;
153
154 // get name
155 if (! extractName(name)) return false;
156
157 // find bounds for type
158 PRINT( std::cerr << idx << " " << str.size() << std::endl; )
159 PRINT( std::cerr << "[");
160 while (isdigit(str.back())) {
161 PRINT(std::cerr << ".");
162 str.pop_back();
163 if (str.size() <= idx) return false;
164 }
165 PRINT( std::cerr << "]" << std::endl );
166 if (str.back() != '_') return false;
167 str.pop_back();
168 PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
169 return str.size() > idx;
170 }
171
172 Type * StringView::parseFunction(Type::Qualifiers tq) {
173 PRINT( std::cerr << "function..." << std::endl; )
174 if (done()) return nullptr;
175 FunctionType * ftype = new FunctionType( tq, false );
176 std::unique_ptr<Type> manager(ftype);
177 Type * retVal = parseType();
178 if (! retVal) return nullptr;
179 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
180 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
181 if (done() || ! expect('_')) return nullptr;
182 while (! done()) {
183 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
184 if (cur() == '_') return manager.release();
185 Type * param = parseType();
186 if (! param) return nullptr;
187 PRINT( std::cerr << "with parameter : " << param << std::endl; )
188 ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
189 }
190 return nullptr;
191 }
192
193 Type * StringView::parseTuple(Type::Qualifiers tq) {
194 PRINT( std::cerr << "tuple..." << std::endl; )
195 std::list< Type * > types;
196 size_t ncomponents;
197 if (! extractNumber(ncomponents)) return nullptr;
198 for (size_t i = 0; i < ncomponents; ++i) {
199 // TODO: delete all on return
200 if (done()) return nullptr;
201 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
202 Type * t = parseType();
203 if (! t) return nullptr;
204 PRINT( std::cerr << "with type : " << t << std::endl; )
205 types.push_back(t);
206 }
207 return new TupleType( tq, types );
208 }
209
210 Type * StringView::parseVoid(Type::Qualifiers tq) {
211 return new VoidType( tq );
212 }
213
214 Type * StringView::parsePointer(Type::Qualifiers tq) {
215 PRINT( std::cerr << "pointer..." << std::endl; )
216 Type * t = parseType();
217 if (! t) return nullptr;
218 return new PointerType( tq, t );
219 }
220
221 Type * StringView::parseArray(Type::Qualifiers tq) {
222 PRINT( std::cerr << "array..." << std::endl; )
223 size_t length;
224 if (! extractNumber(length)) return nullptr;
225 Type * t = parseType();
226 if (! t) return nullptr;
227 return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
228 }
229
230 Type * StringView::parseStruct(Type::Qualifiers tq) {
231 PRINT( std::cerr << "struct..." << std::endl; )
232 std::string name;
233 if (! extractName(name)) return nullptr;
234 return new StructInstType(tq, name);
235 }
236
237 Type * StringView::parseUnion(Type::Qualifiers tq) {
238 PRINT( std::cerr << "union..." << std::endl; )
239 std::string name;
240 if (! extractName(name)) return nullptr;
241 return new UnionInstType(tq, name);
242 }
243
244 Type * StringView::parseEnum(Type::Qualifiers tq) {
245 PRINT( std::cerr << "enum..." << std::endl; )
246 std::string name;
247 if (! extractName(name)) return nullptr;
248 return new EnumInstType(tq, name);
249 }
250
251 Type * StringView::parseType(Type::Qualifiers tq) {
252 PRINT( std::cerr << "type..." << std::endl; )
253 std::string name;
254 if (! extractName(name)) return nullptr;
255 PRINT( std::cerr << "typename..." << name << std::endl; )
256 return new TypeInstType(tq, name, false);
257 }
258
259 Type * StringView::parseType() {
260 if (done()) return nullptr;
261
262 std::list<TypeDecl *> forall;
263 if (isPrefix(Encoding::forall)) {
264 PRINT( std::cerr << "polymorphic with..." << std::endl; )
265 size_t dcount, fcount, vcount, acount;
266 if (! extractNumber(dcount)) return nullptr;
267 PRINT( std::cerr << dcount << " dtypes" << std::endl; )
268 if (! expect('_')) return nullptr;
269 if (! extractNumber(fcount)) return nullptr;
270 PRINT( std::cerr << fcount << " ftypes" << std::endl; )
271 if (! expect('_')) return nullptr;
272 if (! extractNumber(vcount)) return nullptr;
273 PRINT( std::cerr << vcount << " ttypes" << std::endl; )
274 if (! expect('_')) return nullptr;
275 if (! extractNumber(acount)) return nullptr;
276 PRINT( std::cerr << acount << " assertions" << std::endl; )
277 if (! expect('_')) return nullptr;
278 for (size_t i = 0; i < acount; ++i) {
279 // TODO: need to recursively parse assertions, but for now just return nullptr so that
280 // demangler does not crash if there are assertions
281 return nullptr;
282 }
283 if (! expect('_')) return nullptr;
284 }
285
286 // qualifiers
287 Type::Qualifiers tq;
288 while (true) {
289 auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
290 return isPrefix(val.second);
291 });
292 if (qual == Encoding::qualifiers.end()) break;
293 tq |= qual->first;
294 }
295
296 // find the correct type parser and use it
297 auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
298 return isPrefix(p.first);
299 });
300 assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
301 Type * ret = iter->second(tq);
302 if (! ret) return nullptr;
303 ret->forall = std::move(forall);
304 return ret;
305 }
306
307 bool StringView::parse(std::string & name, Type *& type) {
308 if (! stripMangleName(name)) return false;
309 PRINT( std::cerr << "stripped name: " << name << std::endl; )
310 Type * t = parseType();
311 if (! t) return false;
312 type = t;
313 return true;
314 }
315
316 std::string demangle(const std::string & mangleName) {
317 SymTab::Mangler::StringView view(mangleName);
318 std::string name;
319 Type * type = nullptr;
320 if (! view.parse(name, type)) return mangleName;
321 auto info = CodeGen::operatorLookupByOutput(name);
322 if (info) name = info->inputName;
323 std::unique_ptr<Type> manager(type);
324 return CodeGen::genType(type, name);
325 }
326 } // namespace
327 } // namespace Mangler
328} // namespace SymTab
329
330extern "C" {
331 char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
332 const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
333 return strdup(demangleName.c_str());
334 }
335}
336
337// Local Variables: //
338// tab-width: 4 //
339// mode: c++ //
340// compile-command: "make install" //
341// End: //
Note: See TracBrowser for help on using the repository browser.