diff options
| author | Enrico Granata <egranata@apple.com> | 2015-09-01 01:01:48 +0000 |
|---|---|---|
| committer | Enrico Granata <egranata@apple.com> | 2015-09-01 01:01:48 +0000 |
| commit | 2233895a3b7fa414eb7a1e459ff1829170ea6b31 (patch) | |
| tree | d4baaf4020acfb48e9a44f3a8b1ac7985c4c79a7 /lldb/source/DataFormatters | |
| parent | 989364c10153a3b60260abb131295ee571c49117 (diff) | |
| download | bcm5719-llvm-2233895a3b7fa414eb7a1e459ff1829170ea6b31.tar.gz bcm5719-llvm-2233895a3b7fa414eb7a1e459ff1829170ea6b31.zip | |
Add support for language plugins to provide data formatters
Historically, data formatters all exist in a global repository (the category map)
On top of that, some formatters can be "hardcoded" when the conditions under which they apply are not expressible as a typename (or typename regex)
This change paves the way to move formatters into per-language buckets such that the C++ plugin is responsible for ownership of the C++ formatters, and so on
The advantages of this are:
a) language formatters only get created when they might apply
b) formatters for a language are clearly owned by the matching language plugin
The current model is one of static instantiation, that is a language knows the full set of formatters it vends and that is only asked-for once, and then handed off to the FormatManager
In a future revision it might be interesting to add similar ability to the language runtimes, and monitor for certain shared library events to add even more library-specific formatters
No formatters are moved as part of this change, so practically speaking this is NFC
llvm-svn: 246515
Diffstat (limited to 'lldb/source/DataFormatters')
| -rw-r--r-- | lldb/source/DataFormatters/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lldb/source/DataFormatters/FormatManager.cpp | 150 | ||||
| -rw-r--r-- | lldb/source/DataFormatters/LanguageCategory.cpp | 133 | ||||
| -rw-r--r-- | lldb/source/DataFormatters/TypeCategoryMap.cpp | 20 |
4 files changed, 276 insertions, 28 deletions
diff --git a/lldb/source/DataFormatters/CMakeLists.txt b/lldb/source/DataFormatters/CMakeLists.txt index ad29369b730..691190a5768 100644 --- a/lldb/source/DataFormatters/CMakeLists.txt +++ b/lldb/source/DataFormatters/CMakeLists.txt @@ -9,6 +9,7 @@ add_lldb_library(lldbDataFormatters FormatCache.cpp FormatClasses.cpp FormatManager.cpp + LanguageCategory.cpp LibCxx.cpp LibCxxInitializerList.cpp LibCxxList.cpp diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp index e41d341a21e..52209cae3be 100644 --- a/lldb/source/DataFormatters/FormatManager.cpp +++ b/lldb/source/DataFormatters/FormatManager.cpp @@ -16,10 +16,13 @@ #include "lldb/Core/Debugger.h" #include "lldb/DataFormatters/CXXFormatterFunctions.h" +#include "lldb/DataFormatters/LanguageCategory.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "llvm/ADT/STLExtras.h" +#include <initializer_list> + using namespace lldb; using namespace lldb_private; @@ -472,6 +475,20 @@ FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp) return validator_chosen_sp; } +void +FormatManager::LoopThroughCategories (CategoryCallback callback, void* param) +{ + m_categories_map.LoopThrough(callback, param); + for (const auto& entry : m_language_categories_map) + { + if (auto category_sp = entry.second->GetCategory()) + { + if (!callback(param, category_sp)) + break; + } + } +} + lldb::TypeCategoryImplSP FormatManager::GetCategory (const ConstString& category_name, bool can_create) @@ -596,8 +613,8 @@ FormatManager::GetValidTypeName (const ConstString& type) } ConstString -GetTypeForCache (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +FormatManager::GetTypeForCache (ValueObject& valobj, + lldb::DynamicValueType use_dynamic) { if (use_dynamic == lldb::eNoDynamicValues) { @@ -618,6 +635,28 @@ GetTypeForCache (ValueObject& valobj, return ConstString(); } +static std::initializer_list<lldb::LanguageType> +GetCandidateLanguages (ValueObject& valobj) +{ + lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage(); + switch (lang_type) + { + default: + return {lang_type}; + } +} + +LanguageCategory* +FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type) +{ + auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end(); + if (iter != end) + return iter->second.get(); + LanguageCategory* lang_category = new LanguageCategory(lang_type); + m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category); + return lang_category; +} + lldb::TypeFormatImplSP FormatManager::GetHardcodedFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic) @@ -655,7 +694,29 @@ FormatManager::GetFormat (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route"); } - retval = m_categories_map.GetFormat(valobj, use_dynamic); + + FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic); + + retval = m_categories_map.GetFormat(valobj, use_dynamic, matches); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj)) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(valobj, use_dynamic, matches, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetFormat] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) @@ -713,7 +774,29 @@ FormatManager::GetSummaryFormat (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route"); } - retval = m_categories_map.GetSummaryFormat(valobj, use_dynamic); + + FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic); + + retval = m_categories_map.GetSummaryFormat(valobj, use_dynamic, matches); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj)) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(valobj, use_dynamic, matches, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) @@ -772,7 +855,29 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route"); } - retval = m_categories_map.GetSyntheticChildren(valobj, use_dynamic); + + FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic); + + retval = m_categories_map.GetSyntheticChildren(valobj, use_dynamic, matches); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj)) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(valobj, use_dynamic, matches, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) @@ -818,7 +923,29 @@ FormatManager::GetValidator (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route"); } - retval = m_categories_map.GetValidator(valobj, use_dynamic); + + FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic); + + retval = m_categories_map.GetValidator(valobj, use_dynamic, matches); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj)) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(valobj, use_dynamic, matches, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetValidator] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) @@ -857,6 +984,7 @@ FormatManager::FormatManager() : m_named_summaries_map(this), m_last_revision(0), m_categories_map(this), + m_language_categories_map(), m_default_category_name(ConstString("default")), m_system_category_name(ConstString("system")), m_gnu_cpp_category_name(ConstString("gnu-libstdc++")), @@ -1083,17 +1211,7 @@ FormatManager::LoadLibcxxFormatters() lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider")); TypeCategoryImpl::SharedPointer libcxx_category_sp = GetCategory(m_libcxx_category_name); - - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"), - std_string_summary_sp); - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"), - std_string_summary_sp); - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"), - std_wstring_summary_sp); - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"), - std_wstring_summary_sp); - SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); diff --git a/lldb/source/DataFormatters/LanguageCategory.cpp b/lldb/source/DataFormatters/LanguageCategory.cpp new file mode 100644 index 00000000000..5d6d43228f8 --- /dev/null +++ b/lldb/source/DataFormatters/LanguageCategory.cpp @@ -0,0 +1,133 @@ +//===-- LanguageCategory.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/DataFormatters/LanguageCategory.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/DataFormatters/FormatManager.h" +#include "lldb/DataFormatters/TypeCategory.h" +#include "lldb/DataFormatters/TypeFormat.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/DataFormatters/TypeValidator.h" +#include "lldb/Target/Language.h" + +using namespace lldb; +using namespace lldb_private; + +LanguageCategory::LanguageCategory (lldb::LanguageType lang_type) : + m_category_sp(), + m_format_cache() +{ + if (Language* language_plugin = Language::FindPlugin(lang_type)) + m_category_sp = language_plugin->GetFormatters(); + if (m_category_sp) + m_category_sp->Enable(true, 1); +} + +bool +LanguageCategory::Get (ValueObject& valobj, + lldb::DynamicValueType dynamic, + FormattersMatchVector matches, + lldb::TypeFormatImplSP& format_sp) +{ + if (!m_category_sp) + return false; + + ConstString type_name = FormatManager::GetTypeForCache(valobj, dynamic); + if (type_name) + { + if (m_format_cache.GetFormat(type_name, format_sp)) + return true; + } + bool result = m_category_sp->Get(valobj, matches, format_sp); + if (type_name && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetFormat(type_name, format_sp); + } + return result; +} + +bool +LanguageCategory::Get (ValueObject& valobj, + lldb::DynamicValueType dynamic, + FormattersMatchVector matches, + lldb::TypeSummaryImplSP& format_sp) +{ + if (!m_category_sp) + return false; + + ConstString type_name = FormatManager::GetTypeForCache(valobj, dynamic); + if (type_name) + { + if (m_format_cache.GetSummary(type_name, format_sp)) + return true; + } + bool result = m_category_sp->Get(valobj, matches, format_sp); + if (type_name && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetSummary(type_name, format_sp); + } + return result; +} + +bool +LanguageCategory::Get (ValueObject& valobj, + lldb::DynamicValueType dynamic, + FormattersMatchVector matches, + lldb::SyntheticChildrenSP& format_sp) +{ + if (!m_category_sp) + return false; + + ConstString type_name = FormatManager::GetTypeForCache(valobj, dynamic); + if (type_name) + { + if (m_format_cache.GetSynthetic(type_name, format_sp)) + return true; + } + bool result = m_category_sp->Get(valobj, matches, format_sp); + if (type_name && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetSynthetic(type_name, format_sp); + } + return result; +} + +bool +LanguageCategory::Get (ValueObject& valobj, + lldb::DynamicValueType dynamic, + FormattersMatchVector matches, + lldb::TypeValidatorImplSP& format_sp) +{ + if (!m_category_sp) + return false; + + ConstString type_name = FormatManager::GetTypeForCache(valobj, dynamic); + if (type_name) + { + if (m_format_cache.GetValidator(type_name, format_sp)) + return true; + } + bool result = m_category_sp->Get(valobj, matches, format_sp); + if (type_name && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetValidator(type_name, format_sp); + } + return result; +} + +lldb::TypeCategoryImplSP +LanguageCategory::GetCategory () const +{ + return m_category_sp; +} diff --git a/lldb/source/DataFormatters/TypeCategoryMap.cpp b/lldb/source/DataFormatters/TypeCategoryMap.cpp index 96b9e6df8a4..3494a8a6860 100644 --- a/lldb/source/DataFormatters/TypeCategoryMap.cpp +++ b/lldb/source/DataFormatters/TypeCategoryMap.cpp @@ -219,7 +219,8 @@ TypeCategoryMap::AnyMatches (ConstString type_name, lldb::TypeFormatImplSP TypeCategoryMap::GetFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) + lldb::DynamicValueType use_dynamic, + FormattersMatchVector matches) { Mutex::Locker locker(m_map_mutex); @@ -228,8 +229,6 @@ TypeCategoryMap::GetFormat (ValueObject& valobj, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); - for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; @@ -247,7 +246,8 @@ TypeCategoryMap::GetFormat (ValueObject& valobj, lldb::TypeSummaryImplSP TypeCategoryMap::GetSummaryFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) + lldb::DynamicValueType use_dynamic, + FormattersMatchVector matches) { Mutex::Locker locker(m_map_mutex); @@ -256,8 +256,6 @@ TypeCategoryMap::GetSummaryFormat (ValueObject& valobj, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); - for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; @@ -276,7 +274,8 @@ TypeCategoryMap::GetSummaryFormat (ValueObject& valobj, #ifndef LLDB_DISABLE_PYTHON lldb::SyntheticChildrenSP TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) + lldb::DynamicValueType use_dynamic, + FormattersMatchVector matches) { Mutex::Locker locker(m_map_mutex); @@ -286,8 +285,6 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); - for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; @@ -306,7 +303,8 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, lldb::TypeValidatorImplSP TypeCategoryMap::GetValidator (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) + lldb::DynamicValueType use_dynamic, + FormattersMatchVector matches) { Mutex::Locker locker(m_map_mutex); @@ -315,8 +313,6 @@ TypeCategoryMap::GetValidator (ValueObject& valobj, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); - for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; |

