sgraenitz updated this revision to Diff 158638.
sgraenitz added a comment.
Minor improvements.
https://reviews.llvm.org/D50071
Files:
include/lldb/Core/Mangled.h
include/lldb/Core/RichManglingInfo.h
include/lldb/Symbol/Symtab.h
include/lldb/Utility/ConstString.h
include/lldb/lldb-forward.h
source/Core/CMakeLists.txt
source/Core/Mangled.cpp
source/Core/RichManglingInfo.cpp
source/Symbol/Symtab.cpp
Index: source/Symbol/Symtab.cpp
===================================================================
--- source/Symbol/Symtab.cpp
+++ source/Symbol/Symtab.cpp
@@ -10,9 +10,10 @@
#include <map>
#include <set>
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
#include "lldb/Core/Module.h"
+#include "lldb/Core/RichManglingInfo.h"
#include "lldb/Core/STLUtils.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -215,6 +216,39 @@
//----------------------------------------------------------------------
// InitNameIndexes
//----------------------------------------------------------------------
+static bool
+lldb_skip_name(llvm::StringRef mangled, Mangled::ManglingScheme scheme) {
+ switch (scheme) {
+ case Mangled::eManglingSchemeItanium: {
+ if (mangled.size() < 3 || !mangled.startswith("_Z"))
+ return true;
+
+ // Avoid the following types of symbols in the index.
+ switch (mangled[2]) {
+ case 'G': // guard variables
+ case 'T': // virtual tables, VTT structures, typeinfo structures + names
+ case 'Z': // named local entities (if we eventually handle
+ // eSymbolTypeData, we will want this back)
+ return true;
+
+ default:
+ break;
+ }
+
+ // Include this name in the index.
+ return false;
+ }
+
+ // No filters for this scheme yet. Include all names in indexing.
+ case Mangled::eManglingSchemeMSVC:
+ return false;
+
+ // Don't try and demangle things we can't categorize.
+ case Mangled::eManglingSchemeNone:
+ return true;
+ }
+}
+
void Symtab::InitNameIndexes() {
// Protected function, no need to lock mutex...
if (!m_name_indexes_computed) {
@@ -243,25 +277,30 @@
m_name_to_index.Reserve(actual_count);
#endif
- NameToIndexMap::Entry entry;
-
// The "const char *" in "class_contexts" must come from a
// ConstString::GetCString()
std::set<const char *> class_contexts;
UniqueCStringMap<uint32_t> mangled_name_to_index;
std::vector<const char *> symbol_contexts(num_symbols, nullptr);
+ // Instantiation of the demangler is expensive, so better use a single one
+ // for all entries during batch processing.
+ RichManglingContext MC;
+ NameToIndexMap::Entry entry;
+
for (entry.value = 0; entry.value < num_symbols; ++entry.value) {
- const Symbol *symbol = &m_symbols[entry.value];
+ Symbol *symbol = &m_symbols[entry.value];
// Don't let trampolines get into the lookup by name map If we ever need
// the trampoline symbols to be searchable by name we can remove this and
// then possibly add a new bool to any of the Symtab functions that
// lookup symbols by name to indicate if they want trampolines.
if (symbol->IsTrampoline())
continue;
- const Mangled &mangled = symbol->GetMangled();
+ // If the symbol's name string matched a Mangled::ManglingScheme, it is
+ // stored in the mangled field.
+ Mangled &mangled = symbol->GetMangled();
entry.cstring = mangled.GetMangledName();
if (entry.cstring) {
m_name_to_index.Append(entry);
@@ -274,70 +313,18 @@
m_name_to_index.Append(entry);
}
- const SymbolType symbol_type = symbol->GetType();
- if (symbol_type == eSymbolTypeCode ||
- symbol_type == eSymbolTypeResolver) {
- llvm::StringRef entry_ref(entry.cstring.GetStringRef());
- if (entry_ref[0] == '_' && entry_ref[1] == 'Z' &&
- (entry_ref[2] != 'T' && // avoid virtual table, VTT structure,
- // typeinfo structure, and typeinfo
- // name
- entry_ref[2] != 'G' && // avoid guard variables
- entry_ref[2] != 'Z')) // named local entities (if we
- // eventually handle eSymbolTypeData,
- // we will want this back)
- {
- CPlusPlusLanguage::MethodName cxx_method(
- mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
- entry.cstring = ConstString(cxx_method.GetBasename());
- if (entry.cstring) {
- // ConstString objects permanently store the string in the pool
- // so calling GetCString() on the value gets us a const char *
- // that will never go away
- const char *const_context =
- ConstString(cxx_method.GetContext()).GetCString();
-
- if (!const_context || const_context[0] == 0) {
- // No context for this function so this has to be a basename
- m_basename_to_index.Append(entry);
- // If there is no context (no namespaces or class scopes that
- // come before the function name) then this also could be a
- // fullname.
- m_name_to_index.Append(entry);
- } else {
- entry_ref = entry.cstring.GetStringRef();
- if (entry_ref[0] == '~' ||
- !cxx_method.GetQualifiers().empty()) {
- // The first character of the demangled basename is '~' which
- // means we have a class destructor. We can use this
- // information to help us know what is a class and what
- // isn't.
- if (class_contexts.find(const_context) == class_contexts.end())
- class_contexts.insert(const_context);
- m_method_to_index.Append(entry);
- } else {
- if (class_contexts.find(const_context) !=
- class_contexts.end()) {
- // The current decl context is in our "class_contexts"
- // which means this is a method on a class
- m_method_to_index.Append(entry);
- } else {
- // We don't know if this is a function basename or a
- // method, so put it into a temporary collection so once we
- // are done we can look in class_contexts to see if each
- // entry is a class or just a function and will put any
- // remaining items into m_method_to_index or
- // m_basename_to_index as needed
- mangled_name_to_index.Append(entry);
- symbol_contexts[entry.value] = const_context;
- }
- }
- }
- }
- }
+ const SymbolType type = symbol->GetType();
+ if (type == eSymbolTypeCode || type == eSymbolTypeResolver) {
+ if (const RichManglingInfo *info =
+ mangled.DemangleWithRichManglingInfo(MC, lldb_skip_name))
+ RegisterMangledNameEntry(entry, class_contexts,
+ mangled_name_to_index, symbol_contexts,
+ *info);
}
}
+ // Symbol name strings that didn't match a Mangled::ManglingScheme, are
+ // stored in the demangled field.
entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
if (entry.cstring) {
m_name_to_index.Append(entry);
@@ -379,7 +366,7 @@
m_method_to_index.Append(entry);
} else {
// If we got here, we have something that had a context (was inside
- // a namespace or class) yet we don't know if the entry
+ // a namespace or class) yet we don't know the entry
m_method_to_index.Append(entry);
m_basename_to_index.Append(entry);
}
@@ -397,6 +384,54 @@
}
}
+void Symtab::RegisterMangledNameEntry(
+ NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts,
+ UniqueCStringMap<uint32_t> &mangled_name_to_index,
+ std::vector<const char *> &symbol_contexts, const RichManglingInfo &info) {
+ // Only register functions that have a base name.
+ llvm::StringRef base_name = info.GetFunctionBaseName();
+ if (base_name.empty())
+ return;
+
+ // The base name will be our entry's name.
+ entry.cstring = ConstString(base_name.data());
+
+ // Register functions with no context.
+ llvm::StringRef decl_context = info.GetFunctionDeclContextName();
+ if (decl_context.empty()) {
+ // This has to be a basename
+ m_basename_to_index.Append(entry);
+ // If there is no context (no namespaces or class scopes that come before
+ // the function name) then this also could be a fullname.
+ m_name_to_index.Append(entry);
+ return;
+ }
+
+ // Add decl_context to the pool and see if we already know it.
+ auto decl_context_cstr = ConstString(decl_context).GetCString();
+ auto it = class_contexts.find(decl_context_cstr);
+
+ // Register constructors and destructors. They are methods and create
+ // declaration contexts.
+ if (info.IsCtorOrDtor()) {
+ m_method_to_index.Append(entry);
+ if (it == class_contexts.end())
+ class_contexts.insert(it, decl_context_cstr);
+ return;
+ }
+
+ // Register regular methods with a known declaration context.
+ if (it != class_contexts.end()) {
+ m_method_to_index.Append(entry);
+ return;
+ }
+
+ // Regular methods in unknown declaration contexts are put to the backlog. We
+ // will revisit them once we processed all remaining symbols.
+ mangled_name_to_index.Append(entry);
+ symbol_contexts[entry.value] = decl_context_cstr;
+}
+
void Symtab::PreloadSymbols() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
InitNameIndexes();
Index: source/Core/RichManglingInfo.cpp
===================================================================
--- /dev/null
+++ source/Core/RichManglingInfo.cpp
@@ -0,0 +1,95 @@
+//===-- RichManglingInfo.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/RichManglingInfo.h"
+#include "lldb/Utility/ConstString.h"
+
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+
+#include "llvm/ADT/StringRef.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void RichManglingInfo::ResetProvider() {
+ // If we want to support parsers for other languages some day, we need a
+ // switch here to delete the correct parser type.
+ if (m_legacy_parser.hasValue()) {
+ assert(m_provider == RichManglingInfo::PluginCxxLanguage);
+ delete get<CPlusPlusLanguage::MethodName>();
+ m_legacy_parser = nullptr;
+ }
+}
+
+RichManglingInfo *RichManglingContext::SetItaniumInfo() {
+ m_info.ResetProvider();
+ m_info.m_provider = RichManglingInfo::ItaniumPartialDemangler;
+ m_info.m_IPD = &m_IPD;
+ return &m_info;
+}
+
+RichManglingInfo *
+RichManglingContext::SetLegacyCxxParserInfo(const ConstString &mangled) {
+ m_info.ResetProvider();
+ m_info.m_provider = RichManglingInfo::PluginCxxLanguage;
+ m_info.m_legacy_parser = new CPlusPlusLanguage::MethodName(mangled);
+ return &m_info;
+}
+
+RichManglingInfo::~RichManglingInfo() {
+ ResetProvider();
+ delete m_IPD_buf;
+}
+
+bool RichManglingInfo::IsCtorOrDtor() const {
+ switch (m_provider) {
+ case ItaniumPartialDemangler:
+ return m_IPD->isCtorOrDtor();
+ case PluginCxxLanguage: {
+ // We can only check for destructors here.
+ auto base_name = get<CPlusPlusLanguage::MethodName>()->GetBasename();
+ return base_name.front() == '~';
+ }
+ }
+}
+
+bool RichManglingInfo::IsFunction() const {
+ switch (m_provider) {
+ case ItaniumPartialDemangler:
+ return m_IPD->isFunction();
+ case PluginCxxLanguage:
+ return get<CPlusPlusLanguage::MethodName>()->IsValid();
+ }
+}
+
+llvm::StringRef RichManglingInfo::GetFunctionBaseName() const {
+ switch (m_provider) {
+ case ItaniumPartialDemangler:
+ if (auto buf = m_IPD->getFunctionBaseName(m_IPD_buf, &m_IPD_size)) {
+ m_IPD_buf = buf;
+ return llvm::StringRef(m_IPD_buf, m_IPD_size);
+ }
+ return llvm::StringRef();
+ case PluginCxxLanguage:
+ return get<CPlusPlusLanguage::MethodName>()->GetBasename().data();
+ }
+}
+
+llvm::StringRef RichManglingInfo::GetFunctionDeclContextName() const {
+ switch (m_provider) {
+ case ItaniumPartialDemangler:
+ if (auto buf = m_IPD->getFunctionDeclContextName(m_IPD_buf, &m_IPD_size)) {
+ m_IPD_buf = buf;
+ return llvm::StringRef(m_IPD_buf, m_IPD_size);
+ }
+ return llvm::StringRef();
+ case PluginCxxLanguage:
+ return get<CPlusPlusLanguage::MethodName>()->GetContext().data();
+ }
+}
Index: source/Core/Mangled.cpp
===================================================================
--- source/Core/Mangled.cpp
+++ source/Core/Mangled.cpp
@@ -16,6 +16,7 @@
#pragma comment(lib, "dbghelp.lib")
#endif
+#include "lldb/Core/RichManglingInfo.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
@@ -195,7 +196,7 @@
int Mangled::Compare(const Mangled &a, const Mangled &b) {
return ConstString::Compare(
a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled),
- a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
+ b.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
}
//----------------------------------------------------------------------
@@ -232,6 +233,127 @@
}
}
+//----------------------------------------------------------------------
+// Local helpers for different demangling implementations.
+//----------------------------------------------------------------------
+namespace {
+
+char *GetMSVCDemangledCStr(const char *M) {
+#if defined(_MSC_VER)
+ const size_t demangled_length = 2048;
+ char *demangled_cstr = static_cast<char *>(::malloc(demangled_length));
+ ::ZeroMemory(demangled_cstr, demangled_length);
+ DWORD result = safeUndecorateName(M, demangled_cstr, demangled_length);
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
+ if (demangled_cstr && demangled_cstr[0])
+ log->Printf("demangled msvc: %s -> \"%s\"", M, demangled_cstr);
+ else
+ log->Printf("demangled msvc: %s -> error: 0x%lu", M, result);
+ }
+
+ if (result != 0) {
+ return demangled_cstr;
+ } else {
+ ::free(demangled_cstr);
+ return nullptr;
+ }
+#else
+ return nullptr;
+#endif
+}
+
+char *GetItaniumRichDemangleInfo(const char *M,
+ llvm::ItaniumPartialDemangler &IPD) {
+ char *demangled_cstr = nullptr;
+ bool err = IPD.partialDemangle(M);
+ if (!err) {
+ // Default buffer and size (will realloc in case it's too small).
+ size_t demangled_size = 80;
+ demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
+ demangled_cstr = IPD.finishDemangle(demangled_cstr, &demangled_size);
+ }
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
+ if (demangled_cstr)
+ log->Printf("demangled itanium: %s -> \"%s\"", M, demangled_cstr);
+ else
+ log->Printf("demangled itanium: %s -> error: failed to demangle", M);
+ }
+
+ return demangled_cstr;
+}
+} // namespace
+
+//----------------------------------------------------------------------
+// Explicit demangling for scheduled requests during batch processing. This
+// makes use of ItaniumPartialDemangler's rich demangle info
+//----------------------------------------------------------------------
+const RichManglingInfo *
+Mangled::DemangleWithRichManglingInfo(RichManglingContext &context,
+ SkipMangledNameFn *skip_mangled_name) {
+ // We need to generate and cache the demangled name.
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
+ "Mangled::DemangleWithRichNameIndexInfo (m_mangled = %s)",
+ m_mangled.GetCString());
+
+ // Others are not meant to arrive here. ObjC names or C's main() for example
+ // have their names stored in m_demangled, while m_mangled is empty.
+ assert(m_mangled);
+
+ // Check whether or not we are interested in this name at all.
+ llvm::StringRef M = m_mangled.GetStringRef();
+ ManglingScheme S = cstring_mangling_scheme(M.data());
+ if (skip_mangled_name && skip_mangled_name(M, S))
+ return nullptr;
+
+ switch (S) {
+ case eManglingSchemeNone:
+ // The current mangled_name_filter would allow llvm_unreachable here.
+ return nullptr;
+
+ case eManglingSchemeItanium:
+ // We want the rich mangling info here, so we don't care whether or not
+ // there is a demangled string in the pool already.
+ if (char *D = GetItaniumRichDemangleInfo(M.data(), context.GetIPD())) {
+ // Connect the counterparts in the string pool to accelerate subsequent
+ // access in GetDemangledName().
+ m_demangled.SetCStringWithMangledCounterpart(D, m_mangled);
+ std::free(D);
+
+ return context.SetItaniumInfo();
+ } else {
+ m_demangled.SetCString("");
+ return nullptr;
+ }
+
+ case eManglingSchemeMSVC: {
+ // We have no rich mangling for MSVC-mangled names yet, so first try to
+ // demangle it if necessary.
+ if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
+ if (char *D = GetMSVCDemangledCStr(M.data())) {
+ // Connect the counterparts in the string pool to accelerate
+ // subsequent access in GetDemangledName().
+ m_demangled.SetCStringWithMangledCounterpart(D, m_mangled);
+ ::free(D);
+ } else {
+ m_demangled.SetCString("");
+ }
+ }
+
+ if (m_demangled.IsEmpty()) {
+ // Cannot demangle it, so don't try parsing.
+ return nullptr;
+ } else {
+ // Demangled successfully, we can try and parse it with
+ // CPlusPlusLanguage::MethodName.
+ return context.SetLegacyCxxParserInfo(m_mangled);
+ }
+ }
+ }
+}
+
//----------------------------------------------------------------------
// Generate the demangled name on demand using this accessor. Code in this
// class will need to use this accessor if it wishes to decode the demangled
@@ -242,14 +364,12 @@
Mangled::GetDemangledName(lldb::LanguageType language) const {
// Check to make sure we have a valid mangled name and that we haven't
// already decoded our mangled name.
- if (m_mangled && !m_demangled) {
+ if (m_mangled && m_demangled.IsNull()) {
// We need to generate and cache the demangled name.
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "Mangled::GetDemangledName (m_mangled = %s)",
m_mangled.GetCString());
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE);
-
// Don't bother running anything that isn't mangled
const char *mangled_name = m_mangled.GetCString();
ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
@@ -259,60 +379,23 @@
// add it to our map.
char *demangled_name = nullptr;
switch (mangling_scheme) {
- case eManglingSchemeMSVC: {
-#if defined(_MSC_VER)
- if (log)
- log->Printf("demangle msvc: %s", mangled_name);
- const size_t demangled_length = 2048;
- demangled_name = static_cast<char *>(::malloc(demangled_length));
- ::ZeroMemory(demangled_name, demangled_length);
- DWORD result =
- safeUndecorateName(mangled_name, demangled_name, demangled_length);
- if (log) {
- if (demangled_name && demangled_name[0])
- log->Printf("demangled msvc: %s -> \"%s\"", mangled_name,
- demangled_name);
- else
- log->Printf("demangled msvc: %s -> error: 0x%lu", mangled_name,
- result);
- }
-
- if (result == 0) {
- free(demangled_name);
- demangled_name = nullptr;
- }
-#endif
+ case eManglingSchemeMSVC:
+ demangled_name = GetMSVCDemangledCStr(mangled_name);
break;
- }
case eManglingSchemeItanium: {
llvm::ItaniumPartialDemangler IPD;
- bool demangle_err = IPD.partialDemangle(mangled_name);
- if (!demangle_err) {
- // Default buffer and size (realloc is used in case it's too small).
- size_t demangled_size = 80;
- demangled_name = static_cast<char *>(::malloc(demangled_size));
- demangled_name = IPD.finishDemangle(demangled_name, &demangled_size);
- }
-
- if (log) {
- if (demangled_name)
- log->Printf("demangled itanium: %s -> \"%s\"", mangled_name,
- demangled_name);
- else
- log->Printf("demangled itanium: %s -> error: failed to demangle",
- mangled_name);
- }
+ demangled_name = GetItaniumRichDemangleInfo(mangled_name, IPD);
break;
}
case eManglingSchemeNone:
- break;
+ llvm_unreachable("eManglingSchemeNone was handled already");
}
if (demangled_name) {
m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
free(demangled_name);
}
}
- if (!m_demangled) {
+ if (m_demangled.IsNull()) {
// Set the demangled string to the empty string to indicate we tried to
// parse it once and failed.
m_demangled.SetCString("");
Index: source/Core/CMakeLists.txt
===================================================================
--- source/Core/CMakeLists.txt
+++ source/Core/CMakeLists.txt
@@ -34,6 +34,7 @@
Opcode.cpp
PluginManager.cpp
RegisterValue.cpp
+ RichManglingInfo.cpp
Scalar.cpp
SearchFilter.cpp
Section.cpp
Index: include/lldb/lldb-forward.h
===================================================================
--- include/lldb/lldb-forward.h
+++ include/lldb/lldb-forward.h
@@ -191,6 +191,8 @@
class RegisterValue;
class RegularExpression;
class REPL;
+class RichManglingInfo;
+class RichManglingContext;
class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
@@ -492,5 +494,15 @@
} // namespace lldb
+//----------------------------------------------------------------------
+// llvm forward declarations
+//----------------------------------------------------------------------
+namespace llvm {
+
+struct ItaniumPartialDemangler;
+class StringRef;
+
+} // namespace llvm
+
#endif // #if defined(__cplusplus)
#endif // LLDB_lldb_forward_h_
Index: include/lldb/Utility/ConstString.h
===================================================================
--- include/lldb/Utility/ConstString.h
+++ include/lldb/Utility/ConstString.h
@@ -345,6 +345,15 @@
//------------------------------------------------------------------
bool IsEmpty() const { return m_string == nullptr || m_string[0] == '\0'; }
+ //------------------------------------------------------------------
+ /// Test for null string.
+ ///
+ /// @return
+ /// @li \b true if there is no string associated with this instance.
+ /// @li \b false if there is a string associated with this instance.
+ //------------------------------------------------------------------
+ bool IsNull() const { return m_string == nullptr; }
+
//------------------------------------------------------------------
/// Set the C string value.
///
Index: include/lldb/Symbol/Symtab.h
===================================================================
--- include/lldb/Symbol/Symtab.h
+++ include/lldb/Symbol/Symtab.h
@@ -197,6 +197,11 @@
void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes,
SymbolContextList &sc_list);
+ void RegisterMangledNameEntry(
+ NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts,
+ UniqueCStringMap<uint32_t> &mangled_name_to_index,
+ std::vector<const char *> &symbol_contexts, const RichManglingInfo &info);
+
DISALLOW_COPY_AND_ASSIGN(Symtab);
};
Index: include/lldb/Core/RichManglingInfo.h
===================================================================
--- /dev/null
+++ include/lldb/Core/RichManglingInfo.h
@@ -0,0 +1,96 @@
+//===-- RichManglingInfo.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RichManglingInfo_h_
+#define liblldb_RichManglingInfo_h_
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/ADT/Any.h"
+#include "llvm/Demangle/Demangle.h"
+
+namespace lldb_private {
+
+/// Uniform wrapper for access to rich mangling information from different
+/// providers. See Mangled::DemangleWithRichManglingInfo()
+class RichManglingInfo {
+public:
+ /// If this symbol describes a constructor or destructor.
+ bool IsCtorOrDtor() const;
+
+ /// If this symbol describes a function.
+ bool IsFunction() const;
+
+ /// Get the base name of a function. This doesn't include trailing template
+ /// arguments, ie for "a::b<int>" this function returns "b".
+ llvm::StringRef GetFunctionBaseName() const;
+
+ /// Get the context name for a function. For "a::b::c", this function returns
+ /// "a::b".
+ llvm::StringRef GetFunctionDeclContextName() const;
+
+private:
+ enum InfoProvider { ItaniumPartialDemangler, PluginCxxLanguage };
+
+ /// Selects the rich mangling info provider. Initially undefined. Configured
+ /// from RichManglingContext::SetX (instance not accessible before).
+ InfoProvider m_provider;
+
+ /// Members for ItaniumPartialDemangler
+ llvm::ItaniumPartialDemangler *m_IPD = nullptr;
+ mutable size_t m_IPD_size = 0;
+ mutable char *m_IPD_buf = nullptr;
+
+ /// Members for PluginCxxLanguage
+ /// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The
+ /// respective header is in Plugins and including it from here causes cyclic
+ /// dependency. Instead keep a llvm::Any and cast it on-access in the cpp.
+ mutable llvm::Any m_legacy_parser;
+
+ /// Obtain the legacy parser casted to the given type. Ideally we had a type
+ /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we
+ /// can't access CPlusPlusLanguage::MethodName from within the header.
+ template <class ParserT> ParserT *get() const {
+ assert(m_legacy_parser.hasValue());
+ assert(llvm::any_isa<ParserT>(m_legacy_parser));
+ return llvm::any_cast<ParserT *>(m_legacy_parser);
+ }
+
+ /// Reset the provider and clean up memory before reassigning/destroying.
+ void ResetProvider();
+
+ // Default construction in undefined state from RichManglingContext.
+ RichManglingInfo() = default;
+
+ // Destruction from RichManglingContext.
+ ~RichManglingInfo();
+
+ // Declare RichManglingContext as friend so it can access the default ctor and
+ // assign to members in its SetX methods.
+ friend class RichManglingContext;
+};
+
+//----------------------------------------------------------------------
+
+/// Unique owner of RichManglingInfo. Handles configuration and lifetime.
+class RichManglingContext {
+public:
+ RichManglingInfo *SetItaniumInfo();
+ RichManglingInfo *SetLegacyCxxParserInfo(const ConstString &mangled);
+
+ llvm::ItaniumPartialDemangler &GetIPD() { return m_IPD; }
+
+private:
+ RichManglingInfo m_info;
+ llvm::ItaniumPartialDemangler m_IPD;
+};
+
+} // namespace lldb_private
+
+#endif
Index: include/lldb/Core/Mangled.h
===================================================================
--- include/lldb/Core/Mangled.h
+++ include/lldb/Core/Mangled.h
@@ -11,18 +11,13 @@
#define liblldb_Mangled_h_
#if defined(__cplusplus)
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-enumerations.h" // for LanguageType
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
-#include <stddef.h> // for size_t
-
-namespace lldb_private {
-class RegularExpression;
-}
-namespace lldb_private {
-class Stream;
-}
+#include <memory>
+#include <stddef.h>
namespace lldb_private {
@@ -238,7 +233,6 @@
return true;
return GetDemangledName(language) == name;
}
-
bool NameMatches(const RegularExpression ®ex,
lldb::LanguageType language) const;
@@ -300,6 +294,38 @@
//----------------------------------------------------------------------
lldb::LanguageType GuessLanguage() const;
+ /// Function signature for filtering mangled names.
+ using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);
+
+ //----------------------------------------------------------------------
+ /// Trigger explicit demangling to obtain rich mangling information. This is
+ /// optimized for batch processing while populating a name index. To get the
+ /// pure demangled name string for a single entity, use GetDemangledName()
+ /// instead.
+ ///
+ /// For names that match the Itanium mangling scheme, this uses LLVM's
+ /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
+ /// parser currently.
+ ///
+ /// This function is thread-safe when used with different \a context
+ /// instances in different threads.
+ ///
+ /// @param[in] context
+ /// The context for this function. A single instance can be stack-
+ /// allocated in the caller's frame and used for multiple calls.
+ ///
+ /// @param[in] skip_mangled_name
+ /// A filtering function for skipping entities based on name and mangling
+ /// scheme. This can be null if unused.
+ ///
+ /// @return
+ /// The rich mangling info on success, null otherwise. Expect the pointer
+ /// to be valid only until the next call to this funtion.
+ //----------------------------------------------------------------------
+ const RichManglingInfo *
+ DemangleWithRichManglingInfo(RichManglingContext &context,
+ SkipMangledNameFn *skip_mangled_name);
+
private:
//----------------------------------------------------------------------
/// Mangled member variables.
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits