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