xref: /llvm-project/lldb/source/DataFormatters/FormatManager.cpp (revision 3de08c5f0c972ade61b6dd0ea4561c33e09c58fc)
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::ForEachCategory(TypeCategoryMap::ForEachCallback callback)
490 {
491     m_categories_map.ForEach(callback);
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(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(&valobj))
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 
594         // also ask the child's type if it has any opinion
595         CompilerType child_compiler_type(child_sp->GetCompilerType());
596         if (child_compiler_type.IsValid())
597         {
598             switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get()))
599             {
600                 case eLazyBoolYes:
601                     // an opinion of yes is only binding for the child, so keep going
602                 case eLazyBoolCalculate:
603                     break;
604                 case eLazyBoolNo:
605                     // but if the child says no, then it's a veto on the whole thing
606                     return false;
607             }
608         }
609 
610         // if we decided to define synthetic children for a type, we probably care enough
611         // to show them, but avoid nesting children in children
612         if (child_sp->GetSyntheticChildren().get() != nullptr)
613         {
614             ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
615             // wait.. wat? just get out of here..
616             if (!synth_sp)
617                 return false;
618             // but if we only have them to provide a value, keep going
619             if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue())
620                 is_synth_val = true;
621             else
622                 return false;
623         }
624 
625         total_children_name_len += child_sp->GetName().GetLength();
626 
627         // 50 itself is a "randomly" chosen number - the idea is that
628         // overly long structs should not get this treatment
629         // FIXME: maybe make this a user-tweakable setting?
630         if (total_children_name_len > 50)
631             return false;
632 
633         // if a summary is there..
634         if (child_sp->GetSummaryFormat())
635         {
636             // and it wants children, then bail out
637             if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
638                 return false;
639         }
640 
641         // if this child has children..
642         if (child_sp->GetNumChildren())
643         {
644             // ...and no summary...
645             // (if it had a summary and the summary wanted children, we would have bailed out anyway
646             //  so this only makes us bail out if this has no summary and we would then print children)
647             if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child
648                 return false; // then bail out
649         }
650     }
651     return true;
652 }
653 
654 ConstString
655 FormatManager::GetValidTypeName (const ConstString& type)
656 {
657     return ::GetValidTypeName_Impl(type);
658 }
659 
660 ConstString
661 FormatManager::GetTypeForCache (ValueObject& valobj,
662                                 lldb::DynamicValueType use_dynamic)
663 {
664     ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(use_dynamic, valobj.IsSynthetic());
665     if (valobj_sp && valobj_sp->GetCompilerType().IsValid())
666     {
667         if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
668             return valobj_sp->GetQualifiedTypeName();
669     }
670     return ConstString();
671 }
672 
673 std::vector<lldb::LanguageType>
674 FormatManager::GetCandidateLanguages (ValueObject& valobj)
675 {
676     lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
677     return GetCandidateLanguages(lang_type);
678 }
679 
680 std::vector<lldb::LanguageType>
681 FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type)
682 {
683     switch (lang_type)
684     {
685         case lldb::eLanguageTypeC:
686         case lldb::eLanguageTypeC89:
687         case lldb::eLanguageTypeC99:
688         case lldb::eLanguageTypeC11:
689         case lldb::eLanguageTypeC_plus_plus:
690         case lldb::eLanguageTypeC_plus_plus_03:
691         case lldb::eLanguageTypeC_plus_plus_11:
692         case lldb::eLanguageTypeC_plus_plus_14:
693             return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC};
694         default:
695             return {lang_type};
696     }
697 }
698 
699 LanguageCategory*
700 FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type)
701 {
702     Mutex::Locker locker(m_language_categories_mutex);
703     auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end();
704     if (iter != end)
705         return iter->second.get();
706     LanguageCategory* lang_category = new LanguageCategory(lang_type);
707     m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category);
708     return lang_category;
709 }
710 
711 lldb::TypeFormatImplSP
712 FormatManager::GetHardcodedFormat (FormattersMatchData& match_data)
713 {
714     TypeFormatImplSP retval_sp;
715 
716     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
717     {
718         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
719         {
720             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
721                 break;
722         }
723     }
724 
725     return retval_sp;
726 }
727 
728 lldb::TypeFormatImplSP
729 FormatManager::GetFormat (ValueObject& valobj,
730                           lldb::DynamicValueType use_dynamic)
731 {
732     FormattersMatchData match_data(valobj, use_dynamic);
733 
734     TypeFormatImplSP retval;
735     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
736     if (match_data.GetTypeForCache())
737     {
738         if (log)
739             log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
740         if (m_format_cache.GetFormat(match_data.GetTypeForCache(),retval))
741         {
742             if (log)
743             {
744                 log->Printf("[FormatManager::GetFormat] Cache search success. Returning.");
745                 if (log->GetDebug())
746                     log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
747             }
748             return retval;
749         }
750         if (log)
751             log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route");
752     }
753 
754     retval = m_categories_map.GetFormat(match_data);
755     if (!retval)
756     {
757         if (log)
758             log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance.");
759         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
760         {
761             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
762             {
763                 if (lang_category->Get(match_data, retval))
764                     break;
765             }
766         }
767         if (retval)
768         {
769             if (log)
770                 log->Printf("[FormatManager::GetFormat] Language search success. Returning.");
771             return retval;
772         }
773     }
774     if (!retval)
775     {
776         if (log)
777             log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
778         retval = GetHardcodedFormat(match_data);
779     }
780 
781     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
782     {
783         if (log)
784             log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
785                         static_cast<void*>(retval.get()),
786                         match_data.GetTypeForCache().AsCString("<invalid>"));
787         m_format_cache.SetFormat(match_data.GetTypeForCache(),retval);
788     }
789     if (log && log->GetDebug())
790         log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
791     return retval;
792 }
793 
794 lldb::TypeSummaryImplSP
795 FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data)
796 {
797     TypeSummaryImplSP retval_sp;
798 
799     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
800     {
801         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
802         {
803             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
804                 break;
805         }
806     }
807 
808     return retval_sp;
809 }
810 
811 lldb::TypeSummaryImplSP
812 FormatManager::GetSummaryFormat (ValueObject& valobj,
813                                  lldb::DynamicValueType use_dynamic)
814 {
815     FormattersMatchData match_data(valobj, use_dynamic);
816 
817     TypeSummaryImplSP retval;
818     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
819     if (match_data.GetTypeForCache())
820     {
821         if (log)
822             log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
823         if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval))
824         {
825             if (log)
826             {
827                 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. Returning.");
828                 if (log->GetDebug())
829                     log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
830             }
831             return retval;
832         }
833         if (log)
834             log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route");
835     }
836 
837     retval = m_categories_map.GetSummaryFormat(match_data);
838     if (!retval)
839     {
840         if (log)
841             log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance.");
842         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
843         {
844             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
845             {
846                 if (lang_category->Get(match_data, retval))
847                     break;
848             }
849         }
850         if (retval)
851         {
852             if (log)
853                 log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning.");
854             return retval;
855         }
856     }
857     if (!retval)
858     {
859         if (log)
860             log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
861         retval = GetHardcodedSummaryFormat(match_data);
862     }
863 
864     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
865     {
866         if (log)
867             log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
868                         static_cast<void*>(retval.get()),
869                         match_data.GetTypeForCache().AsCString("<invalid>"));
870         m_format_cache.SetSummary(match_data.GetTypeForCache(),retval);
871     }
872     if (log && log->GetDebug())
873         log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
874     return retval;
875 }
876 
877 #ifndef LLDB_DISABLE_PYTHON
878 lldb::SyntheticChildrenSP
879 FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data)
880 {
881     SyntheticChildrenSP retval_sp;
882 
883     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
884     {
885         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
886         {
887             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
888                 break;
889         }
890     }
891 
892     return retval_sp;
893 }
894 
895 lldb::SyntheticChildrenSP
896 FormatManager::GetSyntheticChildren (ValueObject& valobj,
897                                      lldb::DynamicValueType use_dynamic)
898 {
899     FormattersMatchData match_data(valobj, use_dynamic);
900 
901     SyntheticChildrenSP retval;
902     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
903     if (match_data.GetTypeForCache())
904     {
905         if (log)
906             log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
907         if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval))
908         {
909             if (log)
910             {
911                 log->Printf("[FormatManager::GetSyntheticChildren] Cache search success. Returning.");
912                 if (log->GetDebug())
913                     log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
914             }
915             return retval;
916         }
917         if (log)
918             log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route");
919     }
920 
921     retval = m_categories_map.GetSyntheticChildren(match_data);
922     if (!retval)
923     {
924         if (log)
925             log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance.");
926         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
927         {
928             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
929             {
930                 if (lang_category->Get(match_data, retval))
931                     break;
932             }
933         }
934         if (retval)
935         {
936             if (log)
937                 log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning.");
938             return retval;
939         }
940     }
941     if (!retval)
942     {
943         if (log)
944             log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
945         retval = GetHardcodedSyntheticChildren(match_data);
946     }
947 
948     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
949     {
950         if (log)
951             log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",
952                         static_cast<void*>(retval.get()),
953                         match_data.GetTypeForCache().AsCString("<invalid>"));
954         m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval);
955     }
956     if (log && log->GetDebug())
957         log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
958     return retval;
959 }
960 #endif
961 
962 lldb::TypeValidatorImplSP
963 FormatManager::GetValidator (ValueObject& valobj,
964                              lldb::DynamicValueType use_dynamic)
965 {
966     FormattersMatchData match_data(valobj, use_dynamic);
967 
968     TypeValidatorImplSP retval;
969     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
970     if (match_data.GetTypeForCache())
971     {
972         if (log)
973             log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
974         if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval))
975         {
976             if (log)
977             {
978                 log->Printf("[FormatManager::GetValidator] Cache search success. Returning.");
979                 if (log->GetDebug())
980                     log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
981             }
982             return retval;
983         }
984         if (log)
985             log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route");
986     }
987 
988     retval = m_categories_map.GetValidator(match_data);
989     if (!retval)
990     {
991         if (log)
992             log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance.");
993         for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
994         {
995             if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
996             {
997                 if (lang_category->Get(match_data, retval))
998                     break;
999             }
1000         }
1001         if (retval)
1002         {
1003             if (log)
1004                 log->Printf("[FormatManager::GetValidator] Language search success. Returning.");
1005             return retval;
1006         }
1007     }
1008     if (!retval)
1009     {
1010         if (log)
1011             log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance.");
1012         retval = GetHardcodedValidator(match_data);
1013     }
1014 
1015     if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
1016     {
1017         if (log)
1018             log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
1019                         static_cast<void*>(retval.get()),
1020                         match_data.GetTypeForCache().AsCString("<invalid>"));
1021         m_format_cache.SetValidator(match_data.GetTypeForCache(),retval);
1022     }
1023     if (log && log->GetDebug())
1024         log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
1025     return retval;
1026 }
1027 
1028 lldb::TypeValidatorImplSP
1029 FormatManager::GetHardcodedValidator (FormattersMatchData& match_data)
1030 {
1031     TypeValidatorImplSP retval_sp;
1032 
1033     for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
1034     {
1035         if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
1036         {
1037             if (lang_category->GetHardcoded(*this, match_data, retval_sp))
1038                 break;
1039         }
1040     }
1041 
1042     return retval_sp;
1043 }
1044 
1045 FormatManager::FormatManager() :
1046     m_format_cache(),
1047     m_named_summaries_map(this),
1048     m_last_revision(0),
1049     m_categories_map(this),
1050     m_language_categories_map(),
1051     m_language_categories_mutex(Mutex::eMutexTypeRecursive),
1052     m_default_category_name(ConstString("default")),
1053     m_system_category_name(ConstString("system")),
1054     m_vectortypes_category_name(ConstString("VectorTypes"))
1055 {
1056     LoadSystemFormatters();
1057     LoadVectorFormatters();
1058 
1059     EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
1060     EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
1061 }
1062 
1063 void
1064 FormatManager::LoadSystemFormatters()
1065 {
1066 
1067     TypeSummaryImpl::Flags string_flags;
1068     string_flags.SetCascades(true)
1069     .SetSkipPointers(true)
1070     .SetSkipReferences(false)
1071     .SetDontShowChildren(true)
1072     .SetDontShowValue(false)
1073     .SetShowMembersOneLiner(false)
1074     .SetHideItemNames(false);
1075 
1076     TypeSummaryImpl::Flags string_array_flags;
1077     string_array_flags.SetCascades(true)
1078     .SetSkipPointers(true)
1079     .SetSkipReferences(false)
1080     .SetDontShowChildren(true)
1081     .SetDontShowValue(true)
1082     .SetShowMembersOneLiner(false)
1083     .SetHideItemNames(false);
1084 
1085     lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(string_flags, "${var%s}"));
1086 
1087 
1088     lldb::TypeSummaryImplSP string_array_format(new StringSummaryFormat(string_array_flags,
1089                                                                         "${var%s}"));
1090 
1091     lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]"));
1092     lldb::RegularExpressionSP any_size_wchar_arr(new RegularExpression("wchar_t \\[[0-9]+\\]"));
1093 
1094     TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name);
1095 
1096     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), string_format);
1097     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("unsigned char *"), string_format);
1098     sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, string_array_format);
1099 
1100     lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
1101                                                                    .SetSkipPointers(true)
1102                                                                    .SetSkipReferences(true)
1103                                                                    .SetDontShowChildren(true)
1104                                                                    .SetDontShowValue(false)
1105                                                                    .SetShowMembersOneLiner(false)
1106                                                                    .SetHideItemNames(false),
1107                                                                    "${var%O}"));
1108 
1109     sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary);
1110 
1111 #ifndef LLDB_DISABLE_PYTHON
1112     TypeFormatImpl::Flags fourchar_flags;
1113     fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true);
1114 
1115     AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags);
1116 #endif
1117 }
1118 
1119 void
1120 FormatManager::LoadVectorFormatters()
1121 {
1122     TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
1123 
1124     TypeSummaryImpl::Flags vector_flags;
1125     vector_flags.SetCascades(true)
1126     .SetSkipPointers(true)
1127     .SetSkipReferences(false)
1128     .SetDontShowChildren(true)
1129     .SetDontShowValue(false)
1130     .SetShowMembersOneLiner(true)
1131     .SetHideItemNames(true);
1132 
1133     AddStringSummary(vectors_category_sp,
1134                      "${var.uint128}",
1135                      ConstString("builtin_type_vec128"),
1136                      vector_flags);
1137 
1138     AddStringSummary(vectors_category_sp,
1139                      "",
1140                      ConstString("float [4]"),
1141                      vector_flags);
1142     AddStringSummary(vectors_category_sp,
1143                      "",
1144                      ConstString("int32_t [4]"),
1145                      vector_flags);
1146     AddStringSummary(vectors_category_sp,
1147                      "",
1148                      ConstString("int16_t [8]"),
1149                      vector_flags);
1150     AddStringSummary(vectors_category_sp,
1151                      "",
1152                      ConstString("vDouble"),
1153                      vector_flags);
1154     AddStringSummary(vectors_category_sp,
1155                      "",
1156                      ConstString("vFloat"),
1157                      vector_flags);
1158     AddStringSummary(vectors_category_sp,
1159                      "",
1160                      ConstString("vSInt8"),
1161                      vector_flags);
1162     AddStringSummary(vectors_category_sp,
1163                      "",
1164                      ConstString("vSInt16"),
1165                      vector_flags);
1166     AddStringSummary(vectors_category_sp,
1167                      "",
1168                      ConstString("vSInt32"),
1169                      vector_flags);
1170     AddStringSummary(vectors_category_sp,
1171                      "",
1172                      ConstString("vUInt16"),
1173                      vector_flags);
1174     AddStringSummary(vectors_category_sp,
1175                      "",
1176                      ConstString("vUInt8"),
1177                      vector_flags);
1178     AddStringSummary(vectors_category_sp,
1179                      "",
1180                      ConstString("vUInt16"),
1181                      vector_flags);
1182     AddStringSummary(vectors_category_sp,
1183                      "",
1184                      ConstString("vUInt32"),
1185                      vector_flags);
1186     AddStringSummary(vectors_category_sp,
1187                      "",
1188                      ConstString("vBool32"),
1189                      vector_flags);
1190 }
1191