source: src/SymTab/Demangle.cc @ 790d835

Last change on this file since 790d835 was 934fa0f, checked in by Andrew Beach <ajbeach@…>, 7 months ago

Translated the demangling code from the old ast to the new ast.

  • Property mode set to 100644
File size: 22.4 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 "AST/Pass.hpp"
20#include "AST/Type.hpp"
21#include "CodeGen/GenType.h"
22#include "CodeGen/OperatorTable.h"
23#include "Common/PassVisitor.h"
24#include "Common/utility.h"                                                             // isPrefix
25#include "Mangler.h"
26#include "SynTree/Type.h"
27#include "SynTree/Declaration.h"
28
29#define DEBUG
30#ifdef DEBUG
31#define PRINT(x) x
32#else
33#define PRINT(x) {}
34#endif
35
36namespace SymTab {
37        namespace Mangler {
38                namespace {
39                        struct StringView {
40                        private:
41                                std::string str;
42                                size_t idx = 0;
43                                // typedef Type * (StringView::*parser)(Type::Qualifiers);
44                                typedef std::function<Type * (Type::Qualifiers)> parser;
45                                std::vector<std::pair<std::string, parser>> parsers;
46                        public:
47                                StringView(const std::string & str);
48
49                                bool done() const { return idx >= str.size(); }
50                                char cur() const { assert(! done()); return str[idx]; }
51
52                                bool expect(char ch) { return str[idx++] == ch; }
53                                void next(size_t inc = 1) { idx += inc; }
54
55                                /// determines if `pref` is a prefix of `str`
56                                bool isPrefix(const std::string & pref);
57                                bool extractNumber(size_t & out);
58                                bool extractName(std::string & out);
59                                bool stripMangleName(std::string & name);
60
61                                Type * parseFunction(Type::Qualifiers tq);
62                                Type * parseTuple(Type::Qualifiers tq);
63                                Type * parseVoid(Type::Qualifiers tq);
64                                Type * parsePointer(Type::Qualifiers tq);
65                                Type * parseArray(Type::Qualifiers tq);
66                                Type * parseStruct(Type::Qualifiers tq);
67                                Type * parseUnion(Type::Qualifiers tq);
68                                Type * parseEnum(Type::Qualifiers tq);
69                                Type * parseType(Type::Qualifiers tq);
70
71                                Type * parseType();
72                                bool parse(std::string & name, Type *& type);
73                        };
74
75                        StringView::StringView(const std::string & str) : str(str) {
76                                // basic types
77                                for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
78                                        parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
79                                                PRINT( std::cerr << "basic type: " << k << std::endl; )
80                                                return new BasicType(tq, (BasicType::Kind)k);
81                                        });
82                                }
83                                // type variable types
84                                for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
85                                        static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
86                                        static_assert(
87                                                sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
88                                                "Each type variable kind should have a demangle name prefix"
89                                        );
90                                        parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
91                                                PRINT( std::cerr << "type variable type: " << k << std::endl; )
92                                                size_t N;
93                                                if (! extractNumber(N)) return nullptr;
94                                                return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
95                                        });
96                                }
97                                // everything else
98                                parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
99                                parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
100                                parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
101                                parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
102                                parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
103                                parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
104                                parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
105                                parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
106                                parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
107                                parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
108                                parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
109                        }
110
111                        bool StringView::extractNumber(size_t & out) {
112                                std::stringstream numss;
113                                if (idx >= str.size()) return false;
114                                while (isdigit(str[idx])) {
115                                        numss << str[idx];
116                                        ++idx;
117                                        if (idx == str.size()) break;
118                                }
119                                if (! (numss >> out)) return false;
120                                PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
121                                return true;
122                        }
123
124                        bool StringView::extractName(std::string & out) {
125                                size_t len;
126                                if (! extractNumber(len)) return false;
127                                if (idx+len > str.size()) return false;
128                                out = str.substr(idx, len);
129                                idx += len;
130                                PRINT( std::cerr << "extractName success: " << out << std::endl; )
131                                return true;
132                        }
133
134                        bool StringView::isPrefix(const std::string & pref) {
135                                // if ( pref.size() > str.size()-idx ) return false;
136                                // auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
137                                // if (its.first == pref.end()) {
138                                //      idx += pref.size();
139                                //      return true;
140                                // }
141
142                                // This update is untested because there are no tests for this code.
143                                if ( ::isPrefix( str, pref, idx ) ) {
144                                        idx += pref.size();
145                                        return true;
146                                }
147                                return false;
148                        }
149
150                        // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
151                        bool StringView::stripMangleName(std::string & name) {
152                                PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
153                                if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
154                                if ( ! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back() ) ) return false;
155
156                                // get name
157                                if (! extractName(name)) return false;
158
159                                // find bounds for type
160                                PRINT( std::cerr << idx << " " << str.size() << std::endl; )
161                                PRINT( std::cerr << "[");
162                                while (isdigit(str.back())) {
163                                        PRINT(std::cerr << ".");
164                                        str.pop_back();
165                                        if (str.size() <= idx) return false;
166                                }
167                                PRINT( std::cerr << "]" << std::endl );
168                                if (str.back() != '_') return false;
169                                str.pop_back();
170                                PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
171                                return str.size() > idx;
172                        }
173
174                        Type * StringView::parseFunction(Type::Qualifiers tq) {
175                                PRINT( std::cerr << "function..." << std::endl; )
176                                if (done()) return nullptr;
177                                FunctionType * ftype = new FunctionType( tq, false );
178                                std::unique_ptr<Type> manager(ftype);
179                                Type * retVal = parseType();
180                                if (! retVal) return nullptr;
181                                PRINT( std::cerr << "with return type: " << retVal << std::endl; )
182                                ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
183                                if (done() || ! expect('_')) return nullptr;
184                                while (! done()) {
185                                        PRINT( std::cerr << "got ch: " << cur() << std::endl; )
186                                        if (cur() == '_') return manager.release();
187                                        Type * param = parseType();
188                                        if (! param) return nullptr;
189                                        PRINT( std::cerr << "with parameter : " << param << std::endl; )
190                                        ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
191                                }
192                                return nullptr;
193                        }
194
195                        Type * StringView::parseTuple(Type::Qualifiers tq) {
196                                PRINT( std::cerr << "tuple..." << std::endl; )
197                                std::list< Type * > types;
198                                size_t ncomponents;
199                                if (! extractNumber(ncomponents)) return nullptr;
200                                for (size_t i = 0; i < ncomponents; ++i) {
201                                        // TODO: delete all on return
202                                        if (done()) return nullptr;
203                                        PRINT( std::cerr << "got ch: " << cur() << std::endl; )
204                                        Type * t = parseType();
205                                        if (! t) return nullptr;
206                                        PRINT( std::cerr << "with type : " << t << std::endl; )
207                                        types.push_back(t);
208                                }
209                                return new TupleType( tq, types );
210                        }
211
212                        Type * StringView::parseVoid(Type::Qualifiers tq) {
213                                return new VoidType( tq );
214                        }
215
216                        Type * StringView::parsePointer(Type::Qualifiers tq) {
217                                PRINT( std::cerr << "pointer..." << std::endl; )
218                                Type * t = parseType();
219                                if (! t) return nullptr;
220                                return new PointerType( tq, t );
221                        }
222
223                        Type * StringView::parseArray(Type::Qualifiers tq) {
224                                PRINT( std::cerr << "array..." << std::endl; )
225                                size_t length;
226                                if (! extractNumber(length)) return nullptr;
227                                Type * t = parseType();
228                                if (! t) return nullptr;
229                                return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
230                        }
231
232                        Type * StringView::parseStruct(Type::Qualifiers tq) {
233                                PRINT( std::cerr << "struct..." << std::endl; )
234                                std::string name;
235                                if (! extractName(name)) return nullptr;
236                                return new StructInstType(tq, name);
237                        }
238
239                        Type * StringView::parseUnion(Type::Qualifiers tq) {
240                                PRINT( std::cerr << "union..." << std::endl; )
241                                std::string name;
242                                if (! extractName(name)) return nullptr;
243                                return new UnionInstType(tq, name);
244                        }
245
246                        Type * StringView::parseEnum(Type::Qualifiers tq) {
247                                PRINT( std::cerr << "enum..." << std::endl; )
248                                std::string name;
249                                if (! extractName(name)) return nullptr;
250                                return new EnumInstType(tq, name);
251                        }
252
253                        Type * StringView::parseType(Type::Qualifiers tq) {
254                                PRINT( std::cerr << "type..." << std::endl; )
255                                std::string name;
256                                if (! extractName(name)) return nullptr;
257                                PRINT( std::cerr << "typename..." << name << std::endl; )
258                                return new TypeInstType(tq, name, false);
259                        }
260
261                        Type * StringView::parseType() {
262                                if (done()) return nullptr;
263
264                                std::list<TypeDecl *> forall;
265                                if (isPrefix(Encoding::forall)) {
266                                        PRINT( std::cerr << "polymorphic with..." << std::endl; )
267                                        size_t dcount, fcount, vcount, acount;
268                                        if (! extractNumber(dcount)) return nullptr;
269                                        PRINT( std::cerr << dcount << " dtypes" << std::endl; )
270                                        if (! expect('_')) return nullptr;
271                                        if (! extractNumber(fcount)) return nullptr;
272                                        PRINT( std::cerr << fcount << " ftypes" << std::endl; )
273                                        if (! expect('_')) return nullptr;
274                                        if (! extractNumber(vcount)) return nullptr;
275                                        PRINT( std::cerr << vcount << " ttypes" << std::endl; )
276                                        if (! expect('_')) return nullptr;
277                                        if (! extractNumber(acount)) return nullptr;
278                                        PRINT( std::cerr << acount << " assertions" << std::endl; )
279                                        if (! expect('_')) return nullptr;
280                                        for (size_t i = 0; i < acount; ++i) {
281                                                // TODO: need to recursively parse assertions, but for now just return nullptr so that
282                                                // demangler does not crash if there are assertions
283                                                return nullptr;
284                                        }
285                                        if (! expect('_')) return nullptr;
286                                }
287
288                                // qualifiers
289                                Type::Qualifiers tq;
290                                while (true) {
291                                        auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
292                                                return isPrefix(val.second);
293                                        });
294                                        if (qual == Encoding::qualifiers.end()) break;
295                                        tq |= qual->first;
296                                }
297
298                                // find the correct type parser and use it
299                                auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
300                                        return isPrefix(p.first);
301                                });
302                                assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
303                                Type * ret = iter->second(tq);
304                                if (! ret) return nullptr;
305                                ret->forall = std::move(forall);
306                                return ret;
307                        }
308
309                        bool StringView::parse(std::string & name, Type *& type) {
310                                if (! stripMangleName(name)) return false;
311                                PRINT( std::cerr << "stripped name: " << name << std::endl; )
312                                Type * t = parseType();
313                                if (! t) return false;
314                                type = t;
315                                return true;
316                        }
317
318                        std::string demangle(const std::string & mangleName) {
319                                SymTab::Mangler::StringView view(mangleName);
320                                std::string name;
321                                Type * type = nullptr;
322                                if (! view.parse(name, type)) return mangleName;
323                                auto info = CodeGen::operatorLookupByOutput(name);
324                                if (info) name = info->inputName;
325                                std::unique_ptr<Type> manager(type);
326                                return CodeGen::genType(type, name);
327                        }
328                } // namespace
329        } // namespace Mangler
330} // namespace SymTab
331
332namespace Mangle {
333
334namespace {
335
336struct Demangler {
337private:
338        std::string str;
339        size_t index = 0;
340        using Parser = std::function<ast::Type * ( ast::CV::Qualifiers )>;
341        std::vector<std::pair<std::string, Parser>> parsers;
342public:
343        Demangler( const std::string & str );
344
345        bool done() const { return str.size() <= index; }
346        char cur() const { assert( !done() ); return str[index]; }
347        bool expect( char ch ) { return str[index++] == ch; }
348
349        bool isPrefix( const std::string & pref );
350        bool extractNumber( size_t & out );
351        bool extractName( std::string & out );
352        bool stripMangleName( std::string & name );
353
354        ast::Type * parseFunction( ast::CV::Qualifiers tq );
355        ast::Type * parseTuple( ast::CV::Qualifiers tq );
356        ast::Type * parsePointer( ast::CV::Qualifiers tq );
357        ast::Type * parseArray( ast::CV::Qualifiers tq );
358        ast::Type * parseStruct( ast::CV::Qualifiers tq );
359        ast::Type * parseUnion( ast::CV::Qualifiers tq );
360        ast::Type * parseEnum( ast::CV::Qualifiers tq );
361        ast::Type * parseType( ast::CV::Qualifiers tq );
362        ast::Type * parseZero( ast::CV::Qualifiers tq );
363        ast::Type * parseOne( ast::CV::Qualifiers tq );
364
365        ast::Type * parseType();
366        bool parse( std::string & name, ast::Type *& type );
367};
368
369Demangler::Demangler(const std::string & str) : str(str) {
370        for (size_t k = 0; k < ast::BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
371                parsers.emplace_back(Encoding::basicTypes[k], [k]( ast::CV::Qualifiers tq ) {
372                        PRINT( std::cerr << "basic type: " << k << std::endl; )
373                        return new ast::BasicType( (ast::BasicType::Kind)k, tq );
374                });
375        }
376
377        for (size_t k = 0; k < ast::TypeDecl::NUMBER_OF_KINDS; ++k) {
378                static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
379                static_assert(
380                        sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == ast::TypeDecl::NUMBER_OF_KINDS,
381                        "Each type variable kind should have a demangle name prefix"
382                );
383                parsers.emplace_back(Encoding::typeVariables[k], [k, this]( ast::CV::Qualifiers tq ) -> ast::TypeInstType * {
384                        PRINT( std::cerr << "type variable type: " << k << std::endl; )
385                        size_t N;
386                        if (!extractNumber(N)) return nullptr;
387                        return new ast::TypeInstType(
388                                toString(typeVariableNames[k], N),
389                                (ast::TypeDecl::Kind)k,
390                                tq );
391                });
392        }
393
394        parsers.emplace_back(Encoding::void_t, [this]( ast::CV::Qualifiers tq ) { return new ast::VoidType(tq); });
395        parsers.emplace_back(Encoding::function, [this]( ast::CV::Qualifiers tq ) { return parseFunction(tq); });
396        parsers.emplace_back(Encoding::pointer, [this]( ast::CV::Qualifiers tq ) { return parsePointer(tq); });
397        parsers.emplace_back(Encoding::array, [this]( ast::CV::Qualifiers tq ) { return parseArray(tq); });
398        parsers.emplace_back(Encoding::tuple, [this]( ast::CV::Qualifiers tq ) { return parseTuple(tq); });
399        parsers.emplace_back(Encoding::struct_t, [this]( ast::CV::Qualifiers tq ) { return parseStruct(tq); });
400        parsers.emplace_back(Encoding::union_t, [this]( ast::CV::Qualifiers tq ) { return parseUnion(tq); });
401        parsers.emplace_back(Encoding::enum_t, [this]( ast::CV::Qualifiers tq ) { return parseEnum(tq); });
402        parsers.emplace_back(Encoding::type, [this]( ast::CV::Qualifiers tq ) { return parseType(tq); });
403        parsers.emplace_back(Encoding::zero, []( ast::CV::Qualifiers tq ) { return new ast::ZeroType(tq); });
404        parsers.emplace_back(Encoding::one, []( ast::CV::Qualifiers tq ) { return new ast::OneType(tq); });
405}
406
407bool Demangler::extractNumber( size_t & out ) {
408        std::stringstream numss;
409        if ( str.size() <= index ) return false;
410        while ( isdigit( str[index] ) ) {
411                numss << str[index];
412                ++index;
413                if ( str.size() == index ) break;
414        }
415        if ( !(numss >> out) ) return false;
416        PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
417        return true;
418}
419
420bool Demangler::extractName( std::string & out ) {
421        size_t len;
422        if ( !extractNumber(len) ) return false;
423        if ( str.size() < index + len ) return false;
424        out = str.substr( index, len );
425        index += len;
426        PRINT( std::cerr << "extractName success: " << out << std::endl; )
427        return true;
428}
429
430bool Demangler::isPrefix( const std::string & pref ) {
431        // Wraps the utility isPrefix function.
432        if ( ::isPrefix( str, pref, index ) ) {
433                index += pref.size();
434                return true;
435        }
436        return false;
437}
438
439// strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
440bool Demangler::stripMangleName( std::string & name ) {
441        PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
442        if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
443        if ( !isPrefix(Encoding::manglePrefix) || !isdigit(str.back() ) ) return false;
444
445        if (!extractName(name)) return false;
446
447        // Find bounds for type.
448        PRINT( std::cerr << index << " " << str.size() << std::endl; )
449        PRINT( std::cerr << "[");
450        while (isdigit(str.back())) {
451                PRINT(std::cerr << ".");
452                str.pop_back();
453                if (str.size() <= index) return false;
454        }
455        PRINT( std::cerr << "]" << std::endl );
456        if (str.back() != '_') return false;
457        str.pop_back();
458        PRINT( std::cerr << str.size() << " " << name << " " << str.substr(index) << std::endl; )
459        return index < str.size();
460}
461
462ast::Type * Demangler::parseFunction( ast::CV::Qualifiers tq ) {
463        PRINT( std::cerr << "function..." << std::endl; )
464        if ( done() ) return nullptr;
465        ast::FunctionType * ftype = new ast::FunctionType( ast::FixedArgs, tq );
466        std::unique_ptr<ast::Type> manager( ftype );
467        ast::Type * retVal = parseType();
468        if ( !retVal ) return nullptr;
469        PRINT( std::cerr << "with return type: " << retVal << std::endl; )
470        ftype->returns.emplace_back( retVal );
471        if ( done() || !expect('_') ) return nullptr;
472        while ( !done() ) {
473                PRINT( std::cerr << "got ch: " << cur() << std::endl; )
474                if ( cur() == '_' ) return manager.release();
475                ast::Type * param = parseType();
476                if ( !param ) return nullptr;
477                PRINT( std::cerr << "with parameter : " << param << std::endl; )
478                ftype->params.emplace_back( param );
479        }
480        return nullptr;
481}
482
483ast::Type * Demangler::parseTuple( ast::CV::Qualifiers tq ) {
484        PRINT( std::cerr << "tuple..." << std::endl; )
485        std::vector<ast::ptr<ast::Type>> types;
486        size_t ncomponents;
487        if ( !extractNumber(ncomponents) ) return nullptr;
488        for ( size_t i = 0; i < ncomponents; ++i ) {
489                if ( done() ) return nullptr;
490                PRINT( std::cerr << "got ch: " << cur() << std::endl; )
491                ast::Type * t = parseType();
492                if ( !t ) return nullptr;
493                PRINT( std::cerr << "with type : " << t << std::endl; )
494                types.push_back( t );
495        }
496        return new ast::TupleType( std::move( types ), tq );
497}
498
499ast::Type * Demangler::parsePointer( ast::CV::Qualifiers tq ) {
500        PRINT( std::cerr << "pointer..." << std::endl; )
501        ast::Type * t = parseType();
502        if ( !t ) return nullptr;
503        return new ast::PointerType( t, tq );
504}
505
506ast::Type * Demangler::parseArray( ast::CV::Qualifiers tq ) {
507        PRINT( std::cerr << "array..." << std::endl; )
508        size_t length;
509        if ( !extractNumber(length) ) return nullptr;
510        ast::Type * t = parseType();
511        if ( !t ) return nullptr;
512        return new ast::ArrayType(
513                t,
514                ast::ConstantExpr::from_ulong( CodeLocation(), length ),
515                ast::FixedLen,
516                ast::DynamicDim,
517                tq );
518}
519
520ast::Type * Demangler::parseStruct( ast::CV::Qualifiers tq ) {
521        PRINT( std::cerr << "struct..." << std::endl; )
522        std::string name;
523        if ( !extractName(name) ) return nullptr;
524        return new ast::StructInstType( name, tq );
525}
526
527ast::Type * Demangler::parseUnion( ast::CV::Qualifiers tq ) {
528        PRINT( std::cerr << "union..." << std::endl; )
529        std::string name;
530        if ( !extractName(name) ) return nullptr;
531        return new ast::UnionInstType( name, tq );
532}
533
534ast::Type * Demangler::parseEnum( ast::CV::Qualifiers tq ) {
535        PRINT( std::cerr << "enum..." << std::endl; )
536        std::string name;
537        if ( !extractName(name) ) return nullptr;
538        return new ast::EnumInstType( name, tq );
539}
540
541ast::Type * Demangler::parseType( ast::CV::Qualifiers tq ) {
542        PRINT( std::cerr << "type..." << std::endl; )
543        std::string name;
544        if ( !extractName(name) ) return nullptr;
545        PRINT( std::cerr << "typename..." << name << std::endl; )
546        return new ast::TypeInstType( name, ast::TypeDecl::Dtype, tq );
547}
548
549ast::Type * Demangler::parseType() {
550        if (done()) return nullptr;
551
552        std::list<TypeDecl *> forall;
553        if (isPrefix(Encoding::forall)) {
554                PRINT( std::cerr << "polymorphic with..." << std::endl; )
555                size_t dcount, fcount, vcount, acount;
556                if ( !extractNumber(dcount) ) return nullptr;
557                PRINT( std::cerr << dcount << " dtypes" << std::endl; )
558                if ( !expect('_') ) return nullptr;
559                if ( !extractNumber(fcount) ) return nullptr;
560                PRINT( std::cerr << fcount << " ftypes" << std::endl; )
561                if ( !expect('_')) return nullptr;
562                if ( !extractNumber(vcount)) return nullptr;
563                PRINT( std::cerr << vcount << " ttypes" << std::endl; )
564                if ( !expect('_') ) return nullptr;
565                if ( !extractNumber(acount) ) return nullptr;
566                PRINT( std::cerr << acount << " assertions" << std::endl; )
567                if ( !expect('_') ) return nullptr;
568                for ( size_t i = 0 ; i < acount ; ++i ) {
569                        // TODO: need to recursively parse assertions, but for now just return nullptr so that
570                        // demangler does not crash if there are assertions
571                        return nullptr;
572                }
573                if ( !expect('_') ) return nullptr;
574        }
575
576        ast::CV::Qualifiers tq;
577        while (true) {
578                auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
579                        return isPrefix(val.second);
580                });
581                if (qual == Encoding::qualifiers.end()) break;
582                tq |= qual->first;
583        }
584
585        // Find the correct type parser and then apply it.
586        auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, Parser> & p) {
587                return isPrefix(p.first);
588        });
589        assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), index);
590        ast::Type * ret = iter->second(tq);
591        if ( !ret ) return nullptr;
592        return ret;
593}
594
595bool Demangler::parse( std::string & name, ast::Type *& type) {
596        if ( !stripMangleName(name) ) return false;
597        PRINT( std::cerr << "stripped name: " << name << std::endl; )
598        ast::Type * t = parseType();
599        if ( !t ) return false;
600        type = t;
601        return true;
602}
603
604std::string demangle( const std::string & mangleName ) {
605        using namespace CodeGen;
606        Demangler demangler( mangleName );
607        std::string name;
608        ast::Type * type = nullptr;
609        if ( !demangler.parse( name, type ) ) return mangleName;
610        ast::readonly<ast::Type> roType = type;
611        if ( auto info = operatorLookupByOutput( name ) ) name = info->inputName;
612        return genType( type, name, Options( false, false, false, false ) );
613}
614
615} // namespace
616
617} // namespace Mangle
618
619extern "C" {
620        char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
621                const std::string & demangleName = Mangle::demangle(mangleName);
622                return strdup(demangleName.c_str());
623        }
624}
625
626// Local Variables: //
627// tab-width: 4 //
628// mode: c++ //
629// compile-command: "make install" //
630// End: //
Note: See TracBrowser for help on using the repository browser.