xref: /src/contrib/llvm-project/lldb/source/DataFormatters/FormatManager.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- FormatManager.cpp -------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/DataFormatters/FormatManager.h"
10f034231aSEd Maste 
11f034231aSEd Maste #include "lldb/Core/Debugger.h"
12ac9a064cSDimitry Andric #include "lldb/Core/ValueObject.h"
13e81d9d49SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
14e81d9d49SDimitry Andric #include "lldb/DataFormatters/LanguageCategory.h"
15e3b55780SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
16f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
17e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
18145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
1974a628f7SDimitry Andric #include "lldb/Utility/Log.h"
20145449b1SDimitry Andric #include "llvm/ADT/STLExtras.h"
21f034231aSEd Maste 
22f034231aSEd Maste using namespace lldb;
23f034231aSEd Maste using namespace lldb_private;
24e81d9d49SDimitry Andric using namespace lldb_private::formatters;
25f034231aSEd Maste 
2614f1b3e8SDimitry Andric struct FormatInfo {
27f034231aSEd Maste   Format format;
2814f1b3e8SDimitry Andric   const char format_char;  // One or more format characters that can be used for
2914f1b3e8SDimitry Andric                            // this format.
3014f1b3e8SDimitry Andric   const char *format_name; // Long format name that can be used to specify the
3114f1b3e8SDimitry Andric                            // current format
32f034231aSEd Maste };
33f034231aSEd Maste 
34ead24645SDimitry Andric static constexpr FormatInfo g_format_infos[] = {
35f034231aSEd Maste     {eFormatDefault, '\0', "default"},
36f034231aSEd Maste     {eFormatBoolean, 'B', "boolean"},
37f034231aSEd Maste     {eFormatBinary, 'b', "binary"},
38f034231aSEd Maste     {eFormatBytes, 'y', "bytes"},
39f034231aSEd Maste     {eFormatBytesWithASCII, 'Y', "bytes with ASCII"},
40f034231aSEd Maste     {eFormatChar, 'c', "character"},
41f034231aSEd Maste     {eFormatCharPrintable, 'C', "printable character"},
42f034231aSEd Maste     {eFormatComplexFloat, 'F', "complex float"},
43f034231aSEd Maste     {eFormatCString, 's', "c-string"},
44f034231aSEd Maste     {eFormatDecimal, 'd', "decimal"},
45f034231aSEd Maste     {eFormatEnum, 'E', "enumeration"},
46f034231aSEd Maste     {eFormatHex, 'x', "hex"},
47f034231aSEd Maste     {eFormatHexUppercase, 'X', "uppercase hex"},
48f034231aSEd Maste     {eFormatFloat, 'f', "float"},
49f034231aSEd Maste     {eFormatOctal, 'o', "octal"},
50f034231aSEd Maste     {eFormatOSType, 'O', "OSType"},
51f034231aSEd Maste     {eFormatUnicode16, 'U', "unicode16"},
52f034231aSEd Maste     {eFormatUnicode32, '\0', "unicode32"},
53f034231aSEd Maste     {eFormatUnsigned, 'u', "unsigned decimal"},
54f034231aSEd Maste     {eFormatPointer, 'p', "pointer"},
55f034231aSEd Maste     {eFormatVectorOfChar, '\0', "char[]"},
56f034231aSEd Maste     {eFormatVectorOfSInt8, '\0', "int8_t[]"},
57f034231aSEd Maste     {eFormatVectorOfUInt8, '\0', "uint8_t[]"},
58f034231aSEd Maste     {eFormatVectorOfSInt16, '\0', "int16_t[]"},
59f034231aSEd Maste     {eFormatVectorOfUInt16, '\0', "uint16_t[]"},
60f034231aSEd Maste     {eFormatVectorOfSInt32, '\0', "int32_t[]"},
61f034231aSEd Maste     {eFormatVectorOfUInt32, '\0', "uint32_t[]"},
62f034231aSEd Maste     {eFormatVectorOfSInt64, '\0', "int64_t[]"},
63f034231aSEd Maste     {eFormatVectorOfUInt64, '\0', "uint64_t[]"},
64e81d9d49SDimitry Andric     {eFormatVectorOfFloat16, '\0', "float16[]"},
65f034231aSEd Maste     {eFormatVectorOfFloat32, '\0', "float32[]"},
66f034231aSEd Maste     {eFormatVectorOfFloat64, '\0', "float64[]"},
67f034231aSEd Maste     {eFormatVectorOfUInt128, '\0', "uint128_t[]"},
68f034231aSEd Maste     {eFormatComplexInteger, 'I', "complex integer"},
69f034231aSEd Maste     {eFormatCharArray, 'a', "character array"},
70f034231aSEd Maste     {eFormatAddressInfo, 'A', "address"},
71f034231aSEd Maste     {eFormatHexFloat, '\0', "hex float"},
72f034231aSEd Maste     {eFormatInstruction, 'i', "instruction"},
73ead24645SDimitry Andric     {eFormatVoid, 'v', "void"},
74ead24645SDimitry Andric     {eFormatUnicode8, 'u', "unicode8"},
75ead24645SDimitry Andric };
76ead24645SDimitry Andric 
77ead24645SDimitry Andric static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) ==
78ead24645SDimitry Andric                   kNumFormats,
79ead24645SDimitry Andric               "All formats must have a corresponding info entry.");
80f034231aSEd Maste 
81e3b55780SDimitry Andric static uint32_t g_num_format_infos = std::size(g_format_infos);
82f034231aSEd Maste 
GetFormatFromFormatChar(char format_char,Format & format)8314f1b3e8SDimitry Andric static bool GetFormatFromFormatChar(char format_char, Format &format) {
8414f1b3e8SDimitry Andric   for (uint32_t i = 0; i < g_num_format_infos; ++i) {
8514f1b3e8SDimitry Andric     if (g_format_infos[i].format_char == format_char) {
86f034231aSEd Maste       format = g_format_infos[i].format;
87f034231aSEd Maste       return true;
88f034231aSEd Maste     }
89f034231aSEd Maste   }
90f034231aSEd Maste   format = eFormatInvalid;
91f034231aSEd Maste   return false;
92f034231aSEd Maste }
93f034231aSEd Maste 
GetFormatFromFormatName(llvm::StringRef format_name,Format & format)94145449b1SDimitry Andric static bool GetFormatFromFormatName(llvm::StringRef format_name,
95ac9a064cSDimitry Andric                                     Format &format) {
96f034231aSEd Maste   uint32_t i;
9714f1b3e8SDimitry Andric   for (i = 0; i < g_num_format_infos; ++i) {
98145449b1SDimitry Andric     if (format_name.equals_insensitive(g_format_infos[i].format_name)) {
99f034231aSEd Maste       format = g_format_infos[i].format;
100f034231aSEd Maste       return true;
101f034231aSEd Maste     }
102f034231aSEd Maste   }
103f034231aSEd Maste 
10414f1b3e8SDimitry Andric   for (i = 0; i < g_num_format_infos; ++i) {
105145449b1SDimitry Andric     if (llvm::StringRef(g_format_infos[i].format_name)
1067fa27ce4SDimitry Andric             .starts_with_insensitive(format_name)) {
107f034231aSEd Maste       format = g_format_infos[i].format;
108f034231aSEd Maste       return true;
109f034231aSEd Maste     }
110f034231aSEd Maste   }
111f034231aSEd Maste   format = eFormatInvalid;
112f034231aSEd Maste   return false;
113f034231aSEd Maste }
114f034231aSEd Maste 
Changed()11514f1b3e8SDimitry Andric void FormatManager::Changed() {
116e81d9d49SDimitry Andric   ++m_last_revision;
117e81d9d49SDimitry Andric   m_format_cache.Clear();
118f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
11914f1b3e8SDimitry Andric   for (auto &iter : m_language_categories_map) {
120e81d9d49SDimitry Andric     if (iter.second)
121e81d9d49SDimitry Andric       iter.second->GetFormatCache().Clear();
122e81d9d49SDimitry Andric   }
123e81d9d49SDimitry Andric }
124e81d9d49SDimitry Andric 
GetFormatFromCString(const char * format_cstr,lldb::Format & format)12514f1b3e8SDimitry Andric bool FormatManager::GetFormatFromCString(const char *format_cstr,
12614f1b3e8SDimitry Andric                                          lldb::Format &format) {
127f034231aSEd Maste   bool success = false;
12814f1b3e8SDimitry Andric   if (format_cstr && format_cstr[0]) {
12914f1b3e8SDimitry Andric     if (format_cstr[1] == '\0') {
130f034231aSEd Maste       success = GetFormatFromFormatChar(format_cstr[0], format);
131f034231aSEd Maste       if (success)
132f034231aSEd Maste         return true;
133f034231aSEd Maste     }
134f034231aSEd Maste 
135ac9a064cSDimitry Andric     success = GetFormatFromFormatName(format_cstr, format);
136f034231aSEd Maste   }
137f034231aSEd Maste   if (!success)
138f034231aSEd Maste     format = eFormatInvalid;
139f034231aSEd Maste   return success;
140f034231aSEd Maste }
141f034231aSEd Maste 
GetFormatAsFormatChar(lldb::Format format)14214f1b3e8SDimitry Andric char FormatManager::GetFormatAsFormatChar(lldb::Format format) {
14314f1b3e8SDimitry Andric   for (uint32_t i = 0; i < g_num_format_infos; ++i) {
144f034231aSEd Maste     if (g_format_infos[i].format == format)
145f034231aSEd Maste       return g_format_infos[i].format_char;
146f034231aSEd Maste   }
147f034231aSEd Maste   return '\0';
148f034231aSEd Maste }
149f034231aSEd Maste 
GetFormatAsCString(Format format)15014f1b3e8SDimitry Andric const char *FormatManager::GetFormatAsCString(Format format) {
151f034231aSEd Maste   if (format >= eFormatDefault && format < kNumFormats)
152f034231aSEd Maste     return g_format_infos[format].format_name;
1535f29bb8aSDimitry Andric   return nullptr;
154f034231aSEd Maste }
155f034231aSEd Maste 
EnableAllCategories()15614f1b3e8SDimitry Andric void FormatManager::EnableAllCategories() {
157e81d9d49SDimitry Andric   m_categories_map.EnableAllCategories();
158f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
15914f1b3e8SDimitry Andric   for (auto &iter : m_language_categories_map) {
160e81d9d49SDimitry Andric     if (iter.second)
161e81d9d49SDimitry Andric       iter.second->Enable();
162e81d9d49SDimitry Andric   }
163e81d9d49SDimitry Andric }
164e81d9d49SDimitry Andric 
DisableAllCategories()16514f1b3e8SDimitry Andric void FormatManager::DisableAllCategories() {
166e81d9d49SDimitry Andric   m_categories_map.DisableAllCategories();
167f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
16814f1b3e8SDimitry Andric   for (auto &iter : m_language_categories_map) {
169e81d9d49SDimitry Andric     if (iter.second)
170e81d9d49SDimitry Andric       iter.second->Disable();
171e81d9d49SDimitry Andric   }
172e81d9d49SDimitry Andric }
173e81d9d49SDimitry Andric 
GetPossibleMatches(ValueObject & valobj,CompilerType compiler_type,lldb::DynamicValueType use_dynamic,FormattersMatchVector & entries,FormattersMatchCandidate::Flags current_flags,bool root_level)17414f1b3e8SDimitry Andric void FormatManager::GetPossibleMatches(
175cfca06d7SDimitry Andric     ValueObject &valobj, CompilerType compiler_type,
17614f1b3e8SDimitry Andric     lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries,
177e3b55780SDimitry Andric     FormattersMatchCandidate::Flags current_flags, bool root_level) {
178e81d9d49SDimitry Andric   compiler_type = compiler_type.GetTypeForFormatters();
179cfca06d7SDimitry Andric   ConstString type_name(compiler_type.GetTypeName());
180ac9a064cSDimitry Andric   // A ValueObject that couldn't be made correctly won't necessarily have a
181ac9a064cSDimitry Andric   // target.  We aren't going to find a formatter in this case anyway, so we
182ac9a064cSDimitry Andric   // should just exit.
183ac9a064cSDimitry Andric   TargetSP target_sp = valobj.GetTargetSP();
184ac9a064cSDimitry Andric   if (!target_sp)
185ac9a064cSDimitry Andric     return;
186e3b55780SDimitry Andric   ScriptInterpreter *script_interpreter =
187ac9a064cSDimitry Andric       target_sp->GetDebugger().GetScriptInterpreter();
18814f1b3e8SDimitry Andric   if (valobj.GetBitfieldBitSize() > 0) {
18986758c71SEd Maste     StreamString sstring;
19086758c71SEd Maste     sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize());
19114f1b3e8SDimitry Andric     ConstString bitfieldname(sstring.GetString());
192e3b55780SDimitry Andric     entries.push_back({bitfieldname, script_interpreter,
193e3b55780SDimitry Andric                        TypeImpl(compiler_type), current_flags});
19486758c71SEd Maste   }
195e81d9d49SDimitry Andric 
19614f1b3e8SDimitry Andric   if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) {
197e3b55780SDimitry Andric     entries.push_back({type_name, script_interpreter, TypeImpl(compiler_type),
198e3b55780SDimitry Andric                        current_flags});
19986758c71SEd Maste 
200cfca06d7SDimitry Andric     ConstString display_type_name(compiler_type.GetTypeName());
2010cac4ca3SEd Maste     if (display_type_name != type_name)
202e3b55780SDimitry Andric       entries.push_back({display_type_name, script_interpreter,
203e3b55780SDimitry Andric                          TypeImpl(compiler_type), current_flags});
204e81d9d49SDimitry Andric   }
2050cac4ca3SEd Maste 
20614f1b3e8SDimitry Andric   for (bool is_rvalue_ref = true, j = true;
20714f1b3e8SDimitry Andric        j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) {
208e81d9d49SDimitry Andric     CompilerType non_ref_type = compiler_type.GetNonReferenceType();
209e3b55780SDimitry Andric     GetPossibleMatches(valobj, non_ref_type, use_dynamic, entries,
210e3b55780SDimitry Andric                        current_flags.WithStrippedReference());
21114f1b3e8SDimitry Andric     if (non_ref_type.IsTypedefType()) {
212e81d9d49SDimitry Andric       CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
21314f1b3e8SDimitry Andric       deffed_referenced_type =
21414f1b3e8SDimitry Andric           is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType()
21514f1b3e8SDimitry Andric                         : deffed_referenced_type.GetLValueReferenceType();
216e3b55780SDimitry Andric       // this is not exactly the usual meaning of stripping typedefs
21714f1b3e8SDimitry Andric       GetPossibleMatches(
21814f1b3e8SDimitry Andric           valobj, deffed_referenced_type,
219e3b55780SDimitry Andric           use_dynamic, entries, current_flags.WithStrippedTypedef());
22086758c71SEd Maste     }
2210cac4ca3SEd Maste   }
2220cac4ca3SEd Maste 
22314f1b3e8SDimitry Andric   if (compiler_type.IsPointerType()) {
224e81d9d49SDimitry Andric     CompilerType non_ptr_type = compiler_type.GetPointeeType();
225e3b55780SDimitry Andric     GetPossibleMatches(valobj, non_ptr_type, use_dynamic, entries,
226e3b55780SDimitry Andric                        current_flags.WithStrippedPointer());
22714f1b3e8SDimitry Andric     if (non_ptr_type.IsTypedefType()) {
22814f1b3e8SDimitry Andric       CompilerType deffed_pointed_type =
22914f1b3e8SDimitry Andric           non_ptr_type.GetTypedefedType().GetPointerType();
230e3b55780SDimitry Andric       // this is not exactly the usual meaning of stripping typedefs
231e3b55780SDimitry Andric       GetPossibleMatches(valobj, deffed_pointed_type, use_dynamic, entries,
232e3b55780SDimitry Andric                          current_flags.WithStrippedTypedef());
2330cac4ca3SEd Maste     }
23486758c71SEd Maste   }
23586758c71SEd Maste 
236706b4fc4SDimitry Andric   // For arrays with typedef-ed elements, we add a candidate with the typedef
237706b4fc4SDimitry Andric   // stripped.
238706b4fc4SDimitry Andric   uint64_t array_size;
239706b4fc4SDimitry Andric   if (compiler_type.IsArrayType(nullptr, &array_size, nullptr)) {
240b60736ecSDimitry Andric     ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
241b60736ecSDimitry Andric     CompilerType element_type = compiler_type.GetArrayElementType(
242b60736ecSDimitry Andric         exe_ctx.GetBestExecutionContextScope());
243706b4fc4SDimitry Andric     if (element_type.IsTypedefType()) {
244706b4fc4SDimitry Andric       // Get the stripped element type and compute the stripped array type
245706b4fc4SDimitry Andric       // from it.
246706b4fc4SDimitry Andric       CompilerType deffed_array_type =
247706b4fc4SDimitry Andric           element_type.GetTypedefedType().GetArrayType(array_size);
248e3b55780SDimitry Andric       // this is not exactly the usual meaning of stripping typedefs
249706b4fc4SDimitry Andric       GetPossibleMatches(
250706b4fc4SDimitry Andric           valobj, deffed_array_type,
251e3b55780SDimitry Andric           use_dynamic, entries, current_flags.WithStrippedTypedef());
252706b4fc4SDimitry Andric     }
253706b4fc4SDimitry Andric   }
254706b4fc4SDimitry Andric 
255706b4fc4SDimitry Andric   for (lldb::LanguageType language_type :
256706b4fc4SDimitry Andric        GetCandidateLanguages(valobj.GetObjectRuntimeLanguage())) {
25714f1b3e8SDimitry Andric     if (Language *language = Language::FindPlugin(language_type)) {
258e3b55780SDimitry Andric       for (const FormattersMatchCandidate& candidate :
25914f1b3e8SDimitry Andric            language->GetPossibleFormattersMatches(valobj, use_dynamic)) {
260e3b55780SDimitry Andric         entries.push_back(candidate);
261e81d9d49SDimitry Andric       }
262e81d9d49SDimitry Andric     }
26386758c71SEd Maste   }
26486758c71SEd Maste 
26586758c71SEd Maste   // try to strip typedef chains
26614f1b3e8SDimitry Andric   if (compiler_type.IsTypedefType()) {
267e81d9d49SDimitry Andric     CompilerType deffed_type = compiler_type.GetTypedefedType();
268e3b55780SDimitry Andric     GetPossibleMatches(valobj, deffed_type, use_dynamic, entries,
269e3b55780SDimitry Andric                        current_flags.WithStrippedTypedef());
27086758c71SEd Maste   }
27186758c71SEd Maste 
27214f1b3e8SDimitry Andric   if (root_level) {
27386758c71SEd Maste     do {
274e81d9d49SDimitry Andric       if (!compiler_type.IsValid())
27586758c71SEd Maste         break;
27686758c71SEd Maste 
27714f1b3e8SDimitry Andric       CompilerType unqual_compiler_ast_type =
27814f1b3e8SDimitry Andric           compiler_type.GetFullyUnqualifiedType();
279e81d9d49SDimitry Andric       if (!unqual_compiler_ast_type.IsValid())
28086758c71SEd Maste         break;
28114f1b3e8SDimitry Andric       if (unqual_compiler_ast_type.GetOpaqueQualType() !=
28214f1b3e8SDimitry Andric           compiler_type.GetOpaqueQualType())
283e3b55780SDimitry Andric         GetPossibleMatches(valobj, unqual_compiler_ast_type, use_dynamic,
284e3b55780SDimitry Andric                            entries, current_flags);
28586758c71SEd Maste     } while (false);
28686758c71SEd Maste 
28786758c71SEd Maste     // if all else fails, go to static type
28814f1b3e8SDimitry Andric     if (valobj.IsDynamic()) {
28986758c71SEd Maste       lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
29086758c71SEd Maste       if (static_value_sp)
291e3b55780SDimitry Andric         GetPossibleMatches(*static_value_sp.get(),
292e3b55780SDimitry Andric                            static_value_sp->GetCompilerType(), use_dynamic,
293e3b55780SDimitry Andric                            entries, current_flags, true);
29486758c71SEd Maste     }
29586758c71SEd Maste   }
29686758c71SEd Maste }
29786758c71SEd Maste 
298f21a844fSEd Maste lldb::TypeFormatImplSP
GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp)29914f1b3e8SDimitry Andric FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
300f21a844fSEd Maste   if (!type_sp)
301f21a844fSEd Maste     return lldb::TypeFormatImplSP();
302f21a844fSEd Maste   lldb::TypeFormatImplSP format_chosen_sp;
303f21a844fSEd Maste   uint32_t num_categories = m_categories_map.GetCount();
304f21a844fSEd Maste   lldb::TypeCategoryImplSP category_sp;
305f21a844fSEd Maste   uint32_t prio_category = UINT32_MAX;
30614f1b3e8SDimitry Andric   for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
307f21a844fSEd Maste     category_sp = GetCategoryAtIndex(category_id);
30894994d37SDimitry Andric     if (!category_sp->IsEnabled())
309f21a844fSEd Maste       continue;
31014f1b3e8SDimitry Andric     lldb::TypeFormatImplSP format_current_sp =
31114f1b3e8SDimitry Andric         category_sp->GetFormatForType(type_sp);
31214f1b3e8SDimitry Andric     if (format_current_sp &&
3135f29bb8aSDimitry Andric         (format_chosen_sp.get() == nullptr ||
31414f1b3e8SDimitry Andric          (prio_category > category_sp->GetEnabledPosition()))) {
315f21a844fSEd Maste       prio_category = category_sp->GetEnabledPosition();
316f21a844fSEd Maste       format_chosen_sp = format_current_sp;
317f21a844fSEd Maste     }
318f21a844fSEd Maste   }
319f21a844fSEd Maste   return format_chosen_sp;
320f21a844fSEd Maste }
321f21a844fSEd Maste 
322f034231aSEd Maste lldb::TypeSummaryImplSP
GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp)32314f1b3e8SDimitry Andric FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
324f034231aSEd Maste   if (!type_sp)
325f034231aSEd Maste     return lldb::TypeSummaryImplSP();
326f034231aSEd Maste   lldb::TypeSummaryImplSP summary_chosen_sp;
327f034231aSEd Maste   uint32_t num_categories = m_categories_map.GetCount();
328f034231aSEd Maste   lldb::TypeCategoryImplSP category_sp;
329f034231aSEd Maste   uint32_t prio_category = UINT32_MAX;
33014f1b3e8SDimitry Andric   for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
331f034231aSEd Maste     category_sp = GetCategoryAtIndex(category_id);
33294994d37SDimitry Andric     if (!category_sp->IsEnabled())
333f034231aSEd Maste       continue;
33414f1b3e8SDimitry Andric     lldb::TypeSummaryImplSP summary_current_sp =
33514f1b3e8SDimitry Andric         category_sp->GetSummaryForType(type_sp);
33614f1b3e8SDimitry Andric     if (summary_current_sp &&
3375f29bb8aSDimitry Andric         (summary_chosen_sp.get() == nullptr ||
33814f1b3e8SDimitry Andric          (prio_category > category_sp->GetEnabledPosition()))) {
339f034231aSEd Maste       prio_category = category_sp->GetEnabledPosition();
340f034231aSEd Maste       summary_chosen_sp = summary_current_sp;
341f034231aSEd Maste     }
342f034231aSEd Maste   }
343f034231aSEd Maste   return summary_chosen_sp;
344f034231aSEd Maste }
345f034231aSEd Maste 
346f034231aSEd Maste lldb::TypeFilterImplSP
GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp)34714f1b3e8SDimitry Andric FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
348f034231aSEd Maste   if (!type_sp)
349f034231aSEd Maste     return lldb::TypeFilterImplSP();
350f034231aSEd Maste   lldb::TypeFilterImplSP filter_chosen_sp;
351f034231aSEd Maste   uint32_t num_categories = m_categories_map.GetCount();
352f034231aSEd Maste   lldb::TypeCategoryImplSP category_sp;
353f034231aSEd Maste   uint32_t prio_category = UINT32_MAX;
35414f1b3e8SDimitry Andric   for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
355f034231aSEd Maste     category_sp = GetCategoryAtIndex(category_id);
35694994d37SDimitry Andric     if (!category_sp->IsEnabled())
357f034231aSEd Maste       continue;
35814f1b3e8SDimitry Andric     lldb::TypeFilterImplSP filter_current_sp(
35914f1b3e8SDimitry Andric         (TypeFilterImpl *)category_sp->GetFilterForType(type_sp).get());
36014f1b3e8SDimitry Andric     if (filter_current_sp &&
3615f29bb8aSDimitry Andric         (filter_chosen_sp.get() == nullptr ||
36214f1b3e8SDimitry Andric          (prio_category > category_sp->GetEnabledPosition()))) {
363f034231aSEd Maste       prio_category = category_sp->GetEnabledPosition();
364f034231aSEd Maste       filter_chosen_sp = filter_current_sp;
365f034231aSEd Maste     }
366f034231aSEd Maste   }
367f034231aSEd Maste   return filter_chosen_sp;
368f034231aSEd Maste }
369f034231aSEd Maste 
370f034231aSEd Maste lldb::ScriptedSyntheticChildrenSP
GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp)37114f1b3e8SDimitry Andric FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
372f034231aSEd Maste   if (!type_sp)
373f034231aSEd Maste     return lldb::ScriptedSyntheticChildrenSP();
374f034231aSEd Maste   lldb::ScriptedSyntheticChildrenSP synth_chosen_sp;
375f034231aSEd Maste   uint32_t num_categories = m_categories_map.GetCount();
376f034231aSEd Maste   lldb::TypeCategoryImplSP category_sp;
377f034231aSEd Maste   uint32_t prio_category = UINT32_MAX;
37814f1b3e8SDimitry Andric   for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
379f034231aSEd Maste     category_sp = GetCategoryAtIndex(category_id);
38094994d37SDimitry Andric     if (!category_sp->IsEnabled())
381f034231aSEd Maste       continue;
38214f1b3e8SDimitry Andric     lldb::ScriptedSyntheticChildrenSP synth_current_sp(
38314f1b3e8SDimitry Andric         (ScriptedSyntheticChildren *)category_sp->GetSyntheticForType(type_sp)
38414f1b3e8SDimitry Andric             .get());
38514f1b3e8SDimitry Andric     if (synth_current_sp &&
3865f29bb8aSDimitry Andric         (synth_chosen_sp.get() == nullptr ||
38714f1b3e8SDimitry Andric          (prio_category > category_sp->GetEnabledPosition()))) {
388f034231aSEd Maste       prio_category = category_sp->GetEnabledPosition();
389f034231aSEd Maste       synth_chosen_sp = synth_current_sp;
390f034231aSEd Maste     }
391f034231aSEd Maste   }
392f034231aSEd Maste   return synth_chosen_sp;
393f034231aSEd Maste }
394f034231aSEd Maste 
ForEachCategory(TypeCategoryMap::ForEachCallback callback)39514f1b3e8SDimitry Andric void FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) {
396e81d9d49SDimitry Andric   m_categories_map.ForEach(callback);
397f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
39814f1b3e8SDimitry Andric   for (const auto &entry : m_language_categories_map) {
39914f1b3e8SDimitry Andric     if (auto category_sp = entry.second->GetCategory()) {
400e81d9d49SDimitry Andric       if (!callback(category_sp))
401e81d9d49SDimitry Andric         break;
402e81d9d49SDimitry Andric     }
403e81d9d49SDimitry Andric   }
404e81d9d49SDimitry Andric }
405e81d9d49SDimitry Andric 
406f034231aSEd Maste lldb::TypeCategoryImplSP
GetCategory(ConstString category_name,bool can_create)4075f29bb8aSDimitry Andric FormatManager::GetCategory(ConstString category_name, bool can_create) {
408f034231aSEd Maste   if (!category_name)
409f034231aSEd Maste     return GetCategory(m_default_category_name);
410f034231aSEd Maste   lldb::TypeCategoryImplSP category;
411f034231aSEd Maste   if (m_categories_map.Get(category_name, category))
412f034231aSEd Maste     return category;
413f034231aSEd Maste 
414f034231aSEd Maste   if (!can_create)
415f034231aSEd Maste     return lldb::TypeCategoryImplSP();
416f034231aSEd Maste 
41714f1b3e8SDimitry Andric   m_categories_map.Add(
41814f1b3e8SDimitry Andric       category_name,
41914f1b3e8SDimitry Andric       lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name)));
420f034231aSEd Maste   return GetCategory(category_name);
421f034231aSEd Maste }
422f034231aSEd Maste 
GetSingleItemFormat(lldb::Format vector_format)42314f1b3e8SDimitry Andric lldb::Format FormatManager::GetSingleItemFormat(lldb::Format vector_format) {
42414f1b3e8SDimitry Andric   switch (vector_format) {
425f034231aSEd Maste   case eFormatVectorOfChar:
426f034231aSEd Maste     return eFormatCharArray;
427f034231aSEd Maste 
428f034231aSEd Maste   case eFormatVectorOfSInt8:
429f034231aSEd Maste   case eFormatVectorOfSInt16:
430f034231aSEd Maste   case eFormatVectorOfSInt32:
431f034231aSEd Maste   case eFormatVectorOfSInt64:
432f034231aSEd Maste     return eFormatDecimal;
433f034231aSEd Maste 
434f034231aSEd Maste   case eFormatVectorOfUInt8:
435f034231aSEd Maste   case eFormatVectorOfUInt16:
436f034231aSEd Maste   case eFormatVectorOfUInt32:
437f034231aSEd Maste   case eFormatVectorOfUInt64:
438f034231aSEd Maste   case eFormatVectorOfUInt128:
439f034231aSEd Maste     return eFormatHex;
440f034231aSEd Maste 
441e81d9d49SDimitry Andric   case eFormatVectorOfFloat16:
442f034231aSEd Maste   case eFormatVectorOfFloat32:
443f034231aSEd Maste   case eFormatVectorOfFloat64:
444f034231aSEd Maste     return eFormatFloat;
445f034231aSEd Maste 
446f034231aSEd Maste   default:
447f034231aSEd Maste     return lldb::eFormatInvalid;
448f034231aSEd Maste   }
449f034231aSEd Maste }
450f034231aSEd Maste 
ShouldPrintAsOneLiner(ValueObject & valobj)45114f1b3e8SDimitry Andric bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
452ac9a064cSDimitry Andric   TargetSP target_sp = valobj.GetTargetSP();
453f21a844fSEd Maste   // if settings say no oneline whatsoever
454ac9a064cSDimitry Andric   if (target_sp && !target_sp->GetDebugger().GetAutoOneLineSummaries())
455f21a844fSEd Maste     return false; // then don't oneline
456f21a844fSEd Maste 
457205afe67SEd Maste   // if this object has a summary, then ask the summary
458f21a844fSEd Maste   if (valobj.GetSummaryFormat().get() != nullptr)
459205afe67SEd Maste     return valobj.GetSummaryFormat()->IsOneLiner();
460f21a844fSEd Maste 
461ac9a064cSDimitry Andric   const size_t max_num_children =
462ac9a064cSDimitry Andric       (target_sp ? *target_sp : Target::GetGlobalProperties())
463ac9a064cSDimitry Andric           .GetMaximumNumberOfChildrenToDisplay();
464ac9a064cSDimitry Andric   auto num_children = valobj.GetNumChildren(max_num_children);
465ac9a064cSDimitry Andric   if (!num_children) {
466ac9a064cSDimitry Andric     llvm::consumeError(num_children.takeError());
467ac9a064cSDimitry Andric     return true;
468ac9a064cSDimitry Andric   }
469f21a844fSEd Maste   // no children, no party
470ac9a064cSDimitry Andric   if (*num_children == 0)
471f21a844fSEd Maste     return false;
472f21a844fSEd Maste 
473f73363f1SDimitry Andric   // ask the type if it has any opinion about this eLazyBoolCalculate == no
474f73363f1SDimitry Andric   // opinion; other values should be self explanatory
475e81d9d49SDimitry Andric   CompilerType compiler_type(valobj.GetCompilerType());
47614f1b3e8SDimitry Andric   if (compiler_type.IsValid()) {
47714f1b3e8SDimitry Andric     switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) {
478e81d9d49SDimitry Andric     case eLazyBoolNo:
479e81d9d49SDimitry Andric       return false;
480e81d9d49SDimitry Andric     case eLazyBoolYes:
481e81d9d49SDimitry Andric       return true;
482e81d9d49SDimitry Andric     case eLazyBoolCalculate:
483e81d9d49SDimitry Andric       break;
484e81d9d49SDimitry Andric     }
485e81d9d49SDimitry Andric   }
486e81d9d49SDimitry Andric 
487f21a844fSEd Maste   size_t total_children_name_len = 0;
488f21a844fSEd Maste 
489ac9a064cSDimitry Andric   for (size_t idx = 0; idx < *num_children; idx++) {
490205afe67SEd Maste     bool is_synth_val = false;
4917fa27ce4SDimitry Andric     ValueObjectSP child_sp(valobj.GetChildAtIndex(idx));
492f21a844fSEd Maste     // something is wrong here - bail out
493f21a844fSEd Maste     if (!child_sp)
494f21a844fSEd Maste       return false;
495e81d9d49SDimitry Andric 
496e81d9d49SDimitry Andric     // also ask the child's type if it has any opinion
497e81d9d49SDimitry Andric     CompilerType child_compiler_type(child_sp->GetCompilerType());
49814f1b3e8SDimitry Andric     if (child_compiler_type.IsValid()) {
49914f1b3e8SDimitry Andric       switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) {
500e81d9d49SDimitry Andric       case eLazyBoolYes:
501e81d9d49SDimitry Andric       // an opinion of yes is only binding for the child, so keep going
502e81d9d49SDimitry Andric       case eLazyBoolCalculate:
503e81d9d49SDimitry Andric         break;
504e81d9d49SDimitry Andric       case eLazyBoolNo:
505e81d9d49SDimitry Andric         // but if the child says no, then it's a veto on the whole thing
506e81d9d49SDimitry Andric         return false;
507e81d9d49SDimitry Andric       }
508e81d9d49SDimitry Andric     }
509e81d9d49SDimitry Andric 
51014f1b3e8SDimitry Andric     // if we decided to define synthetic children for a type, we probably care
511f73363f1SDimitry Andric     // enough to show them, but avoid nesting children in children
51214f1b3e8SDimitry Andric     if (child_sp->GetSyntheticChildren().get() != nullptr) {
513205afe67SEd Maste       ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
514205afe67SEd Maste       // wait.. wat? just get out of here..
515205afe67SEd Maste       if (!synth_sp)
516f21a844fSEd Maste         return false;
517205afe67SEd Maste       // but if we only have them to provide a value, keep going
51894994d37SDimitry Andric       if (!synth_sp->MightHaveChildren() &&
51914f1b3e8SDimitry Andric           synth_sp->DoesProvideSyntheticValue())
520205afe67SEd Maste         is_synth_val = true;
521205afe67SEd Maste       else
522205afe67SEd Maste         return false;
523205afe67SEd Maste     }
524f21a844fSEd Maste 
525f21a844fSEd Maste     total_children_name_len += child_sp->GetName().GetLength();
526f21a844fSEd Maste 
527f21a844fSEd Maste     // 50 itself is a "randomly" chosen number - the idea is that
528f21a844fSEd Maste     // overly long structs should not get this treatment
529f21a844fSEd Maste     // FIXME: maybe make this a user-tweakable setting?
530f21a844fSEd Maste     if (total_children_name_len > 50)
531f21a844fSEd Maste       return false;
532f21a844fSEd Maste 
533f21a844fSEd Maste     // if a summary is there..
53414f1b3e8SDimitry Andric     if (child_sp->GetSummaryFormat()) {
535f21a844fSEd Maste       // and it wants children, then bail out
5360cac4ca3SEd Maste       if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
537f21a844fSEd Maste         return false;
538f21a844fSEd Maste     }
539f21a844fSEd Maste 
540f21a844fSEd Maste     // if this child has children..
541ac9a064cSDimitry Andric     if (child_sp->HasChildren()) {
542f21a844fSEd Maste       // ...and no summary...
54314f1b3e8SDimitry Andric       // (if it had a summary and the summary wanted children, we would have
54414f1b3e8SDimitry Andric       // bailed out anyway
54514f1b3e8SDimitry Andric       //  so this only makes us bail out if this has no summary and we would
54614f1b3e8SDimitry Andric       //  then print children)
54714f1b3e8SDimitry Andric       if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do
54814f1b3e8SDimitry Andric                                                           // that if not a
54914f1b3e8SDimitry Andric                                                           // synthetic valued
55014f1b3e8SDimitry Andric                                                           // child
551f21a844fSEd Maste         return false;                                     // then bail out
552f21a844fSEd Maste     }
553f21a844fSEd Maste   }
554f21a844fSEd Maste   return true;
555f21a844fSEd Maste }
556f21a844fSEd Maste 
GetTypeForCache(ValueObject & valobj,lldb::DynamicValueType use_dynamic)55714f1b3e8SDimitry Andric ConstString FormatManager::GetTypeForCache(ValueObject &valobj,
55814f1b3e8SDimitry Andric                                            lldb::DynamicValueType use_dynamic) {
55914f1b3e8SDimitry Andric   ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(
56014f1b3e8SDimitry Andric       use_dynamic, valobj.IsSynthetic());
56114f1b3e8SDimitry Andric   if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) {
562e81d9d49SDimitry Andric     if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
563e81d9d49SDimitry Andric       return valobj_sp->GetQualifiedTypeName();
564f034231aSEd Maste   }
565f034231aSEd Maste   return ConstString();
566f034231aSEd Maste }
567f034231aSEd Maste 
568e81d9d49SDimitry Andric std::vector<lldb::LanguageType>
GetCandidateLanguages(lldb::LanguageType lang_type)56914f1b3e8SDimitry Andric FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type) {
57014f1b3e8SDimitry Andric   switch (lang_type) {
571e81d9d49SDimitry Andric   case lldb::eLanguageTypeC:
572e81d9d49SDimitry Andric   case lldb::eLanguageTypeC89:
573e81d9d49SDimitry Andric   case lldb::eLanguageTypeC99:
574e81d9d49SDimitry Andric   case lldb::eLanguageTypeC11:
575e81d9d49SDimitry Andric   case lldb::eLanguageTypeC_plus_plus:
576e81d9d49SDimitry Andric   case lldb::eLanguageTypeC_plus_plus_03:
577e81d9d49SDimitry Andric   case lldb::eLanguageTypeC_plus_plus_11:
578e81d9d49SDimitry Andric   case lldb::eLanguageTypeC_plus_plus_14:
579e81d9d49SDimitry Andric     return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC};
580e81d9d49SDimitry Andric   default:
581e81d9d49SDimitry Andric     return {lang_type};
582e81d9d49SDimitry Andric   }
583706b4fc4SDimitry Andric   llvm_unreachable("Fully covered switch");
584e81d9d49SDimitry Andric }
585e81d9d49SDimitry Andric 
586e81d9d49SDimitry Andric LanguageCategory *
GetCategoryForLanguage(lldb::LanguageType lang_type)58714f1b3e8SDimitry Andric FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) {
588f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
58914f1b3e8SDimitry Andric   auto iter = m_language_categories_map.find(lang_type),
59014f1b3e8SDimitry Andric        end = m_language_categories_map.end();
591e81d9d49SDimitry Andric   if (iter != end)
592e81d9d49SDimitry Andric     return iter->second.get();
593e81d9d49SDimitry Andric   LanguageCategory *lang_category = new LanguageCategory(lang_type);
59414f1b3e8SDimitry Andric   m_language_categories_map[lang_type] =
59514f1b3e8SDimitry Andric       LanguageCategory::UniquePointer(lang_category);
596e81d9d49SDimitry Andric   return lang_category;
597e81d9d49SDimitry Andric }
598e81d9d49SDimitry Andric 
599706b4fc4SDimitry Andric template <typename ImplSP>
GetHardcoded(FormattersMatchData & match_data)600706b4fc4SDimitry Andric ImplSP FormatManager::GetHardcoded(FormattersMatchData &match_data) {
601706b4fc4SDimitry Andric   ImplSP retval_sp;
60214f1b3e8SDimitry Andric   for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
60314f1b3e8SDimitry Andric     if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
604e81d9d49SDimitry Andric       if (lang_category->GetHardcoded(*this, match_data, retval_sp))
605706b4fc4SDimitry Andric         return retval_sp;
606706b4fc4SDimitry Andric     }
607706b4fc4SDimitry Andric   }
608706b4fc4SDimitry Andric   return retval_sp;
609706b4fc4SDimitry Andric }
610706b4fc4SDimitry Andric 
6117fa27ce4SDimitry Andric namespace {
6127fa27ce4SDimitry Andric template <typename ImplSP> const char *FormatterKind;
6137fa27ce4SDimitry Andric template <> const char *FormatterKind<lldb::TypeFormatImplSP> = "format";
6147fa27ce4SDimitry Andric template <> const char *FormatterKind<lldb::TypeSummaryImplSP> = "summary";
6157fa27ce4SDimitry Andric template <> const char *FormatterKind<lldb::SyntheticChildrenSP> = "synthetic";
6167fa27ce4SDimitry Andric } // namespace
6177fa27ce4SDimitry Andric 
6187fa27ce4SDimitry Andric #define FORMAT_LOG(Message) "[%s] " Message, FormatterKind<ImplSP>
6197fa27ce4SDimitry Andric 
620706b4fc4SDimitry Andric template <typename ImplSP>
Get(ValueObject & valobj,lldb::DynamicValueType use_dynamic)621706b4fc4SDimitry Andric ImplSP FormatManager::Get(ValueObject &valobj,
622706b4fc4SDimitry Andric                           lldb::DynamicValueType use_dynamic) {
623706b4fc4SDimitry Andric   FormattersMatchData match_data(valobj, use_dynamic);
624706b4fc4SDimitry Andric   if (ImplSP retval_sp = GetCached<ImplSP>(match_data))
625706b4fc4SDimitry Andric     return retval_sp;
626706b4fc4SDimitry Andric 
627145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
628706b4fc4SDimitry Andric 
6297fa27ce4SDimitry Andric   LLDB_LOGF(log, FORMAT_LOG("Search failed. Giving language a chance."));
630706b4fc4SDimitry Andric   for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
631706b4fc4SDimitry Andric     if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
632706b4fc4SDimitry Andric       ImplSP retval_sp;
633706b4fc4SDimitry Andric       if (lang_category->Get(match_data, retval_sp))
634706b4fc4SDimitry Andric         if (retval_sp) {
6357fa27ce4SDimitry Andric           LLDB_LOGF(log, FORMAT_LOG("Language search success. Returning."));
636706b4fc4SDimitry Andric           return retval_sp;
637706b4fc4SDimitry Andric         }
638e81d9d49SDimitry Andric     }
639e81d9d49SDimitry Andric   }
640e81d9d49SDimitry Andric 
6417fa27ce4SDimitry Andric   LLDB_LOGF(log, FORMAT_LOG("Search failed. Giving hardcoded a chance."));
642706b4fc4SDimitry Andric   return GetHardcoded<ImplSP>(match_data);
643706b4fc4SDimitry Andric }
644706b4fc4SDimitry Andric 
645706b4fc4SDimitry Andric template <typename ImplSP>
GetCached(FormattersMatchData & match_data)646706b4fc4SDimitry Andric ImplSP FormatManager::GetCached(FormattersMatchData &match_data) {
647706b4fc4SDimitry Andric   ImplSP retval_sp;
648145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
649706b4fc4SDimitry Andric   if (match_data.GetTypeForCache()) {
6507fa27ce4SDimitry Andric     LLDB_LOGF(log, "\n\n" FORMAT_LOG("Looking into cache for type %s"),
651706b4fc4SDimitry Andric               match_data.GetTypeForCache().AsCString("<invalid>"));
652706b4fc4SDimitry Andric     if (m_format_cache.Get(match_data.GetTypeForCache(), retval_sp)) {
653706b4fc4SDimitry Andric       if (log) {
6547fa27ce4SDimitry Andric         LLDB_LOGF(log, FORMAT_LOG("Cache search success. Returning."));
655706b4fc4SDimitry Andric         LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
656706b4fc4SDimitry Andric                   m_format_cache.GetCacheHits(),
657706b4fc4SDimitry Andric                   m_format_cache.GetCacheMisses());
658706b4fc4SDimitry Andric       }
659706b4fc4SDimitry Andric       return retval_sp;
660706b4fc4SDimitry Andric     }
6617fa27ce4SDimitry Andric     LLDB_LOGF(log, FORMAT_LOG("Cache search failed. Going normal route"));
662706b4fc4SDimitry Andric   }
663706b4fc4SDimitry Andric 
664706b4fc4SDimitry Andric   m_categories_map.Get(match_data, retval_sp);
665706b4fc4SDimitry Andric   if (match_data.GetTypeForCache() && (!retval_sp || !retval_sp->NonCacheable())) {
6667fa27ce4SDimitry Andric     LLDB_LOGF(log, FORMAT_LOG("Caching %p for type %s"),
667706b4fc4SDimitry Andric               static_cast<void *>(retval_sp.get()),
668706b4fc4SDimitry Andric               match_data.GetTypeForCache().AsCString("<invalid>"));
669706b4fc4SDimitry Andric     m_format_cache.Set(match_data.GetTypeForCache(), retval_sp);
670706b4fc4SDimitry Andric   }
671706b4fc4SDimitry Andric   LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
672706b4fc4SDimitry Andric             m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
673e81d9d49SDimitry Andric   return retval_sp;
674f21a844fSEd Maste }
675f21a844fSEd Maste 
6767fa27ce4SDimitry Andric #undef FORMAT_LOG
6777fa27ce4SDimitry Andric 
678f21a844fSEd Maste lldb::TypeFormatImplSP
GetFormat(ValueObject & valobj,lldb::DynamicValueType use_dynamic)679f21a844fSEd Maste FormatManager::GetFormat(ValueObject &valobj,
68014f1b3e8SDimitry Andric                          lldb::DynamicValueType use_dynamic) {
681706b4fc4SDimitry Andric   return Get<lldb::TypeFormatImplSP>(valobj, use_dynamic);
682f21a844fSEd Maste }
683f21a844fSEd Maste 
684f034231aSEd Maste lldb::TypeSummaryImplSP
GetSummaryFormat(ValueObject & valobj,lldb::DynamicValueType use_dynamic)685f034231aSEd Maste FormatManager::GetSummaryFormat(ValueObject &valobj,
68614f1b3e8SDimitry Andric                                 lldb::DynamicValueType use_dynamic) {
687706b4fc4SDimitry Andric   return Get<lldb::TypeSummaryImplSP>(valobj, use_dynamic);
688f21a844fSEd Maste }
689f21a844fSEd Maste 
690f034231aSEd Maste lldb::SyntheticChildrenSP
GetSyntheticChildren(ValueObject & valobj,lldb::DynamicValueType use_dynamic)691f034231aSEd Maste FormatManager::GetSyntheticChildren(ValueObject &valobj,
69214f1b3e8SDimitry Andric                                     lldb::DynamicValueType use_dynamic) {
693706b4fc4SDimitry Andric   return Get<lldb::SyntheticChildrenSP>(valobj, use_dynamic);
694205afe67SEd Maste }
695205afe67SEd Maste 
FormatManager()696f3fbd1c0SDimitry Andric FormatManager::FormatManager()
69714f1b3e8SDimitry Andric     : m_last_revision(0), m_format_cache(), m_language_categories_mutex(),
69814f1b3e8SDimitry Andric       m_language_categories_map(), m_named_summaries_map(this),
69914f1b3e8SDimitry Andric       m_categories_map(this), m_default_category_name(ConstString("default")),
700f034231aSEd Maste       m_system_category_name(ConstString("system")),
70114f1b3e8SDimitry Andric       m_vectortypes_category_name(ConstString("VectorTypes")) {
702f034231aSEd Maste   LoadSystemFormatters();
703e81d9d49SDimitry Andric   LoadVectorFormatters();
704f034231aSEd Maste 
70514f1b3e8SDimitry Andric   EnableCategory(m_vectortypes_category_name, TypeCategoryMap::Last,
70614f1b3e8SDimitry Andric                  lldb::eLanguageTypeObjC_plus_plus);
70714f1b3e8SDimitry Andric   EnableCategory(m_system_category_name, TypeCategoryMap::Last,
70814f1b3e8SDimitry Andric                  lldb::eLanguageTypeObjC_plus_plus);
709f034231aSEd Maste }
710f034231aSEd Maste 
LoadSystemFormatters()71114f1b3e8SDimitry Andric void FormatManager::LoadSystemFormatters() {
712f034231aSEd Maste   TypeSummaryImpl::Flags string_flags;
713f034231aSEd Maste   string_flags.SetCascades(true)
714f034231aSEd Maste       .SetSkipPointers(true)
715f034231aSEd Maste       .SetSkipReferences(false)
716f034231aSEd Maste       .SetDontShowChildren(true)
717f034231aSEd Maste       .SetDontShowValue(false)
718f034231aSEd Maste       .SetShowMembersOneLiner(false)
719f034231aSEd Maste       .SetHideItemNames(false);
720f034231aSEd Maste 
7215e95aa85SEd Maste   TypeSummaryImpl::Flags string_array_flags;
722e81d9d49SDimitry Andric   string_array_flags.SetCascades(true)
723f034231aSEd Maste       .SetSkipPointers(true)
724f034231aSEd Maste       .SetSkipReferences(false)
725f034231aSEd Maste       .SetDontShowChildren(true)
726f034231aSEd Maste       .SetDontShowValue(true)
727f034231aSEd Maste       .SetShowMembersOneLiner(false)
7285e95aa85SEd Maste       .SetHideItemNames(false);
7295e95aa85SEd Maste 
73014f1b3e8SDimitry Andric   lldb::TypeSummaryImplSP string_format(
73114f1b3e8SDimitry Andric       new StringSummaryFormat(string_flags, "${var%s}"));
7325e95aa85SEd Maste 
73314f1b3e8SDimitry Andric   lldb::TypeSummaryImplSP string_array_format(
734c0981da4SDimitry Andric       new StringSummaryFormat(string_array_flags, "${var%char[]}"));
7355e95aa85SEd Maste 
73614f1b3e8SDimitry Andric   TypeCategoryImpl::SharedPointer sys_category_sp =
73714f1b3e8SDimitry Andric       GetCategory(m_system_category_name);
738f034231aSEd Maste 
739e3b55780SDimitry Andric   sys_category_sp->AddTypeSummary(R"(^(unsigned )?char ?(\*|\[\])$)",
740e3b55780SDimitry Andric                                   eFormatterMatchRegex, string_format);
74177fc4c14SDimitry Andric 
742e3b55780SDimitry Andric   sys_category_sp->AddTypeSummary(R"(^((un)?signed )?char ?\[[0-9]+\]$)",
743e3b55780SDimitry Andric                                   eFormatterMatchRegex, string_array_format);
744f034231aSEd Maste 
74514f1b3e8SDimitry Andric   lldb::TypeSummaryImplSP ostype_summary(
74614f1b3e8SDimitry Andric       new StringSummaryFormat(TypeSummaryImpl::Flags()
74714f1b3e8SDimitry Andric                                   .SetCascades(false)
748f034231aSEd Maste                                   .SetSkipPointers(true)
749f034231aSEd Maste                                   .SetSkipReferences(true)
750f034231aSEd Maste                                   .SetDontShowChildren(true)
751f034231aSEd Maste                                   .SetDontShowValue(false)
752f034231aSEd Maste                                   .SetShowMembersOneLiner(false)
753f034231aSEd Maste                                   .SetHideItemNames(false),
754f034231aSEd Maste                               "${var%O}"));
755f034231aSEd Maste 
756e3b55780SDimitry Andric   sys_category_sp->AddTypeSummary("OSType", eFormatterMatchExact,
75714f1b3e8SDimitry Andric                                   ostype_summary);
758f034231aSEd Maste 
759f21a844fSEd Maste   TypeFormatImpl::Flags fourchar_flags;
76014f1b3e8SDimitry Andric   fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(
76114f1b3e8SDimitry Andric       true);
762f21a844fSEd Maste 
7637fa27ce4SDimitry Andric   AddFormat(sys_category_sp, lldb::eFormatOSType, "FourCharCode",
76414f1b3e8SDimitry Andric             fourchar_flags);
765f034231aSEd Maste }
766f034231aSEd Maste 
LoadVectorFormatters()76714f1b3e8SDimitry Andric void FormatManager::LoadVectorFormatters() {
76814f1b3e8SDimitry Andric   TypeCategoryImpl::SharedPointer vectors_category_sp =
76914f1b3e8SDimitry Andric       GetCategory(m_vectortypes_category_name);
770f034231aSEd Maste 
771f034231aSEd Maste   TypeSummaryImpl::Flags vector_flags;
772f034231aSEd Maste   vector_flags.SetCascades(true)
773f034231aSEd Maste       .SetSkipPointers(true)
774f034231aSEd Maste       .SetSkipReferences(false)
775f034231aSEd Maste       .SetDontShowChildren(true)
776f034231aSEd Maste       .SetDontShowValue(false)
777f034231aSEd Maste       .SetShowMembersOneLiner(true)
778f034231aSEd Maste       .SetHideItemNames(true);
779f034231aSEd Maste 
7807fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "${var.uint128}", "builtin_type_vec128",
781f034231aSEd Maste                    vector_flags);
7827fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "float[4]", vector_flags);
7837fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "int32_t[4]", vector_flags);
7847fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "int16_t[8]", vector_flags);
7857fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vDouble", vector_flags);
7867fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vFloat", vector_flags);
7877fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vSInt8", vector_flags);
7887fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vSInt16", vector_flags);
7897fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vSInt32", vector_flags);
7907fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vUInt16", vector_flags);
7917fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vUInt8", vector_flags);
7927fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vUInt16", vector_flags);
7937fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vUInt32", vector_flags);
7947fa27ce4SDimitry Andric   AddStringSummary(vectors_category_sp, "", "vBool32", vector_flags);
795f034231aSEd Maste }
796