]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[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"
13 #include "lldb/Core/ValueObject.h"
14 #include "lldb/DataFormatters/TypeSynthetic.h"
15 #include "lldb/Target/ExecutionContext.h"
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Logging.h"
18 #include "lldb/Utility/SharingPtr.h"
19 #include "lldb/Utility/Status.h"
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);
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   ValueObject *valobj_for_frontend = m_parent;
133   if (m_synth_sp->WantsDereference())
134   {
135     CompilerType type = m_parent->GetCompilerType();
136     if (type.IsValid() && type.IsPointerOrReferenceType())
137     {
138       Status error;
139       lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
140       if (error.Success())
141         valobj_for_frontend = deref_sp.get();
142     }
143   }
144   m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
145   if (!m_synth_filter_ap.get())
146     m_synth_filter_ap = llvm::make_unique<DummySyntheticFrontEnd>(*m_parent);
147 }
148
149 bool ValueObjectSynthetic::UpdateValue() {
150   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
151
152   SetValueIsValid(false);
153   m_error.Clear();
154
155   if (!m_parent->UpdateValueIfNeeded(false)) {
156     // our parent could not update.. as we are meaningless without a parent,
157     // just stop
158     if (m_parent->GetError().Fail())
159       m_error = m_parent->GetError();
160     return false;
161   }
162
163   // regenerate the synthetic filter if our typename changes
164   // <rdar://problem/12424824>
165   ConstString new_parent_type_name = m_parent->GetTypeName();
166   if (new_parent_type_name != m_parent_type_name) {
167     if (log)
168       log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed "
169                   "from %s to %s, recomputing synthetic filter",
170                   GetName().AsCString(), m_parent_type_name.AsCString(),
171                   new_parent_type_name.AsCString());
172     m_parent_type_name = new_parent_type_name;
173     CreateSynthFilter();
174   }
175
176   // let our backend do its update
177   if (!m_synth_filter_ap->Update()) {
178     if (log)
179       log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
180                   "filter said caches are stale - clearing",
181                   GetName().AsCString());
182     // filter said that cached values are stale
183     m_children_byindex.Clear();
184     m_name_toindex.Clear();
185     // usually, an object's value can change but this does not alter its
186     // children count for a synthetic VO that might indeed happen, so we need
187     // to tell the upper echelons that they need to come back to us asking for
188     // children
189     m_children_count_valid = false;
190     m_synthetic_children_cache.Clear();
191     m_synthetic_children_count = UINT32_MAX;
192     m_might_have_children = eLazyBoolCalculate;
193   } else {
194     if (log)
195       log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
196                   "filter said caches are still valid",
197                   GetName().AsCString());
198   }
199
200   m_provides_value = eLazyBoolCalculate;
201
202   lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue());
203
204   if (synth_val && synth_val->CanProvideValue()) {
205     if (log)
206       log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
207                   "filter said it can provide a value",
208                   GetName().AsCString());
209
210     m_provides_value = eLazyBoolYes;
211     CopyValueData(synth_val.get());
212   } else {
213     if (log)
214       log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
215                   "filter said it will not provide a value",
216                   GetName().AsCString());
217
218     m_provides_value = eLazyBoolNo;
219     CopyValueData(m_parent);
220   }
221
222   SetValueIsValid(true);
223   return true;
224 }
225
226 lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
227                                                           bool can_create) {
228   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
229
230   if (log)
231     log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving "
232                 "child at index %zu",
233                 GetName().AsCString(), idx);
234
235   UpdateValueIfNeeded();
236
237   ValueObject *valobj;
238   if (!m_children_byindex.GetValueForKey(idx, valobj)) {
239     if (can_create && m_synth_filter_ap.get() != nullptr) {
240       if (log)
241         log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
242                     "index %zu not cached and will be created",
243                     GetName().AsCString(), idx);
244
245       lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex(idx);
246
247       if (log)
248         log->Printf(
249             "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index "
250             "%zu created as %p (is "
251             "synthetic: %s)",
252             GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()),
253             synth_guy.get()
254                 ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
255                 : "no");
256
257       if (!synth_guy)
258         return synth_guy;
259
260       if (synth_guy->IsSyntheticChildrenGenerated())
261         m_synthetic_children_cache.AppendObject(synth_guy);
262       m_children_byindex.SetValueForKey(idx, synth_guy.get());
263       synth_guy->SetPreferredDisplayLanguageIfNeeded(
264           GetPreferredDisplayLanguage());
265       return synth_guy;
266     } else {
267       if (log)
268         log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
269                     "index %zu not cached and cannot "
270                     "be created (can_create = %s, synth_filter = %p)",
271                     GetName().AsCString(), idx, can_create ? "yes" : "no",
272                     static_cast<void *>(m_synth_filter_ap.get()));
273
274       return lldb::ValueObjectSP();
275     }
276   } else {
277     if (log)
278       log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
279                   "index %zu cached as %p",
280                   GetName().AsCString(), idx, static_cast<void *>(valobj));
281
282     return valobj->GetSP();
283   }
284 }
285
286 lldb::ValueObjectSP
287 ValueObjectSynthetic::GetChildMemberWithName(const ConstString &name,
288                                              bool can_create) {
289   UpdateValueIfNeeded();
290
291   uint32_t index = GetIndexOfChildWithName(name);
292
293   if (index == UINT32_MAX)
294     return lldb::ValueObjectSP();
295
296   return GetChildAtIndex(index, can_create);
297 }
298
299 size_t ValueObjectSynthetic::GetIndexOfChildWithName(const ConstString &name) {
300   UpdateValueIfNeeded();
301
302   uint32_t found_index = UINT32_MAX;
303   bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
304
305   if (!did_find && m_synth_filter_ap.get() != nullptr) {
306     uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName(name);
307     if (index == UINT32_MAX)
308       return index;
309     m_name_toindex.SetValueForKey(name.GetCString(), index);
310     return index;
311   } else if (!did_find && m_synth_filter_ap.get() == nullptr)
312     return UINT32_MAX;
313   else /*if (iter != m_name_toindex.end())*/
314     return found_index;
315 }
316
317 bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); }
318
319 lldb::ValueObjectSP ValueObjectSynthetic::GetNonSyntheticValue() {
320   return m_parent->GetSP();
321 }
322
323 void ValueObjectSynthetic::CopyValueData(ValueObject *source) {
324   m_value = (source->UpdateValueIfNeeded(), source->GetValue());
325   ExecutionContext exe_ctx(GetExecutionContextRef());
326   m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
327 }
328
329 bool ValueObjectSynthetic::CanProvideValue() {
330   if (!UpdateValueIfNeeded())
331     return false;
332   if (m_provides_value == eLazyBoolYes)
333     return true;
334   return m_parent->CanProvideValue();
335 }
336
337 bool ValueObjectSynthetic::SetValueFromCString(const char *value_str,
338                                                Status &error) {
339   return m_parent->SetValueFromCString(value_str, error);
340 }
341
342 void ValueObjectSynthetic::SetFormat(lldb::Format format) {
343   if (m_parent) {
344     m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
345     m_parent->SetFormat(format);
346   }
347   this->ValueObject::SetFormat(format);
348   this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
349 }
350
351 void ValueObjectSynthetic::SetPreferredDisplayLanguage(
352     lldb::LanguageType lang) {
353   this->ValueObject::SetPreferredDisplayLanguage(lang);
354   if (m_parent)
355     m_parent->SetPreferredDisplayLanguage(lang);
356 }
357
358 lldb::LanguageType ValueObjectSynthetic::GetPreferredDisplayLanguage() {
359   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
360     if (m_parent)
361       return m_parent->GetPreferredDisplayLanguage();
362     return lldb::eLanguageTypeUnknown;
363   } else
364     return m_preferred_display_language;
365 }
366
367 bool ValueObjectSynthetic::IsSyntheticChildrenGenerated() {
368   if (m_parent)
369     return m_parent->IsSyntheticChildrenGenerated();
370   return false;
371 }
372
373 void ValueObjectSynthetic::SetSyntheticChildrenGenerated(bool b) {
374   if (m_parent)
375     m_parent->SetSyntheticChildrenGenerated(b);
376   this->ValueObject::SetSyntheticChildrenGenerated(b);
377 }
378
379 bool ValueObjectSynthetic::GetDeclaration(Declaration &decl) {
380   if (m_parent)
381     return m_parent->GetDeclaration(decl);
382
383   return ValueObject::GetDeclaration(decl);
384 }
385
386 uint64_t ValueObjectSynthetic::GetLanguageFlags() {
387   if (m_parent)
388     return m_parent->GetLanguageFlags();
389   return this->ValueObject::GetLanguageFlags();
390 }
391
392 void ValueObjectSynthetic::SetLanguageFlags(uint64_t flags) {
393   if (m_parent)
394     m_parent->SetLanguageFlags(flags);
395   else
396     this->ValueObject::SetLanguageFlags(flags);
397 }