source: src/SymTab/Demangle.cc@ 90cac45

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since 90cac45 was 90cac45, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Add options parameter to cforall_demangle

  • Property mode set to 100644
File size: 16.3 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// Demangler.cc --
8//
9// Author : Rob Schluntz
10// Created On : Thu Jul 19 12:52:41 2018
11// Last Modified By : Rob Schluntz
12// Last Modified On : Thu Jul 19 12:54:35 2018
13// Update Count : 2
14//
15
16#include <algorithm>
17#include <sstream>
18
19#include "CodeGen/GenType.h"
20#include "Common/PassVisitor.h"
21#include "Mangler.h"
22#include "SynTree/Type.h"
23#include "SynTree/Declaration.h"
24
25// #define DEBUG
26#ifdef DEBUG
27#define PRINT(x) x
28#else
29#define PRINT(x) {}
30#endif
31
32namespace {
33 struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
34 std::string typeString;
35 GenType( const std::string &typeString );
36
37 void previsit( BaseSyntaxNode * );
38 void postvisit( BaseSyntaxNode * );
39
40 void postvisit( FunctionType * funcType );
41 void postvisit( VoidType * voidType );
42 void postvisit( BasicType * basicType );
43 void postvisit( PointerType * pointerType );
44 void postvisit( ArrayType * arrayType );
45 void postvisit( ReferenceType * refType );
46 void postvisit( StructInstType * structInst );
47 void postvisit( UnionInstType * unionInst );
48 void postvisit( EnumInstType * enumInst );
49 void postvisit( TypeInstType * typeInst );
50 void postvisit( TupleType * tupleType );
51 void postvisit( VarArgsType * varArgsType );
52 void postvisit( ZeroType * zeroType );
53 void postvisit( OneType * oneType );
54 void postvisit( GlobalScopeType * globalType );
55 void postvisit( QualifiedType * qualType );
56
57 private:
58 void handleQualifiers( Type *type );
59 std::string handleGeneric( ReferenceToType * refType );
60 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
61 };
62
63 std::string genDemangleType( Type * type, const std::string & baseString ) {
64 PassVisitor<GenType> gt( baseString );
65 assert( type );
66 type->accept( gt );
67 return gt.pass.typeString;
68 }
69
70 GenType::GenType( const std::string &typeString ) : typeString( typeString ) {}
71
72 // *** BaseSyntaxNode
73 void GenType::previsit( BaseSyntaxNode * ) {
74 // turn off automatic recursion for all nodes, to allow each visitor to
75 // precisely control the order in which its children are visited.
76 visit_children = false;
77 }
78
79 void GenType::postvisit( BaseSyntaxNode * node ) {
80 std::stringstream ss;
81 node->print( ss );
82 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
83 }
84
85 void GenType::postvisit( VoidType * voidType ) {
86 typeString = "void " + typeString;
87 handleQualifiers( voidType );
88 }
89
90 void GenType::postvisit( BasicType * basicType ) {
91 BasicType::Kind kind = basicType->kind;
92 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );
93 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;
94 handleQualifiers( basicType );
95 }
96
97 void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool ) {
98 std::ostringstream os;
99 if ( typeString != "" ) {
100 if ( typeString[ 0 ] == '*' ) {
101 os << "(" << typeString << ")";
102 } else {
103 os << typeString;
104 } // if
105 } // if
106 os << "[";
107
108 if ( qualifiers.is_const ) {
109 os << "const ";
110 } // if
111 if ( qualifiers.is_volatile ) {
112 os << "volatile ";
113 } // if
114 if ( qualifiers.is_restrict ) {
115 os << "__restrict ";
116 } // if
117 if ( qualifiers.is_atomic ) {
118 os << "_Atomic ";
119 } // if
120 if ( dimension != 0 ) {
121 // TODO: ???
122 // PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
123 // dimension->accept( cg );
124 } else if ( isVarLen ) {
125 // no dimension expression on a VLA means it came in with the * token
126 os << "*";
127 } // if
128 os << "]";
129
130 typeString = os.str();
131
132 base->accept( *visitor );
133 }
134
135 void GenType::postvisit( PointerType * pointerType ) {
136 assert( pointerType->base != 0);
137 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {
138 assert(false);
139 genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );
140 } else {
141 handleQualifiers( pointerType );
142 if ( typeString[ 0 ] == '?' ) {
143 typeString = "* " + typeString;
144 } else {
145 typeString = "*" + typeString;
146 } // if
147 pointerType->base->accept( *visitor );
148 } // if
149 }
150
151 void GenType::postvisit( ArrayType * arrayType ) {
152 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );
153 }
154
155 void GenType::postvisit( ReferenceType * refType ) {
156 assert( false );
157 assert( refType->base != 0);
158 handleQualifiers( refType );
159 typeString = "&" + typeString;
160 refType->base->accept( *visitor );
161 }
162
163 void GenType::postvisit( FunctionType * funcType ) {
164 std::ostringstream os;
165
166 if ( typeString != "" ) {
167 if ( typeString[0] == '*' ) {
168 os << "(" << typeString << ")";
169 } else {
170 os << typeString;
171 } // if
172 } // if
173
174 /************* parameters ***************/
175 const std::list<DeclarationWithType *> &pars = funcType->parameters;
176
177 if ( pars.empty() ) {
178 if ( funcType->get_isVarArgs() ) {
179 os << "()";
180 } else {
181 os << "(void)";
182 } // if
183 } else {
184 os << "(" ;
185
186 unsigned int i = 0;
187 for (DeclarationWithType * p : pars) {
188 os << genDemangleType( p->get_type(), "" );
189 if (++i != pars.size()) os << ", ";
190 }
191
192 if ( funcType->get_isVarArgs() ) {
193 os << ", ...";
194 } // if
195 os << ")";
196 } // if
197
198 typeString = os.str();
199
200 if ( funcType->returnVals.size() == 0 ) {
201 typeString += ": void";
202 } else {
203 typeString += ": " + genDemangleType(funcType->returnVals.front()->get_type(), "");
204 } // if
205
206 // add forall
207 if( ! funcType->forall.empty() ) {
208 std::ostringstream os;
209 os << "forall(";
210 unsigned int i = 0;
211 for ( auto td : funcType->forall ) {
212 os << td->typeString() << " " << td->name;
213 if (! td->assertions.empty()) {
214 os << " | { ";
215 unsigned int j = 0;
216 for (DeclarationWithType * assert : td->assertions) {
217 os << genDemangleType(assert->get_type(), assert->name);
218 if (++j != td->assertions.size()) os << ", ";
219 }
220 os << "}";
221 }
222 if (++i != funcType->forall.size()) os << ", ";
223 }
224 os << ")";
225 typeString = typeString + " -> " + os.str();
226 }
227 }
228
229 std::string GenType::handleGeneric( ReferenceToType * refType ) {
230 if ( ! refType->parameters.empty() ) {
231 std::ostringstream os;
232 // TODO: ???
233 // PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
234 os << "(";
235 // cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
236 os << ") ";
237 return os.str();
238 }
239 return "";
240 }
241
242 void GenType::postvisit( StructInstType * structInst ) {
243 typeString = "struct " + structInst->name + handleGeneric( structInst ) + " " + typeString;
244 handleQualifiers( structInst );
245 }
246
247 void GenType::postvisit( UnionInstType * unionInst ) {
248 typeString = "union " + unionInst->name + handleGeneric( unionInst ) + " " + typeString;
249 handleQualifiers( unionInst );
250 }
251
252 void GenType::postvisit( EnumInstType * enumInst ) {
253 typeString = "enum " + enumInst->name + " " + typeString;
254 handleQualifiers( enumInst );
255 }
256
257 void GenType::postvisit( TypeInstType * typeInst ) {
258 typeString = typeInst->name + " " + typeString;
259 handleQualifiers( typeInst );
260 }
261
262 void GenType::postvisit( TupleType * tupleType ) {
263 unsigned int i = 0;
264 std::ostringstream os;
265 os << "[";
266 for ( Type * t : *tupleType ) {
267 i++;
268 os << genDemangleType( t, "" ) << (i == tupleType->size() ? "" : ", ");
269 }
270 os << "] ";
271 typeString = os.str() + typeString;
272 }
273
274 void GenType::postvisit( VarArgsType * varArgsType ) {
275 typeString = "__builtin_va_list " + typeString;
276 handleQualifiers( varArgsType );
277 }
278
279 void GenType::postvisit( ZeroType * zeroType ) {
280 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
281 typeString = "zero_t " + typeString;
282 handleQualifiers( zeroType );
283 }
284
285 void GenType::postvisit( OneType * oneType ) {
286 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
287 typeString = "one_t " + typeString;
288 handleQualifiers( oneType );
289 }
290
291 void GenType::postvisit( GlobalScopeType * globalType ) {
292 handleQualifiers( globalType );
293 }
294
295 void GenType::postvisit( QualifiedType * qualType ) {
296 std::ostringstream os;
297 os << genDemangleType( qualType->parent, "" ) << "." << genDemangleType( qualType->child, "" ) << typeString;
298 typeString = os.str();
299 handleQualifiers( qualType );
300 }
301
302 void GenType::handleQualifiers( Type * type ) {
303 if ( type->get_const() ) {
304 typeString = "const " + typeString;
305 } // if
306 if ( type->get_volatile() ) {
307 typeString = "volatile " + typeString;
308 } // if
309 if ( type->get_restrict() ) {
310 typeString = "__restrict " + typeString;
311 } // if
312 if ( type->get_atomic() ) {
313 typeString = "_Atomic " + typeString;
314 } // if
315 if ( type->get_lvalue() ) {
316 // when not generating C code, print lvalue for debugging.
317 typeString = "lvalue " + typeString;
318 }
319 }
320}
321
322
323namespace SymTab {
324 namespace Mangler {
325 namespace {
326 struct StringView {
327 private:
328 std::string str;
329 size_t idx = 0;
330 // typedef Type * (StringView::*parser)(Type::Qualifiers);
331 typedef std::function<Type * (Type::Qualifiers)> parser;
332 std::vector<std::pair<std::string, parser>> parsers;
333 public:
334 StringView(const std::string & str);
335
336 bool done() const { return idx >= str.size(); }
337 char cur() const { assert(! done()); return str[idx]; }
338
339 bool expect(char ch) { return str[idx++] == ch; }
340 void next(size_t inc = 1) { idx += inc; }
341
342 /// determines if `pref` is a prefix of `str`
343 bool isPrefix(const std::string & pref);
344 bool extractNumber(size_t & out);
345 bool extractName(std::string & out);
346 bool stripMangleName(std::string & name);
347
348 Type * parseFunction(Type::Qualifiers tq);
349 Type * parseTuple(Type::Qualifiers tq);
350 Type * parseVoid(Type::Qualifiers tq);
351 Type * parsePointer(Type::Qualifiers tq);
352 Type * parseStruct(Type::Qualifiers tq);
353
354 Type * parseType();
355 bool parse(std::string & name, Type *& type);
356 };
357
358 StringView::StringView(const std::string & str) : str(str) {
359 // basic types
360 for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
361 parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
362 PRINT( std::cerr << "basic type: " << k << std::endl; )
363 return new BasicType(tq, (BasicType::Kind)k);
364 });
365 }
366 // everything else
367 parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
368 parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
369 parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
370 parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
371 parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
372 }
373
374 bool StringView::extractNumber(size_t & out) {
375 std::stringstream numss;
376 while (isdigit(str[idx])) {
377 numss << str[idx];
378 ++idx;
379 if (idx >= str.size()) return false;
380 }
381 if (! (numss >> out)) return false;
382 return true;
383 }
384
385 bool StringView::extractName(std::string & out) {
386 size_t len;
387 if (! extractNumber(len)) return false;
388 if (idx+len >= str.size()) return false;
389 out = str.substr(idx, len);
390 idx += len;
391 return true;
392 }
393
394 bool StringView::isPrefix(const std::string & pref) {
395 if ( pref.size() > str.size()-idx ) return false;
396 auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
397 if (its.first == pref.end()) {
398 idx += pref.size();
399 return true;
400 }
401 return false;
402 }
403
404 // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
405 bool StringView::stripMangleName(std::string & name) {
406 PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
407 if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
408 if (! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back())) return false;
409
410 // get name
411 if (! extractName(name)) return false;
412
413 // find bounds for type
414 PRINT( std::cerr << idx << " " << str.size() << std::endl; )
415 PRINT( std::cerr << "[");
416 while (isdigit(str.back())) {
417 PRINT(std::cerr << ".");
418 str.pop_back();
419 if (str.size() <= idx) return false;
420 }
421 PRINT( std::cerr << "]" << std::endl );
422 if (str.back() != '_') return false;
423 str.pop_back();
424 PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
425 return str.size() > idx;
426 }
427
428 Type * StringView::parseFunction(Type::Qualifiers tq) {
429 PRINT( std::cerr << "function..." << std::endl; )
430 if (done()) return nullptr;
431 FunctionType * ftype = new FunctionType( tq, false );
432 std::unique_ptr<Type> manager(ftype);
433 Type * retVal = parseType();
434 if (! retVal) return nullptr;
435 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
436 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
437 if (done() || ! expect('_')) return nullptr;
438 while (! done()) {
439 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
440 if (cur() == '_') return manager.release();
441 Type * param = parseType();
442 if (! param) return nullptr;
443 PRINT( std::cerr << "with parameter : " << param << std::endl; )
444 ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
445 }
446 return nullptr;
447 }
448
449 Type * StringView::parseTuple(Type::Qualifiers tq) {
450 PRINT( std::cerr << "tuple..." << std::endl; )
451 std::list< Type * > types;
452 size_t ncomponents;
453 if (! extractNumber(ncomponents)) return nullptr;
454 for (size_t i = 0; i < ncomponents; ++i) {
455 // TODO: delete all on return
456 if (done()) return nullptr;
457 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
458 Type * t = parseType();
459 if (! t) return nullptr;
460 PRINT( std::cerr << "with type : " << t << std::endl; )
461 types.push_back(t);
462 }
463 return new TupleType( tq, types );
464 }
465
466 Type * StringView::parseVoid(Type::Qualifiers tq) {
467 return new VoidType( tq );
468 }
469
470 Type * StringView::parsePointer(Type::Qualifiers tq) {
471 PRINT( std::cerr << "pointer..." << std::endl; )
472 Type * t = parseType();
473 if (! t) return nullptr;
474 return new PointerType( tq, t );
475 }
476
477 Type * StringView::parseStruct(Type::Qualifiers tq) {
478 PRINT( std::cerr << "struct..." << std::endl; )
479 std::string name;
480 if (! extractName(name)) return nullptr;
481 return new StructInstType(tq, name);
482 }
483
484 Type * StringView::parseType() {
485 if (done()) return nullptr;
486
487 // qualifiers
488 Type::Qualifiers tq;
489 while (true) {
490 auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
491 return isPrefix(val.second);
492 });
493 if (qual == Encoding::qualifiers.end()) break;
494 tq |= qual->first;
495 }
496
497 // find the correct type parser and use it
498 auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
499 return isPrefix(p.first);
500 });
501 assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
502 return iter->second(tq);
503 }
504
505 bool StringView::parse(std::string & name, Type *& type) {
506 if (! stripMangleName(name)) return false;
507 PRINT( std::cerr << "stripped name: " << name << std::endl; )
508 Type * t = parseType();
509 if (! t) return false;
510 type = t;
511 return true;
512 }
513
514 std::string demangle(const std::string & mangleName) {
515 SymTab::Mangler::StringView view(mangleName);
516 std::string name;
517 Type * type = nullptr;
518 if (! view.parse(name, type)) return mangleName;
519 std::unique_ptr<Type> manager(type);
520 return genDemangleType(type, name);
521 }
522 } // namespace
523 } // namespace Mangler
524} // namespace SymTab
525
526extern "C" {
527 char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
528 const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
529 return strdup(demangleName.c_str());
530 }
531}
532
533// Local Variables: //
534// tab-width: 4 //
535// mode: c++ //
536// compile-command: "make install" //
537// End: //
Note: See TracBrowser for help on using the repository browser.