source: src/SymTab/Demangle.cc@ 1b54b54

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since 1b54b54 was 56b53b2, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Fixed warning and remove u flags in call to ar which is ignored any way

  • Property mode set to 100644
File size: 20.0 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 * parseArray(Type::Qualifiers tq);
353 Type * parseStruct(Type::Qualifiers tq);
354 Type * parseUnion(Type::Qualifiers tq);
355 Type * parseEnum(Type::Qualifiers tq);
356 Type * parseType(Type::Qualifiers tq);
357
358 Type * parseType();
359 bool parse(std::string & name, Type *& type);
360 };
361
362 StringView::StringView(const std::string & str) : str(str) {
363 // basic types
364 for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
365 parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
366 PRINT( std::cerr << "basic type: " << k << std::endl; )
367 return new BasicType(tq, (BasicType::Kind)k);
368 });
369 }
370 // type variable types
371 for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
372 static const std::string typeVariableNames[] = { "DT", "FT", "TT", };
373 static_assert(
374 sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
375 "Each type variable kind should have a demangle name prefix"
376 );
377 parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
378 PRINT( std::cerr << "type variable type: " << k << std::endl; )
379 size_t N;
380 if (! extractNumber(N)) return nullptr;
381 return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
382 });
383 }
384 // everything else
385 parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
386 parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
387 parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
388 parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
389 parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
390 parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
391 parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
392 parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
393 parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
394 parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
395 parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
396 }
397
398 bool StringView::extractNumber(size_t & out) {
399 std::stringstream numss;
400 if (idx >= str.size()) return false;
401 while (isdigit(str[idx])) {
402 numss << str[idx];
403 ++idx;
404 if (idx == str.size()) break;
405 }
406 if (! (numss >> out)) return false;
407 PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
408 return true;
409 }
410
411 bool StringView::extractName(std::string & out) {
412 size_t len;
413 if (! extractNumber(len)) return false;
414 if (idx+len > str.size()) return false;
415 out = str.substr(idx, len);
416 idx += len;
417 PRINT( std::cerr << "extractName success: " << out << std::endl; )
418 return true;
419 }
420
421 bool StringView::isPrefix(const std::string & pref) {
422 if ( pref.size() > str.size()-idx ) return false;
423 auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
424 if (its.first == pref.end()) {
425 idx += pref.size();
426 return true;
427 }
428 return false;
429 }
430
431 // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
432 bool StringView::stripMangleName(std::string & name) {
433 PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
434 if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
435 if (! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back())) return false;
436
437 // get name
438 if (! extractName(name)) return false;
439
440 // find bounds for type
441 PRINT( std::cerr << idx << " " << str.size() << std::endl; )
442 PRINT( std::cerr << "[");
443 while (isdigit(str.back())) {
444 PRINT(std::cerr << ".");
445 str.pop_back();
446 if (str.size() <= idx) return false;
447 }
448 PRINT( std::cerr << "]" << std::endl );
449 if (str.back() != '_') return false;
450 str.pop_back();
451 PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
452 return str.size() > idx;
453 }
454
455 Type * StringView::parseFunction(Type::Qualifiers tq) {
456 PRINT( std::cerr << "function..." << std::endl; )
457 if (done()) return nullptr;
458 FunctionType * ftype = new FunctionType( tq, false );
459 std::unique_ptr<Type> manager(ftype);
460 Type * retVal = parseType();
461 if (! retVal) return nullptr;
462 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
463 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
464 if (done() || ! expect('_')) return nullptr;
465 while (! done()) {
466 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
467 if (cur() == '_') return manager.release();
468 Type * param = parseType();
469 if (! param) return nullptr;
470 PRINT( std::cerr << "with parameter : " << param << std::endl; )
471 ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
472 }
473 return nullptr;
474 }
475
476 Type * StringView::parseTuple(Type::Qualifiers tq) {
477 PRINT( std::cerr << "tuple..." << std::endl; )
478 std::list< Type * > types;
479 size_t ncomponents;
480 if (! extractNumber(ncomponents)) return nullptr;
481 for (size_t i = 0; i < ncomponents; ++i) {
482 // TODO: delete all on return
483 if (done()) return nullptr;
484 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
485 Type * t = parseType();
486 if (! t) return nullptr;
487 PRINT( std::cerr << "with type : " << t << std::endl; )
488 types.push_back(t);
489 }
490 return new TupleType( tq, types );
491 }
492
493 Type * StringView::parseVoid(Type::Qualifiers tq) {
494 return new VoidType( tq );
495 }
496
497 Type * StringView::parsePointer(Type::Qualifiers tq) {
498 PRINT( std::cerr << "pointer..." << std::endl; )
499 Type * t = parseType();
500 if (! t) return nullptr;
501 return new PointerType( tq, t );
502 }
503
504 Type * StringView::parseArray(Type::Qualifiers tq) {
505 PRINT( std::cerr << "array..." << std::endl; )
506 size_t length;
507 if (! extractNumber(length)) return nullptr;
508 Type * t = parseType();
509 if (! t) return nullptr;
510 return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
511 }
512
513 Type * StringView::parseStruct(Type::Qualifiers tq) {
514 PRINT( std::cerr << "struct..." << std::endl; )
515 std::string name;
516 if (! extractName(name)) return nullptr;
517 return new StructInstType(tq, name);
518 }
519
520 Type * StringView::parseUnion(Type::Qualifiers tq) {
521 PRINT( std::cerr << "union..." << std::endl; )
522 std::string name;
523 if (! extractName(name)) return nullptr;
524 return new UnionInstType(tq, name);
525 }
526
527 Type * StringView::parseEnum(Type::Qualifiers tq) {
528 PRINT( std::cerr << "enum..." << std::endl; )
529 std::string name;
530 if (! extractName(name)) return nullptr;
531 return new EnumInstType(tq, name);
532 }
533
534 Type * StringView::parseType(Type::Qualifiers tq) {
535 PRINT( std::cerr << "type..." << std::endl; )
536 std::string name;
537 if (! extractName(name)) return nullptr;
538 PRINT( std::cerr << "typename..." << name << std::endl; )
539 return new TypeInstType(tq, name, false);
540 }
541
542 Type * StringView::parseType() {
543 if (done()) return nullptr;
544
545 std::list<TypeDecl *> forall;
546 if (isPrefix(Encoding::forall)) {
547 PRINT( std::cerr << "polymorphic with..." << std::endl; )
548 size_t dcount, fcount, vcount, acount;
549 if (! extractNumber(dcount)) return nullptr;
550 PRINT( std::cerr << dcount << " dtypes" << std::endl; )
551 if (! expect('_')) return nullptr;
552 if (! extractNumber(fcount)) return nullptr;
553 PRINT( std::cerr << fcount << " ftypes" << std::endl; )
554 if (! expect('_')) return nullptr;
555 if (! extractNumber(vcount)) return nullptr;
556 PRINT( std::cerr << vcount << " ttypes" << std::endl; )
557 if (! expect('_')) return nullptr;
558 if (! extractNumber(acount)) return nullptr;
559 PRINT( std::cerr << acount << " assertions" << std::endl; )
560 if (! expect('_')) return nullptr;
561 for (size_t i = 0; i < acount; ++i) {
562 // TODO: need to recursively parse assertions, but for now just return nullptr so that
563 // demangler does not crash if there are assertions
564 return nullptr;
565 }
566 if (! expect('_')) return nullptr;
567 }
568
569 // qualifiers
570 Type::Qualifiers tq;
571 while (true) {
572 auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
573 return isPrefix(val.second);
574 });
575 if (qual == Encoding::qualifiers.end()) break;
576 tq |= qual->first;
577 }
578
579 // find the correct type parser and use it
580 auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
581 return isPrefix(p.first);
582 });
583 assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
584 Type * ret = iter->second(tq);
585 if (! ret) return nullptr;
586 ret->forall = std::move(forall);
587 return ret;
588 }
589
590 bool StringView::parse(std::string & name, Type *& type) {
591 if (! stripMangleName(name)) return false;
592 PRINT( std::cerr << "stripped name: " << name << std::endl; )
593 Type * t = parseType();
594 if (! t) return false;
595 type = t;
596 return true;
597 }
598
599 std::string demangle(const std::string & mangleName) {
600 SymTab::Mangler::StringView view(mangleName);
601 std::string name;
602 Type * type = nullptr;
603 if (! view.parse(name, type)) return mangleName;
604 std::unique_ptr<Type> manager(type);
605 return genDemangleType(type, name);
606 }
607 } // namespace
608 } // namespace Mangler
609} // namespace SymTab
610
611extern "C" {
612 char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
613 const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
614 return strdup(demangleName.c_str());
615 }
616}
617
618// Local Variables: //
619// tab-width: 4 //
620// mode: c++ //
621// compile-command: "make install" //
622// End: //
Note: See TracBrowser for help on using the repository browser.