1 //===-- FormatManager.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/DataFormatters/FormatManager.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/DataFormatters/FormattersHelpers.h"
13 #include "lldb/DataFormatters/LanguageCategory.h"
14 #include "lldb/Interpreter/ScriptInterpreter.h"
15 #include "lldb/Target/ExecutionContext.h"
16 #include "lldb/Target/Language.h"
17 #include "lldb/Utility/LLDBLog.h"
18 #include "lldb/Utility/Log.h"
19 #include "lldb/ValueObject/ValueObject.h"
20 #include "llvm/ADT/STLExtras.h"
23 using namespace lldb_private
;
24 using namespace lldb_private::formatters
;
28 const char format_char
; // One or more format characters that can be used for
30 const char *format_name
; // Long format name that can be used to specify the
34 static constexpr 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 {eFormatUnicode8
, 'u', "unicode8"},
77 static_assert((sizeof(g_format_infos
) / sizeof(g_format_infos
[0])) ==
79 "All formats must have a corresponding info entry.");
81 static uint32_t g_num_format_infos
= std::size(g_format_infos
);
83 static bool GetFormatFromFormatChar(char format_char
, Format
&format
) {
84 for (uint32_t i
= 0; i
< g_num_format_infos
; ++i
) {
85 if (g_format_infos
[i
].format_char
== format_char
) {
86 format
= g_format_infos
[i
].format
;
90 format
= eFormatInvalid
;
94 static bool GetFormatFromFormatName(llvm::StringRef format_name
,
97 for (i
= 0; i
< g_num_format_infos
; ++i
) {
98 if (format_name
.equals_insensitive(g_format_infos
[i
].format_name
)) {
99 format
= g_format_infos
[i
].format
;
104 for (i
= 0; i
< g_num_format_infos
; ++i
) {
105 if (llvm::StringRef(g_format_infos
[i
].format_name
)
106 .starts_with_insensitive(format_name
)) {
107 format
= g_format_infos
[i
].format
;
111 format
= eFormatInvalid
;
115 void FormatManager::Changed() {
117 m_format_cache
.Clear();
118 std::lock_guard
<std::recursive_mutex
> guard(m_language_categories_mutex
);
119 for (auto &iter
: m_language_categories_map
) {
121 iter
.second
->GetFormatCache().Clear();
125 bool FormatManager::GetFormatFromCString(const char *format_cstr
,
126 lldb::Format
&format
) {
127 bool success
= false;
128 if (format_cstr
&& format_cstr
[0]) {
129 if (format_cstr
[1] == '\0') {
130 success
= GetFormatFromFormatChar(format_cstr
[0], format
);
135 success
= GetFormatFromFormatName(format_cstr
, format
);
138 format
= eFormatInvalid
;
142 char FormatManager::GetFormatAsFormatChar(lldb::Format format
) {
143 for (uint32_t i
= 0; i
< g_num_format_infos
; ++i
) {
144 if (g_format_infos
[i
].format
== format
)
145 return g_format_infos
[i
].format_char
;
150 const char *FormatManager::GetFormatAsCString(Format format
) {
151 if (format
>= eFormatDefault
&& format
< kNumFormats
)
152 return g_format_infos
[format
].format_name
;
156 void FormatManager::EnableAllCategories() {
157 m_categories_map
.EnableAllCategories();
158 std::lock_guard
<std::recursive_mutex
> guard(m_language_categories_mutex
);
159 for (auto &iter
: m_language_categories_map
) {
161 iter
.second
->Enable();
165 void FormatManager::DisableAllCategories() {
166 m_categories_map
.DisableAllCategories();
167 std::lock_guard
<std::recursive_mutex
> guard(m_language_categories_mutex
);
168 for (auto &iter
: m_language_categories_map
) {
170 iter
.second
->Disable();
174 void FormatManager::GetPossibleMatches(
175 ValueObject
&valobj
, CompilerType compiler_type
,
176 lldb::DynamicValueType use_dynamic
, FormattersMatchVector
&entries
,
177 FormattersMatchCandidate::Flags current_flags
, bool root_level
) {
178 compiler_type
= compiler_type
.GetTypeForFormatters();
179 ConstString
type_name(compiler_type
.GetTypeName());
180 // A ValueObject that couldn't be made correctly won't necessarily have a
181 // target. We aren't going to find a formatter in this case anyway, so we
183 TargetSP target_sp
= valobj
.GetTargetSP();
186 ScriptInterpreter
*script_interpreter
=
187 target_sp
->GetDebugger().GetScriptInterpreter();
188 if (valobj
.GetBitfieldBitSize() > 0) {
189 StreamString sstring
;
190 sstring
.Printf("%s:%d", type_name
.AsCString(), valobj
.GetBitfieldBitSize());
191 ConstString
bitfieldname(sstring
.GetString());
192 entries
.push_back({bitfieldname
, script_interpreter
,
193 TypeImpl(compiler_type
), current_flags
});
196 if (!compiler_type
.IsMeaninglessWithoutDynamicResolution()) {
197 entries
.push_back({type_name
, script_interpreter
, TypeImpl(compiler_type
),
200 ConstString
display_type_name(compiler_type
.GetTypeName());
201 if (display_type_name
!= type_name
)
202 entries
.push_back({display_type_name
, script_interpreter
,
203 TypeImpl(compiler_type
), current_flags
});
206 for (bool is_rvalue_ref
= true, j
= true;
207 j
&& compiler_type
.IsReferenceType(nullptr, &is_rvalue_ref
); j
= false) {
208 CompilerType non_ref_type
= compiler_type
.GetNonReferenceType();
209 GetPossibleMatches(valobj
, non_ref_type
, use_dynamic
, entries
,
210 current_flags
.WithStrippedReference());
211 if (non_ref_type
.IsTypedefType()) {
212 CompilerType deffed_referenced_type
= non_ref_type
.GetTypedefedType();
213 deffed_referenced_type
=
214 is_rvalue_ref
? deffed_referenced_type
.GetRValueReferenceType()
215 : deffed_referenced_type
.GetLValueReferenceType();
216 // this is not exactly the usual meaning of stripping typedefs
218 valobj
, deffed_referenced_type
,
219 use_dynamic
, entries
, current_flags
.WithStrippedTypedef());
223 if (compiler_type
.IsPointerType()) {
224 CompilerType non_ptr_type
= compiler_type
.GetPointeeType();
225 GetPossibleMatches(valobj
, non_ptr_type
, use_dynamic
, entries
,
226 current_flags
.WithStrippedPointer());
227 if (non_ptr_type
.IsTypedefType()) {
228 CompilerType deffed_pointed_type
=
229 non_ptr_type
.GetTypedefedType().GetPointerType();
230 // this is not exactly the usual meaning of stripping typedefs
231 GetPossibleMatches(valobj
, deffed_pointed_type
, use_dynamic
, entries
,
232 current_flags
.WithStrippedTypedef());
236 // For arrays with typedef-ed elements, we add a candidate with the typedef
239 if (compiler_type
.IsArrayType(nullptr, &array_size
, nullptr)) {
240 ExecutionContext
exe_ctx(valobj
.GetExecutionContextRef());
241 CompilerType element_type
= compiler_type
.GetArrayElementType(
242 exe_ctx
.GetBestExecutionContextScope());
243 if (element_type
.IsTypedefType()) {
244 // Get the stripped element type and compute the stripped array type
246 CompilerType deffed_array_type
=
247 element_type
.GetTypedefedType().GetArrayType(array_size
);
248 // this is not exactly the usual meaning of stripping typedefs
250 valobj
, deffed_array_type
,
251 use_dynamic
, entries
, current_flags
.WithStrippedTypedef());
255 for (lldb::LanguageType language_type
:
256 GetCandidateLanguages(valobj
.GetObjectRuntimeLanguage())) {
257 if (Language
*language
= Language::FindPlugin(language_type
)) {
258 for (const FormattersMatchCandidate
& candidate
:
259 language
->GetPossibleFormattersMatches(valobj
, use_dynamic
)) {
260 entries
.push_back(candidate
);
265 // try to strip typedef chains
266 if (compiler_type
.IsTypedefType()) {
267 CompilerType deffed_type
= compiler_type
.GetTypedefedType();
268 GetPossibleMatches(valobj
, deffed_type
, use_dynamic
, entries
,
269 current_flags
.WithStrippedTypedef());
274 if (!compiler_type
.IsValid())
277 CompilerType unqual_compiler_ast_type
=
278 compiler_type
.GetFullyUnqualifiedType();
279 if (!unqual_compiler_ast_type
.IsValid())
281 if (unqual_compiler_ast_type
.GetOpaqueQualType() !=
282 compiler_type
.GetOpaqueQualType())
283 GetPossibleMatches(valobj
, unqual_compiler_ast_type
, use_dynamic
,
284 entries
, current_flags
);
287 // if all else fails, go to static type
288 if (valobj
.IsDynamic()) {
289 lldb::ValueObjectSP
static_value_sp(valobj
.GetStaticValue());
291 GetPossibleMatches(*static_value_sp
.get(),
292 static_value_sp
->GetCompilerType(), use_dynamic
,
293 entries
, current_flags
, true);
298 lldb::TypeFormatImplSP
299 FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp
) {
301 return lldb::TypeFormatImplSP();
302 lldb::TypeFormatImplSP format_chosen_sp
;
303 uint32_t num_categories
= m_categories_map
.GetCount();
304 lldb::TypeCategoryImplSP category_sp
;
305 uint32_t prio_category
= UINT32_MAX
;
306 for (uint32_t category_id
= 0; category_id
< num_categories
; category_id
++) {
307 category_sp
= GetCategoryAtIndex(category_id
);
308 if (!category_sp
->IsEnabled())
310 lldb::TypeFormatImplSP format_current_sp
=
311 category_sp
->GetFormatForType(type_sp
);
312 if (format_current_sp
&&
313 (format_chosen_sp
.get() == nullptr ||
314 (prio_category
> category_sp
->GetEnabledPosition()))) {
315 prio_category
= category_sp
->GetEnabledPosition();
316 format_chosen_sp
= format_current_sp
;
319 return format_chosen_sp
;
322 lldb::TypeSummaryImplSP
323 FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp
) {
325 return lldb::TypeSummaryImplSP();
326 lldb::TypeSummaryImplSP summary_chosen_sp
;
327 uint32_t num_categories
= m_categories_map
.GetCount();
328 lldb::TypeCategoryImplSP category_sp
;
329 uint32_t prio_category
= UINT32_MAX
;
330 for (uint32_t category_id
= 0; category_id
< num_categories
; category_id
++) {
331 category_sp
= GetCategoryAtIndex(category_id
);
332 if (!category_sp
->IsEnabled())
334 lldb::TypeSummaryImplSP summary_current_sp
=
335 category_sp
->GetSummaryForType(type_sp
);
336 if (summary_current_sp
&&
337 (summary_chosen_sp
.get() == nullptr ||
338 (prio_category
> category_sp
->GetEnabledPosition()))) {
339 prio_category
= category_sp
->GetEnabledPosition();
340 summary_chosen_sp
= summary_current_sp
;
343 return summary_chosen_sp
;
346 lldb::TypeFilterImplSP
347 FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp
) {
349 return lldb::TypeFilterImplSP();
350 lldb::TypeFilterImplSP filter_chosen_sp
;
351 uint32_t num_categories
= m_categories_map
.GetCount();
352 lldb::TypeCategoryImplSP category_sp
;
353 uint32_t prio_category
= UINT32_MAX
;
354 for (uint32_t category_id
= 0; category_id
< num_categories
; category_id
++) {
355 category_sp
= GetCategoryAtIndex(category_id
);
356 if (!category_sp
->IsEnabled())
358 lldb::TypeFilterImplSP
filter_current_sp(
359 (TypeFilterImpl
*)category_sp
->GetFilterForType(type_sp
).get());
360 if (filter_current_sp
&&
361 (filter_chosen_sp
.get() == nullptr ||
362 (prio_category
> category_sp
->GetEnabledPosition()))) {
363 prio_category
= category_sp
->GetEnabledPosition();
364 filter_chosen_sp
= filter_current_sp
;
367 return filter_chosen_sp
;
370 lldb::ScriptedSyntheticChildrenSP
371 FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp
) {
373 return lldb::ScriptedSyntheticChildrenSP();
374 lldb::ScriptedSyntheticChildrenSP synth_chosen_sp
;
375 uint32_t num_categories
= m_categories_map
.GetCount();
376 lldb::TypeCategoryImplSP category_sp
;
377 uint32_t prio_category
= UINT32_MAX
;
378 for (uint32_t category_id
= 0; category_id
< num_categories
; category_id
++) {
379 category_sp
= GetCategoryAtIndex(category_id
);
380 if (!category_sp
->IsEnabled())
382 lldb::ScriptedSyntheticChildrenSP
synth_current_sp(
383 (ScriptedSyntheticChildren
*)category_sp
->GetSyntheticForType(type_sp
)
385 if (synth_current_sp
&&
386 (synth_chosen_sp
.get() == nullptr ||
387 (prio_category
> category_sp
->GetEnabledPosition()))) {
388 prio_category
= category_sp
->GetEnabledPosition();
389 synth_chosen_sp
= synth_current_sp
;
392 return synth_chosen_sp
;
395 void FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback
) {
396 m_categories_map
.ForEach(callback
);
397 std::lock_guard
<std::recursive_mutex
> guard(m_language_categories_mutex
);
398 for (const auto &entry
: m_language_categories_map
) {
399 if (auto category_sp
= entry
.second
->GetCategory()) {
400 if (!callback(category_sp
))
406 lldb::TypeCategoryImplSP
407 FormatManager::GetCategory(ConstString category_name
, bool can_create
) {
409 return GetCategory(m_default_category_name
);
410 lldb::TypeCategoryImplSP category
;
411 if (m_categories_map
.Get(category_name
, category
))
415 return lldb::TypeCategoryImplSP();
417 m_categories_map
.Add(
419 lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name
)));
420 return GetCategory(category_name
);
423 lldb::Format
FormatManager::GetSingleItemFormat(lldb::Format vector_format
) {
424 switch (vector_format
) {
425 case eFormatVectorOfChar
:
426 return eFormatCharArray
;
428 case eFormatVectorOfSInt8
:
429 case eFormatVectorOfSInt16
:
430 case eFormatVectorOfSInt32
:
431 case eFormatVectorOfSInt64
:
432 return eFormatDecimal
;
434 case eFormatVectorOfUInt8
:
435 case eFormatVectorOfUInt16
:
436 case eFormatVectorOfUInt32
:
437 case eFormatVectorOfUInt64
:
438 case eFormatVectorOfUInt128
:
441 case eFormatVectorOfFloat16
:
442 case eFormatVectorOfFloat32
:
443 case eFormatVectorOfFloat64
:
447 return lldb::eFormatInvalid
;
451 bool FormatManager::ShouldPrintAsOneLiner(ValueObject
&valobj
) {
452 TargetSP target_sp
= valobj
.GetTargetSP();
453 // if settings say no oneline whatsoever
454 if (target_sp
&& !target_sp
->GetDebugger().GetAutoOneLineSummaries())
455 return false; // then don't oneline
457 // if this object has a summary, then ask the summary
458 if (valobj
.GetSummaryFormat().get() != nullptr)
459 return valobj
.GetSummaryFormat()->IsOneLiner();
461 const size_t max_num_children
=
462 (target_sp
? *target_sp
: Target::GetGlobalProperties())
463 .GetMaximumNumberOfChildrenToDisplay();
464 auto num_children
= valobj
.GetNumChildren(max_num_children
);
466 llvm::consumeError(num_children
.takeError());
469 // no children, no party
470 if (*num_children
== 0)
473 // ask the type if it has any opinion about this eLazyBoolCalculate == no
474 // opinion; other values should be self explanatory
475 CompilerType
compiler_type(valobj
.GetCompilerType());
476 if (compiler_type
.IsValid()) {
477 switch (compiler_type
.ShouldPrintAsOneLiner(&valobj
)) {
482 case eLazyBoolCalculate
:
487 size_t total_children_name_len
= 0;
489 for (size_t idx
= 0; idx
< *num_children
; idx
++) {
490 bool is_synth_val
= false;
491 ValueObjectSP
child_sp(valobj
.GetChildAtIndex(idx
));
492 // something is wrong here - bail out
496 // also ask the child's type if it has any opinion
497 CompilerType
child_compiler_type(child_sp
->GetCompilerType());
498 if (child_compiler_type
.IsValid()) {
499 switch (child_compiler_type
.ShouldPrintAsOneLiner(child_sp
.get())) {
501 // an opinion of yes is only binding for the child, so keep going
502 case eLazyBoolCalculate
:
505 // but if the child says no, then it's a veto on the whole thing
510 // if we decided to define synthetic children for a type, we probably care
511 // enough to show them, but avoid nesting children in children
512 if (child_sp
->GetSyntheticChildren().get() != nullptr) {
513 ValueObjectSP
synth_sp(child_sp
->GetSyntheticValue());
514 // wait.. wat? just get out of here..
517 // but if we only have them to provide a value, keep going
518 if (!synth_sp
->MightHaveChildren() &&
519 synth_sp
->DoesProvideSyntheticValue())
525 total_children_name_len
+= child_sp
->GetName().GetLength();
527 // 50 itself is a "randomly" chosen number - the idea is that
528 // overly long structs should not get this treatment
529 // FIXME: maybe make this a user-tweakable setting?
530 if (total_children_name_len
> 50)
533 // if a summary is there..
534 if (child_sp
->GetSummaryFormat()) {
535 // and it wants children, then bail out
536 if (child_sp
->GetSummaryFormat()->DoesPrintChildren(child_sp
.get()))
540 // if this child has children..
541 if (child_sp
->HasChildren()) {
542 // ...and no summary...
543 // (if it had a summary and the summary wanted children, we would have
545 // so this only makes us bail out if this has no summary and we would
546 // then print children)
547 if (!child_sp
->GetSummaryFormat() && !is_synth_val
) // but again only do
551 return false; // then bail out
557 ConstString
FormatManager::GetTypeForCache(ValueObject
&valobj
,
558 lldb::DynamicValueType use_dynamic
) {
559 ValueObjectSP valobj_sp
= valobj
.GetQualifiedRepresentationIfAvailable(
560 use_dynamic
, valobj
.IsSynthetic());
561 if (valobj_sp
&& valobj_sp
->GetCompilerType().IsValid()) {
562 if (!valobj_sp
->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
563 return valobj_sp
->GetQualifiedTypeName();
565 return ConstString();
568 std::vector
<lldb::LanguageType
>
569 FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type
) {
571 case lldb::eLanguageTypeC
:
572 case lldb::eLanguageTypeC89
:
573 case lldb::eLanguageTypeC99
:
574 case lldb::eLanguageTypeC11
:
575 case lldb::eLanguageTypeC_plus_plus
:
576 case lldb::eLanguageTypeC_plus_plus_03
:
577 case lldb::eLanguageTypeC_plus_plus_11
:
578 case lldb::eLanguageTypeC_plus_plus_14
:
579 return {lldb::eLanguageTypeC_plus_plus
, lldb::eLanguageTypeObjC
};
583 llvm_unreachable("Fully covered switch");
587 FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type
) {
588 std::lock_guard
<std::recursive_mutex
> guard(m_language_categories_mutex
);
589 auto iter
= m_language_categories_map
.find(lang_type
),
590 end
= m_language_categories_map
.end();
592 return iter
->second
.get();
593 LanguageCategory
*lang_category
= new LanguageCategory(lang_type
);
594 m_language_categories_map
[lang_type
] =
595 LanguageCategory::UniquePointer(lang_category
);
596 return lang_category
;
599 template <typename ImplSP
>
600 ImplSP
FormatManager::GetHardcoded(FormattersMatchData
&match_data
) {
602 for (lldb::LanguageType lang_type
: match_data
.GetCandidateLanguages()) {
603 if (LanguageCategory
*lang_category
= GetCategoryForLanguage(lang_type
)) {
604 if (lang_category
->GetHardcoded(*this, match_data
, retval_sp
))
612 template <typename ImplSP
> const char *FormatterKind
;
613 template <> const char *FormatterKind
<lldb::TypeFormatImplSP
> = "format";
614 template <> const char *FormatterKind
<lldb::TypeSummaryImplSP
> = "summary";
615 template <> const char *FormatterKind
<lldb::SyntheticChildrenSP
> = "synthetic";
618 #define FORMAT_LOG(Message) "[%s] " Message, FormatterKind<ImplSP>
620 template <typename ImplSP
>
621 ImplSP
FormatManager::Get(ValueObject
&valobj
,
622 lldb::DynamicValueType use_dynamic
) {
623 FormattersMatchData
match_data(valobj
, use_dynamic
);
624 if (ImplSP retval_sp
= GetCached
<ImplSP
>(match_data
))
627 Log
*log
= GetLog(LLDBLog::DataFormatters
);
629 LLDB_LOGF(log
, FORMAT_LOG("Search failed. Giving language a chance."));
630 for (lldb::LanguageType lang_type
: match_data
.GetCandidateLanguages()) {
631 if (LanguageCategory
*lang_category
= GetCategoryForLanguage(lang_type
)) {
633 if (lang_category
->Get(match_data
, retval_sp
))
635 LLDB_LOGF(log
, FORMAT_LOG("Language search success. Returning."));
641 LLDB_LOGF(log
, FORMAT_LOG("Search failed. Giving hardcoded a chance."));
642 return GetHardcoded
<ImplSP
>(match_data
);
645 template <typename ImplSP
>
646 ImplSP
FormatManager::GetCached(FormattersMatchData
&match_data
) {
648 Log
*log
= GetLog(LLDBLog::DataFormatters
);
649 if (match_data
.GetTypeForCache()) {
650 LLDB_LOGF(log
, "\n\n" FORMAT_LOG("Looking into cache for type %s"),
651 match_data
.GetTypeForCache().AsCString("<invalid>"));
652 if (m_format_cache
.Get(match_data
.GetTypeForCache(), retval_sp
)) {
654 LLDB_LOGF(log
, FORMAT_LOG("Cache search success. Returning."));
655 LLDB_LOGV(log
, "Cache hits: {0} - Cache Misses: {1}",
656 m_format_cache
.GetCacheHits(),
657 m_format_cache
.GetCacheMisses());
661 LLDB_LOGF(log
, FORMAT_LOG("Cache search failed. Going normal route"));
664 m_categories_map
.Get(match_data
, retval_sp
);
665 if (match_data
.GetTypeForCache() && (!retval_sp
|| !retval_sp
->NonCacheable())) {
666 LLDB_LOGF(log
, FORMAT_LOG("Caching %p for type %s"),
667 static_cast<void *>(retval_sp
.get()),
668 match_data
.GetTypeForCache().AsCString("<invalid>"));
669 m_format_cache
.Set(match_data
.GetTypeForCache(), retval_sp
);
671 LLDB_LOGV(log
, "Cache hits: {0} - Cache Misses: {1}",
672 m_format_cache
.GetCacheHits(), m_format_cache
.GetCacheMisses());
678 lldb::TypeFormatImplSP
679 FormatManager::GetFormat(ValueObject
&valobj
,
680 lldb::DynamicValueType use_dynamic
) {
681 return Get
<lldb::TypeFormatImplSP
>(valobj
, use_dynamic
);
684 lldb::TypeSummaryImplSP
685 FormatManager::GetSummaryFormat(ValueObject
&valobj
,
686 lldb::DynamicValueType use_dynamic
) {
687 return Get
<lldb::TypeSummaryImplSP
>(valobj
, use_dynamic
);
690 lldb::SyntheticChildrenSP
691 FormatManager::GetSyntheticChildren(ValueObject
&valobj
,
692 lldb::DynamicValueType use_dynamic
) {
693 return Get
<lldb::SyntheticChildrenSP
>(valobj
, use_dynamic
);
696 FormatManager::FormatManager()
697 : m_last_revision(0), m_format_cache(), m_language_categories_mutex(),
698 m_language_categories_map(), m_named_summaries_map(this),
699 m_categories_map(this), m_default_category_name(ConstString("default")),
700 m_system_category_name(ConstString("system")),
701 m_vectortypes_category_name(ConstString("VectorTypes")) {
702 LoadSystemFormatters();
703 LoadVectorFormatters();
705 EnableCategory(m_vectortypes_category_name
, TypeCategoryMap::Last
,
706 lldb::eLanguageTypeObjC_plus_plus
);
707 EnableCategory(m_system_category_name
, TypeCategoryMap::Last
,
708 lldb::eLanguageTypeObjC_plus_plus
);
711 void FormatManager::LoadSystemFormatters() {
712 TypeSummaryImpl::Flags string_flags
;
713 string_flags
.SetCascades(true)
714 .SetSkipPointers(true)
715 .SetSkipReferences(false)
716 .SetDontShowChildren(true)
717 .SetDontShowValue(false)
718 .SetShowMembersOneLiner(false)
719 .SetHideItemNames(false);
721 TypeSummaryImpl::Flags string_array_flags
;
722 string_array_flags
.SetCascades(true)
723 .SetSkipPointers(true)
724 .SetSkipReferences(false)
725 .SetDontShowChildren(true)
726 .SetDontShowValue(true)
727 .SetShowMembersOneLiner(false)
728 .SetHideItemNames(false);
730 lldb::TypeSummaryImplSP
string_format(
731 new StringSummaryFormat(string_flags
, "${var%s}"));
733 lldb::TypeSummaryImplSP
string_array_format(
734 new StringSummaryFormat(string_array_flags
, "${var%char[]}"));
736 TypeCategoryImpl::SharedPointer sys_category_sp
=
737 GetCategory(m_system_category_name
);
739 sys_category_sp
->AddTypeSummary(R
"(^(unsigned )?char ?(\*|\[\])$)",
740 eFormatterMatchRegex
, string_format
);
742 sys_category_sp
->AddTypeSummary(R
"(^((un)?signed )?char ?\[[0-9]+\]$)",
743 eFormatterMatchRegex
, string_array_format
);
745 lldb::TypeSummaryImplSP
ostype_summary(
746 new StringSummaryFormat(TypeSummaryImpl::Flags()
748 .SetSkipPointers(true)
749 .SetSkipReferences(true)
750 .SetDontShowChildren(true)
751 .SetDontShowValue(false)
752 .SetShowMembersOneLiner(false)
753 .SetHideItemNames(false),
756 sys_category_sp
->AddTypeSummary("OSType", eFormatterMatchExact
,
759 TypeFormatImpl::Flags fourchar_flags
;
760 fourchar_flags
.SetCascades(true).SetSkipPointers(true).SetSkipReferences(
763 AddFormat(sys_category_sp
, lldb::eFormatOSType
, "FourCharCode",
767 void FormatManager::LoadVectorFormatters() {
768 TypeCategoryImpl::SharedPointer vectors_category_sp
=
769 GetCategory(m_vectortypes_category_name
);
771 TypeSummaryImpl::Flags vector_flags
;
772 vector_flags
.SetCascades(true)
773 .SetSkipPointers(true)
774 .SetSkipReferences(false)
775 .SetDontShowChildren(true)
776 .SetDontShowValue(false)
777 .SetShowMembersOneLiner(true)
778 .SetHideItemNames(true);
780 AddStringSummary(vectors_category_sp
, "${var.uint128}", "builtin_type_vec128",
782 AddStringSummary(vectors_category_sp
, "", "float[4]", vector_flags
);
783 AddStringSummary(vectors_category_sp
, "", "int32_t[4]", vector_flags
);
784 AddStringSummary(vectors_category_sp
, "", "int16_t[8]", vector_flags
);
785 AddStringSummary(vectors_category_sp
, "", "vDouble", vector_flags
);
786 AddStringSummary(vectors_category_sp
, "", "vFloat", vector_flags
);
787 AddStringSummary(vectors_category_sp
, "", "vSInt8", vector_flags
);
788 AddStringSummary(vectors_category_sp
, "", "vSInt16", vector_flags
);
789 AddStringSummary(vectors_category_sp
, "", "vSInt32", vector_flags
);
790 AddStringSummary(vectors_category_sp
, "", "vUInt16", vector_flags
);
791 AddStringSummary(vectors_category_sp
, "", "vUInt8", vector_flags
);
792 AddStringSummary(vectors_category_sp
, "", "vUInt16", vector_flags
);
793 AddStringSummary(vectors_category_sp
, "", "vUInt32", vector_flags
);
794 AddStringSummary(vectors_category_sp
, "", "vBool32", vector_flags
);