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