blob: 37b33f24eb6c923af078f41a5a0f6a58f78923fc [file] [log] [blame]
Greg Clayton4a33d312011-06-23 17:59:56 +00001//===-- 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
Enrico Granata5548cb52013-01-28 23:47:25 +000010#include "lldb/DataFormatters/FormatManager.h"
Greg Clayton4a33d312011-06-23 17:59:56 +000011
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16
Enrico Granataf2bbf712011-07-15 02:26:42 +000017#include "lldb/Core/Debugger.h"
Enrico Granata419d7912015-09-04 00:33:51 +000018#include "lldb/DataFormatters/CXXFunctionPointer.h"
Enrico Granata419d7912015-09-04 00:33:51 +000019#include "lldb/DataFormatters/VectorType.h"
Enrico Granatadf7e79e2015-09-02 01:21:31 +000020#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granata980c0482015-09-01 18:22:39 +000021#include "lldb/DataFormatters/LanguageCategory.h"
Enrico Granata5548cb52013-01-28 23:47:25 +000022#include "lldb/Target/ExecutionContext.h"
Enrico Granata33e97e62015-09-04 21:01:18 +000023#include "lldb/Target/Language.h"
Enrico Granata5548cb52013-01-28 23:47:25 +000024#include "lldb/Target/Platform.h"
Saleem Abdulrasool28606952014-06-27 05:17:41 +000025#include "llvm/ADT/STLExtras.h"
Enrico Granataf2bbf712011-07-15 02:26:42 +000026
Enrico Granata980c0482015-09-01 18:22:39 +000027#include <initializer_list>
28
Greg Clayton4a33d312011-06-23 17:59:56 +000029using namespace lldb;
30using namespace lldb_private;
Enrico Granatadf7e79e2015-09-02 01:21:31 +000031using namespace lldb_private::formatters;
Greg Claytonbb7f31f2011-06-23 21:22:24 +000032
33struct FormatInfo
34{
35 Format format;
36 const char format_char; // One or more format characters that can be used for this format.
37 const char *format_name; // Long format name that can be used to specify the current format
38};
39
40static FormatInfo
41g_format_infos[] =
42{
43 { eFormatDefault , '\0' , "default" },
44 { eFormatBoolean , 'B' , "boolean" },
45 { eFormatBinary , 'b' , "binary" },
46 { eFormatBytes , 'y' , "bytes" },
47 { eFormatBytesWithASCII , 'Y' , "bytes with ASCII" },
48 { eFormatChar , 'c' , "character" },
49 { eFormatCharPrintable , 'C' , "printable character" },
50 { eFormatComplexFloat , 'F' , "complex float" },
51 { eFormatCString , 's' , "c-string" },
Greg Clayton5009f9d2011-10-27 17:55:14 +000052 { eFormatDecimal , 'd' , "decimal" },
Greg Claytonbb7f31f2011-06-23 21:22:24 +000053 { eFormatEnum , 'E' , "enumeration" },
54 { eFormatHex , 'x' , "hex" },
Enrico Granata7ec18e32012-08-09 19:33:34 +000055 { eFormatHexUppercase , 'X' , "uppercase hex" },
Greg Claytonbb7f31f2011-06-23 21:22:24 +000056 { eFormatFloat , 'f' , "float" },
57 { eFormatOctal , 'o' , "octal" },
58 { eFormatOSType , 'O' , "OSType" },
59 { eFormatUnicode16 , 'U' , "unicode16" },
60 { eFormatUnicode32 , '\0' , "unicode32" },
61 { eFormatUnsigned , 'u' , "unsigned decimal" },
62 { eFormatPointer , 'p' , "pointer" },
63 { eFormatVectorOfChar , '\0' , "char[]" },
64 { eFormatVectorOfSInt8 , '\0' , "int8_t[]" },
65 { eFormatVectorOfUInt8 , '\0' , "uint8_t[]" },
66 { eFormatVectorOfSInt16 , '\0' , "int16_t[]" },
67 { eFormatVectorOfUInt16 , '\0' , "uint16_t[]" },
Enrico Granatae443ba72011-07-06 15:56:06 +000068 { eFormatVectorOfSInt32 , '\0' , "int32_t[]" },
69 { eFormatVectorOfUInt32 , '\0' , "uint32_t[]" },
70 { eFormatVectorOfSInt64 , '\0' , "int64_t[]" },
71 { eFormatVectorOfUInt64 , '\0' , "uint64_t[]" },
Greg Claytonbb7f31f2011-06-23 21:22:24 +000072 { eFormatVectorOfFloat32, '\0' , "float32[]" },
73 { eFormatVectorOfFloat64, '\0' , "float64[]" },
74 { eFormatVectorOfUInt128, '\0' , "uint128_t[]" },
75 { eFormatComplexInteger , 'I' , "complex integer" },
Greg Clayton5009f9d2011-10-27 17:55:14 +000076 { eFormatCharArray , 'a' , "character array" },
77 { eFormatAddressInfo , 'A' , "address" },
Enrico Granata7ec18e32012-08-09 19:33:34 +000078 { eFormatHexFloat , '\0' , "hex float" },
Sean Callananbf154da2012-08-08 17:35:10 +000079 { eFormatInstruction , 'i' , "instruction" },
80 { eFormatVoid , 'v' , "void" }
Greg Claytonbb7f31f2011-06-23 21:22:24 +000081};
82
Saleem Abdulrasool28606952014-06-27 05:17:41 +000083static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos);
Greg Claytonbb7f31f2011-06-23 21:22:24 +000084
85static bool
86GetFormatFromFormatChar (char format_char, Format &format)
87{
88 for (uint32_t i=0; i<g_num_format_infos; ++i)
89 {
90 if (g_format_infos[i].format_char == format_char)
91 {
92 format = g_format_infos[i].format;
93 return true;
94 }
95 }
96 format = eFormatInvalid;
97 return false;
98}
99
100static bool
101GetFormatFromFormatName (const char *format_name, bool partial_match_ok, Format &format)
102{
103 uint32_t i;
104 for (i=0; i<g_num_format_infos; ++i)
105 {
106 if (strcasecmp (g_format_infos[i].format_name, format_name) == 0)
107 {
108 format = g_format_infos[i].format;
109 return true;
110 }
111 }
112
113 if (partial_match_ok)
114 {
115 for (i=0; i<g_num_format_infos; ++i)
116 {
117 if (strcasestr (g_format_infos[i].format_name, format_name) == g_format_infos[i].format_name)
118 {
119 format = g_format_infos[i].format;
120 return true;
121 }
122 }
123 }
124 format = eFormatInvalid;
125 return false;
126}
127
128bool
129FormatManager::GetFormatFromCString (const char *format_cstr,
130 bool partial_match_ok,
131 lldb::Format &format)
132{
133 bool success = false;
134 if (format_cstr && format_cstr[0])
135 {
136 if (format_cstr[1] == '\0')
137 {
138 success = GetFormatFromFormatChar (format_cstr[0], format);
139 if (success)
140 return true;
141 }
142
143 success = GetFormatFromFormatName (format_cstr, partial_match_ok, format);
144 }
145 if (!success)
146 format = eFormatInvalid;
147 return success;
148}
149
150char
151FormatManager::GetFormatAsFormatChar (lldb::Format format)
152{
153 for (uint32_t i=0; i<g_num_format_infos; ++i)
154 {
155 if (g_format_infos[i].format == format)
156 return g_format_infos[i].format_char;
157 }
158 return '\0';
159}
Greg Claytonbb7f31f2011-06-23 21:22:24 +0000160
161const char *
162FormatManager::GetFormatAsCString (Format format)
163{
164 if (format >= eFormatDefault && format < kNumFormats)
165 return g_format_infos[format].format_name;
166 return NULL;
167}
Enrico Granata0a3958e2011-07-02 00:25:22 +0000168
Enrico Granatade61cec2013-11-22 00:02:13 +0000169void
Enrico Granata33e97e62015-09-04 21:01:18 +0000170FormatManager::EnableAllCategories ()
171{
172 m_categories_map.EnableAllCategories ();
173 Mutex::Locker lang_locker(m_language_categories_mutex);
174 for (auto& iter : m_language_categories_map)
175 {
176 if (iter.second)
177 iter.second->Enable();
178 }
179}
180
181void
182FormatManager::DisableAllCategories ()
183{
184 m_categories_map.DisableAllCategories ();
185 Mutex::Locker lang_locker(m_language_categories_mutex);
186 for (auto& iter : m_language_categories_map)
187 {
188 if (iter.second)
189 iter.second->Disable();
190 }
191}
192
193void
Enrico Granatade61cec2013-11-22 00:02:13 +0000194FormatManager::GetPossibleMatches (ValueObject& valobj,
Greg Claytona1e5dc82015-08-11 22:53:00 +0000195 CompilerType clang_type,
Enrico Granatade61cec2013-11-22 00:02:13 +0000196 uint32_t reason,
197 lldb::DynamicValueType use_dynamic,
198 FormattersMatchVector& entries,
199 bool did_strip_ptr,
200 bool did_strip_ref,
201 bool did_strip_typedef,
202 bool root_level)
203{
Greg Claytond8d4a572015-08-11 21:38:15 +0000204 clang_type = ClangASTContext::RemoveFastQualifiers(clang_type);
Enrico Granatade61cec2013-11-22 00:02:13 +0000205 ConstString type_name(clang_type.GetConstTypeName());
206 if (valobj.GetBitfieldBitSize() > 0)
207 {
208 StreamString sstring;
209 sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize());
210 ConstString bitfieldname = ConstString(sstring.GetData());
211 entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef});
212 reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
213 }
214 entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
Enrico Granatae8daa2f2014-05-17 19:14:17 +0000215
216 ConstString display_type_name(clang_type.GetDisplayTypeName());
217 if (display_type_name != type_name)
218 entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
219
Enrico Granata1ac62962014-04-10 00:14:07 +0000220 for (bool is_rvalue_ref = true, j = true; j && clang_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
Enrico Granatade61cec2013-11-22 00:02:13 +0000221 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000222 CompilerType non_ref_type = clang_type.GetNonReferenceType();
Enrico Granatade61cec2013-11-22 00:02:13 +0000223 GetPossibleMatches(valobj,
224 non_ref_type,
225 reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
226 use_dynamic,
227 entries,
228 did_strip_ptr,
229 true,
230 did_strip_typedef);
Enrico Granata1ac62962014-04-10 00:14:07 +0000231 if (non_ref_type.IsTypedefType())
232 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000233 CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
Greg Claytond8d4a572015-08-11 21:38:15 +0000234 deffed_referenced_type = is_rvalue_ref ? ClangASTContext::GetRValueReferenceType(deffed_referenced_type) : ClangASTContext::GetLValueReferenceType(deffed_referenced_type);
Enrico Granata1ac62962014-04-10 00:14:07 +0000235 GetPossibleMatches(valobj,
236 deffed_referenced_type,
237 reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
238 use_dynamic,
239 entries,
240 did_strip_ptr,
241 did_strip_ref,
242 true); // this is not exactly the usual meaning of stripping typedefs
243 }
Enrico Granatade61cec2013-11-22 00:02:13 +0000244 }
Enrico Granata1ac62962014-04-10 00:14:07 +0000245
246 if (clang_type.IsPointerType())
Enrico Granatade61cec2013-11-22 00:02:13 +0000247 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000248 CompilerType non_ptr_type = clang_type.GetPointeeType();
Enrico Granatade61cec2013-11-22 00:02:13 +0000249 GetPossibleMatches(valobj,
250 non_ptr_type,
251 reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
252 use_dynamic,
253 entries,
254 true,
255 did_strip_ref,
256 did_strip_typedef);
Enrico Granata1ac62962014-04-10 00:14:07 +0000257 if (non_ptr_type.IsTypedefType())
258 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000259 CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
Enrico Granata1ac62962014-04-10 00:14:07 +0000260 GetPossibleMatches(valobj,
261 deffed_pointed_type,
262 reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
263 use_dynamic,
264 entries,
265 did_strip_ptr,
266 did_strip_ref,
267 true); // this is not exactly the usual meaning of stripping typedefs
268 }
Enrico Granatade61cec2013-11-22 00:02:13 +0000269 }
Enrico Granatade61cec2013-11-22 00:02:13 +0000270
Enrico Granatad3233c12015-09-09 01:10:46 +0000271 for (lldb::LanguageType language_type : GetCandidateLanguages(valobj))
Enrico Granatade61cec2013-11-22 00:02:13 +0000272 {
Enrico Granatad3233c12015-09-09 01:10:46 +0000273 if (Language* language = Language::FindPlugin(language_type))
Enrico Granatade61cec2013-11-22 00:02:13 +0000274 {
Enrico Granatad3233c12015-09-09 01:10:46 +0000275 for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic))
Enrico Granatade61cec2013-11-22 00:02:13 +0000276 {
Enrico Granatad3233c12015-09-09 01:10:46 +0000277 entries.push_back({candidate,
278 reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin,
279 did_strip_ptr,
280 did_strip_ref,
281 did_strip_typedef});
282 }
Enrico Granatade61cec2013-11-22 00:02:13 +0000283 }
Enrico Granatade61cec2013-11-22 00:02:13 +0000284 }
Enrico Granatad3233c12015-09-09 01:10:46 +0000285
Enrico Granatade61cec2013-11-22 00:02:13 +0000286 // try to strip typedef chains
287 if (clang_type.IsTypedefType())
288 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000289 CompilerType deffed_type = clang_type.GetTypedefedType();
Enrico Granatade61cec2013-11-22 00:02:13 +0000290 GetPossibleMatches(valobj,
291 deffed_type,
292 reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
293 use_dynamic,
294 entries,
295 did_strip_ptr,
296 did_strip_ref,
297 true);
298 }
299
300 if (root_level)
301 {
302 do {
303 if (!clang_type.IsValid())
304 break;
305
Greg Claytona1e5dc82015-08-11 22:53:00 +0000306 CompilerType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
Enrico Granatade61cec2013-11-22 00:02:13 +0000307 if (!unqual_clang_ast_type.IsValid())
308 break;
309 if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
310 GetPossibleMatches (valobj,
311 unqual_clang_ast_type,
312 reason,
313 use_dynamic,
314 entries,
315 did_strip_ptr,
316 did_strip_ref,
317 did_strip_typedef);
318 } while(false);
319
320
321 // if all else fails, go to static type
322 if (valobj.IsDynamic())
323 {
324 lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
325 if (static_value_sp)
326 GetPossibleMatches(*static_value_sp.get(),
Greg Clayton99558cc42015-08-24 23:46:31 +0000327 static_value_sp->GetCompilerType(),
Enrico Granatade61cec2013-11-22 00:02:13 +0000328 reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
329 use_dynamic,
330 entries,
331 did_strip_ptr,
332 did_strip_ref,
333 did_strip_typedef,
334 true);
335 }
336 }
337}
338
Enrico Granata852cc952013-10-08 19:03:22 +0000339lldb::TypeFormatImplSP
340FormatManager::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
341{
342 if (!type_sp)
343 return lldb::TypeFormatImplSP();
344 lldb::TypeFormatImplSP format_chosen_sp;
345 uint32_t num_categories = m_categories_map.GetCount();
346 lldb::TypeCategoryImplSP category_sp;
347 uint32_t prio_category = UINT32_MAX;
348 for (uint32_t category_id = 0;
349 category_id < num_categories;
350 category_id++)
351 {
352 category_sp = GetCategoryAtIndex(category_id);
353 if (category_sp->IsEnabled() == false)
354 continue;
355 lldb::TypeFormatImplSP format_current_sp = category_sp->GetFormatForType(type_sp);
356 if (format_current_sp && (format_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
357 {
358 prio_category = category_sp->GetEnabledPosition();
359 format_chosen_sp = format_current_sp;
360 }
361 }
362 return format_chosen_sp;
363}
364
Enrico Granataa777dc22012-05-08 21:49:57 +0000365lldb::TypeSummaryImplSP
366FormatManager::GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp)
367{
368 if (!type_sp)
369 return lldb::TypeSummaryImplSP();
370 lldb::TypeSummaryImplSP summary_chosen_sp;
371 uint32_t num_categories = m_categories_map.GetCount();
372 lldb::TypeCategoryImplSP category_sp;
373 uint32_t prio_category = UINT32_MAX;
374 for (uint32_t category_id = 0;
375 category_id < num_categories;
376 category_id++)
377 {
378 category_sp = GetCategoryAtIndex(category_id);
379 if (category_sp->IsEnabled() == false)
380 continue;
381 lldb::TypeSummaryImplSP summary_current_sp = category_sp->GetSummaryForType(type_sp);
382 if (summary_current_sp && (summary_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
383 {
384 prio_category = category_sp->GetEnabledPosition();
385 summary_chosen_sp = summary_current_sp;
386 }
387 }
388 return summary_chosen_sp;
389}
390
391lldb::TypeFilterImplSP
392FormatManager::GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp)
393{
394 if (!type_sp)
395 return lldb::TypeFilterImplSP();
396 lldb::TypeFilterImplSP filter_chosen_sp;
397 uint32_t num_categories = m_categories_map.GetCount();
398 lldb::TypeCategoryImplSP category_sp;
399 uint32_t prio_category = UINT32_MAX;
400 for (uint32_t category_id = 0;
401 category_id < num_categories;
402 category_id++)
403 {
404 category_sp = GetCategoryAtIndex(category_id);
405 if (category_sp->IsEnabled() == false)
406 continue;
407 lldb::TypeFilterImplSP filter_current_sp((TypeFilterImpl*)category_sp->GetFilterForType(type_sp).get());
408 if (filter_current_sp && (filter_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
409 {
410 prio_category = category_sp->GetEnabledPosition();
411 filter_chosen_sp = filter_current_sp;
412 }
413 }
414 return filter_chosen_sp;
415}
416
Jason Molenda7a9a72b2012-05-16 00:38:08 +0000417#ifndef LLDB_DISABLE_PYTHON
Enrico Granata5548cb52013-01-28 23:47:25 +0000418lldb::ScriptedSyntheticChildrenSP
Enrico Granataa777dc22012-05-08 21:49:57 +0000419FormatManager::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp)
420{
421 if (!type_sp)
Enrico Granata5548cb52013-01-28 23:47:25 +0000422 return lldb::ScriptedSyntheticChildrenSP();
423 lldb::ScriptedSyntheticChildrenSP synth_chosen_sp;
Enrico Granataa777dc22012-05-08 21:49:57 +0000424 uint32_t num_categories = m_categories_map.GetCount();
425 lldb::TypeCategoryImplSP category_sp;
426 uint32_t prio_category = UINT32_MAX;
427 for (uint32_t category_id = 0;
428 category_id < num_categories;
429 category_id++)
430 {
431 category_sp = GetCategoryAtIndex(category_id);
432 if (category_sp->IsEnabled() == false)
433 continue;
Enrico Granata5548cb52013-01-28 23:47:25 +0000434 lldb::ScriptedSyntheticChildrenSP synth_current_sp((ScriptedSyntheticChildren*)category_sp->GetSyntheticForType(type_sp).get());
Enrico Granataa777dc22012-05-08 21:49:57 +0000435 if (synth_current_sp && (synth_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
436 {
437 prio_category = category_sp->GetEnabledPosition();
438 synth_chosen_sp = synth_current_sp;
439 }
440 }
441 return synth_chosen_sp;
442}
Jason Molenda7a9a72b2012-05-16 00:38:08 +0000443#endif
Enrico Granataa777dc22012-05-08 21:49:57 +0000444
Jason Molenda7a9a72b2012-05-16 00:38:08 +0000445#ifndef LLDB_DISABLE_PYTHON
Enrico Granataa777dc22012-05-08 21:49:57 +0000446lldb::SyntheticChildrenSP
447FormatManager::GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp)
448{
449 if (!type_sp)
450 return lldb::SyntheticChildrenSP();
451 lldb::TypeFilterImplSP filter_sp = GetFilterForType(type_sp);
Enrico Granata5548cb52013-01-28 23:47:25 +0000452 lldb::ScriptedSyntheticChildrenSP synth_sp = GetSyntheticForType(type_sp);
Enrico Granataa777dc22012-05-08 21:49:57 +0000453 if (filter_sp->GetRevision() > synth_sp->GetRevision())
454 return lldb::SyntheticChildrenSP(filter_sp.get());
455 else
456 return lldb::SyntheticChildrenSP(synth_sp.get());
457}
Jason Molenda7a9a72b2012-05-16 00:38:08 +0000458#endif
Enrico Granataa777dc22012-05-08 21:49:57 +0000459
Enrico Granatac5827132014-09-05 20:45:07 +0000460lldb::TypeValidatorImplSP
461FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
462{
463 if (!type_sp)
464 return lldb::TypeValidatorImplSP();
465 lldb::TypeValidatorImplSP validator_chosen_sp;
466 uint32_t num_categories = m_categories_map.GetCount();
467 lldb::TypeCategoryImplSP category_sp;
468 uint32_t prio_category = UINT32_MAX;
469 for (uint32_t category_id = 0;
470 category_id < num_categories;
471 category_id++)
472 {
473 category_sp = GetCategoryAtIndex(category_id);
474 if (category_sp->IsEnabled() == false)
475 continue;
476 lldb::TypeValidatorImplSP validator_current_sp(category_sp->GetValidatorForType(type_sp).get());
477 if (validator_current_sp && (validator_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
478 {
479 prio_category = category_sp->GetEnabledPosition();
480 validator_chosen_sp = validator_current_sp;
481 }
482 }
483 return validator_chosen_sp;
484}
485
Enrico Granata980c0482015-09-01 18:22:39 +0000486void
487FormatManager::LoopThroughCategories (CategoryCallback callback, void* param)
488{
489 m_categories_map.LoopThrough(callback, param);
490 Mutex::Locker locker(m_language_categories_mutex);
491 for (const auto& entry : m_language_categories_map)
492 {
493 if (auto category_sp = entry.second->GetCategory())
494 {
495 if (!callback(param, category_sp))
496 break;
497 }
498 }
499}
500
Enrico Granata061858c2012-02-15 02:34:21 +0000501lldb::TypeCategoryImplSP
Enrico Granata9128ee22011-09-06 19:20:51 +0000502FormatManager::GetCategory (const ConstString& category_name,
Enrico Granatadb595cd2015-03-06 19:37:57 +0000503 bool can_create)
Enrico Granatadc940732011-08-23 00:32:52 +0000504{
505 if (!category_name)
Enrico Granata9128ee22011-09-06 19:20:51 +0000506 return GetCategory(m_default_category_name);
Enrico Granata061858c2012-02-15 02:34:21 +0000507 lldb::TypeCategoryImplSP category;
Enrico Granatadc940732011-08-23 00:32:52 +0000508 if (m_categories_map.Get(category_name, category))
509 return category;
510
511 if (!can_create)
Enrico Granata061858c2012-02-15 02:34:21 +0000512 return lldb::TypeCategoryImplSP();
Enrico Granatadc940732011-08-23 00:32:52 +0000513
Enrico Granata061858c2012-02-15 02:34:21 +0000514 m_categories_map.Add(category_name,lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name)));
Enrico Granata9128ee22011-09-06 19:20:51 +0000515 return GetCategory(category_name);
Enrico Granatadc940732011-08-23 00:32:52 +0000516}
517
Enrico Granataf4efecd2011-07-12 22:56:10 +0000518lldb::Format
519FormatManager::GetSingleItemFormat(lldb::Format vector_format)
520{
521 switch(vector_format)
522 {
523 case eFormatVectorOfChar:
524 return eFormatCharArray;
525
526 case eFormatVectorOfSInt8:
527 case eFormatVectorOfSInt16:
528 case eFormatVectorOfSInt32:
529 case eFormatVectorOfSInt64:
530 return eFormatDecimal;
531
532 case eFormatVectorOfUInt8:
533 case eFormatVectorOfUInt16:
534 case eFormatVectorOfUInt32:
535 case eFormatVectorOfUInt64:
536 case eFormatVectorOfUInt128:
537 return eFormatHex;
538
539 case eFormatVectorOfFloat32:
540 case eFormatVectorOfFloat64:
541 return eFormatFloat;
542
543 default:
544 return lldb::eFormatInvalid;
545 }
Greg Clayton3418c852011-08-10 02:10:13 +0000546}
Enrico Granatac482a192011-08-17 22:13:59 +0000547
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000548bool
549FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
550{
Enrico Granata553fad52013-10-25 23:09:40 +0000551 // if settings say no oneline whatsoever
Enrico Granata90a8db32013-10-31 21:01:07 +0000552 if (valobj.GetTargetSP().get() && valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries() == false)
Enrico Granata553fad52013-10-25 23:09:40 +0000553 return false; // then don't oneline
554
Enrico Granata42fa4af2014-09-11 23:00:27 +0000555 // if this object has a summary, then ask the summary
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000556 if (valobj.GetSummaryFormat().get() != nullptr)
Enrico Granata42fa4af2014-09-11 23:00:27 +0000557 return valobj.GetSummaryFormat()->IsOneLiner();
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000558
559 // no children, no party
560 if (valobj.GetNumChildren() == 0)
561 return false;
562
563 size_t total_children_name_len = 0;
564
565 for (size_t idx = 0;
566 idx < valobj.GetNumChildren();
567 idx++)
568 {
Enrico Granataddac7612014-10-09 18:47:36 +0000569 bool is_synth_val = false;
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000570 ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true));
571 // something is wrong here - bail out
572 if (!child_sp)
573 return false;
574 // if we decided to define synthetic children for a type, we probably care enough
575 // to show them, but avoid nesting children in children
576 if (child_sp->GetSyntheticChildren().get() != nullptr)
Enrico Granataddac7612014-10-09 18:47:36 +0000577 {
578 ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
579 // wait.. wat? just get out of here..
580 if (!synth_sp)
581 return false;
582 // but if we only have them to provide a value, keep going
583 if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue())
584 is_synth_val = true;
585 else
586 return false;
587 }
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000588
589 total_children_name_len += child_sp->GetName().GetLength();
590
591 // 50 itself is a "randomly" chosen number - the idea is that
592 // overly long structs should not get this treatment
593 // FIXME: maybe make this a user-tweakable setting?
594 if (total_children_name_len > 50)
595 return false;
596
597 // if a summary is there..
598 if (child_sp->GetSummaryFormat())
599 {
600 // and it wants children, then bail out
Enrico Granata8a068e62014-04-23 23:16:25 +0000601 if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000602 return false;
603 }
604
Enrico Granatac89e4ca2013-10-23 01:34:31 +0000605 // if this child has children..
606 if (child_sp->GetNumChildren())
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000607 {
Enrico Granatac89e4ca2013-10-23 01:34:31 +0000608 // ...and no summary...
609 // (if it had a summary and the summary wanted children, we would have bailed out anyway
610 // so this only makes us bail out if this has no summary and we would then print children)
Enrico Granataddac7612014-10-09 18:47:36 +0000611 if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child
Enrico Granatac89e4ca2013-10-23 01:34:31 +0000612 return false; // then bail out
Enrico Granataa29cb0b2013-10-04 23:14:13 +0000613 }
614 }
615 return true;
616}
617
Enrico Granata02b66762011-08-19 01:14:49 +0000618ConstString
619FormatManager::GetValidTypeName (const ConstString& type)
620{
621 return ::GetValidTypeName_Impl(type);
622}
623
Enrico Granata5548cb52013-01-28 23:47:25 +0000624ConstString
Enrico Granata980c0482015-09-01 18:22:39 +0000625FormatManager::GetTypeForCache (ValueObject& valobj,
626 lldb::DynamicValueType use_dynamic)
Enrico Granata5548cb52013-01-28 23:47:25 +0000627{
628 if (use_dynamic == lldb::eNoDynamicValues)
629 {
630 if (valobj.IsDynamic())
631 {
632 if (valobj.GetStaticValue())
633 return valobj.GetStaticValue()->GetQualifiedTypeName();
634 else
635 return ConstString();
636 }
637 else
638 return valobj.GetQualifiedTypeName();
639 }
640 if (valobj.IsDynamic())
641 return valobj.GetQualifiedTypeName();
642 if (valobj.GetDynamicValue(use_dynamic))
643 return valobj.GetDynamicValue(use_dynamic)->GetQualifiedTypeName();
644 return ConstString();
645}
646
Enrico Granatad3233c12015-09-09 01:10:46 +0000647std::vector<lldb::LanguageType>
648FormatManager::GetCandidateLanguages (ValueObject& valobj)
Enrico Granata980c0482015-09-01 18:22:39 +0000649{
650 lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
Enrico Granataac494532015-09-09 22:30:24 +0000651 return GetCandidateLanguages(lang_type);
652}
653
654std::vector<lldb::LanguageType>
655FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type)
656{
Enrico Granata980c0482015-09-01 18:22:39 +0000657 switch (lang_type)
658 {
Enrico Granata33e97e62015-09-04 21:01:18 +0000659 case lldb::eLanguageTypeC:
660 case lldb::eLanguageTypeC89:
661 case lldb::eLanguageTypeC99:
662 case lldb::eLanguageTypeC11:
663 case lldb::eLanguageTypeC_plus_plus:
664 case lldb::eLanguageTypeC_plus_plus_03:
665 case lldb::eLanguageTypeC_plus_plus_11:
666 case lldb::eLanguageTypeC_plus_plus_14:
Enrico Granata170c3952015-09-14 22:18:32 +0000667 return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC};
Enrico Granata980c0482015-09-01 18:22:39 +0000668 default:
669 return {lang_type};
670 }
671}
672
673LanguageCategory*
674FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type)
675{
676 Mutex::Locker locker(m_language_categories_mutex);
677 auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end();
678 if (iter != end)
679 return iter->second.get();
680 LanguageCategory* lang_category = new LanguageCategory(lang_type);
681 m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category);
682 return lang_category;
683}
684
Enrico Granataecd02bc2014-08-19 18:47:58 +0000685lldb::TypeFormatImplSP
686FormatManager::GetHardcodedFormat (ValueObject& valobj,
687 lldb::DynamicValueType use_dynamic)
Enrico Granata686f3de2013-10-30 23:46:27 +0000688{
Enrico Granataecd02bc2014-08-19 18:47:58 +0000689 for (const auto& candidate: m_hardcoded_formats)
690 {
691 auto result = candidate(valobj,use_dynamic,*this);
692 if (result)
693 return result;
694 }
695 return nullptr;
Enrico Granata686f3de2013-10-30 23:46:27 +0000696}
697
Enrico Granata852cc952013-10-08 19:03:22 +0000698lldb::TypeFormatImplSP
699FormatManager::GetFormat (ValueObject& valobj,
700 lldb::DynamicValueType use_dynamic)
701{
702 TypeFormatImplSP retval;
Enrico Granata52b4b6c2013-10-17 22:27:19 +0000703 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
704 ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
705 if (valobj_type)
706 {
707 if (log)
708 log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
709 if (m_format_cache.GetFormat(valobj_type,retval))
710 {
711 if (log)
712 {
713 log->Printf("[FormatManager::GetFormat] Cache search success. Returning.");
714 if (log->GetDebug())
715 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
716 }
717 return retval;
718 }
719 if (log)
720 log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route");
721 }
Enrico Granata980c0482015-09-01 18:22:39 +0000722
723 FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic);
724
725 retval = m_categories_map.GetFormat(valobj, use_dynamic, matches);
726 if (!retval)
727 {
728 if (log)
729 log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance.");
730 for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj))
731 {
732 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
733 {
734 if (lang_category->Get(valobj, use_dynamic, matches, retval))
735 break;
736 }
737 }
738 if (retval)
739 {
740 if (log)
741 log->Printf("[FormatManager::GetFormat] Language search success. Returning.");
742 return retval;
743 }
744 }
Enrico Granata686f3de2013-10-30 23:46:27 +0000745 if (!retval)
746 {
747 if (log)
748 log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
749 retval = GetHardcodedFormat(valobj, use_dynamic);
750 }
Enrico Granatad4cb1dd2015-07-01 20:06:40 +0000751
752 if (valobj_type && (!retval || !retval->NonCacheable()))
Enrico Granata52b4b6c2013-10-17 22:27:19 +0000753 {
754 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000755 log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
756 static_cast<void*>(retval.get()),
757 valobj_type.AsCString("<invalid>"));
Enrico Granata52b4b6c2013-10-17 22:27:19 +0000758 m_format_cache.SetFormat(valobj_type,retval);
759 }
760 if (log && log->GetDebug())
761 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
Enrico Granata852cc952013-10-08 19:03:22 +0000762 return retval;
763}
764
Enrico Granataecd02bc2014-08-19 18:47:58 +0000765lldb::TypeSummaryImplSP
766FormatManager::GetHardcodedSummaryFormat (ValueObject& valobj,
767 lldb::DynamicValueType use_dynamic)
Enrico Granata686f3de2013-10-30 23:46:27 +0000768{
Enrico Granataecd02bc2014-08-19 18:47:58 +0000769 for (const auto& candidate: m_hardcoded_summaries)
770 {
771 auto result = candidate(valobj,use_dynamic,*this);
772 if (result)
773 return result;
774 }
775 return nullptr;
Enrico Granata686f3de2013-10-30 23:46:27 +0000776}
777
Enrico Granata5548cb52013-01-28 23:47:25 +0000778lldb::TypeSummaryImplSP
779FormatManager::GetSummaryFormat (ValueObject& valobj,
780 lldb::DynamicValueType use_dynamic)
781{
782 TypeSummaryImplSP retval;
Greg Clayton5160ce52013-03-27 23:08:40 +0000783 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
Enrico Granata5548cb52013-01-28 23:47:25 +0000784 ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
785 if (valobj_type)
786 {
787 if (log)
Enrico Granata68ae4112013-06-18 18:23:07 +0000788 log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
Enrico Granata5548cb52013-01-28 23:47:25 +0000789 if (m_format_cache.GetSummary(valobj_type,retval))
Enrico Granata68ae4112013-06-18 18:23:07 +0000790 {
791 if (log)
792 {
793 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. Returning.");
Enrico Granatac2a96402013-06-26 01:03:38 +0000794 if (log->GetDebug())
Michael Sartain89c862f2013-08-07 19:05:15 +0000795 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
Enrico Granata68ae4112013-06-18 18:23:07 +0000796 }
Enrico Granata5548cb52013-01-28 23:47:25 +0000797 return retval;
Enrico Granata68ae4112013-06-18 18:23:07 +0000798 }
Enrico Granata5548cb52013-01-28 23:47:25 +0000799 if (log)
800 log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route");
801 }
Enrico Granata980c0482015-09-01 18:22:39 +0000802
803 FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic);
804
805 retval = m_categories_map.GetSummaryFormat(valobj, use_dynamic, matches);
806 if (!retval)
807 {
808 if (log)
809 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance.");
810 for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj))
811 {
812 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
813 {
814 if (lang_category->Get(valobj, use_dynamic, matches, retval))
815 break;
816 }
817 }
818 if (retval)
819 {
820 if (log)
821 log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning.");
822 return retval;
823 }
824 }
Enrico Granata686f3de2013-10-30 23:46:27 +0000825 if (!retval)
826 {
827 if (log)
828 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
829 retval = GetHardcodedSummaryFormat(valobj, use_dynamic);
830 }
Enrico Granatad4cb1dd2015-07-01 20:06:40 +0000831
832 if (valobj_type && (!retval || !retval->NonCacheable()))
Enrico Granata5548cb52013-01-28 23:47:25 +0000833 {
834 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000835 log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
836 static_cast<void*>(retval.get()),
837 valobj_type.AsCString("<invalid>"));
Enrico Granata5548cb52013-01-28 23:47:25 +0000838 m_format_cache.SetSummary(valobj_type,retval);
839 }
Enrico Granatac2a96402013-06-26 01:03:38 +0000840 if (log && log->GetDebug())
Michael Sartain89c862f2013-08-07 19:05:15 +0000841 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
Enrico Granata5548cb52013-01-28 23:47:25 +0000842 return retval;
843}
844
845#ifndef LLDB_DISABLE_PYTHON
Enrico Granataecd02bc2014-08-19 18:47:58 +0000846lldb::SyntheticChildrenSP
847FormatManager::GetHardcodedSyntheticChildren (ValueObject& valobj,
848 lldb::DynamicValueType use_dynamic)
Enrico Granata686f3de2013-10-30 23:46:27 +0000849{
Enrico Granataecd02bc2014-08-19 18:47:58 +0000850 for (const auto& candidate: m_hardcoded_synthetics)
851 {
852 auto result = candidate(valobj,use_dynamic,*this);
853 if (result)
854 return result;
855 }
856 return nullptr;
Enrico Granata686f3de2013-10-30 23:46:27 +0000857}
858
Enrico Granata5548cb52013-01-28 23:47:25 +0000859lldb::SyntheticChildrenSP
860FormatManager::GetSyntheticChildren (ValueObject& valobj,
Enrico Granatac2a96402013-06-26 01:03:38 +0000861 lldb::DynamicValueType use_dynamic)
Enrico Granata5548cb52013-01-28 23:47:25 +0000862{
863 SyntheticChildrenSP retval;
Greg Clayton5160ce52013-03-27 23:08:40 +0000864 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
Enrico Granata5548cb52013-01-28 23:47:25 +0000865 ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
866 if (valobj_type)
867 {
868 if (log)
Enrico Granata68ae4112013-06-18 18:23:07 +0000869 log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
Enrico Granata5548cb52013-01-28 23:47:25 +0000870 if (m_format_cache.GetSynthetic(valobj_type,retval))
Enrico Granata68ae4112013-06-18 18:23:07 +0000871 {
872 if (log)
873 {
874 log->Printf("[FormatManager::GetSyntheticChildren] Cache search success. Returning.");
Enrico Granatac2a96402013-06-26 01:03:38 +0000875 if (log->GetDebug())
Michael Sartain89c862f2013-08-07 19:05:15 +0000876 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
Enrico Granata68ae4112013-06-18 18:23:07 +0000877 }
Enrico Granata5548cb52013-01-28 23:47:25 +0000878 return retval;
Enrico Granata68ae4112013-06-18 18:23:07 +0000879 }
Enrico Granata5548cb52013-01-28 23:47:25 +0000880 if (log)
Enrico Granata68ae4112013-06-18 18:23:07 +0000881 log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route");
Enrico Granata5548cb52013-01-28 23:47:25 +0000882 }
Enrico Granata980c0482015-09-01 18:22:39 +0000883
884 FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic);
885
886 retval = m_categories_map.GetSyntheticChildren(valobj, use_dynamic, matches);
887 if (!retval)
888 {
889 if (log)
890 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance.");
891 for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj))
892 {
893 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
894 {
895 if (lang_category->Get(valobj, use_dynamic, matches, retval))
896 break;
897 }
898 }
899 if (retval)
900 {
901 if (log)
902 log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning.");
903 return retval;
904 }
905 }
Enrico Granata686f3de2013-10-30 23:46:27 +0000906 if (!retval)
907 {
908 if (log)
909 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
910 retval = GetHardcodedSyntheticChildren(valobj, use_dynamic);
911 }
Enrico Granatad4cb1dd2015-07-01 20:06:40 +0000912
913 if (valobj_type && (!retval || !retval->NonCacheable()))
Enrico Granata5548cb52013-01-28 23:47:25 +0000914 {
915 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000916 log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",
917 static_cast<void*>(retval.get()),
918 valobj_type.AsCString("<invalid>"));
Enrico Granata5548cb52013-01-28 23:47:25 +0000919 m_format_cache.SetSynthetic(valobj_type,retval);
920 }
Enrico Granatac2a96402013-06-26 01:03:38 +0000921 if (log && log->GetDebug())
Michael Sartain89c862f2013-08-07 19:05:15 +0000922 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
Enrico Granata5548cb52013-01-28 23:47:25 +0000923 return retval;
924}
925#endif
Enrico Granata5548cb52013-01-28 23:47:25 +0000926
Enrico Granatac5827132014-09-05 20:45:07 +0000927lldb::TypeValidatorImplSP
928FormatManager::GetValidator (ValueObject& valobj,
929 lldb::DynamicValueType use_dynamic)
930{
931 TypeValidatorImplSP retval;
932 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
933 ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
934 if (valobj_type)
935 {
936 if (log)
937 log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
938 if (m_format_cache.GetValidator(valobj_type,retval))
939 {
940 if (log)
941 {
942 log->Printf("[FormatManager::GetValidator] Cache search success. Returning.");
943 if (log->GetDebug())
944 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
945 }
946 return retval;
947 }
948 if (log)
949 log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route");
950 }
Enrico Granata980c0482015-09-01 18:22:39 +0000951
952 FormattersMatchVector matches = GetPossibleMatches(valobj, use_dynamic);
953
954 retval = m_categories_map.GetValidator(valobj, use_dynamic, matches);
955 if (!retval)
956 {
957 if (log)
958 log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance.");
959 for (lldb::LanguageType lang_type : GetCandidateLanguages(valobj))
960 {
961 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
962 {
963 if (lang_category->Get(valobj, use_dynamic, matches, retval))
964 break;
965 }
966 }
967 if (retval)
968 {
969 if (log)
970 log->Printf("[FormatManager::GetValidator] Language search success. Returning.");
971 return retval;
972 }
973 }
Enrico Granatac5827132014-09-05 20:45:07 +0000974 if (!retval)
975 {
976 if (log)
977 log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance.");
978 retval = GetHardcodedValidator(valobj, use_dynamic);
979 }
Enrico Granatad4cb1dd2015-07-01 20:06:40 +0000980
981 if (valobj_type && (!retval || !retval->NonCacheable()))
Enrico Granatac5827132014-09-05 20:45:07 +0000982 {
983 if (log)
984 log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
985 static_cast<void*>(retval.get()),
986 valobj_type.AsCString("<invalid>"));
987 m_format_cache.SetValidator(valobj_type,retval);
988 }
989 if (log && log->GetDebug())
990 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
991 return retval;
992}
993
994lldb::TypeValidatorImplSP
995FormatManager::GetHardcodedValidator (ValueObject& valobj,
996 lldb::DynamicValueType use_dynamic)
997{
998 for (const auto& candidate: m_hardcoded_validators)
999 {
1000 auto result = candidate(valobj,use_dynamic,*this);
1001 if (result)
1002 return result;
1003 }
1004 return nullptr;
1005}
1006
Enrico Granata5548cb52013-01-28 23:47:25 +00001007FormatManager::FormatManager() :
1008 m_format_cache(),
Enrico Granatac482a192011-08-17 22:13:59 +00001009 m_named_summaries_map(this),
1010 m_last_revision(0),
1011 m_categories_map(this),
Enrico Granata980c0482015-09-01 18:22:39 +00001012 m_language_categories_map(),
1013 m_language_categories_mutex(Mutex::eMutexTypeRecursive),
Enrico Granata1d887492011-08-22 18:36:52 +00001014 m_default_category_name(ConstString("default")),
1015 m_system_category_name(ConstString("system")),
Enrico Granatad3d444f2012-02-23 23:10:03 +00001016 m_vectortypes_category_name(ConstString("VectorTypes")),
Enrico Granataecd02bc2014-08-19 18:47:58 +00001017 m_hardcoded_formats(),
1018 m_hardcoded_summaries(),
Enrico Granatac5827132014-09-05 20:45:07 +00001019 m_hardcoded_synthetics(),
1020 m_hardcoded_validators()
Enrico Granataecd02bc2014-08-19 18:47:58 +00001021
Enrico Granatac482a192011-08-17 22:13:59 +00001022{
Enrico Granata864e3e82012-02-17 03:18:30 +00001023 LoadSystemFormatters();
Enrico Granata170c3952015-09-14 22:18:32 +00001024 LoadVectorFormatters();
Enrico Granataecd02bc2014-08-19 18:47:58 +00001025 LoadHardcodedFormatters();
Enrico Granata864e3e82012-02-17 03:18:30 +00001026
Enrico Granata5548cb52013-01-28 23:47:25 +00001027 EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last);
1028 EnableCategory(m_system_category_name,TypeCategoryMap::Last);
Enrico Granata864e3e82012-02-17 03:18:30 +00001029}
1030
1031void
Enrico Granata864e3e82012-02-17 03:18:30 +00001032FormatManager::LoadSystemFormatters()
1033{
Enrico Granataf68df122013-01-10 22:08:35 +00001034
1035 TypeSummaryImpl::Flags string_flags;
Enrico Granata0337c272013-02-22 00:37:31 +00001036 string_flags.SetCascades(true)
Enrico Granataf68df122013-01-10 22:08:35 +00001037 .SetSkipPointers(true)
1038 .SetSkipReferences(false)
1039 .SetDontShowChildren(true)
1040 .SetDontShowValue(false)
1041 .SetShowMembersOneLiner(false)
1042 .SetHideItemNames(false);
1043
Enrico Granatabc2c2b02015-06-15 23:01:47 +00001044 TypeSummaryImpl::Flags string_array_flags;
Enrico Granatad2911632015-07-28 02:13:03 +00001045 string_array_flags.SetCascades(true)
Enrico Granatabc2c2b02015-06-15 23:01:47 +00001046 .SetSkipPointers(true)
1047 .SetSkipReferences(false)
1048 .SetDontShowChildren(true)
1049 .SetDontShowValue(true)
1050 .SetShowMembersOneLiner(false)
1051 .SetHideItemNames(false);
1052
Enrico Granataf68df122013-01-10 22:08:35 +00001053 lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(string_flags, "${var%s}"));
Enrico Granatac482a192011-08-17 22:13:59 +00001054
1055
Enrico Granatabc2c2b02015-06-15 23:01:47 +00001056 lldb::TypeSummaryImplSP string_array_format(new StringSummaryFormat(string_array_flags,
Enrico Granata061858c2012-02-15 02:34:21 +00001057 "${var%s}"));
Enrico Granatac482a192011-08-17 22:13:59 +00001058
1059 lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]"));
Enrico Granatabc2c2b02015-06-15 23:01:47 +00001060 lldb::RegularExpressionSP any_size_wchar_arr(new RegularExpression("wchar_t \\[[0-9]+\\]"));
Enrico Granatac482a192011-08-17 22:13:59 +00001061
Enrico Granata061858c2012-02-15 02:34:21 +00001062 TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name);
Enrico Granatac482a192011-08-17 22:13:59 +00001063
Enrico Granatab72a5012013-12-20 09:38:13 +00001064 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), string_format);
1065 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("unsigned char *"), string_format);
1066 sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, string_array_format);
Enrico Granataaff65652013-10-21 17:29:51 +00001067
Enrico Granata4ed7ef12012-07-13 18:54:40 +00001068 lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
1069 .SetSkipPointers(true)
1070 .SetSkipReferences(true)
1071 .SetDontShowChildren(true)
1072 .SetDontShowValue(false)
1073 .SetShowMembersOneLiner(false)
1074 .SetHideItemNames(false),
1075 "${var%O}"));
1076
Enrico Granatab72a5012013-12-20 09:38:13 +00001077 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary);
Enrico Granatad3d444f2012-02-23 23:10:03 +00001078
Jason Molenda1a100cd2013-01-12 04:24:50 +00001079#ifndef LLDB_DISABLE_PYTHON
Enrico Granata4cc21772013-10-08 20:59:02 +00001080 TypeFormatImpl::Flags fourchar_flags;
1081 fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true);
1082
1083 AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags);
Jason Molenda1a100cd2013-01-12 04:24:50 +00001084#endif
Enrico Granatad3d444f2012-02-23 23:10:03 +00001085}
Enrico Granatab2698cd2012-09-13 18:27:09 +00001086
Enrico Granata864e3e82012-02-17 03:18:30 +00001087void
Enrico Granata170c3952015-09-14 22:18:32 +00001088FormatManager::LoadVectorFormatters()
Enrico Granata864e3e82012-02-17 03:18:30 +00001089{
Enrico Granata864e3e82012-02-17 03:18:30 +00001090 TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
Enrico Granata170c3952015-09-14 22:18:32 +00001091
Enrico Granata864e3e82012-02-17 03:18:30 +00001092 TypeSummaryImpl::Flags vector_flags;
1093 vector_flags.SetCascades(true)
1094 .SetSkipPointers(true)
1095 .SetSkipReferences(false)
1096 .SetDontShowChildren(true)
1097 .SetDontShowValue(false)
1098 .SetShowMembersOneLiner(true)
1099 .SetHideItemNames(true);
1100
Enrico Granatae6a6d9a2012-12-10 23:30:25 +00001101 AddStringSummary(vectors_category_sp,
1102 "${var.uint128}",
1103 ConstString("builtin_type_vec128"),
Enrico Granata170c3952015-09-14 22:18:32 +00001104 vector_flags);
1105
Enrico Granatae6a6d9a2012-12-10 23:30:25 +00001106 AddStringSummary(vectors_category_sp,
1107 "",
1108 ConstString("float [4]"),
1109 vector_flags);
1110 AddStringSummary(vectors_category_sp,
1111 "",
1112 ConstString("int32_t [4]"),
1113 vector_flags);
1114 AddStringSummary(vectors_category_sp,
1115 "",
1116 ConstString("int16_t [8]"),
1117 vector_flags);
1118 AddStringSummary(vectors_category_sp,
1119 "",
1120 ConstString("vDouble"),
1121 vector_flags);
1122 AddStringSummary(vectors_category_sp,
1123 "",
1124 ConstString("vFloat"),
1125 vector_flags);
1126 AddStringSummary(vectors_category_sp,
1127 "",
1128 ConstString("vSInt8"),
1129 vector_flags);
1130 AddStringSummary(vectors_category_sp,
1131 "",
1132 ConstString("vSInt16"),
1133 vector_flags);
1134 AddStringSummary(vectors_category_sp,
1135 "",
1136 ConstString("vSInt32"),
1137 vector_flags);
1138 AddStringSummary(vectors_category_sp,
1139 "",
1140 ConstString("vUInt16"),
1141 vector_flags);
1142 AddStringSummary(vectors_category_sp,
1143 "",
1144 ConstString("vUInt8"),
1145 vector_flags);
1146 AddStringSummary(vectors_category_sp,
1147 "",
1148 ConstString("vUInt16"),
1149 vector_flags);
1150 AddStringSummary(vectors_category_sp,
1151 "",
1152 ConstString("vUInt32"),
1153 vector_flags);
1154 AddStringSummary(vectors_category_sp,
1155 "",
1156 ConstString("vBool32"),
1157 vector_flags);
Greg Claytond4e25522011-10-12 00:53:29 +00001158}
Enrico Granataecd02bc2014-08-19 18:47:58 +00001159
1160void
1161FormatManager::LoadHardcodedFormatters()
1162{
1163 {
1164 // insert code to load formats here
1165 }
1166 {
1167 // insert code to load summaries here
Enrico Granataff0f23d2014-12-10 02:00:45 +00001168 m_hardcoded_summaries.push_back(
1169 [](lldb_private::ValueObject& valobj,
1170 lldb::DynamicValueType,
1171 FormatManager&) -> TypeSummaryImpl::SharedPointer {
Enrico Granata419d7912015-09-04 00:33:51 +00001172 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider"));
Greg Clayton99558cc42015-08-24 23:46:31 +00001173 if (valobj.GetCompilerType().IsFunctionPointerType())
Enrico Granataff0f23d2014-12-10 02:00:45 +00001174 {
1175 return formatter_sp;
1176 }
1177 return nullptr;
1178 });
Enrico Granatad529d042015-07-07 00:20:57 +00001179 m_hardcoded_summaries.push_back(
1180 [](lldb_private::ValueObject& valobj,
1181 lldb::DynamicValueType,
1182 FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1183 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
1184 .SetCascades(true)
1185 .SetDontShowChildren(true)
1186 .SetHideItemNames(true)
1187 .SetShowMembersOneLiner(true)
1188 .SetSkipPointers(true)
1189 .SetSkipReferences(false),
1190 lldb_private::formatters::VectorTypeSummaryProvider,
1191 "vector_type pointer summary provider"));
Greg Clayton99558cc42015-08-24 23:46:31 +00001192 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
Enrico Granatad529d042015-07-07 00:20:57 +00001193 {
1194 if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled())
1195 return formatter_sp;
1196 }
1197 return nullptr;
1198 });
Enrico Granataecd02bc2014-08-19 18:47:58 +00001199 }
1200 {
1201 // insert code to load synthetics here
Enrico Granatadb595cd2015-03-06 19:37:57 +00001202 m_hardcoded_synthetics.push_back(
1203 [](lldb_private::ValueObject& valobj,
1204 lldb::DynamicValueType,
1205 FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
Enrico Granatad4cb1dd2015-07-01 20:06:40 +00001206 static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
Enrico Granatadb595cd2015-03-06 19:37:57 +00001207 "vector_type synthetic children",
1208 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
Greg Clayton99558cc42015-08-24 23:46:31 +00001209 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
Enrico Granatadb595cd2015-03-06 19:37:57 +00001210 {
1211 if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled())
1212 return formatter_sp;
1213 }
1214 return nullptr;
1215 });
Enrico Granataecd02bc2014-08-19 18:47:58 +00001216 }
Enrico Granatac5827132014-09-05 20:45:07 +00001217 {
1218 // insert code to load validators here
1219 }
Enrico Granataecd02bc2014-08-19 18:47:58 +00001220}