xref: /llvm-project/lldb/source/DataFormatters/FormatManager.cpp (revision 68aa90a11e29b77ccbccc7ae128d342bc8920b40)
1 //===-- FormatManager.cpp -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/DataFormatters/FormatManager.h"
11 
12 #include "llvm/ADT/STLExtras.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/DataFormatters/FormattersHelpers.h"
22 #include "lldb/DataFormatters/LanguageCategory.h"
23 #include "lldb/Target/ExecutionContext.h"
24 #include "lldb/Target/Language.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 using namespace lldb_private::formatters;
29 
30 struct FormatInfo
31 {
32     Format format;
33     const char format_char; // One or more format characters that can be used for this format.
34     const char *format_name;    // Long format name that can be used to specify the current format
35 };
36 
37 static FormatInfo
38 g_format_infos[] =
39 {
40     { eFormatDefault        , '\0'  , "default"             },
41     { eFormatBoolean        , 'B'   , "boolean"             },
42     { eFormatBinary         , 'b'   , "binary"              },
43     { eFormatBytes          , 'y'   , "bytes"               },
44     { eFormatBytesWithASCII , 'Y'   , "bytes with ASCII"    },
45     { eFormatChar           , 'c'   , "character"           },
46     { eFormatCharPrintable  , 'C'   , "printable character" },
47     { eFormatComplexFloat   , 'F'   , "complex float"       },
48     { eFormatCString        , 's'   , "c-string"            },
49     { eFormatDecimal        , 'd'   , "decimal"             },
50     { eFormatEnum           , 'E'   , "enumeration"         },
51     { eFormatHex            , 'x'   , "hex"                 },
52     { eFormatHexUppercase   , 'X'   , "uppercase hex"       },
53     { eFormatFloat          , 'f'   , "float"               },
54     { eFormatOctal          , 'o'   , "octal"               },
55     { eFormatOSType         , 'O'   , "OSType"              },
56     { eFormatUnicode16      , 'U'   , "unicode16"           },
57     { eFormatUnicode32      , '\0'  , "unicode32"           },
58     { eFormatUnsigned       , 'u'   , "unsigned decimal"    },
59     { eFormatPointer        , 'p'   , "pointer"             },
60     { eFormatVectorOfChar   , '\0'  , "char[]"              },
61     { eFormatVectorOfSInt8  , '\0'  , "int8_t[]"            },
62     { eFormatVectorOfUInt8  , '\0'  , "uint8_t[]"           },
63     { eFormatVectorOfSInt16 , '\0'  , "int16_t[]"           },
64     { eFormatVectorOfUInt16 , '\0'  , "uint16_t[]"          },
65     { eFormatVectorOfSInt32 , '\0'  , "int32_t[]"           },
66     { eFormatVectorOfUInt32 , '\0'  , "uint32_t[]"          },
67     { eFormatVectorOfSInt64 , '\0'  , "int64_t[]"           },
68     { eFormatVectorOfUInt64 , '\0'  , "uint64_t[]"          },
69     { eFormatVectorOfFloat16, '\0'  , "float16[]"           },
70     { eFormatVectorOfFloat32, '\0'  , "float32[]"           },
71     { eFormatVectorOfFloat64, '\0'  , "float64[]"           },
72     { eFormatVectorOfUInt128, '\0'  , "uint128_t[]"         },
73     { eFormatComplexInteger , 'I'   , "complex integer"     },
74     { eFormatCharArray      , 'a'   , "character array"     },
75     { eFormatAddressInfo    , 'A'   , "address"             },
76     { eFormatHexFloat       , '\0'  , "hex float"           },
77     { eFormatInstruction    , 'i'   , "instruction"         },
78     { eFormatVoid           , 'v'   , "void"                }
79 };
80 
81 static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos);
82 
83 static bool
84 GetFormatFromFormatChar (char format_char, Format &format)
85 {
86     for (uint32_t i=0; i<g_num_format_infos; ++i)
87     {
88         if (g_format_infos[i].format_char == format_char)
89         {
90             format = g_format_infos[i].format;
91             return true;
92         }
93     }
94     format = eFormatInvalid;
95     return false;
96 }
97 
98 static bool
99 GetFormatFromFormatName (const char *format_name, bool partial_match_ok, Format &format)
100 {
101     uint32_t i;
102     for (i=0; i<g_num_format_infos; ++i)
103     {
104         if (strcasecmp (g_format_infos[i].format_name, format_name) == 0)
105         {
106             format = g_format_infos[i].format;
107             return true;
108         }
109     }
110 
111     if (partial_match_ok)
112     {
113         for (i=0; i<g_num_format_infos; ++i)
114         {
115             if (strcasestr (g_format_infos[i].format_name, format_name) == g_format_infos[i].format_name)
116             {
117                 format = g_format_infos[i].format;
118                 return true;
119             }
120         }
121     }
122     format = eFormatInvalid;
123     return false;
124 }
125 
126 bool
127 FormatManager::GetFormatFromCString (const char *format_cstr,
128                                      bool partial_match_ok,
129                                      lldb::Format &format)
130 {
131     bool success = false;
132     if (format_cstr && format_cstr[0])
133     {
134         if (format_cstr[1] == '\0')
135         {
136             success = GetFormatFromFormatChar (format_cstr[0], format);
137             if (success)
138                 return true;
139         }
140 
141         success = GetFormatFromFormatName (format_cstr, partial_match_ok, format);
142     }
143     if (!success)
144         format = eFormatInvalid;
145     return success;
146 }
147 
148 char
149 FormatManager::GetFormatAsFormatChar (lldb::Format format)
150 {
151     for (uint32_t i=0; i<g_num_format_infos; ++i)
152     {
153         if (g_format_infos[i].format == format)
154             return g_format_infos[i].format_char;
155     }
156     return '\0';
157 }
158 
159 const char *
160 FormatManager::GetFormatAsCString (Format format)
161 {
162     if (format >= eFormatDefault && format < kNumFormats)
163         return g_format_infos[format].format_name;
164     return NULL;
165 }
166 
167 void
168 FormatManager::EnableAllCategories ()
169 {
170     m_categories_map.EnableAllCategories ();
171     Mutex::Locker lang_locker(m_language_categories_mutex);
172     for (auto& iter : m_language_categories_map)
173     {
174         if (iter.second)
175             iter.second->Enable();
176     }
177 }
178 
179 void
180 FormatManager::DisableAllCategories ()
181 {
182     m_categories_map.DisableAllCategories ();
183     Mutex::Locker lang_locker(m_language_categories_mutex);
184     for (auto& iter : m_language_categories_map)
185     {
186         if (iter.second)
187             iter.second->Disable();
188     }
189 }
190 
191 void
192 FormatManager::GetPossibleMatches (ValueObject& valobj,
193                                    CompilerType compiler_type,
194                                    uint32_t reason,
195                                    lldb::DynamicValueType use_dynamic,
196                                    FormattersMatchVector& entries,
197                                    bool did_strip_ptr,
198                                    bool did_strip_ref,
199                                    bool did_strip_typedef,
200                                    bool root_level)
201 {
202     compiler_type = compiler_type.GetTypeForFormatters();
203     ConstString type_name(compiler_type.GetConstTypeName());
204     if (valobj.GetBitfieldBitSize() > 0)
205     {
206         StreamString sstring;
207         sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize());
208         ConstString bitfieldname = ConstString(sstring.GetData());
209         entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef});
210         reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
211     }
212 
213     if (!compiler_type.IsMeaninglessWithoutDynamicResolution())
214     {
215         entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
216 
217         ConstString display_type_name(compiler_type.GetDisplayTypeName());
218         if (display_type_name != type_name)
219             entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
220     }
221 
222     for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
223     {
224         CompilerType non_ref_type = compiler_type.GetNonReferenceType();
225         GetPossibleMatches(valobj,
226                            non_ref_type,
227                            reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
228                            use_dynamic,
229                            entries,
230                            did_strip_ptr,
231                            true,
232                            did_strip_typedef);
233         if (non_ref_type.IsTypedefType())
234         {
235             CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
236             deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType();
237             GetPossibleMatches(valobj,
238                                deffed_referenced_type,
239                                reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
240                                use_dynamic,
241                                entries,
242                                did_strip_ptr,
243                                did_strip_ref,
244                                true); // this is not exactly the usual meaning of stripping typedefs
245         }
246     }
247 
248     if (compiler_type.IsPointerType())
249     {
250         CompilerType non_ptr_type = compiler_type.GetPointeeType();
251         GetPossibleMatches(valobj,
252                            non_ptr_type,
253                            reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
254                            use_dynamic,
255                            entries,
256                            true,
257                            did_strip_ref,
258                            did_strip_typedef);
259         if (non_ptr_type.IsTypedefType())
260         {
261             CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
262             GetPossibleMatches(valobj,
263                                deffed_pointed_type,
264                                reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
265                                use_dynamic,
266                                entries,
267                                did_strip_ptr,
268                                did_strip_ref,
269                                true); // this is not exactly the usual meaning of stripping typedefs
270         }
271     }
272 
273     for (lldb::LanguageType language_type : GetCandidateLanguages(valobj))
274     {
275         if (Language* language = Language::FindPlugin(language_type))
276         {
277             for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic))
278             {
279                 entries.push_back({candidate,
280                                    reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin,
281                                    did_strip_ptr,
282                                    did_strip_ref,
283                                    did_strip_typedef});
284             }
285         }
286     }
287 
288     // try to strip typedef chains
289     if (compiler_type.IsTypedefType())
290     {
291         CompilerType deffed_type = compiler_type.GetTypedefedType();
292         GetPossibleMatches(valobj,
293                            deffed_type,
294                            reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
295                            use_dynamic,
296                            entries,
297                            did_strip_ptr,
298                            did_strip_ref,
299                            true);
300     }
301 
302     if (root_level)
303     {
304         do {
305             if (!compiler_type.IsValid())
306                 break;
307 
308             CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType();
309             if (!unqual_compiler_ast_type.IsValid())
310                 break;
311             if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType())
312                 GetPossibleMatches (valobj,
313                                     unqual_compiler_ast_type,
314                                     reason,
315                                     use_dynamic,
316                                     entries,
317                                     did_strip_ptr,
318                                     did_strip_ref,
319                                     did_strip_typedef);
320         } while(false);
321 
322 
323         // if all else fails, go to static type
324         if (valobj.IsDynamic())
325         {
326             lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
327             if (static_value_sp)
328                 GetPossibleMatches(*static_value_sp.get(),
329                                    static_value_sp->GetCompilerType(),
330                                    reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
331                                    use_dynamic,
332                                    entries,
333                                    did_strip_ptr,
334                                    did_strip_ref,
335                                    did_strip_typedef,
336                                    true);
337         }
338     }
339 }
340 
341 lldb::TypeFormatImplSP
342 FormatManager::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
343 {
344     if (!type_sp)
345         return lldb::TypeFormatImplSP();
346     lldb::TypeFormatImplSP format_chosen_sp;
347     uint32_t num_categories = m_categories_map.GetCount();
348     lldb::TypeCategoryImplSP category_sp;
349     uint32_t prio_category = UINT32_MAX;
350     for (uint32_t category_id = 0;
351          category_id < num_categories;
352          category_id++)
353     {
354         category_sp = GetCategoryAtIndex(category_id);
355         if (category_sp->IsEnabled() == false)
356             continue;
357         lldb::TypeFormatImplSP format_current_sp = category_sp->GetFormatForType(type_sp);
358         if (format_current_sp && (format_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
359         {
360             prio_category = category_sp->GetEnabledPosition();
361             format_chosen_sp = format_current_sp;
362         }
363     }
364     return format_chosen_sp;
365 }
366 
367 lldb::TypeSummaryImplSP
368 FormatManager::GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp)
369 {
370     if (!type_sp)
371         return lldb::TypeSummaryImplSP();
372     lldb::TypeSummaryImplSP summary_chosen_sp;
373     uint32_t num_categories = m_categories_map.GetCount();
374     lldb::TypeCategoryImplSP category_sp;
375     uint32_t prio_category = UINT32_MAX;
376     for (uint32_t category_id = 0;
377          category_id < num_categories;
378          category_id++)
379     {
380         category_sp = GetCategoryAtIndex(category_id);
381         if (category_sp->IsEnabled() == false)
382             continue;
383         lldb::TypeSummaryImplSP summary_current_sp = category_sp->GetSummaryForType(type_sp);
384         if (summary_current_sp && (summary_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
385         {
386             prio_category = category_sp->GetEnabledPosition();
387             summary_chosen_sp = summary_current_sp;
388         }
389     }
390     return summary_chosen_sp;
391 }
392 
393 lldb::TypeFilterImplSP
394 FormatManager::GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp)
395 {
396     if (!type_sp)
397         return lldb::TypeFilterImplSP();
398     lldb::TypeFilterImplSP filter_chosen_sp;
399     uint32_t num_categories = m_categories_map.GetCount();
400     lldb::TypeCategoryImplSP category_sp;
401     uint32_t prio_category = UINT32_MAX;
402     for (uint32_t category_id = 0;
403          category_id < num_categories;
404          category_id++)
405     {
406         category_sp = GetCategoryAtIndex(category_id);
407         if (category_sp->IsEnabled() == false)
408             continue;
409         lldb::TypeFilterImplSP filter_current_sp((TypeFilterImpl*)category_sp->GetFilterForType(type_sp).get());
410         if (filter_current_sp && (filter_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
411         {
412             prio_category = category_sp->GetEnabledPosition();
413             filter_chosen_sp = filter_current_sp;
414         }
415     }
416     return filter_chosen_sp;
417 }
418 
419 #ifndef LLDB_DISABLE_PYTHON
420 lldb::ScriptedSyntheticChildrenSP
421 FormatManager::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp)
422 {
423     if (!type_sp)
424         return lldb::ScriptedSyntheticChildrenSP();
425     lldb::ScriptedSyntheticChildrenSP synth_chosen_sp;
426     uint32_t num_categories = m_categories_map.GetCount();
427     lldb::TypeCategoryImplSP category_sp;
428     uint32_t prio_category = UINT32_MAX;
429     for (uint32_t category_id = 0;
430          category_id < num_categories;
431          category_id++)
432     {
433         category_sp = GetCategoryAtIndex(category_id);
434         if (category_sp->IsEnabled() == false)
435             continue;
436         lldb::ScriptedSyntheticChildrenSP synth_current_sp((ScriptedSyntheticChildren*)category_sp->GetSyntheticForType(type_sp).get());
437         if (synth_current_sp && (synth_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
438         {
439             prio_category = category_sp->GetEnabledPosition();
440             synth_chosen_sp = synth_current_sp;
441         }
442     }
443     return synth_chosen_sp;
444 }
445 #endif
446 
447 #ifndef LLDB_DISABLE_PYTHON
448 lldb::SyntheticChildrenSP
449 FormatManager::GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp)
450 {
451     if (!type_sp)
452         return lldb::SyntheticChildrenSP();
453     lldb::TypeFilterImplSP filter_sp = GetFilterForType(type_sp);
454     lldb::ScriptedSyntheticChildrenSP synth_sp = GetSyntheticForType(type_sp);
455     if (filter_sp->GetRevision() > synth_sp->GetRevision())
456         return lldb::SyntheticChildrenSP(filter_sp.get());
457     else
458         return lldb::SyntheticChildrenSP(synth_sp.get());
459 }
460 #endif
461 
462 lldb::TypeValidatorImplSP
463 FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
464 {
465     if (!type_sp)
466         return lldb::TypeValidatorImplSP();
467     lldb::TypeValidatorImplSP validator_chosen_sp;
468     uint32_t num_categories = m_categories_map.GetCount();
469     lldb::TypeCategoryImplSP category_sp;
470     uint32_t prio_category = UINT32_MAX;
471     for (uint32_t category_id = 0;
472          category_id < num_categories;
473          category_id++)
474     {
475         category_sp = GetCategoryAtIndex(category_id);
476         if (category_sp->IsEnabled() == false)
477             continue;
478         lldb::TypeValidatorImplSP validator_current_sp(category_sp->GetValidatorForType(type_sp).get());
479         if (validator_current_sp && (validator_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
480         {
481             prio_category = category_sp->GetEnabledPosition();
482             validator_chosen_sp = validator_current_sp;
483         }
484     }
485     return validator_chosen_sp;
486 }
487 
488 void
489 FormatManager::LoopThroughCategories (CategoryCallback callback, void* param)
490 {
491     m_categories_map.LoopThrough(callback, param);
492     Mutex::Locker locker(m_language_categories_mutex);
493     for (const auto& entry : m_language_categories_map)
494     {
495         if (auto category_sp = entry.second->GetCategory())
496         {
497             if (!callback(param, category_sp))
498                 break;
499         }
500     }
501 }
502 
503 void
504 FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback)
505 {
506     m_categories_map.ForEach(callback);
507     Mutex::Locker locker(m_language_categories_mutex);
508     for (const auto& entry : m_language_categories_map)
509     {
510         if (auto category_sp = entry.second->GetCategory())
511         {
512             if (!callback(category_sp))
513                 break;
514         }
515     }
516 }
517 
518 lldb::TypeCategoryImplSP
519 FormatManager::GetCategory (const ConstString& category_name,
520                             bool can_create)
521 {
522     if (!category_name)
523         return GetCategory(m_default_category_name);
524     lldb::TypeCategoryImplSP category;
525     if (m_categories_map.Get(category_name, category))
526         return category;
527 
528     if (!can_create)
529         return lldb::TypeCategoryImplSP();
530 
531     m_categories_map.Add(category_name,lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name)));
532     return GetCategory(category_name);
533 }
534 
535 lldb::Format
536 FormatManager::GetSingleItemFormat(lldb::Format vector_format)
537 {
538     switch(vector_format)
539     {
540         case eFormatVectorOfChar:
541             return eFormatCharArray;
542 
543         case eFormatVectorOfSInt8:
544         case eFormatVectorOfSInt16:
545         case eFormatVectorOfSInt32:
546         case eFormatVectorOfSInt64:
547             return eFormatDecimal;
548 
549         case eFormatVectorOfUInt8:
550         case eFormatVectorOfUInt16:
551         case eFormatVectorOfUInt32:
552         case eFormatVectorOfUInt64:
553         case eFormatVectorOfUInt128:
554             return eFormatHex;
555 
556         case eFormatVectorOfFloat16:
557         case eFormatVectorOfFloat32:
558         case eFormatVectorOfFloat64:
559             return eFormatFloat;
560 
561         default:
562             return lldb::eFormatInvalid;
563     }
564 }
565 
566 bool
567 FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
568 {
569     // if settings say no oneline whatsoever
570     if (valobj.GetTargetSP().get() && valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries() == false)
571         return false; // then don't oneline
572 
573     // if this object has a summary, then ask the summary
574     if (valobj.GetSummaryFormat().get() != nullptr)
575         return valobj.GetSummaryFormat()->IsOneLiner();
576 
577     // no children, no party
578     if (valobj.GetNumChildren() == 0)
579         return false;
580 
581     // ask the type if it has any opinion about this
582     // eLazyBoolCalculate == no opinion; other values should be self explanatory
583     CompilerType compiler_type(valobj.GetCompilerType());
584     if (compiler_type.IsValid())
585     {
586         switch (compiler_type.ShouldPrintAsOneLiner(&valobj))
587         {
588             case eLazyBoolNo:
589                 return false;
590             case eLazyBoolYes:
591                 return true;
592             case eLazyBoolCalculate:
593                 break;
594         }
595     }
596 
597     size_t total_children_name_len = 0;
598 
599     for (size_t idx = 0;
600          idx < valobj.GetNumChildren();
601          idx++)
602     {
603         bool is_synth_val = false;
604         ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true));
605         // something is wrong here - bail out
606         if (!child_sp)
607             return false;
608 
609         // also ask the child's type if it has any opinion
610         CompilerType child_compiler_type(child_sp->GetCompilerType());
611         if (child_compiler_type.IsValid())
612         {
613             switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get()))
614             {
615                 case eLazyBoolYes:
616                     // an opinion of yes is only binding for the child, so keep going
617                 case eLazyBoolCalculate:
618                     break;
619                 case eLazyBoolNo:
620                     // but if the child says no, then it's a veto on the whole thing
621                     return false;
622             }
623         }
624 
625         // if we decided to define synthetic children for a type, we probably care enough
626         // to show them, but avoid nesting children in children
627         if (child_sp->GetSyntheticChildren().get() != nullptr)
628         {
629             ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
630             // wait.. wat? just get out of here..
631             if (!synth_sp)
632                 return false;
633             // but if we only have them to provide a value, keep going
634             if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue())
635                 is_synth_val = true;
636             else
637                 return false;
638         }
639 
640         total_children_name_len += child_sp->GetName().GetLength();
641 
642         // 50 itself is a "randomly" chosen number - the idea is that
643         // overly long structs should not get this treatment
644         // FIXME: maybe make this a user-tweakable setting?
645         if (total_children_name_len > 50)
646             return false;
647 
648         // if a summary is there..
649         if (child_sp->GetSummaryFormat())
650         {
651             // and it wants children, then bail out
652             if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
653                 return false;
654         }
655 
656         // if this child has children..
657         if (child_sp->GetNumChildren())
658         {
659             // ...and no summary...
660             // (if it had a summary and the summary wanted children, we would have bailed out anyway
661             //  so this only makes us bail out if this has no summary and we would then print children)
662             if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child
663                 return false; // then bail out
664         }
665     }
666     return true;
667 }
668 
669 ConstString
670 FormatManager::GetValidTypeName (const ConstString& type)
671 {
672     return ::GetValidTypeName_Impl(type);
673 }
674 
675 ConstString
676 FormatManager::GetTypeForCache (ValueObject& valobj,
677                                 lldb::DynamicValueType use_dynamic)
678 {
679     ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(use_dynamic, valobj.IsSynthetic());
680     if (valobj_sp && valobj_sp->GetCompilerType().IsValid())
681     {
682         if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
683             return valobj_sp->GetQualifiedTypeName();
684     }
685     return ConstString();
686 }
687 
688 std::vector<lldb::LanguageType>
689 FormatManager::GetCandidateLanguages (ValueObject& valobj)
690 {
691     lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
692     return GetCandidateLanguages(lang_type);
693 }
694 
695 std::vector<lldb::LanguageType>
696 FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type)
697 {
698     switch (lang_type)
699     {
700         case lldb::eLanguageTypeC:
701         case lldb::eLanguageTypeC89:
702         case lldb::eLanguageTypeC99:
703         case lldb::eLanguageTypeC11:
704         case lldb::eLanguageTypeC_plus_plus:
705         case lldb::eLanguageTypeC_plus_plus_03:
706         case lldb::eLanguageTypeC_plus_plus_11:
707         case lldb::eLanguageTypeC_plus_plus_14:
708             return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC};
709         default:
710             return {lang_type};
711     }
712 }
713 
714 LanguageCategory*
715 FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type)
716 {
717     Mutex::Locker locker(m_language_categories_mutex);
718     auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end();
719     if (iter != end)
720         return iter->second.get();
721     LanguageCategory* lang_category = new LanguageCategory(lang_type);
722     m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category);
723     return lang_category;
724 }
725 
726 lldb::TypeFormatImplSP
727 FormatManager::GetHardcodedFormat (FormattersMatchData& match_data)
728 {
729     TypeFormatImplSP retval_sp;
730 
731     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
732     {
733         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
734         {
735             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
736                 break;
737         }
738     }
739 
740     return retval_sp;
741 }
742 
743 lldb::TypeFormatImplSP
744 FormatManager::GetFormat (ValueObject& valobj,
745                           lldb::DynamicValueType use_dynamic)
746 {
747     FormattersMatchData match_data(valobj, use_dynamic);
748 
749     TypeFormatImplSP retval;
750     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
751     if (match_data.GetTypeForCache())
752     {
753         if (log)
754             log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
755         if (m_format_cache.GetFormat(match_data.GetTypeForCache(),retval))
756         {
757             if (log)
758             {
759                 log->Printf("[FormatManager::GetFormat] Cache search success. Returning.");
760                 if (log->GetDebug())
761                     log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
762             }
763             return retval;
764         }
765         if (log)
766             log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route");
767     }
768 
769     retval = m_categories_map.GetFormat(match_data);
770     if (!retval)
771     {
772         if (log)
773             log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance.");
774         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
775         {
776             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
777             {
778                 if (lang_category->Get(match_data, retval))
779                     break;
780             }
781         }
782         if (retval)
783         {
784             if (log)
785                 log->Printf("[FormatManager::GetFormat] Language search success. Returning.");
786             return retval;
787         }
788     }
789     if (!retval)
790     {
791         if (log)
792             log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
793         retval = GetHardcodedFormat(match_data);
794     }
795 
796     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
797     {
798         if (log)
799             log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
800                         static_cast<void*>(retval.get()),
801                         match_data.GetTypeForCache().AsCString("<invalid>"));
802         m_format_cache.SetFormat(match_data.GetTypeForCache(),retval);
803     }
804     if (log && log->GetDebug())
805         log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
806     return retval;
807 }
808 
809 lldb::TypeSummaryImplSP
810 FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data)
811 {
812     TypeSummaryImplSP retval_sp;
813 
814     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
815     {
816         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
817         {
818             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
819                 break;
820         }
821     }
822 
823     return retval_sp;
824 }
825 
826 lldb::TypeSummaryImplSP
827 FormatManager::GetSummaryFormat (ValueObject& valobj,
828                                  lldb::DynamicValueType use_dynamic)
829 {
830     FormattersMatchData match_data(valobj, use_dynamic);
831 
832     TypeSummaryImplSP retval;
833     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
834     if (match_data.GetTypeForCache())
835     {
836         if (log)
837             log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
838         if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval))
839         {
840             if (log)
841             {
842                 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. Returning.");
843                 if (log->GetDebug())
844                     log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
845             }
846             return retval;
847         }
848         if (log)
849             log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route");
850     }
851 
852     retval = m_categories_map.GetSummaryFormat(match_data);
853     if (!retval)
854     {
855         if (log)
856             log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance.");
857         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
858         {
859             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
860             {
861                 if (lang_category->Get(match_data, retval))
862                     break;
863             }
864         }
865         if (retval)
866         {
867             if (log)
868                 log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning.");
869             return retval;
870         }
871     }
872     if (!retval)
873     {
874         if (log)
875             log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
876         retval = GetHardcodedSummaryFormat(match_data);
877     }
878 
879     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
880     {
881         if (log)
882             log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
883                         static_cast<void*>(retval.get()),
884                         match_data.GetTypeForCache().AsCString("<invalid>"));
885         m_format_cache.SetSummary(match_data.GetTypeForCache(),retval);
886     }
887     if (log && log->GetDebug())
888         log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
889     return retval;
890 }
891 
892 #ifndef LLDB_DISABLE_PYTHON
893 lldb::SyntheticChildrenSP
894 FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data)
895 {
896     SyntheticChildrenSP retval_sp;
897 
898     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
899     {
900         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
901         {
902             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
903                 break;
904         }
905     }
906 
907     return retval_sp;
908 }
909 
910 lldb::SyntheticChildrenSP
911 FormatManager::GetSyntheticChildren (ValueObject& valobj,
912                                      lldb::DynamicValueType use_dynamic)
913 {
914     FormattersMatchData match_data(valobj, use_dynamic);
915 
916     SyntheticChildrenSP retval;
917     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
918     if (match_data.GetTypeForCache())
919     {
920         if (log)
921             log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
922         if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval))
923         {
924             if (log)
925             {
926                 log->Printf("[FormatManager::GetSyntheticChildren] Cache search success. Returning.");
927                 if (log->GetDebug())
928                     log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
929             }
930             return retval;
931         }
932         if (log)
933             log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route");
934     }
935 
936     retval = m_categories_map.GetSyntheticChildren(match_data);
937     if (!retval)
938     {
939         if (log)
940             log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance.");
941         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
942         {
943             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
944             {
945                 if (lang_category->Get(match_data, retval))
946                     break;
947             }
948         }
949         if (retval)
950         {
951             if (log)
952                 log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning.");
953             return retval;
954         }
955     }
956     if (!retval)
957     {
958         if (log)
959             log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
960         retval = GetHardcodedSyntheticChildren(match_data);
961     }
962 
963     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
964     {
965         if (log)
966             log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",
967                         static_cast<void*>(retval.get()),
968                         match_data.GetTypeForCache().AsCString("<invalid>"));
969         m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval);
970     }
971     if (log && log->GetDebug())
972         log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
973     return retval;
974 }
975 #endif
976 
977 lldb::TypeValidatorImplSP
978 FormatManager::GetValidator (ValueObject& valobj,
979                              lldb::DynamicValueType use_dynamic)
980 {
981     FormattersMatchData match_data(valobj, use_dynamic);
982 
983     TypeValidatorImplSP retval;
984     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
985     if (match_data.GetTypeForCache())
986     {
987         if (log)
988             log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
989         if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval))
990         {
991             if (log)
992             {
993                 log->Printf("[FormatManager::GetValidator] Cache search success. Returning.");
994                 if (log->GetDebug())
995                     log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
996             }
997             return retval;
998         }
999         if (log)
1000             log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route");
1001     }
1002 
1003     retval = m_categories_map.GetValidator(match_data);
1004     if (!retval)
1005     {
1006         if (log)
1007             log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance.");
1008         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
1009         {
1010             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
1011             {
1012                 if (lang_category->Get(match_data, retval))
1013                     break;
1014             }
1015         }
1016         if (retval)
1017         {
1018             if (log)
1019                 log->Printf("[FormatManager::GetValidator] Language search success. Returning.");
1020             return retval;
1021         }
1022     }
1023     if (!retval)
1024     {
1025         if (log)
1026             log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance.");
1027         retval = GetHardcodedValidator(match_data);
1028     }
1029 
1030     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
1031     {
1032         if (log)
1033             log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
1034                         static_cast<void*>(retval.get()),
1035                         match_data.GetTypeForCache().AsCString("<invalid>"));
1036         m_format_cache.SetValidator(match_data.GetTypeForCache(),retval);
1037     }
1038     if (log && log->GetDebug())
1039         log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
1040     return retval;
1041 }
1042 
1043 lldb::TypeValidatorImplSP
1044 FormatManager::GetHardcodedValidator (FormattersMatchData& match_data)
1045 {
1046     TypeValidatorImplSP retval_sp;
1047 
1048     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
1049     {
1050         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
1051         {
1052             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
1053                 break;
1054         }
1055     }
1056 
1057     return retval_sp;
1058 }
1059 
1060 FormatManager::FormatManager() :
1061     m_format_cache(),
1062     m_named_summaries_map(this),
1063     m_last_revision(0),
1064     m_categories_map(this),
1065     m_language_categories_map(),
1066     m_language_categories_mutex(Mutex::eMutexTypeRecursive),
1067     m_default_category_name(ConstString("default")),
1068     m_system_category_name(ConstString("system")),
1069     m_vectortypes_category_name(ConstString("VectorTypes"))
1070 {
1071     LoadSystemFormatters();
1072     LoadVectorFormatters();
1073 
1074     EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
1075     EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
1076 }
1077 
1078 void
1079 FormatManager::LoadSystemFormatters()
1080 {
1081 
1082     TypeSummaryImpl::Flags string_flags;
1083     string_flags.SetCascades(true)
1084     .SetSkipPointers(true)
1085     .SetSkipReferences(false)
1086     .SetDontShowChildren(true)
1087     .SetDontShowValue(false)
1088     .SetShowMembersOneLiner(false)
1089     .SetHideItemNames(false);
1090 
1091     TypeSummaryImpl::Flags string_array_flags;
1092     string_array_flags.SetCascades(true)
1093     .SetSkipPointers(true)
1094     .SetSkipReferences(false)
1095     .SetDontShowChildren(true)
1096     .SetDontShowValue(true)
1097     .SetShowMembersOneLiner(false)
1098     .SetHideItemNames(false);
1099 
1100     lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(string_flags, "${var%s}"));
1101 
1102 
1103     lldb::TypeSummaryImplSP string_array_format(new StringSummaryFormat(string_array_flags,
1104                                                                         "${var%s}"));
1105 
1106     lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]"));
1107     lldb::RegularExpressionSP any_size_wchar_arr(new RegularExpression("wchar_t \\[[0-9]+\\]"));
1108 
1109     TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name);
1110 
1111     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), string_format);
1112     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("unsigned char *"), string_format);
1113     sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, string_array_format);
1114 
1115     lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
1116                                                                    .SetSkipPointers(true)
1117                                                                    .SetSkipReferences(true)
1118                                                                    .SetDontShowChildren(true)
1119                                                                    .SetDontShowValue(false)
1120                                                                    .SetShowMembersOneLiner(false)
1121                                                                    .SetHideItemNames(false),
1122                                                                    "${var%O}"));
1123 
1124     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary);
1125 
1126 #ifndef LLDB_DISABLE_PYTHON
1127     TypeFormatImpl::Flags fourchar_flags;
1128     fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true);
1129 
1130     AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags);
1131 #endif
1132 }
1133 
1134 void
1135 FormatManager::LoadVectorFormatters()
1136 {
1137     TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
1138 
1139     TypeSummaryImpl::Flags vector_flags;
1140     vector_flags.SetCascades(true)
1141     .SetSkipPointers(true)
1142     .SetSkipReferences(false)
1143     .SetDontShowChildren(true)
1144     .SetDontShowValue(false)
1145     .SetShowMembersOneLiner(true)
1146     .SetHideItemNames(true);
1147 
1148     AddStringSummary(vectors_category_sp,
1149                      "${var.uint128}",
1150                      ConstString("builtin_type_vec128"),
1151                      vector_flags);
1152 
1153     AddStringSummary(vectors_category_sp,
1154                      "",
1155                      ConstString("float [4]"),
1156                      vector_flags);
1157     AddStringSummary(vectors_category_sp,
1158                      "",
1159                      ConstString("int32_t [4]"),
1160                      vector_flags);
1161     AddStringSummary(vectors_category_sp,
1162                      "",
1163                      ConstString("int16_t [8]"),
1164                      vector_flags);
1165     AddStringSummary(vectors_category_sp,
1166                      "",
1167                      ConstString("vDouble"),
1168                      vector_flags);
1169     AddStringSummary(vectors_category_sp,
1170                      "",
1171                      ConstString("vFloat"),
1172                      vector_flags);
1173     AddStringSummary(vectors_category_sp,
1174                      "",
1175                      ConstString("vSInt8"),
1176                      vector_flags);
1177     AddStringSummary(vectors_category_sp,
1178                      "",
1179                      ConstString("vSInt16"),
1180                      vector_flags);
1181     AddStringSummary(vectors_category_sp,
1182                      "",
1183                      ConstString("vSInt32"),
1184                      vector_flags);
1185     AddStringSummary(vectors_category_sp,
1186                      "",
1187                      ConstString("vUInt16"),
1188                      vector_flags);
1189     AddStringSummary(vectors_category_sp,
1190                      "",
1191                      ConstString("vUInt8"),
1192                      vector_flags);
1193     AddStringSummary(vectors_category_sp,
1194                      "",
1195                      ConstString("vUInt16"),
1196                      vector_flags);
1197     AddStringSummary(vectors_category_sp,
1198                      "",
1199                      ConstString("vUInt32"),
1200                      vector_flags);
1201     AddStringSummary(vectors_category_sp,
1202                      "",
1203                      ConstString("vBool32"),
1204                      vector_flags);
1205 }
1206