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