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 (FormattersMatchData& match_data)
701 {
702     TypeFormatImplSP retval_sp;
703 
704     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
705     {
706         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
707         {
708             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
709                 break;
710         }
711     }
712 
713     return retval_sp;
714 }
715 
716 lldb::TypeFormatImplSP
717 FormatManager::GetFormat (ValueObject& valobj,
718                           lldb::DynamicValueType use_dynamic)
719 {
720     FormattersMatchData match_data(valobj, use_dynamic);
721 
722     TypeFormatImplSP retval;
723     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
724     if (match_data.GetTypeForCache())
725     {
726         if (log)
727             log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
728         if (m_format_cache.GetFormat(match_data.GetTypeForCache(),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     retval = m_categories_map.GetFormat(match_data);
743     if (!retval)
744     {
745         if (log)
746             log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance.");
747         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
748         {
749             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
750             {
751                 if (lang_category->Get(match_data, retval))
752                     break;
753             }
754         }
755         if (retval)
756         {
757             if (log)
758                 log->Printf("[FormatManager::GetFormat] Language search success. Returning.");
759             return retval;
760         }
761     }
762     if (!retval)
763     {
764         if (log)
765             log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
766         retval = GetHardcodedFormat(match_data);
767     }
768 
769     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
770     {
771         if (log)
772             log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
773                         static_cast<void*>(retval.get()),
774                         match_data.GetTypeForCache().AsCString("<invalid>"));
775         m_format_cache.SetFormat(match_data.GetTypeForCache(),retval);
776     }
777     if (log && log->GetDebug())
778         log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
779     return retval;
780 }
781 
782 lldb::TypeSummaryImplSP
783 FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data)
784 {
785     TypeSummaryImplSP retval_sp;
786 
787     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
788     {
789         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
790         {
791             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
792                 break;
793         }
794     }
795 
796     return retval_sp;
797 }
798 
799 lldb::TypeSummaryImplSP
800 FormatManager::GetSummaryFormat (ValueObject& valobj,
801                                  lldb::DynamicValueType use_dynamic)
802 {
803     FormattersMatchData match_data(valobj, use_dynamic);
804 
805     TypeSummaryImplSP retval;
806     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
807     if (match_data.GetTypeForCache())
808     {
809         if (log)
810             log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
811         if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval))
812         {
813             if (log)
814             {
815                 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. Returning.");
816                 if (log->GetDebug())
817                     log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
818             }
819             return retval;
820         }
821         if (log)
822             log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route");
823     }
824 
825     retval = m_categories_map.GetSummaryFormat(match_data);
826     if (!retval)
827     {
828         if (log)
829             log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance.");
830         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
831         {
832             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
833             {
834                 if (lang_category->Get(match_data, retval))
835                     break;
836             }
837         }
838         if (retval)
839         {
840             if (log)
841                 log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning.");
842             return retval;
843         }
844     }
845     if (!retval)
846     {
847         if (log)
848             log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
849         retval = GetHardcodedSummaryFormat(match_data);
850     }
851 
852     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
853     {
854         if (log)
855             log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
856                         static_cast<void*>(retval.get()),
857                         match_data.GetTypeForCache().AsCString("<invalid>"));
858         m_format_cache.SetSummary(match_data.GetTypeForCache(),retval);
859     }
860     if (log && log->GetDebug())
861         log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
862     return retval;
863 }
864 
865 #ifndef LLDB_DISABLE_PYTHON
866 lldb::SyntheticChildrenSP
867 FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data)
868 {
869     SyntheticChildrenSP retval_sp;
870 
871     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
872     {
873         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
874         {
875             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
876                 break;
877         }
878     }
879 
880     return retval_sp;
881 }
882 
883 lldb::SyntheticChildrenSP
884 FormatManager::GetSyntheticChildren (ValueObject& valobj,
885                                      lldb::DynamicValueType use_dynamic)
886 {
887     FormattersMatchData match_data(valobj, use_dynamic);
888 
889     SyntheticChildrenSP retval;
890     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
891     if (match_data.GetTypeForCache())
892     {
893         if (log)
894             log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
895         if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval))
896         {
897             if (log)
898             {
899                 log->Printf("[FormatManager::GetSyntheticChildren] Cache search success. Returning.");
900                 if (log->GetDebug())
901                     log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
902             }
903             return retval;
904         }
905         if (log)
906             log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route");
907     }
908 
909     retval = m_categories_map.GetSyntheticChildren(match_data);
910     if (!retval)
911     {
912         if (log)
913             log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance.");
914         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
915         {
916             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
917             {
918                 if (lang_category->Get(match_data, retval))
919                     break;
920             }
921         }
922         if (retval)
923         {
924             if (log)
925                 log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning.");
926             return retval;
927         }
928     }
929     if (!retval)
930     {
931         if (log)
932             log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
933         retval = GetHardcodedSyntheticChildren(match_data);
934     }
935 
936     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
937     {
938         if (log)
939             log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",
940                         static_cast<void*>(retval.get()),
941                         match_data.GetTypeForCache().AsCString("<invalid>"));
942         m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval);
943     }
944     if (log && log->GetDebug())
945         log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
946     return retval;
947 }
948 #endif
949 
950 lldb::TypeValidatorImplSP
951 FormatManager::GetValidator (ValueObject& valobj,
952                              lldb::DynamicValueType use_dynamic)
953 {
954     FormattersMatchData match_data(valobj, use_dynamic);
955 
956     TypeValidatorImplSP retval;
957     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
958     if (match_data.GetTypeForCache())
959     {
960         if (log)
961             log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
962         if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval))
963         {
964             if (log)
965             {
966                 log->Printf("[FormatManager::GetValidator] Cache search success. Returning.");
967                 if (log->GetDebug())
968                     log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
969             }
970             return retval;
971         }
972         if (log)
973             log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route");
974     }
975 
976     retval = m_categories_map.GetValidator(match_data);
977     if (!retval)
978     {
979         if (log)
980             log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance.");
981         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
982         {
983             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
984             {
985                 if (lang_category->Get(match_data, retval))
986                     break;
987             }
988         }
989         if (retval)
990         {
991             if (log)
992                 log->Printf("[FormatManager::GetValidator] Language search success. Returning.");
993             return retval;
994         }
995     }
996     if (!retval)
997     {
998         if (log)
999             log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance.");
1000         retval = GetHardcodedValidator(match_data);
1001     }
1002 
1003     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
1004     {
1005         if (log)
1006             log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
1007                         static_cast<void*>(retval.get()),
1008                         match_data.GetTypeForCache().AsCString("<invalid>"));
1009         m_format_cache.SetValidator(match_data.GetTypeForCache(),retval);
1010     }
1011     if (log && log->GetDebug())
1012         log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
1013     return retval;
1014 }
1015 
1016 lldb::TypeValidatorImplSP
1017 FormatManager::GetHardcodedValidator (FormattersMatchData& match_data)
1018 {
1019     TypeValidatorImplSP retval_sp;
1020 
1021     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
1022     {
1023         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
1024         {
1025             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
1026                 break;
1027         }
1028     }
1029 
1030     return retval_sp;
1031 }
1032 
1033 FormatManager::FormatManager() :
1034     m_format_cache(),
1035     m_named_summaries_map(this),
1036     m_last_revision(0),
1037     m_categories_map(this),
1038     m_language_categories_map(),
1039     m_language_categories_mutex(Mutex::eMutexTypeRecursive),
1040     m_default_category_name(ConstString("default")),
1041     m_system_category_name(ConstString("system")),
1042     m_vectortypes_category_name(ConstString("VectorTypes"))
1043 {
1044     LoadSystemFormatters();
1045     LoadVectorFormatters();
1046 
1047     EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
1048     EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
1049 }
1050 
1051 void
1052 FormatManager::LoadSystemFormatters()
1053 {
1054 
1055     TypeSummaryImpl::Flags string_flags;
1056     string_flags.SetCascades(true)
1057     .SetSkipPointers(true)
1058     .SetSkipReferences(false)
1059     .SetDontShowChildren(true)
1060     .SetDontShowValue(false)
1061     .SetShowMembersOneLiner(false)
1062     .SetHideItemNames(false);
1063 
1064     TypeSummaryImpl::Flags string_array_flags;
1065     string_array_flags.SetCascades(true)
1066     .SetSkipPointers(true)
1067     .SetSkipReferences(false)
1068     .SetDontShowChildren(true)
1069     .SetDontShowValue(true)
1070     .SetShowMembersOneLiner(false)
1071     .SetHideItemNames(false);
1072 
1073     lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(string_flags, "${var%s}"));
1074 
1075 
1076     lldb::TypeSummaryImplSP string_array_format(new StringSummaryFormat(string_array_flags,
1077                                                                         "${var%s}"));
1078 
1079     lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]"));
1080     lldb::RegularExpressionSP any_size_wchar_arr(new RegularExpression("wchar_t \\[[0-9]+\\]"));
1081 
1082     TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name);
1083 
1084     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), string_format);
1085     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("unsigned char *"), string_format);
1086     sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, string_array_format);
1087 
1088     lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
1089                                                                    .SetSkipPointers(true)
1090                                                                    .SetSkipReferences(true)
1091                                                                    .SetDontShowChildren(true)
1092                                                                    .SetDontShowValue(false)
1093                                                                    .SetShowMembersOneLiner(false)
1094                                                                    .SetHideItemNames(false),
1095                                                                    "${var%O}"));
1096 
1097     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary);
1098 
1099 #ifndef LLDB_DISABLE_PYTHON
1100     TypeFormatImpl::Flags fourchar_flags;
1101     fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true);
1102 
1103     AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags);
1104 #endif
1105 }
1106 
1107 void
1108 FormatManager::LoadVectorFormatters()
1109 {
1110     TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
1111 
1112     TypeSummaryImpl::Flags vector_flags;
1113     vector_flags.SetCascades(true)
1114     .SetSkipPointers(true)
1115     .SetSkipReferences(false)
1116     .SetDontShowChildren(true)
1117     .SetDontShowValue(false)
1118     .SetShowMembersOneLiner(true)
1119     .SetHideItemNames(true);
1120 
1121     AddStringSummary(vectors_category_sp,
1122                      "${var.uint128}",
1123                      ConstString("builtin_type_vec128"),
1124                      vector_flags);
1125 
1126     AddStringSummary(vectors_category_sp,
1127                      "",
1128                      ConstString("float [4]"),
1129                      vector_flags);
1130     AddStringSummary(vectors_category_sp,
1131                      "",
1132                      ConstString("int32_t [4]"),
1133                      vector_flags);
1134     AddStringSummary(vectors_category_sp,
1135                      "",
1136                      ConstString("int16_t [8]"),
1137                      vector_flags);
1138     AddStringSummary(vectors_category_sp,
1139                      "",
1140                      ConstString("vDouble"),
1141                      vector_flags);
1142     AddStringSummary(vectors_category_sp,
1143                      "",
1144                      ConstString("vFloat"),
1145                      vector_flags);
1146     AddStringSummary(vectors_category_sp,
1147                      "",
1148                      ConstString("vSInt8"),
1149                      vector_flags);
1150     AddStringSummary(vectors_category_sp,
1151                      "",
1152                      ConstString("vSInt16"),
1153                      vector_flags);
1154     AddStringSummary(vectors_category_sp,
1155                      "",
1156                      ConstString("vSInt32"),
1157                      vector_flags);
1158     AddStringSummary(vectors_category_sp,
1159                      "",
1160                      ConstString("vUInt16"),
1161                      vector_flags);
1162     AddStringSummary(vectors_category_sp,
1163                      "",
1164                      ConstString("vUInt8"),
1165                      vector_flags);
1166     AddStringSummary(vectors_category_sp,
1167                      "",
1168                      ConstString("vUInt16"),
1169                      vector_flags);
1170     AddStringSummary(vectors_category_sp,
1171                      "",
1172                      ConstString("vUInt32"),
1173                      vector_flags);
1174     AddStringSummary(vectors_category_sp,
1175                      "",
1176                      ConstString("vBool32"),
1177                      vector_flags);
1178 }
1179