]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Core/ValueObjectSyntheticFilter.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Core / ValueObjectSyntheticFilter.cpp
1 //===-- ValueObjectSyntheticFilter.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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Core/ValueObjectSyntheticFilter.h"
15
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/DataFormatters/TypeSynthetic.h"
19
20 using namespace lldb_private;
21
22 class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd
23 {
24 public:
25     DummySyntheticFrontEnd(ValueObject &backend) :
26     SyntheticChildrenFrontEnd(backend)
27     {}
28
29     size_t
30     CalculateNumChildren() override
31     {
32         return m_backend.GetNumChildren();
33     }
34     
35     lldb::ValueObjectSP
36     GetChildAtIndex(size_t idx) override
37     {
38         return m_backend.GetChildAtIndex(idx, true);
39     }
40
41     size_t
42     GetIndexOfChildWithName(const ConstString &name) override
43     {
44         return m_backend.GetIndexOfChildWithName(name);
45     }
46     
47     bool
48     MightHaveChildren() override
49     {
50         return true;
51     }
52     
53     bool
54     Update() override
55     {
56         return false;
57     }
58 };
59
60 ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
61     ValueObject(parent),
62     m_synth_sp(filter),
63     m_children_byindex(),
64     m_name_toindex(),
65     m_synthetic_children_count(UINT32_MAX),
66     m_synthetic_children_cache(),
67     m_parent_type_name(parent.GetTypeName()),
68     m_might_have_children(eLazyBoolCalculate),
69     m_provides_value(eLazyBoolCalculate)
70 {
71     SetName(parent.GetName());
72     CopyValueData(m_parent);
73     CreateSynthFilter();
74 }
75
76 ValueObjectSynthetic::~ValueObjectSynthetic() = default;
77
78 CompilerType
79 ValueObjectSynthetic::GetCompilerTypeImpl ()
80 {
81     return m_parent->GetCompilerType();
82 }
83
84 ConstString
85 ValueObjectSynthetic::GetTypeName()
86 {
87     return m_parent->GetTypeName();
88 }
89
90 ConstString
91 ValueObjectSynthetic::GetQualifiedTypeName()
92 {
93     return m_parent->GetQualifiedTypeName();
94 }
95
96 ConstString
97 ValueObjectSynthetic::GetDisplayTypeName()
98 {
99     if (ConstString synth_name = m_synth_filter_ap->GetSyntheticTypeName())
100         return synth_name;
101
102     return m_parent->GetDisplayTypeName();
103 }
104
105 size_t
106 ValueObjectSynthetic::CalculateNumChildren(uint32_t max)
107 {
108     Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
109     
110     UpdateValueIfNeeded();
111     if (m_synthetic_children_count < UINT32_MAX)
112         return m_synthetic_children_count <= max ? m_synthetic_children_count : max;
113
114     if (max < UINT32_MAX)
115     {
116         size_t num_children = m_synth_filter_ap->CalculateNumChildren(max);
117         if (log)
118             log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name %s and type %s, the filter returned %zu child values",
119                         GetName().AsCString(),
120                         GetTypeName().AsCString(),
121                         num_children);
122         return num_children;
123     }
124     else
125     {
126         size_t num_children = (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren(max));
127         if (log)
128             log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name %s and type %s, the filter returned %zu child values",
129                         GetName().AsCString(),
130                         GetTypeName().AsCString(),
131                         num_children);
132         return num_children;
133     }
134 }
135
136 lldb::ValueObjectSP
137 ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType)
138 {
139     if (!m_parent)
140         return lldb::ValueObjectSP();
141     if (IsDynamic() && GetDynamicValueType() == valueType)
142         return GetSP();
143     return m_parent->GetDynamicValue(valueType);
144 }
145
146 bool
147 ValueObjectSynthetic::MightHaveChildren()
148 {
149     if (m_might_have_children == eLazyBoolCalculate)
150         m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
151     return (m_might_have_children == eLazyBoolNo ? false : true);
152 }
153
154 uint64_t
155 ValueObjectSynthetic::GetByteSize()
156 {
157     return m_parent->GetByteSize();
158 }
159
160 lldb::ValueType
161 ValueObjectSynthetic::GetValueType() const
162 {
163     return m_parent->GetValueType();
164 }
165
166 void
167 ValueObjectSynthetic::CreateSynthFilter ()
168 {
169     m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
170     if (!m_synth_filter_ap.get())
171         m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent));
172 }
173
174 bool
175 ValueObjectSynthetic::UpdateValue ()
176 {
177     Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
178     
179     SetValueIsValid (false);
180     m_error.Clear();
181
182     if (!m_parent->UpdateValueIfNeeded(false))
183     {
184         // our parent could not update.. as we are meaningless without a parent, just stop
185         if (m_parent->GetError().Fail())
186             m_error = m_parent->GetError();
187         return false;
188     }
189     
190     // regenerate the synthetic filter if our typename changes
191     // <rdar://problem/12424824>
192     ConstString new_parent_type_name = m_parent->GetTypeName();
193     if (new_parent_type_name != m_parent_type_name)
194     {
195         if (log)
196             log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed from %s to %s, recomputing synthetic filter",
197                         GetName().AsCString(),
198                         m_parent_type_name.AsCString(),
199                         new_parent_type_name.AsCString());
200         m_parent_type_name = new_parent_type_name;
201         CreateSynthFilter();
202     }
203
204     // let our backend do its update
205     if (m_synth_filter_ap->Update() == false)
206     {
207         if (log)
208             log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said caches are stale - clearing", GetName().AsCString());
209         // filter said that cached values are stale
210         m_children_byindex.Clear();
211         m_name_toindex.Clear();
212         // usually, an object's value can change but this does not alter its children count
213         // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
214         // that they need to come back to us asking for children
215         m_children_count_valid = false;
216         m_synthetic_children_cache.Clear();
217         m_synthetic_children_count = UINT32_MAX;
218         m_might_have_children = eLazyBoolCalculate;
219     }
220     else
221     {
222         if (log)
223             log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said caches are still valid", GetName().AsCString());
224     }
225     
226     m_provides_value = eLazyBoolCalculate;
227     
228     lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue());
229     
230     if (synth_val && synth_val->CanProvideValue())
231     {
232         if (log)
233             log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said it can provide a value", GetName().AsCString());
234
235         m_provides_value = eLazyBoolYes;
236         CopyValueData(synth_val.get());
237     }
238     else
239     {
240         if (log)
241             log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said it will not provide a value", GetName().AsCString());
242
243         m_provides_value = eLazyBoolNo;
244         CopyValueData(m_parent);
245     }
246     
247     SetValueIsValid(true);
248     return true;
249 }
250
251 lldb::ValueObjectSP
252 ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
253 {
254     Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
255     
256     if (log)
257         log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving child at index %zu",
258                     GetName().AsCString(),
259                     idx);
260     
261     UpdateValueIfNeeded();
262     
263     ValueObject *valobj;
264     if (m_children_byindex.GetValueForKey(idx, valobj) == false)
265     {
266         if (can_create && m_synth_filter_ap.get() != nullptr)
267         {
268             if (log)
269                 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu not cached and will be created",
270                             GetName().AsCString(),
271                             idx);
272
273             lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
274             
275             if (log)
276                 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu created as %p (is synthetic: %s)",
277                             GetName().AsCString(),
278                             idx,
279                             synth_guy.get(),
280                             synth_guy.get() ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no") : "no");
281
282             if (!synth_guy)
283                 return synth_guy;
284             
285             if (synth_guy->IsSyntheticChildrenGenerated())
286                 m_synthetic_children_cache.AppendObject(synth_guy);
287             m_children_byindex.SetValueForKey(idx, synth_guy.get());
288             synth_guy->SetPreferredDisplayLanguageIfNeeded(GetPreferredDisplayLanguage());
289             return synth_guy;
290         }
291         else
292         {
293             if (log)
294                 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu not cached and cannot be created (can_create = %s, synth_filter = %p)",
295                             GetName().AsCString(),
296                             idx,
297                             can_create ? "yes" : "no",
298                             m_synth_filter_ap.get());
299
300             return lldb::ValueObjectSP();
301         }
302     }
303     else
304     {
305         if (log)
306             log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu cached as %p",
307                         GetName().AsCString(),
308                         idx,
309                         valobj);
310
311         return valobj->GetSP();
312     }
313 }
314
315 lldb::ValueObjectSP
316 ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
317 {
318     UpdateValueIfNeeded();
319
320     uint32_t index = GetIndexOfChildWithName(name);
321     
322     if (index == UINT32_MAX)
323         return lldb::ValueObjectSP();
324     
325     return GetChildAtIndex(index, can_create);
326 }
327
328 size_t
329 ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
330 {
331     UpdateValueIfNeeded();
332     
333     uint32_t found_index = UINT32_MAX;
334     bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
335     
336     if (!did_find && m_synth_filter_ap.get() != nullptr)
337     {
338         uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
339         if (index == UINT32_MAX)
340             return index;
341         m_name_toindex.SetValueForKey(name.GetCString(), index);
342         return index;
343     }
344     else if (!did_find && m_synth_filter_ap.get() == nullptr)
345         return UINT32_MAX;
346     else /*if (iter != m_name_toindex.end())*/
347         return found_index;
348 }
349
350 bool
351 ValueObjectSynthetic::IsInScope ()
352 {
353     return m_parent->IsInScope();
354 }
355
356 lldb::ValueObjectSP
357 ValueObjectSynthetic::GetNonSyntheticValue ()
358 {
359     return m_parent->GetSP();
360 }
361
362 void
363 ValueObjectSynthetic::CopyValueData (ValueObject *source)
364 {
365     m_value = (source->UpdateValueIfNeeded(), source->GetValue());
366     ExecutionContext exe_ctx (GetExecutionContextRef());
367     m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
368 }
369
370 bool
371 ValueObjectSynthetic::CanProvideValue ()
372 {
373     if (!UpdateValueIfNeeded())
374         return false;
375     if (m_provides_value == eLazyBoolYes)
376         return true;
377     return m_parent->CanProvideValue();
378 }
379
380 bool
381 ValueObjectSynthetic::SetValueFromCString (const char *value_str, Error& error)
382 {
383     return m_parent->SetValueFromCString(value_str, error);
384 }
385
386 void
387 ValueObjectSynthetic::SetFormat (lldb::Format format)
388 {
389     if (m_parent)
390     {
391         m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
392         m_parent->SetFormat(format);
393     }
394     this->ValueObject::SetFormat(format);
395     this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
396 }
397
398 void
399 ValueObjectSynthetic::SetPreferredDisplayLanguage (lldb::LanguageType lang)
400 {
401     this->ValueObject::SetPreferredDisplayLanguage(lang);
402     if (m_parent)
403         m_parent->SetPreferredDisplayLanguage(lang);
404 }
405
406 lldb::LanguageType
407 ValueObjectSynthetic::GetPreferredDisplayLanguage ()
408 {
409     if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
410     {
411         if (m_parent)
412             return m_parent->GetPreferredDisplayLanguage();
413         return lldb::eLanguageTypeUnknown;
414     }
415     else
416         return m_preferred_display_language;
417 }
418
419 bool
420 ValueObjectSynthetic::IsSyntheticChildrenGenerated ()
421 {
422     if (m_parent)
423         return m_parent->IsSyntheticChildrenGenerated();
424     return false;
425 }
426
427 void
428 ValueObjectSynthetic::SetSyntheticChildrenGenerated (bool b)
429 {
430     if (m_parent)
431         m_parent->SetSyntheticChildrenGenerated(b);
432     this->ValueObject::SetSyntheticChildrenGenerated(b);
433 }
434
435 bool
436 ValueObjectSynthetic::GetDeclaration (Declaration &decl)
437 {
438     if (m_parent)
439         return m_parent->GetDeclaration(decl);
440
441     return ValueObject::GetDeclaration(decl);
442 }
443
444 uint64_t
445 ValueObjectSynthetic::GetLanguageFlags ()
446 {
447     if (m_parent)
448         return m_parent->GetLanguageFlags();
449     return this->ValueObject::GetLanguageFlags();
450 }
451
452 void
453 ValueObjectSynthetic::SetLanguageFlags (uint64_t flags)
454 {
455     if (m_parent)
456         m_parent->SetLanguageFlags(flags);
457     else
458         this->ValueObject::SetLanguageFlags(flags);
459 }