Changeset 934fa0f for src/SymTab


Ignore:
Timestamp:
Nov 7, 2023, 2:25:25 PM (6 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
790d835
Parents:
0589e83
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Demangle.cc

    r0589e83 r934fa0f  
    1717#include <sstream>
    1818
     19#include "AST/Pass.hpp"
     20#include "AST/Type.hpp"
    1921#include "CodeGen/GenType.h"
    2022#include "CodeGen/OperatorTable.h"
     
    328330} // namespace SymTab
    329331
     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
    330619extern "C" {
    331620        char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
    332                 const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
     621                const std::string & demangleName = Mangle::demangle(mangleName);
    333622                return strdup(demangleName.c_str());
    334623        }
Note: See TracChangeset for help on using the changeset viewer.