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