diff options
| author | Peter LaFosse <peter@vector35.com> | 2026-03-10 12:27:34 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2026-03-26 17:56:23 -0400 |
| commit | 260ca61d94134b6743807e29f64b5ce4f6918d73 (patch) | |
| tree | 9b77dc9990873549f096c5eae00a2b924215946b /demangler/gnu3/demangle_gnu3.h | |
| parent | 0789f70c4a7496cf23672011cdb5bf5b8a5738c6 (diff) | |
Rewrite GNU3 demangler for performance using DemangledTypeNode
Replace the TypeBuilder-based demangling path with a lightweight
DemangledTypeNode representation that defers type object construction
until the symbol is fully parsed. This avoids repeated heap allocation
and ref-count churn during recursive descent.
Key changes:
- Add DemangledTypeNode / demangled_type_node.{h,cpp}: a compact IR
that mirrors the type grammar without allocating BN Type objects
- Use a thread_local demangler instance to amortize vector allocations
across calls
- Also commonize some of the demangled string length calculations.
Result: ~3x throughput improvement on a 180K-symbol corpus with
97.7% success rate (matching the previous implementation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'demangler/gnu3/demangle_gnu3.h')
| -rw-r--r-- | demangler/gnu3/demangle_gnu3.h | 134 |
1 files changed, 79 insertions, 55 deletions
diff --git a/demangler/gnu3/demangle_gnu3.h b/demangler/gnu3/demangle_gnu3.h index e26f3305..2e46e05d 100644 --- a/demangler/gnu3/demangle_gnu3.h +++ b/demangler/gnu3/demangle_gnu3.h @@ -35,6 +35,8 @@ #define _STD_VECTOR std::vector #endif +#include "demangled_type_node.h" + class DemangleException: public std::exception { _STD_STRING m_message; @@ -43,47 +45,62 @@ public: virtual const char* what() const noexcept { return m_message.c_str(); } }; -class DemangleGNU3 +class DemangleGNU3Reader { - class Reader +public: + DemangleGNU3Reader(const _STD_STRING& data); + void Reset(const _STD_STRING& data); + _STD_STRING PeekString(size_t count=1); + bool NextIsOneOf(const _STD_STRING& list); + _STD_STRING GetRaw(); + _STD_STRING ReadString(size_t count=1); + _STD_STRING ReadUntil(char sentinal); + + size_t Length() const { return m_data.length() - m_offset; } + + char Peek() + { + if (1 > Length()) + return '\0'; + return (char)m_data[m_offset]; + } + + char Read() { - public: - Reader(const _STD_STRING& data); - _STD_STRING PeekString(size_t count=1); - char Peek(); - bool NextIsOneOf(const _STD_STRING& list); - _STD_STRING GetRaw(); - char Read(); - _STD_STRING ReadString(size_t count=1); - _STD_STRING ReadUntil(char sentinal); - void Consume(size_t count=1); - size_t Length() const; - void UnRead(size_t count=1); - private: - _STD_STRING m_data; - size_t m_offset; - }; + if (1 > Length()) + throw DemangleException(); + return m_data[m_offset++]; + } - class SubstitutionList + void Consume(size_t count=1) { - _STD_VECTOR<BN::TypeBuilder> m_typeList; - public: - SubstitutionList(); - ~SubstitutionList(); - void PushType(BN::TypeBuilder t); - void PopType(); - const BN::TypeBuilder& GetType(size_t reference) const; - void PrintSubstitutionTable() const; - size_t Size() const { return m_typeList.size(); } - void Clear() { m_typeList.clear(); } - }; + if (count > Length()) + throw DemangleException(); + m_offset += count; + } + + void UnRead(size_t count=1) + { + if (count <= m_offset) + m_offset -= count; + } + +private: + _STD_STRING m_data; + size_t m_offset; +}; + + +class DemangleGNU3 +{ + using ParamList = _STD_VECTOR<DemangledTypeNode::Param>; BN::QualifiedName m_varName; - Reader m_reader; + DemangleGNU3Reader m_reader; BN::Architecture* m_arch; - _STD_VECTOR<BN::TypeBuilder> m_substitute; - _STD_VECTOR<BN::TypeBuilder> m_templateSubstitute; - _STD_VECTOR<_STD_VECTOR<BN::TypeBuilder>> m_functionSubstitute; + _STD_VECTOR<DemangledTypeNode> m_substitute; + _STD_VECTOR<DemangledTypeNode> m_templateSubstitute; + _STD_VECTOR<_STD_VECTOR<DemangledTypeNode>> m_functionSubstitute; _STD_STRING m_lastName; BNNameType m_nameType; bool m_localType; @@ -94,46 +111,53 @@ class DemangleGNU3 bool m_isOperatorOverload; enum SymbolType { Function, FunctionWithReturn, Data, VTable, Rtti, Name}; BN::QualifiedName DemangleBaseUnresolvedName(); - BN::TypeBuilder DemangleUnresolvedType(); + DemangledTypeNode DemangleUnresolvedType(); _STD_STRING DemangleUnarySuffixExpression(const _STD_STRING& op); _STD_STRING DemangleUnaryPrefixExpression(const _STD_STRING& op); _STD_STRING DemangleBinaryExpression(const _STD_STRING& op); _STD_STRING DemangleUnaryPrefixType(const _STD_STRING& op); _STD_STRING DemangleTypeString(); _STD_STRING DemangleExpressionList(); - BN::TypeBuilder DemangleUnqualifiedName(); + DemangledTypeNode DemangleUnqualifiedName(); _STD_STRING DemangleSourceName(); _STD_STRING DemangleNumberAsString(); _STD_STRING DemangleInitializer(); _STD_STRING DemangleExpression(); _STD_STRING DemanglePrimaryExpression(); - BN::TypeBuilder DemangleName(); - BN::TypeBuilder DemangleLocalName(); + DemangledTypeNode DemangleName(); + DemangledTypeNode DemangleLocalName(); void DemangleCVQualifiers(bool& cnst, bool& vltl, bool& rstrct); - BN::TypeBuilder DemangleSubstitution(); - const BN::TypeBuilder& DemangleTemplateSubstitution(); - void DemangleTemplateArgs(_STD_VECTOR<BN::FunctionParameter>& args); - bool DemangleEncoding(BN::Type** type, BN::QualifiedName& outName); - BN::TypeBuilder DemangleFunction(bool cnst, bool vltl); - BN::TypeBuilder DemangleType(); + DemangledTypeNode DemangleSubstitution(); + const DemangledTypeNode& DemangleTemplateSubstitution(); + void DemangleTemplateArgs(_STD_VECTOR<_STD_STRING>& args); + DemangledTypeNode DemangleFunction(bool cnst, bool vltl); + DemangledTypeNode DemangleType(); int64_t DemangleNumber(); - BN::TypeBuilder DemangleNestedName(); - void PushTemplateType(BN::TypeBuilder type); - const BN::TypeBuilder& GetTemplateType(size_t ref); - void PushType(BN::TypeBuilder type); - const BN::TypeBuilder& GetType(size_t ref); - static bool DemangleGlobalHeader(_STD_STRING& name, _STD_STRING& header); + DemangledTypeNode DemangleNestedName(); + void PushTemplateType(const DemangledTypeNode& type); + const DemangledTypeNode& GetTemplateType(size_t ref); + void PushType(const DemangledTypeNode& type); + const DemangledTypeNode& GetType(size_t ref); + + DemangledTypeNode CreateUnknownType(const BN::QualifiedName& s); + DemangledTypeNode CreateUnknownType(const _STD_STRING& s); + static void ExtendTypeName(DemangledTypeNode& type, const _STD_STRING& extend); public: DemangleGNU3(BN::Architecture* arch, const _STD_STRING& mangledName); - BN::TypeBuilder DemangleSymbol(BN::QualifiedName& varName); + void Reset(BN::Architecture* arch, const _STD_STRING& mangledName); + DemangledTypeNode DemangleSymbol(BN::QualifiedName& varName); BN::QualifiedName GetVarName() const { return m_varName; } + void PrintTables(); +}; + + +class DemangleGNU3Static +{ +public: static bool IsGNU3MangledString(const _STD_STRING& name); + static bool DemangleGlobalHeader(_STD_STRING& name, _STD_STRING& header); - // Tread lightly on this landmine; a BinaryView* will be converted to a bool; use an explicit (BN::Ref<BN::BinaryView>)view cast - static bool DemangleStringGNU3(BN::Architecture* arch, const _STD_STRING& name, BN::Ref<BN::Type>& outType, BN::QualifiedName& outVarName, const BN::Ref<BN::BinaryView>& view); - static bool DemangleStringGNU3(BN::Architecture* arch, const _STD_STRING& name, BN::Ref<BN::Type>& outType, BN::QualifiedName& outVarName, BN::BinaryView* view); static bool DemangleStringGNU3(BN::Architecture* arch, const _STD_STRING& name, BN::Ref<BN::Type>& outType, BN::QualifiedName& outVarName); - void PrintTables(); }; |
