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