Ignore:
Timestamp:
Aug 2, 2018, 5:16:47 PM (3 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer
Children:
d8cb7df
Parents:
7804e2a
Message:

Update demangler for new name mangling scheme

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Demangle.cc

    r7804e2a rc20fafd  
    324324        namespace Mangler {
    325325                namespace {
    326                         // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
    327                         bool stripMangleName(const std::string & mangleName, std::string & name, std::string & type) {
    328                                 PRINT( std::cerr << "====== " << mangleName.size() << " " << mangleName << std::endl; )
    329                                 if (mangleName.size() < 4+nameSeparator.size()) return false;
    330                                 if (mangleName[0] != '_' || mangleName[1] != '_' || ! isdigit(mangleName.back())) return false;
    331 
    332                                 // find bounds for name
    333                                 size_t nameStart = 2;
    334                                 size_t nameEnd = mangleName.rfind(nameSeparator);
    335                                 PRINT( std::cerr << nameStart << " " << nameEnd << std::endl; )
    336                                 if (nameEnd == std::string::npos) return false;
    337 
    338                                 // find bounds for type
    339                                 size_t typeStart = nameEnd+nameSeparator.size();
    340                                 size_t typeEnd = mangleName.size()-1;
    341                                 PRINT( std::cerr << typeStart << " " << typeEnd << std::endl; )
    342                                 PRINT( std::cerr << "[");
    343                                 while (isdigit(mangleName[typeEnd])) {
    344                                         PRINT(std::cerr << ".");
    345                                         typeEnd--;
    346                                 }
    347                                 PRINT( std::cerr << "]" << std::endl );
    348                                 if (mangleName[typeEnd] != '_') return false;
    349                                 PRINT( std::cerr << typeEnd << std::endl; )
    350 
    351                                 // trim and return
    352                                 name = mangleName.substr(nameStart, nameEnd-nameStart);
    353                                 type = mangleName.substr(typeStart, typeEnd-typeStart);
     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], [this, 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;
    354382                                return true;
    355383                        }
    356384
    357                         /// determines if `pref` is a prefix of `str`
    358                         static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int idx ) {
     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) {
    359395                                if ( pref.size() > str.size()-idx ) return false;
    360396                                auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
    361                                 return its.first == pref.end();
    362                         }
    363 
    364                         Type * parseType(const std::string & typeString, unsigned int & idx) {
    365                                 if (idx >= typeString.size()) return nullptr;
     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                                Type * retVal = parseType();
     433                                if (! retVal) return nullptr;
     434                                PRINT( std::cerr << "with return type: " << retVal << std::endl; )
     435                                ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
     436                                if (done() || ! expect('_')) return nullptr;
     437                                while (! done()) {
     438                                        PRINT( std::cerr << "got ch: " << cur() << std::endl; )
     439                                        if (cur() == '_') return ftype;
     440                                        Type * param = parseType();
     441                                        if (! param) return nullptr;
     442                                        PRINT( std::cerr << "with parameter : " << param << std::endl; )
     443                                        ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
     444                                }
     445                                return nullptr;
     446                        }
     447
     448                        Type * StringView::parseTuple(Type::Qualifiers tq) {
     449                                PRINT( std::cerr << "tuple..." << std::endl; )
     450                                std::list< Type * > types;
     451                                size_t ncomponents;
     452                                if (! extractNumber(ncomponents)) return nullptr;
     453                                for (size_t i = 0; i < ncomponents; ++i) {
     454                                        if (done()) return nullptr;
     455                                        PRINT( std::cerr << "got ch: " << cur() << std::endl; )
     456                                        Type * t = parseType();
     457                                        if (! t) return nullptr;
     458                                        PRINT( std::cerr << "with type : " << t << std::endl; )
     459                                        types.push_back(t);
     460                                }
     461                                return new TupleType( tq, types );
     462                        }
     463
     464                        Type * StringView::parseVoid(Type::Qualifiers tq) {
     465                                return new VoidType( tq );
     466                        }
     467
     468                        Type * StringView::parsePointer(Type::Qualifiers tq) {
     469                                PRINT( std::cerr << "pointer..." << std::endl; )
     470                                Type * t = parseType();
     471                                if (! t) return nullptr;
     472                                return new PointerType( tq, t );
     473                        }
     474
     475                        Type * StringView::parseStruct(Type::Qualifiers tq) {
     476                                PRINT( std::cerr << "struct..." << std::endl; )
     477                                std::string name;
     478                                if (! extractName(name)) return nullptr;
     479                                return new StructInstType(tq, name);
     480                        }
     481
     482                        Type * StringView::parseType() {
     483                                if (done()) return nullptr;
    366484
    367485                                // qualifiers
    368486                                Type::Qualifiers tq;
    369487                                while (true) {
    370                                         auto qual = std::find_if(qualifierLetter.begin(), qualifierLetter.end(), [&idx, &typeString](decltype(qualifierLetter)::value_type val) {
    371                                                 if (isPrefix(typeString, val.second, idx)) {
    372                                                         PRINT( std::cerr << "found qualifier: " << val.second << std::endl; )
    373                                                         idx += std::string(val.second).size();
    374                                                         return true;
    375                                                 }
    376                                                 return false;
     488                                        auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
     489                                                return isPrefix(val.second);
    377490                                        });
    378                                         if (qual == qualifierLetter.end()) break;
     491                                        if (qual == Encoding::qualifiers.end()) break;
    379492                                        tq |= qual->first;
    380493                                }
    381494
    382                                 // basic types
    383                                 const char ** letter = std::find_if(&btLetter[0], &btLetter[numBtLetter], [&idx, &typeString](const std::string & letter) {
    384                                         if (isPrefix(typeString, letter, idx)) {
    385                                                 idx += letter.size();
    386                                                 return true;
    387                                         }
    388                                         return false;
     495                                // find the correct type parser and use it
     496                                auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
     497                                        return isPrefix(p.first);
    389498                                });
    390                                 if (letter != &btLetter[numBtLetter]) {
    391                                         PRINT( std::cerr << "basic type: " << (letter-btLetter) << std::endl; )
    392                                         BasicType::Kind k = (BasicType::Kind)(letter-btLetter);
    393                                         return new BasicType( tq, k );
    394                                 } // BasicType?
    395 
    396                                 // everything else
    397                                 switch(typeString[idx++]) {
    398                                         case 'F': {
    399                                                 PRINT( std::cerr << "function..." << std::endl; )
    400                                                 if (idx >= typeString.size()) return nullptr;
    401                                                 FunctionType * ftype = new FunctionType( tq, false );
    402                                                 Type * retVal = parseType(typeString, idx);
    403                                                 if (! retVal) return nullptr;
    404                                                 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
    405                                                 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
    406                                                 if (idx >= typeString.size() || typeString[idx++] != '_') return nullptr;
    407                                                 while (idx < typeString.size()) {
    408                                                         PRINT( std::cerr << "got ch: " << typeString[idx] << std::endl; )
    409                                                         if (typeString[idx] == '_') break;
    410                                                         Type * param = parseType(typeString, idx);
    411                                                         if (! param) return nullptr;
    412                                                         PRINT( std::cerr << "with parameter : " << param << std::endl; )
    413                                                         ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
    414                                                 }
    415                                                 if (idx >= typeString.size() || typeString[idx] != '_') return nullptr;
    416                                                 ++idx;
    417                                                 return ftype;
    418                                         }
    419                                         case 'v':
    420                                                 return new VoidType( tq );
    421                                         case 'T': {
    422                                                 PRINT( std::cerr << "tuple..." << std::endl; )
    423                                                 std::list< Type * > types;
    424                                                 while (idx < typeString.size()) {
    425                                                         PRINT( std::cerr << "got ch: " << typeString[idx] << std::endl; )
    426                                                         if (typeString[idx] == '_') break;
    427                                                         Type * t = parseType(typeString, idx);
    428                                                         if (! t) return nullptr;
    429                                                         PRINT( std::cerr << "with type : " << t << std::endl; )
    430                                                         types.push_back(t);
    431                                                 }
    432                                                 if (idx >= typeString.size() || typeString[idx] != '_') return nullptr;
    433                                                 ++idx;
    434                                                 return new TupleType( tq, types );
    435                                         }
    436                                         case 'P': {
    437                                                 PRINT( std::cerr << "pointer..." << std::endl; )
    438                                                 Type * t = parseType(typeString, idx);
    439                                                 if (! t) return nullptr;
    440                                                 return new PointerType( tq, t );
    441                                         }
    442 
    443                                         default: assertf(false, "Unhandled type letter: %c at index: %u", typeString[idx], idx);
    444                                 }
    445                                 return nullptr;
    446                         }
    447 
    448                         Type * parseType(const std::string & typeString) {
    449                                 unsigned int idx = 0;
    450                                 return parseType(typeString, idx);
     499                                assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
     500                                return iter->second(tq);
     501                        }
     502
     503                        bool StringView::parse(std::string & name, Type *& type) {
     504                                if (! stripMangleName(name)) return false;
     505                                PRINT( std::cerr << "stripped name: " << name << std::endl; )
     506                                Type * t = parseType();
     507                                if (! t) return false;
     508                                type = t;
     509                                return true;
    451510                        }
    452511                } // namespace
     
    456515extern "C" {
    457516        std::string cforall_demangle(const std::string & mangleName) {
    458                 std::string name, type;
    459                 if (! SymTab::Mangler::stripMangleName(mangleName, name, type)) return mangleName;
    460                 PRINT( std::cerr << name << " " << type << std::endl; )
    461                 Type * t = SymTab::Mangler::parseType(type);
    462                 if (! t) return mangleName;
    463                 return genDemangleType(t, name);
     517                SymTab::Mangler::StringView view(mangleName);
     518                std::string name;
     519                Type * type = nullptr;
     520                if (! view.parse(name, type)) return mangleName;
     521                return genDemangleType(type, name);
    464522        } // extern "C"
    465523}
Note: See TracChangeset for help on using the changeset viewer.