Index: include/lldb/Core/Mangled.h =================================================================== --- include/lldb/Core/Mangled.h +++ include/lldb/Core/Mangled.h @@ -11,8 +11,9 @@ #define liblldb_Mangled_h_ #if defined(__cplusplus) -#include "lldb/Utility/ConstString.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/Utility/ConstString.h" #include "llvm/ADT/StringRef.h" #include @@ -306,20 +307,23 @@ /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin /// parser currently. /// - /// @param[in] spec - /// The RichManglingSpec that provides the context for this function. One - /// instance can be used for multiple calls. Should be stack-allocated in - /// the caller's frame. + /// 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. + /// 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(RichManglingSpec &spec, + DemangleWithRichManglingInfo(RichManglingContext &context, SkipMangledNameFn *skip_mangled_name); private: Index: include/lldb/Core/RichManglingInfo.h =================================================================== --- /dev/null +++ include/lldb/Core/RichManglingInfo.h @@ -0,0 +1,95 @@ +//===-- 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-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" this function returns "b". + const char *GetFunctionBaseName() const; + + /// Get the context name for a function. For "a::b::c", this function returns + /// "a::b". + const char *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 ParserT *get() const { + assert(m_legacy_parser.hasValue()); + assert(llvm::any_isa(m_legacy_parser)); + return llvm::any_cast(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/Symbol/Symtab.h =================================================================== --- include/lldb/Symbol/Symtab.h +++ include/lldb/Symbol/Symtab.h @@ -17,93 +17,9 @@ #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Symbol/Symbol.h" #include "lldb/lldb-private.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" this function returns "b". - const char *getFunctionBaseName() const; - - /// Get the context name for a function. For "a::b::c", this function returns - /// "a::b". - const char *getFunctionDeclContextName() const; - -private: - enum InfoProvider { ItaniumPartialDemangler, PluginCxxLanguage }; - - /// Selects the rich mangling info provider. Initially undefined, but - /// initialized in RichManglingSpec::CreateX (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. Keep a void* here instead and cast it on-demand on the cpp. - void *m_legacy_parser = nullptr; - - /// 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 ParserT *get() const { - assert(m_legacy_parser); - return reinterpret_cast(m_legacy_parser); - } - - /// Reset the provider and clean up memory before reassigning/destroying. - void ResetProvider(); - - // Default construction in undefined state from RichManglingSpec. - RichManglingInfo() = default; - - // Destruction from RichManglingSpec. - ~RichManglingInfo(); - - // No copy - RichManglingInfo(const RichManglingInfo &) = delete; - RichManglingInfo &operator=(const RichManglingInfo &) = delete; - - // No move - RichManglingInfo(RichManglingInfo &&) = delete; - RichManglingInfo &operator=(RichManglingInfo &&) = delete; - - // Declare RichManglingSpec as friend so it can access the default ctor and - // assign to members in its CreateX methods. - friend class RichManglingSpec; -}; - -//---------------------------------------------------------------------- - -/// Unique owner of RichManglingInfo. Handles initialization and lifetime. -class RichManglingSpec { -public: - RichManglingInfo *CreateItaniumInfo(); - RichManglingInfo *CreateLegacyCxxParserInfo(const ConstString &mangled); - - llvm::ItaniumPartialDemangler &GetIPD() { return m_IPD; } - -private: - RichManglingInfo m_info; - llvm::ItaniumPartialDemangler m_IPD; -}; - -//---------------------------------------------------------------------- - class Symtab { public: typedef std::vector IndexCollection; Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -192,7 +192,7 @@ class RegularExpression; class REPL; class RichManglingInfo; -class RichManglingSpec; +class RichManglingContext; class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; 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: 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" @@ -289,7 +290,7 @@ // makes use of ItaniumPartialDemangler's rich demangle info //---------------------------------------------------------------------- const RichManglingInfo * -Mangled::DemangleWithRichManglingInfo(RichManglingSpec &spec, +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); @@ -315,13 +316,13 @@ 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(), spec.GetIPD())) { + 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 spec.CreateItaniumInfo(); + return context.SetItaniumInfo(); } else { m_demangled.SetCString(""); return nullptr; @@ -347,7 +348,7 @@ } else { // Demangled successfully, we can try and parse it with // CPlusPlusLanguage::MethodName. - return spec.CreateLegacyCxxParserInfo(m_mangled); + return context.SetLegacyCxxParserInfo(m_mangled); } } } Index: source/Core/RichManglingInfo.cpp =================================================================== --- /dev/null +++ source/Core/RichManglingInfo.cpp @@ -0,0 +1,93 @@ +//===-- 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" + +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(); + 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()->GetBasename(); + return base_name.front() == '~'; + } + } +} + +bool RichManglingInfo::IsFunction() const { + switch (m_provider) { + case ItaniumPartialDemangler: + return m_IPD->isFunction(); + case PluginCxxLanguage: + return get()->IsValid(); + } +} + +const char *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 buf; + } + return nullptr; + case PluginCxxLanguage: + return get()->GetBasename().data(); + } +} + +const char *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 buf; + } + return nullptr; + case PluginCxxLanguage: + return get()->GetContext().data(); + } +} Index: source/Symbol/Symtab.cpp =================================================================== --- source/Symbol/Symtab.cpp +++ source/Symbol/Symtab.cpp @@ -10,9 +10,10 @@ #include #include -#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" @@ -22,7 +23,6 @@ #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" -#include "llvm/Demangle/Demangle.h" using namespace lldb; using namespace lldb_private; @@ -213,81 +213,6 @@ return nullptr; } -//---------------------------------------------------------------------- -// RichManglingInfo -//---------------------------------------------------------------------- - -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) { - assert(m_provider == RichManglingInfo::PluginCxxLanguage); - delete get(); - m_legacy_parser = nullptr; - } -} - -RichManglingInfo *RichManglingSpec::CreateItaniumInfo() { - m_info.ResetProvider(); - m_info.m_provider = RichManglingInfo::ItaniumPartialDemangler; - m_info.m_IPD = &m_IPD; - return &m_info; -} - -RichManglingInfo * -RichManglingSpec::CreateLegacyCxxParserInfo(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()->GetBasename(); - return base_name.front() == '~'; - } - } -} - -bool RichManglingInfo::isFunction() const { - switch (m_provider) { - case ItaniumPartialDemangler: - return m_IPD->isFunction(); - case PluginCxxLanguage: - return get()->IsValid(); - } -} - -const char *RichManglingInfo::getFunctionBaseName() const { - switch (m_provider) { - case ItaniumPartialDemangler: - m_IPD_buf = m_IPD->getFunctionBaseName(m_IPD_buf, &m_IPD_size); - return m_IPD_buf; - case PluginCxxLanguage: - return get()->GetBasename().data(); - } -} - -const char *RichManglingInfo::getFunctionDeclContextName() const { - switch (m_provider) { - case ItaniumPartialDemangler: - m_IPD_buf = m_IPD->getFunctionDeclContextName(m_IPD_buf, &m_IPD_size); - return m_IPD_buf; - case PluginCxxLanguage: - return get()->GetContext().data(); - } -} - //---------------------------------------------------------------------- // InitNameIndexes //---------------------------------------------------------------------- @@ -361,7 +286,7 @@ // Instantiation of the demangler is expensive, so better use a single one // for all entries during batch processing. - RichManglingSpec spec; + RichManglingContext MC; NameToIndexMap::Entry entry; for (entry.value = 0; entry.value < num_symbols; ++entry.value) { @@ -392,7 +317,7 @@ const SymbolType type = symbol->GetType(); if (type == eSymbolTypeCode || type == eSymbolTypeResolver) { if (const RichManglingInfo *info = - mangled.DemangleWithRichManglingInfo(spec, lldb_skip_name)) + mangled.DemangleWithRichManglingInfo(MC, lldb_skip_name)) RegisterMangledNameEntry(entry, class_contexts, mangled_name_to_index, symbol_contexts, *info); @@ -465,7 +390,7 @@ UniqueCStringMap &mangled_name_to_index, std::vector &symbol_contexts, const RichManglingInfo &info) { // Only register functions that have a base name. - const char *base_name_cstr = info.getFunctionBaseName(); + const char *base_name_cstr = info.GetFunctionBaseName(); if (base_name_cstr == nullptr) return; @@ -473,7 +398,7 @@ entry.cstring = ConstString(base_name_cstr); // Register functions with no context. - ConstString decl_context(info.getFunctionDeclContextName()); + ConstString decl_context(info.GetFunctionDeclContextName()); if (decl_context.IsEmpty()) { // This has to be a basename m_basename_to_index.Append(entry); @@ -488,7 +413,7 @@ // Register constructors and destructors. They are methods and create // declaration contexts. - if (info.isCtorOrDtor()) { + if (info.IsCtorOrDtor()) { m_method_to_index.Append(entry); if (it == class_contexts.end()) class_contexts.insert(it, decl_context.GetCString());