15ffd83dbSDimitry Andric //===-- FormatManager.cpp -------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 12*0fca6ea1SDimitry Andric #include "lldb/Core/ValueObject.h" 130b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h" 140b57cec5SDimitry Andric #include "lldb/DataFormatters/LanguageCategory.h" 15bdd1243dSDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h" 160b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 170b57cec5SDimitry Andric #include "lldb/Target/Language.h" 1881ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 190b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 2081ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace lldb; 230b57cec5SDimitry Andric using namespace lldb_private; 240b57cec5SDimitry Andric using namespace lldb_private::formatters; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric struct FormatInfo { 270b57cec5SDimitry Andric Format format; 280b57cec5SDimitry Andric const char format_char; // One or more format characters that can be used for 290b57cec5SDimitry Andric // this format. 300b57cec5SDimitry Andric const char *format_name; // Long format name that can be used to specify the 310b57cec5SDimitry Andric // current format 320b57cec5SDimitry Andric }; 330b57cec5SDimitry Andric 349dba64beSDimitry Andric static constexpr FormatInfo g_format_infos[] = { 350b57cec5SDimitry Andric {eFormatDefault, '\0', "default"}, 360b57cec5SDimitry Andric {eFormatBoolean, 'B', "boolean"}, 370b57cec5SDimitry Andric {eFormatBinary, 'b', "binary"}, 380b57cec5SDimitry Andric {eFormatBytes, 'y', "bytes"}, 390b57cec5SDimitry Andric {eFormatBytesWithASCII, 'Y', "bytes with ASCII"}, 400b57cec5SDimitry Andric {eFormatChar, 'c', "character"}, 410b57cec5SDimitry Andric {eFormatCharPrintable, 'C', "printable character"}, 420b57cec5SDimitry Andric {eFormatComplexFloat, 'F', "complex float"}, 430b57cec5SDimitry Andric {eFormatCString, 's', "c-string"}, 440b57cec5SDimitry Andric {eFormatDecimal, 'd', "decimal"}, 450b57cec5SDimitry Andric {eFormatEnum, 'E', "enumeration"}, 460b57cec5SDimitry Andric {eFormatHex, 'x', "hex"}, 470b57cec5SDimitry Andric {eFormatHexUppercase, 'X', "uppercase hex"}, 480b57cec5SDimitry Andric {eFormatFloat, 'f', "float"}, 490b57cec5SDimitry Andric {eFormatOctal, 'o', "octal"}, 500b57cec5SDimitry Andric {eFormatOSType, 'O', "OSType"}, 510b57cec5SDimitry Andric {eFormatUnicode16, 'U', "unicode16"}, 520b57cec5SDimitry Andric {eFormatUnicode32, '\0', "unicode32"}, 530b57cec5SDimitry Andric {eFormatUnsigned, 'u', "unsigned decimal"}, 540b57cec5SDimitry Andric {eFormatPointer, 'p', "pointer"}, 550b57cec5SDimitry Andric {eFormatVectorOfChar, '\0', "char[]"}, 560b57cec5SDimitry Andric {eFormatVectorOfSInt8, '\0', "int8_t[]"}, 570b57cec5SDimitry Andric {eFormatVectorOfUInt8, '\0', "uint8_t[]"}, 580b57cec5SDimitry Andric {eFormatVectorOfSInt16, '\0', "int16_t[]"}, 590b57cec5SDimitry Andric {eFormatVectorOfUInt16, '\0', "uint16_t[]"}, 600b57cec5SDimitry Andric {eFormatVectorOfSInt32, '\0', "int32_t[]"}, 610b57cec5SDimitry Andric {eFormatVectorOfUInt32, '\0', "uint32_t[]"}, 620b57cec5SDimitry Andric {eFormatVectorOfSInt64, '\0', "int64_t[]"}, 630b57cec5SDimitry Andric {eFormatVectorOfUInt64, '\0', "uint64_t[]"}, 640b57cec5SDimitry Andric {eFormatVectorOfFloat16, '\0', "float16[]"}, 650b57cec5SDimitry Andric {eFormatVectorOfFloat32, '\0', "float32[]"}, 660b57cec5SDimitry Andric {eFormatVectorOfFloat64, '\0', "float64[]"}, 670b57cec5SDimitry Andric {eFormatVectorOfUInt128, '\0', "uint128_t[]"}, 680b57cec5SDimitry Andric {eFormatComplexInteger, 'I', "complex integer"}, 690b57cec5SDimitry Andric {eFormatCharArray, 'a', "character array"}, 700b57cec5SDimitry Andric {eFormatAddressInfo, 'A', "address"}, 710b57cec5SDimitry Andric {eFormatHexFloat, '\0', "hex float"}, 720b57cec5SDimitry Andric {eFormatInstruction, 'i', "instruction"}, 739dba64beSDimitry Andric {eFormatVoid, 'v', "void"}, 749dba64beSDimitry Andric {eFormatUnicode8, 'u', "unicode8"}, 759dba64beSDimitry Andric }; 769dba64beSDimitry Andric 779dba64beSDimitry Andric static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) == 789dba64beSDimitry Andric kNumFormats, 799dba64beSDimitry Andric "All formats must have a corresponding info entry."); 800b57cec5SDimitry Andric 81bdd1243dSDimitry Andric static uint32_t g_num_format_infos = std::size(g_format_infos); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric static bool GetFormatFromFormatChar(char format_char, Format &format) { 840b57cec5SDimitry Andric for (uint32_t i = 0; i < g_num_format_infos; ++i) { 850b57cec5SDimitry Andric if (g_format_infos[i].format_char == format_char) { 860b57cec5SDimitry Andric format = g_format_infos[i].format; 870b57cec5SDimitry Andric return true; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric format = eFormatInvalid; 910b57cec5SDimitry Andric return false; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 9481ad6265SDimitry Andric static bool GetFormatFromFormatName(llvm::StringRef format_name, 95*0fca6ea1SDimitry Andric Format &format) { 960b57cec5SDimitry Andric uint32_t i; 970b57cec5SDimitry Andric for (i = 0; i < g_num_format_infos; ++i) { 9881ad6265SDimitry Andric if (format_name.equals_insensitive(g_format_infos[i].format_name)) { 990b57cec5SDimitry Andric format = g_format_infos[i].format; 1000b57cec5SDimitry Andric return true; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric for (i = 0; i < g_num_format_infos; ++i) { 10581ad6265SDimitry Andric if (llvm::StringRef(g_format_infos[i].format_name) 10606c3fb27SDimitry Andric .starts_with_insensitive(format_name)) { 1070b57cec5SDimitry Andric format = g_format_infos[i].format; 1080b57cec5SDimitry Andric return true; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric format = eFormatInvalid; 1120b57cec5SDimitry Andric return false; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void FormatManager::Changed() { 1160b57cec5SDimitry Andric ++m_last_revision; 1170b57cec5SDimitry Andric m_format_cache.Clear(); 1180b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex); 1190b57cec5SDimitry Andric for (auto &iter : m_language_categories_map) { 1200b57cec5SDimitry Andric if (iter.second) 1210b57cec5SDimitry Andric iter.second->GetFormatCache().Clear(); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric bool FormatManager::GetFormatFromCString(const char *format_cstr, 1260b57cec5SDimitry Andric lldb::Format &format) { 1270b57cec5SDimitry Andric bool success = false; 1280b57cec5SDimitry Andric if (format_cstr && format_cstr[0]) { 1290b57cec5SDimitry Andric if (format_cstr[1] == '\0') { 1300b57cec5SDimitry Andric success = GetFormatFromFormatChar(format_cstr[0], format); 1310b57cec5SDimitry Andric if (success) 1320b57cec5SDimitry Andric return true; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 135*0fca6ea1SDimitry Andric success = GetFormatFromFormatName(format_cstr, format); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric if (!success) 1380b57cec5SDimitry Andric format = eFormatInvalid; 1390b57cec5SDimitry Andric return success; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric char FormatManager::GetFormatAsFormatChar(lldb::Format format) { 1430b57cec5SDimitry Andric for (uint32_t i = 0; i < g_num_format_infos; ++i) { 1440b57cec5SDimitry Andric if (g_format_infos[i].format == format) 1450b57cec5SDimitry Andric return g_format_infos[i].format_char; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric return '\0'; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric const char *FormatManager::GetFormatAsCString(Format format) { 1510b57cec5SDimitry Andric if (format >= eFormatDefault && format < kNumFormats) 1520b57cec5SDimitry Andric return g_format_infos[format].format_name; 1530b57cec5SDimitry Andric return nullptr; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric void FormatManager::EnableAllCategories() { 1570b57cec5SDimitry Andric m_categories_map.EnableAllCategories(); 1580b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex); 1590b57cec5SDimitry Andric for (auto &iter : m_language_categories_map) { 1600b57cec5SDimitry Andric if (iter.second) 1610b57cec5SDimitry Andric iter.second->Enable(); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric void FormatManager::DisableAllCategories() { 1660b57cec5SDimitry Andric m_categories_map.DisableAllCategories(); 1670b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex); 1680b57cec5SDimitry Andric for (auto &iter : m_language_categories_map) { 1690b57cec5SDimitry Andric if (iter.second) 1700b57cec5SDimitry Andric iter.second->Disable(); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric void FormatManager::GetPossibleMatches( 1755ffd83dbSDimitry Andric ValueObject &valobj, CompilerType compiler_type, 1760b57cec5SDimitry Andric lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries, 177bdd1243dSDimitry Andric FormattersMatchCandidate::Flags current_flags, bool root_level) { 1780b57cec5SDimitry Andric compiler_type = compiler_type.GetTypeForFormatters(); 1795ffd83dbSDimitry Andric ConstString type_name(compiler_type.GetTypeName()); 180*0fca6ea1SDimitry Andric // A ValueObject that couldn't be made correctly won't necessarily have a 181*0fca6ea1SDimitry Andric // target. We aren't going to find a formatter in this case anyway, so we 182*0fca6ea1SDimitry Andric // should just exit. 183*0fca6ea1SDimitry Andric TargetSP target_sp = valobj.GetTargetSP(); 184*0fca6ea1SDimitry Andric if (!target_sp) 185*0fca6ea1SDimitry Andric return; 186bdd1243dSDimitry Andric ScriptInterpreter *script_interpreter = 187*0fca6ea1SDimitry Andric target_sp->GetDebugger().GetScriptInterpreter(); 1880b57cec5SDimitry Andric if (valobj.GetBitfieldBitSize() > 0) { 1890b57cec5SDimitry Andric StreamString sstring; 1900b57cec5SDimitry Andric sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize()); 1910b57cec5SDimitry Andric ConstString bitfieldname(sstring.GetString()); 192bdd1243dSDimitry Andric entries.push_back({bitfieldname, script_interpreter, 193bdd1243dSDimitry Andric TypeImpl(compiler_type), current_flags}); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) { 197bdd1243dSDimitry Andric entries.push_back({type_name, script_interpreter, TypeImpl(compiler_type), 198bdd1243dSDimitry Andric current_flags}); 1990b57cec5SDimitry Andric 2005ffd83dbSDimitry Andric ConstString display_type_name(compiler_type.GetTypeName()); 2010b57cec5SDimitry Andric if (display_type_name != type_name) 202bdd1243dSDimitry Andric entries.push_back({display_type_name, script_interpreter, 203bdd1243dSDimitry Andric TypeImpl(compiler_type), current_flags}); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric for (bool is_rvalue_ref = true, j = true; 2070b57cec5SDimitry Andric j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) { 2080b57cec5SDimitry Andric CompilerType non_ref_type = compiler_type.GetNonReferenceType(); 209bdd1243dSDimitry Andric GetPossibleMatches(valobj, non_ref_type, use_dynamic, entries, 210bdd1243dSDimitry Andric current_flags.WithStrippedReference()); 2110b57cec5SDimitry Andric if (non_ref_type.IsTypedefType()) { 2120b57cec5SDimitry Andric CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); 2130b57cec5SDimitry Andric deffed_referenced_type = 2140b57cec5SDimitry Andric is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() 2150b57cec5SDimitry Andric : deffed_referenced_type.GetLValueReferenceType(); 216bdd1243dSDimitry Andric // this is not exactly the usual meaning of stripping typedefs 2170b57cec5SDimitry Andric GetPossibleMatches( 2180b57cec5SDimitry Andric valobj, deffed_referenced_type, 219bdd1243dSDimitry Andric use_dynamic, entries, current_flags.WithStrippedTypedef()); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric if (compiler_type.IsPointerType()) { 2240b57cec5SDimitry Andric CompilerType non_ptr_type = compiler_type.GetPointeeType(); 225bdd1243dSDimitry Andric GetPossibleMatches(valobj, non_ptr_type, use_dynamic, entries, 226bdd1243dSDimitry Andric current_flags.WithStrippedPointer()); 2270b57cec5SDimitry Andric if (non_ptr_type.IsTypedefType()) { 2280b57cec5SDimitry Andric CompilerType deffed_pointed_type = 2290b57cec5SDimitry Andric non_ptr_type.GetTypedefedType().GetPointerType(); 230bdd1243dSDimitry Andric // this is not exactly the usual meaning of stripping typedefs 231bdd1243dSDimitry Andric GetPossibleMatches(valobj, deffed_pointed_type, use_dynamic, entries, 232bdd1243dSDimitry Andric current_flags.WithStrippedTypedef()); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 236480093f4SDimitry Andric // For arrays with typedef-ed elements, we add a candidate with the typedef 237480093f4SDimitry Andric // stripped. 238480093f4SDimitry Andric uint64_t array_size; 239480093f4SDimitry Andric if (compiler_type.IsArrayType(nullptr, &array_size, nullptr)) { 240e8d8bef9SDimitry Andric ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); 241e8d8bef9SDimitry Andric CompilerType element_type = compiler_type.GetArrayElementType( 242e8d8bef9SDimitry Andric exe_ctx.GetBestExecutionContextScope()); 243480093f4SDimitry Andric if (element_type.IsTypedefType()) { 244480093f4SDimitry Andric // Get the stripped element type and compute the stripped array type 245480093f4SDimitry Andric // from it. 246480093f4SDimitry Andric CompilerType deffed_array_type = 247480093f4SDimitry Andric element_type.GetTypedefedType().GetArrayType(array_size); 248bdd1243dSDimitry Andric // this is not exactly the usual meaning of stripping typedefs 249480093f4SDimitry Andric GetPossibleMatches( 250480093f4SDimitry Andric valobj, deffed_array_type, 251bdd1243dSDimitry Andric use_dynamic, entries, current_flags.WithStrippedTypedef()); 252480093f4SDimitry Andric } 253480093f4SDimitry Andric } 254480093f4SDimitry Andric 255480093f4SDimitry Andric for (lldb::LanguageType language_type : 256480093f4SDimitry Andric GetCandidateLanguages(valobj.GetObjectRuntimeLanguage())) { 2570b57cec5SDimitry Andric if (Language *language = Language::FindPlugin(language_type)) { 258bdd1243dSDimitry Andric for (const FormattersMatchCandidate& candidate : 2590b57cec5SDimitry Andric language->GetPossibleFormattersMatches(valobj, use_dynamic)) { 260bdd1243dSDimitry Andric entries.push_back(candidate); 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric // try to strip typedef chains 2660b57cec5SDimitry Andric if (compiler_type.IsTypedefType()) { 2670b57cec5SDimitry Andric CompilerType deffed_type = compiler_type.GetTypedefedType(); 268bdd1243dSDimitry Andric GetPossibleMatches(valobj, deffed_type, use_dynamic, entries, 269bdd1243dSDimitry Andric current_flags.WithStrippedTypedef()); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric if (root_level) { 2730b57cec5SDimitry Andric do { 2740b57cec5SDimitry Andric if (!compiler_type.IsValid()) 2750b57cec5SDimitry Andric break; 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric CompilerType unqual_compiler_ast_type = 2780b57cec5SDimitry Andric compiler_type.GetFullyUnqualifiedType(); 2790b57cec5SDimitry Andric if (!unqual_compiler_ast_type.IsValid()) 2800b57cec5SDimitry Andric break; 2810b57cec5SDimitry Andric if (unqual_compiler_ast_type.GetOpaqueQualType() != 2820b57cec5SDimitry Andric compiler_type.GetOpaqueQualType()) 283bdd1243dSDimitry Andric GetPossibleMatches(valobj, unqual_compiler_ast_type, use_dynamic, 284bdd1243dSDimitry Andric entries, current_flags); 2850b57cec5SDimitry Andric } while (false); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric // if all else fails, go to static type 2880b57cec5SDimitry Andric if (valobj.IsDynamic()) { 2890b57cec5SDimitry Andric lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); 2900b57cec5SDimitry Andric if (static_value_sp) 291bdd1243dSDimitry Andric GetPossibleMatches(*static_value_sp.get(), 292bdd1243dSDimitry Andric static_value_sp->GetCompilerType(), use_dynamic, 293bdd1243dSDimitry Andric entries, current_flags, true); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric lldb::TypeFormatImplSP 2990b57cec5SDimitry Andric FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) { 3000b57cec5SDimitry Andric if (!type_sp) 3010b57cec5SDimitry Andric return lldb::TypeFormatImplSP(); 3020b57cec5SDimitry Andric lldb::TypeFormatImplSP format_chosen_sp; 3030b57cec5SDimitry Andric uint32_t num_categories = m_categories_map.GetCount(); 3040b57cec5SDimitry Andric lldb::TypeCategoryImplSP category_sp; 3050b57cec5SDimitry Andric uint32_t prio_category = UINT32_MAX; 3060b57cec5SDimitry Andric for (uint32_t category_id = 0; category_id < num_categories; category_id++) { 3070b57cec5SDimitry Andric category_sp = GetCategoryAtIndex(category_id); 3080b57cec5SDimitry Andric if (!category_sp->IsEnabled()) 3090b57cec5SDimitry Andric continue; 3100b57cec5SDimitry Andric lldb::TypeFormatImplSP format_current_sp = 3110b57cec5SDimitry Andric category_sp->GetFormatForType(type_sp); 3120b57cec5SDimitry Andric if (format_current_sp && 3130b57cec5SDimitry Andric (format_chosen_sp.get() == nullptr || 3140b57cec5SDimitry Andric (prio_category > category_sp->GetEnabledPosition()))) { 3150b57cec5SDimitry Andric prio_category = category_sp->GetEnabledPosition(); 3160b57cec5SDimitry Andric format_chosen_sp = format_current_sp; 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric return format_chosen_sp; 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric lldb::TypeSummaryImplSP 3230b57cec5SDimitry Andric FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) { 3240b57cec5SDimitry Andric if (!type_sp) 3250b57cec5SDimitry Andric return lldb::TypeSummaryImplSP(); 3260b57cec5SDimitry Andric lldb::TypeSummaryImplSP summary_chosen_sp; 3270b57cec5SDimitry Andric uint32_t num_categories = m_categories_map.GetCount(); 3280b57cec5SDimitry Andric lldb::TypeCategoryImplSP category_sp; 3290b57cec5SDimitry Andric uint32_t prio_category = UINT32_MAX; 3300b57cec5SDimitry Andric for (uint32_t category_id = 0; category_id < num_categories; category_id++) { 3310b57cec5SDimitry Andric category_sp = GetCategoryAtIndex(category_id); 3320b57cec5SDimitry Andric if (!category_sp->IsEnabled()) 3330b57cec5SDimitry Andric continue; 3340b57cec5SDimitry Andric lldb::TypeSummaryImplSP summary_current_sp = 3350b57cec5SDimitry Andric category_sp->GetSummaryForType(type_sp); 3360b57cec5SDimitry Andric if (summary_current_sp && 3370b57cec5SDimitry Andric (summary_chosen_sp.get() == nullptr || 3380b57cec5SDimitry Andric (prio_category > category_sp->GetEnabledPosition()))) { 3390b57cec5SDimitry Andric prio_category = category_sp->GetEnabledPosition(); 3400b57cec5SDimitry Andric summary_chosen_sp = summary_current_sp; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric return summary_chosen_sp; 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric lldb::TypeFilterImplSP 3470b57cec5SDimitry Andric FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) { 3480b57cec5SDimitry Andric if (!type_sp) 3490b57cec5SDimitry Andric return lldb::TypeFilterImplSP(); 3500b57cec5SDimitry Andric lldb::TypeFilterImplSP filter_chosen_sp; 3510b57cec5SDimitry Andric uint32_t num_categories = m_categories_map.GetCount(); 3520b57cec5SDimitry Andric lldb::TypeCategoryImplSP category_sp; 3530b57cec5SDimitry Andric uint32_t prio_category = UINT32_MAX; 3540b57cec5SDimitry Andric for (uint32_t category_id = 0; category_id < num_categories; category_id++) { 3550b57cec5SDimitry Andric category_sp = GetCategoryAtIndex(category_id); 3560b57cec5SDimitry Andric if (!category_sp->IsEnabled()) 3570b57cec5SDimitry Andric continue; 3580b57cec5SDimitry Andric lldb::TypeFilterImplSP filter_current_sp( 3590b57cec5SDimitry Andric (TypeFilterImpl *)category_sp->GetFilterForType(type_sp).get()); 3600b57cec5SDimitry Andric if (filter_current_sp && 3610b57cec5SDimitry Andric (filter_chosen_sp.get() == nullptr || 3620b57cec5SDimitry Andric (prio_category > category_sp->GetEnabledPosition()))) { 3630b57cec5SDimitry Andric prio_category = category_sp->GetEnabledPosition(); 3640b57cec5SDimitry Andric filter_chosen_sp = filter_current_sp; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric return filter_chosen_sp; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric lldb::ScriptedSyntheticChildrenSP 3710b57cec5SDimitry Andric FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) { 3720b57cec5SDimitry Andric if (!type_sp) 3730b57cec5SDimitry Andric return lldb::ScriptedSyntheticChildrenSP(); 3740b57cec5SDimitry Andric lldb::ScriptedSyntheticChildrenSP synth_chosen_sp; 3750b57cec5SDimitry Andric uint32_t num_categories = m_categories_map.GetCount(); 3760b57cec5SDimitry Andric lldb::TypeCategoryImplSP category_sp; 3770b57cec5SDimitry Andric uint32_t prio_category = UINT32_MAX; 3780b57cec5SDimitry Andric for (uint32_t category_id = 0; category_id < num_categories; category_id++) { 3790b57cec5SDimitry Andric category_sp = GetCategoryAtIndex(category_id); 3800b57cec5SDimitry Andric if (!category_sp->IsEnabled()) 3810b57cec5SDimitry Andric continue; 3820b57cec5SDimitry Andric lldb::ScriptedSyntheticChildrenSP synth_current_sp( 3830b57cec5SDimitry Andric (ScriptedSyntheticChildren *)category_sp->GetSyntheticForType(type_sp) 3840b57cec5SDimitry Andric .get()); 3850b57cec5SDimitry Andric if (synth_current_sp && 3860b57cec5SDimitry Andric (synth_chosen_sp.get() == nullptr || 3870b57cec5SDimitry Andric (prio_category > category_sp->GetEnabledPosition()))) { 3880b57cec5SDimitry Andric prio_category = category_sp->GetEnabledPosition(); 3890b57cec5SDimitry Andric synth_chosen_sp = synth_current_sp; 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric return synth_chosen_sp; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric void FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) { 3960b57cec5SDimitry Andric m_categories_map.ForEach(callback); 3970b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex); 3980b57cec5SDimitry Andric for (const auto &entry : m_language_categories_map) { 3990b57cec5SDimitry Andric if (auto category_sp = entry.second->GetCategory()) { 4000b57cec5SDimitry Andric if (!callback(category_sp)) 4010b57cec5SDimitry Andric break; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric lldb::TypeCategoryImplSP 4070b57cec5SDimitry Andric FormatManager::GetCategory(ConstString category_name, bool can_create) { 4080b57cec5SDimitry Andric if (!category_name) 4090b57cec5SDimitry Andric return GetCategory(m_default_category_name); 4100b57cec5SDimitry Andric lldb::TypeCategoryImplSP category; 4110b57cec5SDimitry Andric if (m_categories_map.Get(category_name, category)) 4120b57cec5SDimitry Andric return category; 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric if (!can_create) 4150b57cec5SDimitry Andric return lldb::TypeCategoryImplSP(); 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric m_categories_map.Add( 4180b57cec5SDimitry Andric category_name, 4190b57cec5SDimitry Andric lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name))); 4200b57cec5SDimitry Andric return GetCategory(category_name); 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric lldb::Format FormatManager::GetSingleItemFormat(lldb::Format vector_format) { 4240b57cec5SDimitry Andric switch (vector_format) { 4250b57cec5SDimitry Andric case eFormatVectorOfChar: 4260b57cec5SDimitry Andric return eFormatCharArray; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric case eFormatVectorOfSInt8: 4290b57cec5SDimitry Andric case eFormatVectorOfSInt16: 4300b57cec5SDimitry Andric case eFormatVectorOfSInt32: 4310b57cec5SDimitry Andric case eFormatVectorOfSInt64: 4320b57cec5SDimitry Andric return eFormatDecimal; 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric case eFormatVectorOfUInt8: 4350b57cec5SDimitry Andric case eFormatVectorOfUInt16: 4360b57cec5SDimitry Andric case eFormatVectorOfUInt32: 4370b57cec5SDimitry Andric case eFormatVectorOfUInt64: 4380b57cec5SDimitry Andric case eFormatVectorOfUInt128: 4390b57cec5SDimitry Andric return eFormatHex; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric case eFormatVectorOfFloat16: 4420b57cec5SDimitry Andric case eFormatVectorOfFloat32: 4430b57cec5SDimitry Andric case eFormatVectorOfFloat64: 4440b57cec5SDimitry Andric return eFormatFloat; 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric default: 4470b57cec5SDimitry Andric return lldb::eFormatInvalid; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) { 452*0fca6ea1SDimitry Andric TargetSP target_sp = valobj.GetTargetSP(); 4530b57cec5SDimitry Andric // if settings say no oneline whatsoever 454*0fca6ea1SDimitry Andric if (target_sp && !target_sp->GetDebugger().GetAutoOneLineSummaries()) 4550b57cec5SDimitry Andric return false; // then don't oneline 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric // if this object has a summary, then ask the summary 4580b57cec5SDimitry Andric if (valobj.GetSummaryFormat().get() != nullptr) 4590b57cec5SDimitry Andric return valobj.GetSummaryFormat()->IsOneLiner(); 4600b57cec5SDimitry Andric 461*0fca6ea1SDimitry Andric const size_t max_num_children = 462*0fca6ea1SDimitry Andric (target_sp ? *target_sp : Target::GetGlobalProperties()) 463*0fca6ea1SDimitry Andric .GetMaximumNumberOfChildrenToDisplay(); 464*0fca6ea1SDimitry Andric auto num_children = valobj.GetNumChildren(max_num_children); 465*0fca6ea1SDimitry Andric if (!num_children) { 466*0fca6ea1SDimitry Andric llvm::consumeError(num_children.takeError()); 467*0fca6ea1SDimitry Andric return true; 468*0fca6ea1SDimitry Andric } 4690b57cec5SDimitry Andric // no children, no party 470*0fca6ea1SDimitry Andric if (*num_children == 0) 4710b57cec5SDimitry Andric return false; 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric // ask the type if it has any opinion about this eLazyBoolCalculate == no 4740b57cec5SDimitry Andric // opinion; other values should be self explanatory 4750b57cec5SDimitry Andric CompilerType compiler_type(valobj.GetCompilerType()); 4760b57cec5SDimitry Andric if (compiler_type.IsValid()) { 4770b57cec5SDimitry Andric switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) { 4780b57cec5SDimitry Andric case eLazyBoolNo: 4790b57cec5SDimitry Andric return false; 4800b57cec5SDimitry Andric case eLazyBoolYes: 4810b57cec5SDimitry Andric return true; 4820b57cec5SDimitry Andric case eLazyBoolCalculate: 4830b57cec5SDimitry Andric break; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric size_t total_children_name_len = 0; 4880b57cec5SDimitry Andric 489*0fca6ea1SDimitry Andric for (size_t idx = 0; idx < *num_children; idx++) { 4900b57cec5SDimitry Andric bool is_synth_val = false; 49106c3fb27SDimitry Andric ValueObjectSP child_sp(valobj.GetChildAtIndex(idx)); 4920b57cec5SDimitry Andric // something is wrong here - bail out 4930b57cec5SDimitry Andric if (!child_sp) 4940b57cec5SDimitry Andric return false; 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric // also ask the child's type if it has any opinion 4970b57cec5SDimitry Andric CompilerType child_compiler_type(child_sp->GetCompilerType()); 4980b57cec5SDimitry Andric if (child_compiler_type.IsValid()) { 4990b57cec5SDimitry Andric switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) { 5000b57cec5SDimitry Andric case eLazyBoolYes: 5010b57cec5SDimitry Andric // an opinion of yes is only binding for the child, so keep going 5020b57cec5SDimitry Andric case eLazyBoolCalculate: 5030b57cec5SDimitry Andric break; 5040b57cec5SDimitry Andric case eLazyBoolNo: 5050b57cec5SDimitry Andric // but if the child says no, then it's a veto on the whole thing 5060b57cec5SDimitry Andric return false; 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric // if we decided to define synthetic children for a type, we probably care 5110b57cec5SDimitry Andric // enough to show them, but avoid nesting children in children 5120b57cec5SDimitry Andric if (child_sp->GetSyntheticChildren().get() != nullptr) { 5130b57cec5SDimitry Andric ValueObjectSP synth_sp(child_sp->GetSyntheticValue()); 5140b57cec5SDimitry Andric // wait.. wat? just get out of here.. 5150b57cec5SDimitry Andric if (!synth_sp) 5160b57cec5SDimitry Andric return false; 5170b57cec5SDimitry Andric // but if we only have them to provide a value, keep going 5180b57cec5SDimitry Andric if (!synth_sp->MightHaveChildren() && 5190b57cec5SDimitry Andric synth_sp->DoesProvideSyntheticValue()) 5200b57cec5SDimitry Andric is_synth_val = true; 5210b57cec5SDimitry Andric else 5220b57cec5SDimitry Andric return false; 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric total_children_name_len += child_sp->GetName().GetLength(); 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric // 50 itself is a "randomly" chosen number - the idea is that 5280b57cec5SDimitry Andric // overly long structs should not get this treatment 5290b57cec5SDimitry Andric // FIXME: maybe make this a user-tweakable setting? 5300b57cec5SDimitry Andric if (total_children_name_len > 50) 5310b57cec5SDimitry Andric return false; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // if a summary is there.. 5340b57cec5SDimitry Andric if (child_sp->GetSummaryFormat()) { 5350b57cec5SDimitry Andric // and it wants children, then bail out 5360b57cec5SDimitry Andric if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get())) 5370b57cec5SDimitry Andric return false; 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric // if this child has children.. 541*0fca6ea1SDimitry Andric if (child_sp->HasChildren()) { 5420b57cec5SDimitry Andric // ...and no summary... 5430b57cec5SDimitry Andric // (if it had a summary and the summary wanted children, we would have 5440b57cec5SDimitry Andric // bailed out anyway 5450b57cec5SDimitry Andric // so this only makes us bail out if this has no summary and we would 5460b57cec5SDimitry Andric // then print children) 5470b57cec5SDimitry Andric if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do 5480b57cec5SDimitry Andric // that if not a 5490b57cec5SDimitry Andric // synthetic valued 5500b57cec5SDimitry Andric // child 5510b57cec5SDimitry Andric return false; // then bail out 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric return true; 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric ConstString FormatManager::GetTypeForCache(ValueObject &valobj, 5580b57cec5SDimitry Andric lldb::DynamicValueType use_dynamic) { 5590b57cec5SDimitry Andric ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable( 5600b57cec5SDimitry Andric use_dynamic, valobj.IsSynthetic()); 5610b57cec5SDimitry Andric if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) { 5620b57cec5SDimitry Andric if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution()) 5630b57cec5SDimitry Andric return valobj_sp->GetQualifiedTypeName(); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric return ConstString(); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric std::vector<lldb::LanguageType> 5690b57cec5SDimitry Andric FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type) { 5700b57cec5SDimitry Andric switch (lang_type) { 5710b57cec5SDimitry Andric case lldb::eLanguageTypeC: 5720b57cec5SDimitry Andric case lldb::eLanguageTypeC89: 5730b57cec5SDimitry Andric case lldb::eLanguageTypeC99: 5740b57cec5SDimitry Andric case lldb::eLanguageTypeC11: 5750b57cec5SDimitry Andric case lldb::eLanguageTypeC_plus_plus: 5760b57cec5SDimitry Andric case lldb::eLanguageTypeC_plus_plus_03: 5770b57cec5SDimitry Andric case lldb::eLanguageTypeC_plus_plus_11: 5780b57cec5SDimitry Andric case lldb::eLanguageTypeC_plus_plus_14: 5790b57cec5SDimitry Andric return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC}; 5800b57cec5SDimitry Andric default: 5810b57cec5SDimitry Andric return {lang_type}; 5820b57cec5SDimitry Andric } 583480093f4SDimitry Andric llvm_unreachable("Fully covered switch"); 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric LanguageCategory * 5870b57cec5SDimitry Andric FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) { 5880b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex); 5890b57cec5SDimitry Andric auto iter = m_language_categories_map.find(lang_type), 5900b57cec5SDimitry Andric end = m_language_categories_map.end(); 5910b57cec5SDimitry Andric if (iter != end) 5920b57cec5SDimitry Andric return iter->second.get(); 5930b57cec5SDimitry Andric LanguageCategory *lang_category = new LanguageCategory(lang_type); 5940b57cec5SDimitry Andric m_language_categories_map[lang_type] = 5950b57cec5SDimitry Andric LanguageCategory::UniquePointer(lang_category); 5960b57cec5SDimitry Andric return lang_category; 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 599480093f4SDimitry Andric template <typename ImplSP> 600480093f4SDimitry Andric ImplSP FormatManager::GetHardcoded(FormattersMatchData &match_data) { 601480093f4SDimitry Andric ImplSP retval_sp; 6020b57cec5SDimitry Andric for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 6030b57cec5SDimitry Andric if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 6040b57cec5SDimitry Andric if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 605480093f4SDimitry Andric return retval_sp; 606480093f4SDimitry Andric } 607480093f4SDimitry Andric } 608480093f4SDimitry Andric return retval_sp; 609480093f4SDimitry Andric } 610480093f4SDimitry Andric 61106c3fb27SDimitry Andric namespace { 61206c3fb27SDimitry Andric template <typename ImplSP> const char *FormatterKind; 61306c3fb27SDimitry Andric template <> const char *FormatterKind<lldb::TypeFormatImplSP> = "format"; 61406c3fb27SDimitry Andric template <> const char *FormatterKind<lldb::TypeSummaryImplSP> = "summary"; 61506c3fb27SDimitry Andric template <> const char *FormatterKind<lldb::SyntheticChildrenSP> = "synthetic"; 61606c3fb27SDimitry Andric } // namespace 61706c3fb27SDimitry Andric 61806c3fb27SDimitry Andric #define FORMAT_LOG(Message) "[%s] " Message, FormatterKind<ImplSP> 61906c3fb27SDimitry Andric 620480093f4SDimitry Andric template <typename ImplSP> 621480093f4SDimitry Andric ImplSP FormatManager::Get(ValueObject &valobj, 622480093f4SDimitry Andric lldb::DynamicValueType use_dynamic) { 623480093f4SDimitry Andric FormattersMatchData match_data(valobj, use_dynamic); 624480093f4SDimitry Andric if (ImplSP retval_sp = GetCached<ImplSP>(match_data)) 625480093f4SDimitry Andric return retval_sp; 626480093f4SDimitry Andric 62781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters); 628480093f4SDimitry Andric 62906c3fb27SDimitry Andric LLDB_LOGF(log, FORMAT_LOG("Search failed. Giving language a chance.")); 630480093f4SDimitry Andric for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 631480093f4SDimitry Andric if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 632480093f4SDimitry Andric ImplSP retval_sp; 633480093f4SDimitry Andric if (lang_category->Get(match_data, retval_sp)) 634480093f4SDimitry Andric if (retval_sp) { 63506c3fb27SDimitry Andric LLDB_LOGF(log, FORMAT_LOG("Language search success. Returning.")); 636480093f4SDimitry Andric return retval_sp; 637480093f4SDimitry Andric } 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 64106c3fb27SDimitry Andric LLDB_LOGF(log, FORMAT_LOG("Search failed. Giving hardcoded a chance.")); 642480093f4SDimitry Andric return GetHardcoded<ImplSP>(match_data); 643480093f4SDimitry Andric } 644480093f4SDimitry Andric 645480093f4SDimitry Andric template <typename ImplSP> 646480093f4SDimitry Andric ImplSP FormatManager::GetCached(FormattersMatchData &match_data) { 647480093f4SDimitry Andric ImplSP retval_sp; 64881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters); 649480093f4SDimitry Andric if (match_data.GetTypeForCache()) { 65006c3fb27SDimitry Andric LLDB_LOGF(log, "\n\n" FORMAT_LOG("Looking into cache for type %s"), 651480093f4SDimitry Andric match_data.GetTypeForCache().AsCString("<invalid>")); 652480093f4SDimitry Andric if (m_format_cache.Get(match_data.GetTypeForCache(), retval_sp)) { 653480093f4SDimitry Andric if (log) { 65406c3fb27SDimitry Andric LLDB_LOGF(log, FORMAT_LOG("Cache search success. Returning.")); 655480093f4SDimitry Andric LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", 656480093f4SDimitry Andric m_format_cache.GetCacheHits(), 657480093f4SDimitry Andric m_format_cache.GetCacheMisses()); 658480093f4SDimitry Andric } 659480093f4SDimitry Andric return retval_sp; 660480093f4SDimitry Andric } 66106c3fb27SDimitry Andric LLDB_LOGF(log, FORMAT_LOG("Cache search failed. Going normal route")); 662480093f4SDimitry Andric } 663480093f4SDimitry Andric 664480093f4SDimitry Andric m_categories_map.Get(match_data, retval_sp); 665480093f4SDimitry Andric if (match_data.GetTypeForCache() && (!retval_sp || !retval_sp->NonCacheable())) { 66606c3fb27SDimitry Andric LLDB_LOGF(log, FORMAT_LOG("Caching %p for type %s"), 667480093f4SDimitry Andric static_cast<void *>(retval_sp.get()), 668480093f4SDimitry Andric match_data.GetTypeForCache().AsCString("<invalid>")); 669480093f4SDimitry Andric m_format_cache.Set(match_data.GetTypeForCache(), retval_sp); 670480093f4SDimitry Andric } 671480093f4SDimitry Andric LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", 672480093f4SDimitry Andric m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 6730b57cec5SDimitry Andric return retval_sp; 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 67606c3fb27SDimitry Andric #undef FORMAT_LOG 67706c3fb27SDimitry Andric 6780b57cec5SDimitry Andric lldb::TypeFormatImplSP 6790b57cec5SDimitry Andric FormatManager::GetFormat(ValueObject &valobj, 6800b57cec5SDimitry Andric lldb::DynamicValueType use_dynamic) { 681480093f4SDimitry Andric return Get<lldb::TypeFormatImplSP>(valobj, use_dynamic); 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric lldb::TypeSummaryImplSP 6850b57cec5SDimitry Andric FormatManager::GetSummaryFormat(ValueObject &valobj, 6860b57cec5SDimitry Andric lldb::DynamicValueType use_dynamic) { 687480093f4SDimitry Andric return Get<lldb::TypeSummaryImplSP>(valobj, use_dynamic); 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric lldb::SyntheticChildrenSP 6910b57cec5SDimitry Andric FormatManager::GetSyntheticChildren(ValueObject &valobj, 6920b57cec5SDimitry Andric lldb::DynamicValueType use_dynamic) { 693480093f4SDimitry Andric return Get<lldb::SyntheticChildrenSP>(valobj, use_dynamic); 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric FormatManager::FormatManager() 6970b57cec5SDimitry Andric : m_last_revision(0), m_format_cache(), m_language_categories_mutex(), 6980b57cec5SDimitry Andric m_language_categories_map(), m_named_summaries_map(this), 6990b57cec5SDimitry Andric m_categories_map(this), m_default_category_name(ConstString("default")), 7000b57cec5SDimitry Andric m_system_category_name(ConstString("system")), 7010b57cec5SDimitry Andric m_vectortypes_category_name(ConstString("VectorTypes")) { 7020b57cec5SDimitry Andric LoadSystemFormatters(); 7030b57cec5SDimitry Andric LoadVectorFormatters(); 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric EnableCategory(m_vectortypes_category_name, TypeCategoryMap::Last, 7060b57cec5SDimitry Andric lldb::eLanguageTypeObjC_plus_plus); 7070b57cec5SDimitry Andric EnableCategory(m_system_category_name, TypeCategoryMap::Last, 7080b57cec5SDimitry Andric lldb::eLanguageTypeObjC_plus_plus); 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric void FormatManager::LoadSystemFormatters() { 7120b57cec5SDimitry Andric TypeSummaryImpl::Flags string_flags; 7130b57cec5SDimitry Andric string_flags.SetCascades(true) 7140b57cec5SDimitry Andric .SetSkipPointers(true) 7150b57cec5SDimitry Andric .SetSkipReferences(false) 7160b57cec5SDimitry Andric .SetDontShowChildren(true) 7170b57cec5SDimitry Andric .SetDontShowValue(false) 7180b57cec5SDimitry Andric .SetShowMembersOneLiner(false) 7190b57cec5SDimitry Andric .SetHideItemNames(false); 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric TypeSummaryImpl::Flags string_array_flags; 7220b57cec5SDimitry Andric string_array_flags.SetCascades(true) 7230b57cec5SDimitry Andric .SetSkipPointers(true) 7240b57cec5SDimitry Andric .SetSkipReferences(false) 7250b57cec5SDimitry Andric .SetDontShowChildren(true) 7260b57cec5SDimitry Andric .SetDontShowValue(true) 7270b57cec5SDimitry Andric .SetShowMembersOneLiner(false) 7280b57cec5SDimitry Andric .SetHideItemNames(false); 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric lldb::TypeSummaryImplSP string_format( 7310b57cec5SDimitry Andric new StringSummaryFormat(string_flags, "${var%s}")); 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric lldb::TypeSummaryImplSP string_array_format( 734349cc55cSDimitry Andric new StringSummaryFormat(string_array_flags, "${var%char[]}")); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric TypeCategoryImpl::SharedPointer sys_category_sp = 7370b57cec5SDimitry Andric GetCategory(m_system_category_name); 7380b57cec5SDimitry Andric 739bdd1243dSDimitry Andric sys_category_sp->AddTypeSummary(R"(^(unsigned )?char ?(\*|\[\])$)", 740bdd1243dSDimitry Andric eFormatterMatchRegex, string_format); 7410eae32dcSDimitry Andric 742bdd1243dSDimitry Andric sys_category_sp->AddTypeSummary(R"(^((un)?signed )?char ?\[[0-9]+\]$)", 743bdd1243dSDimitry Andric eFormatterMatchRegex, string_array_format); 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric lldb::TypeSummaryImplSP ostype_summary( 7460b57cec5SDimitry Andric new StringSummaryFormat(TypeSummaryImpl::Flags() 7470b57cec5SDimitry Andric .SetCascades(false) 7480b57cec5SDimitry Andric .SetSkipPointers(true) 7490b57cec5SDimitry Andric .SetSkipReferences(true) 7500b57cec5SDimitry Andric .SetDontShowChildren(true) 7510b57cec5SDimitry Andric .SetDontShowValue(false) 7520b57cec5SDimitry Andric .SetShowMembersOneLiner(false) 7530b57cec5SDimitry Andric .SetHideItemNames(false), 7540b57cec5SDimitry Andric "${var%O}")); 7550b57cec5SDimitry Andric 756bdd1243dSDimitry Andric sys_category_sp->AddTypeSummary("OSType", eFormatterMatchExact, 7570b57cec5SDimitry Andric ostype_summary); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric TypeFormatImpl::Flags fourchar_flags; 7600b57cec5SDimitry Andric fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences( 7610b57cec5SDimitry Andric true); 7620b57cec5SDimitry Andric 76306c3fb27SDimitry Andric AddFormat(sys_category_sp, lldb::eFormatOSType, "FourCharCode", 7640b57cec5SDimitry Andric fourchar_flags); 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric void FormatManager::LoadVectorFormatters() { 7680b57cec5SDimitry Andric TypeCategoryImpl::SharedPointer vectors_category_sp = 7690b57cec5SDimitry Andric GetCategory(m_vectortypes_category_name); 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric TypeSummaryImpl::Flags vector_flags; 7720b57cec5SDimitry Andric vector_flags.SetCascades(true) 7730b57cec5SDimitry Andric .SetSkipPointers(true) 7740b57cec5SDimitry Andric .SetSkipReferences(false) 7750b57cec5SDimitry Andric .SetDontShowChildren(true) 7760b57cec5SDimitry Andric .SetDontShowValue(false) 7770b57cec5SDimitry Andric .SetShowMembersOneLiner(true) 7780b57cec5SDimitry Andric .SetHideItemNames(true); 7790b57cec5SDimitry Andric 78006c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "${var.uint128}", "builtin_type_vec128", 7810b57cec5SDimitry Andric vector_flags); 78206c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "float[4]", vector_flags); 78306c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "int32_t[4]", vector_flags); 78406c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "int16_t[8]", vector_flags); 78506c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vDouble", vector_flags); 78606c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vFloat", vector_flags); 78706c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vSInt8", vector_flags); 78806c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vSInt16", vector_flags); 78906c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vSInt32", vector_flags); 79006c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vUInt16", vector_flags); 79106c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vUInt8", vector_flags); 79206c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vUInt16", vector_flags); 79306c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vUInt32", vector_flags); 79406c3fb27SDimitry Andric AddStringSummary(vectors_category_sp, "", "vBool32", vector_flags); 7950b57cec5SDimitry Andric } 796