155 changes: 143 additions & 12 deletions lldb/source/DataFormatters/FormatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -472,6 +475,21 @@ FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
return validator_chosen_sp;
}

void
FormatManager::LoopThroughCategories (CategoryCallback callback, void* param)
{
m_categories_map.LoopThrough(callback, param);
Mutex::Locker locker(m_language_categories_mutex);
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)
Expand Down Expand Up @@ -596,8 +614,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)
{
Expand All @@ -618,6 +636,29 @@ 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)
{
Mutex::Locker locker(m_language_categories_mutex);
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)
Expand Down Expand Up @@ -655,7 +696,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)
Expand Down Expand Up @@ -713,7 +776,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)
Expand Down Expand Up @@ -772,7 +857,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)
Expand Down Expand Up @@ -818,7 +925,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)
Expand Down Expand Up @@ -857,6 +986,8 @@ FormatManager::FormatManager() :
m_named_summaries_map(this),
m_last_revision(0),
m_categories_map(this),
m_language_categories_map(),
m_language_categories_mutex(Mutex::eMutexTypeRecursive),
m_default_category_name(ConstString("default")),
m_system_category_name(ConstString("system")),
m_gnu_cpp_category_name(ConstString("gnu-libstdc++")),
Expand Down Expand Up @@ -1083,16 +1214,16 @@ 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);
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);

std_string_summary_sp);
libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"),
std_wstring_summary_sp);
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);
std_wstring_summary_sp);

SyntheticChildren::Flags stl_synth_flags;
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
Expand Down
133 changes: 133 additions & 0 deletions lldb/source/DataFormatters/LanguageCategory.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
20 changes: 8 additions & 12 deletions lldb/source/DataFormatters/TypeCategoryMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Language/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
add_subdirectory(CPlusPlus)
add_subdirectory(ObjC)
add_subdirectory(ObjCPlusPlus)
6 changes: 6 additions & 0 deletions lldb/source/Target/Language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ Language::ForEach (std::function<bool(Language*)> callback)
}
}

lldb::TypeCategoryImplSP
Language::GetFormatters ()
{
return nullptr;
}

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
Expand Down