1cfca06d7SDimitry Andric //===-- ValueObject.cpp ---------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Core/ValueObject.h"
10f034231aSEd Maste
1194994d37SDimitry Andric #include "lldb/Core/Address.h"
12344a3780SDimitry Andric #include "lldb/Core/Declaration.h"
13f034231aSEd Maste #include "lldb/Core/Module.h"
14f034231aSEd Maste #include "lldb/Core/ValueObjectCast.h"
15f034231aSEd Maste #include "lldb/Core/ValueObjectChild.h"
16f034231aSEd Maste #include "lldb/Core/ValueObjectConstResult.h"
17f034231aSEd Maste #include "lldb/Core/ValueObjectDynamicValue.h"
18f034231aSEd Maste #include "lldb/Core/ValueObjectMemory.h"
19f034231aSEd Maste #include "lldb/Core/ValueObjectSyntheticFilter.h"
20b1c73532SDimitry Andric #include "lldb/Core/ValueObjectVTable.h"
21f034231aSEd Maste #include "lldb/DataFormatters/DataVisualization.h"
2294994d37SDimitry Andric #include "lldb/DataFormatters/DumpValueObjectOptions.h"
2394994d37SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
24205afe67SEd Maste #include "lldb/DataFormatters/StringPrinter.h"
2594994d37SDimitry Andric #include "lldb/DataFormatters/TypeFormat.h"
2694994d37SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
27f21a844fSEd Maste #include "lldb/DataFormatters/ValueObjectPrinter.h"
2894994d37SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
29706b4fc4SDimitry Andric #include "lldb/Host/Config.h"
30205afe67SEd Maste #include "lldb/Symbol/CompileUnit.h"
3114f1b3e8SDimitry Andric #include "lldb/Symbol/CompilerType.h"
3294994d37SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
33f034231aSEd Maste #include "lldb/Symbol/Type.h"
345f29bb8aSDimitry Andric #include "lldb/Symbol/Variable.h"
35f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
36e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
37f034231aSEd Maste #include "lldb/Target/LanguageRuntime.h"
38f034231aSEd Maste #include "lldb/Target/Process.h"
3994994d37SDimitry Andric #include "lldb/Target/StackFrame.h"
40f034231aSEd Maste #include "lldb/Target/Target.h"
41f034231aSEd Maste #include "lldb/Target/Thread.h"
4294994d37SDimitry Andric #include "lldb/Target/ThreadList.h"
4394994d37SDimitry Andric #include "lldb/Utility/DataBuffer.h"
4474a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
4594994d37SDimitry Andric #include "lldb/Utility/Flags.h"
46145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
4774a628f7SDimitry Andric #include "lldb/Utility/Log.h"
4894994d37SDimitry Andric #include "lldb/Utility/Scalar.h"
4994994d37SDimitry Andric #include "lldb/Utility/Stream.h"
5074a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
5194994d37SDimitry Andric #include "lldb/lldb-private-types.h"
5274a628f7SDimitry Andric
5394994d37SDimitry Andric #include "llvm/Support/Compiler.h"
5474a628f7SDimitry Andric
5594994d37SDimitry Andric #include <algorithm>
5694994d37SDimitry Andric #include <cstdint>
5794994d37SDimitry Andric #include <cstdlib>
5894994d37SDimitry Andric #include <memory>
59e3b55780SDimitry Andric #include <optional>
6094994d37SDimitry Andric #include <tuple>
6174a628f7SDimitry Andric
62344a3780SDimitry Andric #include <cassert>
63344a3780SDimitry Andric #include <cinttypes>
64344a3780SDimitry Andric #include <cstdio>
65344a3780SDimitry Andric #include <cstring>
66344a3780SDimitry Andric
67344a3780SDimitry Andric #include <lldb/Core/ValueObject.h>
6874a628f7SDimitry Andric
6974a628f7SDimitry Andric namespace lldb_private {
7074a628f7SDimitry Andric class ExecutionContextScope;
7174a628f7SDimitry Andric }
7274a628f7SDimitry Andric namespace lldb_private {
7374a628f7SDimitry Andric class SymbolContextScope;
7474a628f7SDimitry Andric }
75f034231aSEd Maste
76f034231aSEd Maste using namespace lldb;
77f034231aSEd Maste using namespace lldb_private;
78f034231aSEd Maste
79f034231aSEd Maste static user_id_t g_value_obj_uid = 0;
80f034231aSEd Maste
81f034231aSEd Maste // ValueObject constructor
ValueObject(ValueObject & parent)8214f1b3e8SDimitry Andric ValueObject::ValueObject(ValueObject &parent)
83344a3780SDimitry Andric : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
84344a3780SDimitry Andric m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
85344a3780SDimitry Andric m_flags.m_is_synthetic_children_generated =
86344a3780SDimitry Andric parent.m_flags.m_is_synthetic_children_generated;
87706b4fc4SDimitry Andric m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
88706b4fc4SDimitry Andric m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
89f034231aSEd Maste m_manager->ManageObject(this);
90f034231aSEd Maste }
91f034231aSEd Maste
92f034231aSEd Maste // ValueObject constructor
ValueObject(ExecutionContextScope * exe_scope,ValueObjectManager & manager,AddressType child_ptr_or_ref_addr_type)93f034231aSEd Maste ValueObject::ValueObject(ExecutionContextScope *exe_scope,
94cfca06d7SDimitry Andric ValueObjectManager &manager,
9514f1b3e8SDimitry Andric AddressType child_ptr_or_ref_addr_type)
96344a3780SDimitry Andric : m_update_point(exe_scope), m_manager(&manager),
97f034231aSEd Maste m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
98344a3780SDimitry Andric m_id(++g_value_obj_uid) {
99706b4fc4SDimitry Andric if (exe_scope) {
100706b4fc4SDimitry Andric TargetSP target_sp(exe_scope->CalculateTarget());
101706b4fc4SDimitry Andric if (target_sp) {
102706b4fc4SDimitry Andric const ArchSpec &arch = target_sp->GetArchitecture();
103706b4fc4SDimitry Andric m_data.SetByteOrder(arch.GetByteOrder());
104706b4fc4SDimitry Andric m_data.SetAddressByteSize(arch.GetAddressByteSize());
105706b4fc4SDimitry Andric }
106706b4fc4SDimitry Andric }
107f034231aSEd Maste m_manager->ManageObject(this);
108f034231aSEd Maste }
109f034231aSEd Maste
110f034231aSEd Maste // Destructor
111344a3780SDimitry Andric ValueObject::~ValueObject() = default;
112f034231aSEd Maste
UpdateValueIfNeeded(bool update_format)11314f1b3e8SDimitry Andric bool ValueObject::UpdateValueIfNeeded(bool update_format) {
114f034231aSEd Maste
115f034231aSEd Maste bool did_change_formats = false;
116f034231aSEd Maste
117f034231aSEd Maste if (update_format)
118f034231aSEd Maste did_change_formats = UpdateFormatsIfNeeded();
119f034231aSEd Maste
120f73363f1SDimitry Andric // If this is a constant value, then our success is predicated on whether we
121f73363f1SDimitry Andric // have an error or not
12214f1b3e8SDimitry Andric if (GetIsConstant()) {
123f21a844fSEd Maste // if you are constant, things might still have changed behind your back
12414f1b3e8SDimitry Andric // (e.g. you are a frozen object and things have changed deeper than you
125f73363f1SDimitry Andric // cared to freeze-dry yourself) in this case, your value has not changed,
126f73363f1SDimitry Andric // but "computed" entries might have, so you might now have a different
127f73363f1SDimitry Andric // summary, or a different object description. clear these so we will
128f73363f1SDimitry Andric // recompute them
129f034231aSEd Maste if (update_format && !did_change_formats)
13014f1b3e8SDimitry Andric ClearUserVisibleData(eClearUserVisibleDataItemsSummary |
13114f1b3e8SDimitry Andric eClearUserVisibleDataItemsDescription);
132f034231aSEd Maste return m_error.Success();
133f034231aSEd Maste }
134f034231aSEd Maste
135205afe67SEd Maste bool first_update = IsChecksumEmpty();
136f034231aSEd Maste
13714f1b3e8SDimitry Andric if (NeedsUpdating()) {
138f034231aSEd Maste m_update_point.SetUpdated();
139f034231aSEd Maste
140f73363f1SDimitry Andric // Save the old value using swap to avoid a string copy which also will
141f73363f1SDimitry Andric // clear our m_value_str
14214f1b3e8SDimitry Andric if (m_value_str.empty()) {
143344a3780SDimitry Andric m_flags.m_old_value_valid = false;
14414f1b3e8SDimitry Andric } else {
145344a3780SDimitry Andric m_flags.m_old_value_valid = true;
146f034231aSEd Maste m_old_value_str.swap(m_value_str);
147f034231aSEd Maste ClearUserVisibleData(eClearUserVisibleDataItemsValue);
148f034231aSEd Maste }
149f034231aSEd Maste
150f034231aSEd Maste ClearUserVisibleData();
151f034231aSEd Maste
15214f1b3e8SDimitry Andric if (IsInScope()) {
153f034231aSEd Maste const bool value_was_valid = GetValueIsValid();
154f034231aSEd Maste SetValueDidChange(false);
155f034231aSEd Maste
156f034231aSEd Maste m_error.Clear();
157f034231aSEd Maste
158f034231aSEd Maste // Call the pure virtual function to update the value
159205afe67SEd Maste
160205afe67SEd Maste bool need_compare_checksums = false;
161205afe67SEd Maste llvm::SmallVector<uint8_t, 16> old_checksum;
162205afe67SEd Maste
16314f1b3e8SDimitry Andric if (!first_update && CanProvideValue()) {
164205afe67SEd Maste need_compare_checksums = true;
165205afe67SEd Maste old_checksum.resize(m_value_checksum.size());
16614f1b3e8SDimitry Andric std::copy(m_value_checksum.begin(), m_value_checksum.end(),
16714f1b3e8SDimitry Andric old_checksum.begin());
168205afe67SEd Maste }
169205afe67SEd Maste
170f034231aSEd Maste bool success = UpdateValue();
171f034231aSEd Maste
172f034231aSEd Maste SetValueIsValid(success);
173f034231aSEd Maste
17414f1b3e8SDimitry Andric if (success) {
175706b4fc4SDimitry Andric UpdateChildrenAddressType();
176205afe67SEd Maste const uint64_t max_checksum_size = 128;
17714f1b3e8SDimitry Andric m_data.Checksum(m_value_checksum, max_checksum_size);
17814f1b3e8SDimitry Andric } else {
179205afe67SEd Maste need_compare_checksums = false;
180205afe67SEd Maste m_value_checksum.clear();
181205afe67SEd Maste }
182205afe67SEd Maste
18314f1b3e8SDimitry Andric assert(!need_compare_checksums ||
18414f1b3e8SDimitry Andric (!old_checksum.empty() && !m_value_checksum.empty()));
185205afe67SEd Maste
186f034231aSEd Maste if (first_update)
187f034231aSEd Maste SetValueDidChange(false);
188344a3780SDimitry Andric else if (!m_flags.m_value_did_change && !success) {
189f73363f1SDimitry Andric // The value wasn't gotten successfully, so we mark this as changed if
190f73363f1SDimitry Andric // the value used to be valid and now isn't
191f034231aSEd Maste SetValueDidChange(value_was_valid);
19214f1b3e8SDimitry Andric } else if (need_compare_checksums) {
19314f1b3e8SDimitry Andric SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],
19414f1b3e8SDimitry Andric m_value_checksum.size()));
195205afe67SEd Maste }
196205afe67SEd Maste
19714f1b3e8SDimitry Andric } else {
198f034231aSEd Maste m_error.SetErrorString("out of scope");
199f034231aSEd Maste }
200f034231aSEd Maste }
201f034231aSEd Maste return m_error.Success();
202f034231aSEd Maste }
203f034231aSEd Maste
UpdateFormatsIfNeeded()20414f1b3e8SDimitry Andric bool ValueObject::UpdateFormatsIfNeeded() {
205145449b1SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
206ead24645SDimitry Andric LLDB_LOGF(log,
207ead24645SDimitry Andric "[%s %p] checking for FormatManager revisions. ValueObject "
20814f1b3e8SDimitry Andric "rev: %d - Global rev: %d",
2090cac4ca3SEd Maste GetName().GetCString(), static_cast<void *>(this),
210f034231aSEd Maste m_last_format_mgr_revision,
211f034231aSEd Maste DataVisualization::GetCurrentRevision());
212f034231aSEd Maste
213f034231aSEd Maste bool any_change = false;
214f034231aSEd Maste
21514f1b3e8SDimitry Andric if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {
2160cac4ca3SEd Maste m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
2170cac4ca3SEd Maste any_change = true;
2180cac4ca3SEd Maste
219ac9a064cSDimitry Andric SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));
22014f1b3e8SDimitry Andric SetSummaryFormat(
22114f1b3e8SDimitry Andric DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
22214f1b3e8SDimitry Andric SetSyntheticChildren(
22314f1b3e8SDimitry Andric DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
224f034231aSEd Maste }
225f034231aSEd Maste
226f034231aSEd Maste return any_change;
227f034231aSEd Maste }
228f034231aSEd Maste
SetNeedsUpdate()22914f1b3e8SDimitry Andric void ValueObject::SetNeedsUpdate() {
230f034231aSEd Maste m_update_point.SetNeedsUpdate();
23114f1b3e8SDimitry Andric // We have to clear the value string here so ConstResult children will notice
232f73363f1SDimitry Andric // if their values are changed by hand (i.e. with SetValueAsCString).
233f034231aSEd Maste ClearUserVisibleData(eClearUserVisibleDataItemsValue);
234f034231aSEd Maste }
235f034231aSEd Maste
ClearDynamicTypeInformation()23614f1b3e8SDimitry Andric void ValueObject::ClearDynamicTypeInformation() {
237344a3780SDimitry Andric m_flags.m_children_count_valid = false;
238344a3780SDimitry Andric m_flags.m_did_calculate_complete_objc_class_type = false;
239f034231aSEd Maste m_last_format_mgr_revision = 0;
240e81d9d49SDimitry Andric m_override_type = CompilerType();
241f034231aSEd Maste SetValueFormat(lldb::TypeFormatImplSP());
242f034231aSEd Maste SetSummaryFormat(lldb::TypeSummaryImplSP());
243f034231aSEd Maste SetSyntheticChildren(lldb::SyntheticChildrenSP());
244f034231aSEd Maste }
245f034231aSEd Maste
MaybeCalculateCompleteType()24614f1b3e8SDimitry Andric CompilerType ValueObject::MaybeCalculateCompleteType() {
247e81d9d49SDimitry Andric CompilerType compiler_type(GetCompilerTypeImpl());
248f034231aSEd Maste
249344a3780SDimitry Andric if (m_flags.m_did_calculate_complete_objc_class_type) {
250f034231aSEd Maste if (m_override_type.IsValid())
251f034231aSEd Maste return m_override_type;
252f034231aSEd Maste else
253e81d9d49SDimitry Andric return compiler_type;
254f034231aSEd Maste }
255f034231aSEd Maste
256344a3780SDimitry Andric m_flags.m_did_calculate_complete_objc_class_type = true;
257f034231aSEd Maste
25814f1b3e8SDimitry Andric ProcessSP process_sp(
25914f1b3e8SDimitry Andric GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
260f034231aSEd Maste
2615f29bb8aSDimitry Andric if (!process_sp)
2625f29bb8aSDimitry Andric return compiler_type;
263f034231aSEd Maste
2645f29bb8aSDimitry Andric if (auto *runtime =
2655f29bb8aSDimitry Andric process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {
266e3b55780SDimitry Andric if (std::optional<CompilerType> complete_type =
2675f29bb8aSDimitry Andric runtime->GetRuntimeType(compiler_type)) {
268145449b1SDimitry Andric m_override_type = *complete_type;
269f034231aSEd Maste if (m_override_type.IsValid())
270f034231aSEd Maste return m_override_type;
271f034231aSEd Maste }
272f034231aSEd Maste }
273e81d9d49SDimitry Andric return compiler_type;
274f034231aSEd Maste }
275f034231aSEd Maste
276f034231aSEd Maste
277f21a844fSEd Maste
GetDataExtractor()27814f1b3e8SDimitry Andric DataExtractor &ValueObject::GetDataExtractor() {
279f034231aSEd Maste UpdateValueIfNeeded(false);
280f034231aSEd Maste return m_data;
281f034231aSEd Maste }
282f034231aSEd Maste
GetError()283b76161e4SDimitry Andric const Status &ValueObject::GetError() {
284f034231aSEd Maste UpdateValueIfNeeded(false);
285f034231aSEd Maste return m_error;
286f034231aSEd Maste }
287f034231aSEd Maste
GetLocationAsCStringImpl(const Value & value,const DataExtractor & data)28814f1b3e8SDimitry Andric const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
28914f1b3e8SDimitry Andric const DataExtractor &data) {
29014f1b3e8SDimitry Andric if (UpdateValueIfNeeded(false)) {
29114f1b3e8SDimitry Andric if (m_location_str.empty()) {
292f034231aSEd Maste StreamString sstr;
293f034231aSEd Maste
294f034231aSEd Maste Value::ValueType value_type = value.GetValueType();
295f034231aSEd Maste
29614f1b3e8SDimitry Andric switch (value_type) {
297344a3780SDimitry Andric case Value::ValueType::Invalid:
298344a3780SDimitry Andric m_location_str = "invalid";
299344a3780SDimitry Andric break;
300344a3780SDimitry Andric case Value::ValueType::Scalar:
301344a3780SDimitry Andric if (value.GetContextType() == Value::ContextType::RegisterInfo) {
302f034231aSEd Maste RegisterInfo *reg_info = value.GetRegisterInfo();
30314f1b3e8SDimitry Andric if (reg_info) {
304f034231aSEd Maste if (reg_info->name)
305f034231aSEd Maste m_location_str = reg_info->name;
306f034231aSEd Maste else if (reg_info->alt_name)
307f034231aSEd Maste m_location_str = reg_info->alt_name;
308f034231aSEd Maste if (m_location_str.empty())
30914f1b3e8SDimitry Andric m_location_str = (reg_info->encoding == lldb::eEncodingVector)
31014f1b3e8SDimitry Andric ? "vector"
31114f1b3e8SDimitry Andric : "scalar";
312f034231aSEd Maste }
313f034231aSEd Maste }
314f034231aSEd Maste if (m_location_str.empty())
315b60736ecSDimitry Andric m_location_str = "scalar";
316f034231aSEd Maste break;
317f034231aSEd Maste
318344a3780SDimitry Andric case Value::ValueType::LoadAddress:
319344a3780SDimitry Andric case Value::ValueType::FileAddress:
320344a3780SDimitry Andric case Value::ValueType::HostAddress: {
321f034231aSEd Maste uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
32214f1b3e8SDimitry Andric sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,
32314f1b3e8SDimitry Andric value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
324cfca06d7SDimitry Andric m_location_str = std::string(sstr.GetString());
32514f1b3e8SDimitry Andric } break;
326f034231aSEd Maste }
327f034231aSEd Maste }
328f034231aSEd Maste }
329f034231aSEd Maste return m_location_str.c_str();
330f034231aSEd Maste }
331f034231aSEd Maste
ResolveValue(Scalar & scalar)33214f1b3e8SDimitry Andric bool ValueObject::ResolveValue(Scalar &scalar) {
33314f1b3e8SDimitry Andric if (UpdateValueIfNeeded(
33414f1b3e8SDimitry Andric false)) // make sure that you are up to date before returning anything
335f034231aSEd Maste {
336f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
337f034231aSEd Maste Value tmp_value(m_value);
338b1c73532SDimitry Andric scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());
33914f1b3e8SDimitry Andric if (scalar.IsValid()) {
340f034231aSEd Maste const uint32_t bitfield_bit_size = GetBitfieldBitSize();
341f034231aSEd Maste if (bitfield_bit_size)
34214f1b3e8SDimitry Andric return scalar.ExtractBitfield(bitfield_bit_size,
34314f1b3e8SDimitry Andric GetBitfieldBitOffset());
344f034231aSEd Maste return true;
345f034231aSEd Maste }
346f034231aSEd Maste }
347f034231aSEd Maste return false;
348f034231aSEd Maste }
349f034231aSEd Maste
IsLogicalTrue(Status & error)350b76161e4SDimitry Andric bool ValueObject::IsLogicalTrue(Status &error) {
35114f1b3e8SDimitry Andric if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
352e81d9d49SDimitry Andric LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
35314f1b3e8SDimitry Andric switch (is_logical_true) {
354e81d9d49SDimitry Andric case eLazyBoolYes:
355e81d9d49SDimitry Andric case eLazyBoolNo:
356e81d9d49SDimitry Andric return (is_logical_true == true);
357e81d9d49SDimitry Andric case eLazyBoolCalculate:
358e81d9d49SDimitry Andric break;
359e81d9d49SDimitry Andric }
360e81d9d49SDimitry Andric }
361e81d9d49SDimitry Andric
362e81d9d49SDimitry Andric Scalar scalar_value;
363e81d9d49SDimitry Andric
36414f1b3e8SDimitry Andric if (!ResolveValue(scalar_value)) {
365e81d9d49SDimitry Andric error.SetErrorString("failed to get a scalar result");
366e81d9d49SDimitry Andric return false;
367e81d9d49SDimitry Andric }
368e81d9d49SDimitry Andric
369e81d9d49SDimitry Andric bool ret;
37094994d37SDimitry Andric ret = scalar_value.ULongLong(1) != 0;
371e81d9d49SDimitry Andric error.Clear();
372e81d9d49SDimitry Andric return ret;
373e81d9d49SDimitry Andric }
374e81d9d49SDimitry Andric
GetChildAtIndex(uint32_t idx,bool can_create)375ac9a064cSDimitry Andric ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {
376f034231aSEd Maste ValueObjectSP child_sp;
377f034231aSEd Maste // We may need to update our value if we are dynamic
378f034231aSEd Maste if (IsPossibleDynamicType())
379f034231aSEd Maste UpdateValueIfNeeded(false);
380ac9a064cSDimitry Andric if (idx < GetNumChildrenIgnoringErrors()) {
381f034231aSEd Maste // Check if we have already made the child value object?
38214f1b3e8SDimitry Andric if (can_create && !m_children.HasChildAtIndex(idx)) {
383f034231aSEd Maste // No we haven't created the child at this index, so lets have our
384f034231aSEd Maste // subclass do it and cache the result for quick future access.
385ac9a064cSDimitry Andric m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));
386f034231aSEd Maste }
387f034231aSEd Maste
388f034231aSEd Maste ValueObject *child = m_children.GetChildAtIndex(idx);
3895f29bb8aSDimitry Andric if (child != nullptr)
390f034231aSEd Maste return child->GetSP();
391f034231aSEd Maste }
392f034231aSEd Maste return child_sp;
393f034231aSEd Maste }
394f034231aSEd Maste
395f034231aSEd Maste lldb::ValueObjectSP
GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names)3967fa27ce4SDimitry Andric ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
397f21a844fSEd Maste if (names.size() == 0)
398f21a844fSEd Maste return GetSP();
399f21a844fSEd Maste ValueObjectSP root(GetSP());
4007fa27ce4SDimitry Andric for (llvm::StringRef name : names) {
4017fa27ce4SDimitry Andric root = root->GetChildMemberWithName(name);
40214f1b3e8SDimitry Andric if (!root) {
403f21a844fSEd Maste return root;
404f21a844fSEd Maste }
405f21a844fSEd Maste }
406f21a844fSEd Maste return root;
407f21a844fSEd Maste }
408f21a844fSEd Maste
GetIndexOfChildWithName(llvm::StringRef name)4097fa27ce4SDimitry Andric size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
410f034231aSEd Maste bool omit_empty_base_classes = true;
4117fa27ce4SDimitry Andric return GetCompilerType().GetIndexOfChildWithName(name,
41214f1b3e8SDimitry Andric omit_empty_base_classes);
413f034231aSEd Maste }
414f034231aSEd Maste
GetChildMemberWithName(llvm::StringRef name,bool can_create)4157fa27ce4SDimitry Andric ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
41614f1b3e8SDimitry Andric bool can_create) {
417cfca06d7SDimitry Andric // We may need to update our value if we are dynamic.
418f034231aSEd Maste if (IsPossibleDynamicType())
419f034231aSEd Maste UpdateValueIfNeeded(false);
420f034231aSEd Maste
421cfca06d7SDimitry Andric // When getting a child by name, it could be buried inside some base classes
422cfca06d7SDimitry Andric // (which really aren't part of the expression path), so we need a vector of
423cfca06d7SDimitry Andric // indexes that can get us down to the correct child.
424f034231aSEd Maste std::vector<uint32_t> child_indexes;
425f034231aSEd Maste bool omit_empty_base_classes = true;
426706b4fc4SDimitry Andric
427706b4fc4SDimitry Andric if (!GetCompilerType().IsValid())
428706b4fc4SDimitry Andric return ValueObjectSP();
429706b4fc4SDimitry Andric
43014f1b3e8SDimitry Andric const size_t num_child_indexes =
43114f1b3e8SDimitry Andric GetCompilerType().GetIndexOfChildMemberWithName(
4327fa27ce4SDimitry Andric name, omit_empty_base_classes, child_indexes);
433cfca06d7SDimitry Andric if (num_child_indexes == 0)
434cfca06d7SDimitry Andric return nullptr;
435f034231aSEd Maste
436cfca06d7SDimitry Andric ValueObjectSP child_sp = GetSP();
437cfca06d7SDimitry Andric for (uint32_t idx : child_indexes)
438cfca06d7SDimitry Andric if (child_sp)
439cfca06d7SDimitry Andric child_sp = child_sp->GetChildAtIndex(idx, can_create);
440f034231aSEd Maste return child_sp;
441f034231aSEd Maste }
442f034231aSEd Maste
GetNumChildren(uint32_t max)443ac9a064cSDimitry Andric llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {
444f034231aSEd Maste UpdateValueIfNeeded();
445e81d9d49SDimitry Andric
44614f1b3e8SDimitry Andric if (max < UINT32_MAX) {
447344a3780SDimitry Andric if (m_flags.m_children_count_valid) {
448e81d9d49SDimitry Andric size_t children_count = m_children.GetChildrenCount();
449e81d9d49SDimitry Andric return children_count <= max ? children_count : max;
45014f1b3e8SDimitry Andric } else
451e81d9d49SDimitry Andric return CalculateNumChildren(max);
452e81d9d49SDimitry Andric }
453e81d9d49SDimitry Andric
454344a3780SDimitry Andric if (!m_flags.m_children_count_valid) {
455ac9a064cSDimitry Andric auto num_children_or_err = CalculateNumChildren();
456ac9a064cSDimitry Andric if (num_children_or_err)
457ac9a064cSDimitry Andric SetNumChildren(*num_children_or_err);
458ac9a064cSDimitry Andric else
459ac9a064cSDimitry Andric return num_children_or_err;
460f034231aSEd Maste }
461f034231aSEd Maste return m_children.GetChildrenCount();
462f034231aSEd Maste }
463f034231aSEd Maste
GetNumChildrenIgnoringErrors(uint32_t max)464ac9a064cSDimitry Andric uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {
465ac9a064cSDimitry Andric auto value_or_err = GetNumChildren(max);
466ac9a064cSDimitry Andric if (value_or_err)
467ac9a064cSDimitry Andric return *value_or_err;
468ac9a064cSDimitry Andric LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),
469ac9a064cSDimitry Andric "{0}");
470ac9a064cSDimitry Andric return 0;
471ac9a064cSDimitry Andric }
472ac9a064cSDimitry Andric
MightHaveChildren()47314f1b3e8SDimitry Andric bool ValueObject::MightHaveChildren() {
474f034231aSEd Maste bool has_children = false;
475f034231aSEd Maste const uint32_t type_info = GetTypeInfo();
47614f1b3e8SDimitry Andric if (type_info) {
47714f1b3e8SDimitry Andric if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
478f034231aSEd Maste has_children = true;
47914f1b3e8SDimitry Andric } else {
480ac9a064cSDimitry Andric has_children = GetNumChildrenIgnoringErrors() > 0;
481f034231aSEd Maste }
482f034231aSEd Maste return has_children;
483f034231aSEd Maste }
484f034231aSEd Maste
485f034231aSEd Maste // Should only be called by ValueObject::GetNumChildren()
SetNumChildren(uint32_t num_children)486ac9a064cSDimitry Andric void ValueObject::SetNumChildren(uint32_t num_children) {
487344a3780SDimitry Andric m_flags.m_children_count_valid = true;
488f034231aSEd Maste m_children.SetChildrenCount(num_children);
489f034231aSEd Maste }
490f034231aSEd Maste
CreateChildAtIndex(size_t idx)491ac9a064cSDimitry Andric ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {
492f034231aSEd Maste bool omit_empty_base_classes = true;
493ac9a064cSDimitry Andric bool ignore_array_bounds = false;
494ac9a064cSDimitry Andric std::string child_name;
495f034231aSEd Maste uint32_t child_byte_size = 0;
496f034231aSEd Maste int32_t child_byte_offset = 0;
497f034231aSEd Maste uint32_t child_bitfield_bit_size = 0;
498f034231aSEd Maste uint32_t child_bitfield_bit_offset = 0;
499f034231aSEd Maste bool child_is_base_class = false;
500f034231aSEd Maste bool child_is_deref_of_parent = false;
501e81d9d49SDimitry Andric uint64_t language_flags = 0;
502ac9a064cSDimitry Andric const bool transparent_pointers = true;
503f034231aSEd Maste
504f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
505f034231aSEd Maste
506ac9a064cSDimitry Andric auto child_compiler_type_or_err =
507ac9a064cSDimitry Andric GetCompilerType().GetChildCompilerTypeAtIndex(
50814f1b3e8SDimitry Andric &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
509ac9a064cSDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
510ac9a064cSDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset,
511ac9a064cSDimitry Andric child_is_base_class, child_is_deref_of_parent, this, language_flags);
512ac9a064cSDimitry Andric if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {
513ac9a064cSDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
514ac9a064cSDimitry Andric child_compiler_type_or_err.takeError(),
515ac9a064cSDimitry Andric "could not find child: {0}");
516ac9a064cSDimitry Andric return nullptr;
517ac9a064cSDimitry Andric }
518f034231aSEd Maste
519ac9a064cSDimitry Andric return new ValueObjectChild(
520ac9a064cSDimitry Andric *this, *child_compiler_type_or_err, ConstString(child_name),
521ac9a064cSDimitry Andric child_byte_size, child_byte_offset, child_bitfield_bit_size,
522ac9a064cSDimitry Andric child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,
523ac9a064cSDimitry Andric eAddressTypeInvalid, language_flags);
524ac9a064cSDimitry Andric }
525f034231aSEd Maste
CreateSyntheticArrayMember(size_t idx)526ac9a064cSDimitry Andric ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {
527ac9a064cSDimitry Andric bool omit_empty_base_classes = true;
528ac9a064cSDimitry Andric bool ignore_array_bounds = true;
529ac9a064cSDimitry Andric std::string child_name;
530ac9a064cSDimitry Andric uint32_t child_byte_size = 0;
531ac9a064cSDimitry Andric int32_t child_byte_offset = 0;
532ac9a064cSDimitry Andric uint32_t child_bitfield_bit_size = 0;
533ac9a064cSDimitry Andric uint32_t child_bitfield_bit_offset = 0;
534ac9a064cSDimitry Andric bool child_is_base_class = false;
535ac9a064cSDimitry Andric bool child_is_deref_of_parent = false;
536ac9a064cSDimitry Andric uint64_t language_flags = 0;
537ac9a064cSDimitry Andric const bool transparent_pointers = false;
538ac9a064cSDimitry Andric
539ac9a064cSDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
540ac9a064cSDimitry Andric
541ac9a064cSDimitry Andric auto child_compiler_type_or_err =
542ac9a064cSDimitry Andric GetCompilerType().GetChildCompilerTypeAtIndex(
543ac9a064cSDimitry Andric &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
544ac9a064cSDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
545ac9a064cSDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset,
546ac9a064cSDimitry Andric child_is_base_class, child_is_deref_of_parent, this, language_flags);
547ac9a064cSDimitry Andric if (!child_compiler_type_or_err) {
548ac9a064cSDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
549ac9a064cSDimitry Andric child_compiler_type_or_err.takeError(),
550ac9a064cSDimitry Andric "could not find child: {0}");
551ac9a064cSDimitry Andric return nullptr;
552ac9a064cSDimitry Andric }
553ac9a064cSDimitry Andric
554ac9a064cSDimitry Andric if (child_compiler_type_or_err->IsValid()) {
555ac9a064cSDimitry Andric child_byte_offset += child_byte_size * idx;
556ac9a064cSDimitry Andric
557ac9a064cSDimitry Andric return new ValueObjectChild(
558ac9a064cSDimitry Andric *this, *child_compiler_type_or_err, ConstString(child_name),
559ac9a064cSDimitry Andric child_byte_size, child_byte_offset, child_bitfield_bit_size,
560ac9a064cSDimitry Andric child_bitfield_bit_offset, child_is_base_class,
561ac9a064cSDimitry Andric child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
562f034231aSEd Maste }
563f034231aSEd Maste
564cfca06d7SDimitry Andric // In case of an incomplete type, try to use the ValueObject's
565cfca06d7SDimitry Andric // synthetic value to create the child ValueObject.
566ac9a064cSDimitry Andric if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())
567ac9a064cSDimitry Andric return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();
568cfca06d7SDimitry Andric
569ac9a064cSDimitry Andric return nullptr;
570f034231aSEd Maste }
571f034231aSEd Maste
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,lldb::LanguageType lang)57214f1b3e8SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
573e81d9d49SDimitry Andric std::string &destination,
57414f1b3e8SDimitry Andric lldb::LanguageType lang) {
57514f1b3e8SDimitry Andric return GetSummaryAsCString(summary_ptr, destination,
57614f1b3e8SDimitry Andric TypeSummaryOptions().SetLanguage(lang));
577205afe67SEd Maste }
578205afe67SEd Maste
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,const TypeSummaryOptions & options)57914f1b3e8SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
580205afe67SEd Maste std::string &destination,
58114f1b3e8SDimitry Andric const TypeSummaryOptions &options) {
582f034231aSEd Maste destination.clear();
583f034231aSEd Maste
584e3b55780SDimitry Andric // If we have a forcefully completed type, don't try and show a summary from
585e3b55780SDimitry Andric // a valid summary string or function because the type is not complete and
586e3b55780SDimitry Andric // no member variables or member functions will be available.
587e3b55780SDimitry Andric if (GetCompilerType().IsForcefullyCompleted()) {
588e3b55780SDimitry Andric destination = "<incomplete type>";
589e3b55780SDimitry Andric return true;
590e3b55780SDimitry Andric }
591e3b55780SDimitry Andric
592f73363f1SDimitry Andric // ideally we would like to bail out if passing NULL, but if we do so we end
593f73363f1SDimitry Andric // up not providing the summary for function pointers anymore
594344a3780SDimitry Andric if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
595f034231aSEd Maste return false;
596f034231aSEd Maste
597344a3780SDimitry Andric m_flags.m_is_getting_summary = true;
598f034231aSEd Maste
599e81d9d49SDimitry Andric TypeSummaryOptions actual_options(options);
600e81d9d49SDimitry Andric
601e81d9d49SDimitry Andric if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
602e81d9d49SDimitry Andric actual_options.SetLanguage(GetPreferredDisplayLanguage());
603e81d9d49SDimitry Andric
60414f1b3e8SDimitry Andric // this is a hot path in code and we prefer to avoid setting this string all
605f73363f1SDimitry Andric // too often also clearing out other information that we might care to see in
606f73363f1SDimitry Andric // a crash log. might be useful in very specific situations though.
60714f1b3e8SDimitry Andric /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
60814f1b3e8SDimitry Andric Summary provider's description is %s",
609f034231aSEd Maste GetTypeName().GetCString(),
610f034231aSEd Maste GetName().GetCString(),
611f034231aSEd Maste summary_ptr->GetDescription().c_str());*/
612f034231aSEd Maste
61314f1b3e8SDimitry Andric if (UpdateValueIfNeeded(false) && summary_ptr) {
614f034231aSEd Maste if (HasSyntheticValue())
61514f1b3e8SDimitry Andric m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
61614f1b3e8SDimitry Andric // the synthetic children being
61714f1b3e8SDimitry Andric // up-to-date (e.g. ${svar%#})
618e81d9d49SDimitry Andric summary_ptr->FormatObject(this, destination, actual_options);
619f034231aSEd Maste }
620344a3780SDimitry Andric m_flags.m_is_getting_summary = false;
621f034231aSEd Maste return !destination.empty();
622f034231aSEd Maste }
623f034231aSEd Maste
GetSummaryAsCString(lldb::LanguageType lang)62414f1b3e8SDimitry Andric const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
62514f1b3e8SDimitry Andric if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {
626e81d9d49SDimitry Andric TypeSummaryOptions summary_options;
627e81d9d49SDimitry Andric summary_options.SetLanguage(lang);
62814f1b3e8SDimitry Andric GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,
629e81d9d49SDimitry Andric summary_options);
630f034231aSEd Maste }
631f034231aSEd Maste if (m_summary_str.empty())
6325f29bb8aSDimitry Andric return nullptr;
633f034231aSEd Maste return m_summary_str.c_str();
634f034231aSEd Maste }
635f034231aSEd Maste
GetSummaryAsCString(std::string & destination,const TypeSummaryOptions & options)63614f1b3e8SDimitry Andric bool ValueObject::GetSummaryAsCString(std::string &destination,
63714f1b3e8SDimitry Andric const TypeSummaryOptions &options) {
63814f1b3e8SDimitry Andric return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);
639205afe67SEd Maste }
640205afe67SEd Maste
IsCStringContainer(bool check_pointer)64114f1b3e8SDimitry Andric bool ValueObject::IsCStringContainer(bool check_pointer) {
642e81d9d49SDimitry Andric CompilerType pointee_or_element_compiler_type;
643e81d9d49SDimitry Andric const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));
644205afe67SEd Maste bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
645e81d9d49SDimitry Andric pointee_or_element_compiler_type.IsCharType());
646f034231aSEd Maste if (!is_char_arr_ptr)
647f034231aSEd Maste return false;
648f034231aSEd Maste if (!check_pointer)
649f034231aSEd Maste return true;
650205afe67SEd Maste if (type_flags.Test(eTypeIsArray))
651f034231aSEd Maste return true;
652f034231aSEd Maste addr_t cstr_address = LLDB_INVALID_ADDRESS;
653f034231aSEd Maste AddressType cstr_address_type = eAddressTypeInvalid;
654cfca06d7SDimitry Andric cstr_address = GetPointerValue(&cstr_address_type);
655f034231aSEd Maste return (cstr_address != LLDB_INVALID_ADDRESS);
656f034231aSEd Maste }
657f034231aSEd Maste
GetPointeeData(DataExtractor & data,uint32_t item_idx,uint32_t item_count)65814f1b3e8SDimitry Andric size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
65914f1b3e8SDimitry Andric uint32_t item_count) {
660e81d9d49SDimitry Andric CompilerType pointee_or_element_compiler_type;
661e81d9d49SDimitry Andric const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);
662205afe67SEd Maste const bool is_pointer_type = type_info & eTypeIsPointer;
663205afe67SEd Maste const bool is_array_type = type_info & eTypeIsArray;
664f034231aSEd Maste if (!(is_pointer_type || is_array_type))
665f034231aSEd Maste return 0;
666f034231aSEd Maste
667f034231aSEd Maste if (item_count == 0)
668f034231aSEd Maste return 0;
669f034231aSEd Maste
67012bd4897SEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
67112bd4897SEd Maste
672e3b55780SDimitry Andric std::optional<uint64_t> item_type_size =
67394994d37SDimitry Andric pointee_or_element_compiler_type.GetByteSize(
67414f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope());
67594994d37SDimitry Andric if (!item_type_size)
67694994d37SDimitry Andric return 0;
67794994d37SDimitry Andric const uint64_t bytes = item_count * *item_type_size;
67894994d37SDimitry Andric const uint64_t offset = item_idx * *item_type_size;
679f034231aSEd Maste
680f034231aSEd Maste if (item_idx == 0 && item_count == 1) // simply a deref
681f034231aSEd Maste {
68214f1b3e8SDimitry Andric if (is_pointer_type) {
683b76161e4SDimitry Andric Status error;
684f034231aSEd Maste ValueObjectSP pointee_sp = Dereference(error);
6855f29bb8aSDimitry Andric if (error.Fail() || pointee_sp.get() == nullptr)
686f034231aSEd Maste return 0;
6870cac4ca3SEd Maste return pointee_sp->GetData(data, error);
68814f1b3e8SDimitry Andric } else {
6897fa27ce4SDimitry Andric ValueObjectSP child_sp = GetChildAtIndex(0);
6905f29bb8aSDimitry Andric if (child_sp.get() == nullptr)
691f034231aSEd Maste return 0;
692b76161e4SDimitry Andric Status error;
6930cac4ca3SEd Maste return child_sp->GetData(data, error);
694f034231aSEd Maste }
695f034231aSEd Maste return true;
69614f1b3e8SDimitry Andric } else /* (items > 1) */
697f034231aSEd Maste {
698b76161e4SDimitry Andric Status error;
6995f29bb8aSDimitry Andric lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
70014f1b3e8SDimitry Andric lldb::DataBufferSP data_sp(heap_buf_ptr =
70114f1b3e8SDimitry Andric new lldb_private::DataBufferHeap());
702f034231aSEd Maste
703f034231aSEd Maste AddressType addr_type;
70414f1b3e8SDimitry Andric lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type)
70514f1b3e8SDimitry Andric : GetAddressOf(true, &addr_type);
706f034231aSEd Maste
70714f1b3e8SDimitry Andric switch (addr_type) {
70814f1b3e8SDimitry Andric case eAddressTypeFile: {
709f034231aSEd Maste ModuleSP module_sp(GetModule());
71014f1b3e8SDimitry Andric if (module_sp) {
711f034231aSEd Maste addr = addr + offset;
712f034231aSEd Maste Address so_addr;
713f034231aSEd Maste module_sp->ResolveFileAddress(addr, so_addr);
714f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
715f034231aSEd Maste Target *target = exe_ctx.GetTargetPtr();
71614f1b3e8SDimitry Andric if (target) {
717f034231aSEd Maste heap_buf_ptr->SetByteSize(bytes);
71814f1b3e8SDimitry Andric size_t bytes_read = target->ReadMemory(
719344a3780SDimitry Andric so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
72014f1b3e8SDimitry Andric if (error.Success()) {
721f034231aSEd Maste data.SetData(data_sp);
722f034231aSEd Maste return bytes_read;
723f034231aSEd Maste }
724f034231aSEd Maste }
725f034231aSEd Maste }
72614f1b3e8SDimitry Andric } break;
72714f1b3e8SDimitry Andric case eAddressTypeLoad: {
728f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
729f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
73014f1b3e8SDimitry Andric if (process) {
731f034231aSEd Maste heap_buf_ptr->SetByteSize(bytes);
73214f1b3e8SDimitry Andric size_t bytes_read = process->ReadMemory(
73314f1b3e8SDimitry Andric addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
73414f1b3e8SDimitry Andric if (error.Success() || bytes_read > 0) {
735f034231aSEd Maste data.SetData(data_sp);
736f034231aSEd Maste return bytes_read;
737f034231aSEd Maste }
738f034231aSEd Maste }
73914f1b3e8SDimitry Andric } break;
74014f1b3e8SDimitry Andric case eAddressTypeHost: {
74194994d37SDimitry Andric auto max_bytes =
74214f1b3e8SDimitry Andric GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
74394994d37SDimitry Andric if (max_bytes && *max_bytes > offset) {
74494994d37SDimitry Andric size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
7455e95aa85SEd Maste addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
746e81d9d49SDimitry Andric if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
7475e95aa85SEd Maste break;
748f034231aSEd Maste heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);
749f034231aSEd Maste data.SetData(data_sp);
750f034231aSEd Maste return bytes_read;
751f034231aSEd Maste }
75214f1b3e8SDimitry Andric } break;
753f034231aSEd Maste case eAddressTypeInvalid:
754f034231aSEd Maste break;
755f034231aSEd Maste }
756f034231aSEd Maste }
757f034231aSEd Maste return 0;
758f034231aSEd Maste }
759f034231aSEd Maste
GetData(DataExtractor & data,Status & error)760b76161e4SDimitry Andric uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
761f034231aSEd Maste UpdateValueIfNeeded(false);
762f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
763ead24645SDimitry Andric error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
76414f1b3e8SDimitry Andric if (error.Fail()) {
76514f1b3e8SDimitry Andric if (m_data.GetByteSize()) {
766f034231aSEd Maste data = m_data;
767e81d9d49SDimitry Andric error.Clear();
768f034231aSEd Maste return data.GetByteSize();
76914f1b3e8SDimitry Andric } else {
770f034231aSEd Maste return 0;
771f034231aSEd Maste }
772f034231aSEd Maste }
773f034231aSEd Maste data.SetAddressByteSize(m_data.GetAddressByteSize());
774f034231aSEd Maste data.SetByteOrder(m_data.GetByteOrder());
775f034231aSEd Maste return data.GetByteSize();
776f034231aSEd Maste }
777f034231aSEd Maste
SetData(DataExtractor & data,Status & error)778b76161e4SDimitry Andric bool ValueObject::SetData(DataExtractor &data, Status &error) {
779f034231aSEd Maste error.Clear();
780f034231aSEd Maste // Make sure our value is up to date first so that our location and location
781f034231aSEd Maste // type is valid.
78214f1b3e8SDimitry Andric if (!UpdateValueIfNeeded(false)) {
783f034231aSEd Maste error.SetErrorString("unable to read value");
784f034231aSEd Maste return false;
785f034231aSEd Maste }
786f034231aSEd Maste
787f034231aSEd Maste uint64_t count = 0;
788e81d9d49SDimitry Andric const Encoding encoding = GetCompilerType().GetEncoding(count);
789f034231aSEd Maste
790145449b1SDimitry Andric const size_t byte_size = GetByteSize().value_or(0);
791f034231aSEd Maste
792f034231aSEd Maste Value::ValueType value_type = m_value.GetValueType();
793f034231aSEd Maste
79414f1b3e8SDimitry Andric switch (value_type) {
795344a3780SDimitry Andric case Value::ValueType::Invalid:
796344a3780SDimitry Andric error.SetErrorString("invalid location");
797344a3780SDimitry Andric return false;
798344a3780SDimitry Andric case Value::ValueType::Scalar: {
799b76161e4SDimitry Andric Status set_error =
80014f1b3e8SDimitry Andric m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
801f034231aSEd Maste
80214f1b3e8SDimitry Andric if (!set_error.Success()) {
80314f1b3e8SDimitry Andric error.SetErrorStringWithFormat("unable to set scalar value: %s",
80414f1b3e8SDimitry Andric set_error.AsCString());
805f034231aSEd Maste return false;
806f034231aSEd Maste }
80714f1b3e8SDimitry Andric } break;
808344a3780SDimitry Andric case Value::ValueType::LoadAddress: {
809f034231aSEd Maste // If it is a load address, then the scalar value is the storage location
810f034231aSEd Maste // of the data, and we have to shove this value down to that load location.
811f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
812f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
81314f1b3e8SDimitry Andric if (process) {
814f034231aSEd Maste addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
81514f1b3e8SDimitry Andric size_t bytes_written = process->WriteMemory(
81614f1b3e8SDimitry Andric target_addr, data.GetDataStart(), byte_size, error);
817f034231aSEd Maste if (!error.Success())
818f034231aSEd Maste return false;
81914f1b3e8SDimitry Andric if (bytes_written != byte_size) {
820f034231aSEd Maste error.SetErrorString("unable to write value to memory");
821f034231aSEd Maste return false;
822f034231aSEd Maste }
823f034231aSEd Maste }
82414f1b3e8SDimitry Andric } break;
825344a3780SDimitry Andric case Value::ValueType::HostAddress: {
82614f1b3e8SDimitry Andric // If it is a host address, then we stuff the scalar as a DataBuffer into
82714f1b3e8SDimitry Andric // the Value's data.
828f034231aSEd Maste DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
829f034231aSEd Maste m_data.SetData(buffer_sp, 0);
83014f1b3e8SDimitry Andric data.CopyByteOrderedData(0, byte_size,
831f034231aSEd Maste const_cast<uint8_t *>(m_data.GetDataStart()),
83214f1b3e8SDimitry Andric byte_size, m_data.GetByteOrder());
833f034231aSEd Maste m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
83414f1b3e8SDimitry Andric } break;
835344a3780SDimitry Andric case Value::ValueType::FileAddress:
836f034231aSEd Maste break;
837f034231aSEd Maste }
838f034231aSEd Maste
839f73363f1SDimitry Andric // If we have reached this point, then we have successfully changed the
840f73363f1SDimitry Andric // value.
841f034231aSEd Maste SetNeedsUpdate();
842f034231aSEd Maste return true;
843f034231aSEd Maste }
844f034231aSEd Maste
CopyStringDataToBufferSP(const StreamString & source,lldb::WritableDataBufferSP & destination)84514f1b3e8SDimitry Andric static bool CopyStringDataToBufferSP(const StreamString &source,
846145449b1SDimitry Andric lldb::WritableDataBufferSP &destination) {
847c0981da4SDimitry Andric llvm::StringRef src = source.GetString();
848145449b1SDimitry Andric src = src.rtrim('\0');
849c0981da4SDimitry Andric destination = std::make_shared<DataBufferHeap>(src.size(), 0);
850c0981da4SDimitry Andric memcpy(destination->GetBytes(), src.data(), src.size());
851205afe67SEd Maste return true;
852205afe67SEd Maste }
853205afe67SEd Maste
854e81d9d49SDimitry Andric std::pair<size_t, bool>
ReadPointedString(lldb::WritableDataBufferSP & buffer_sp,Status & error,bool honor_array)855145449b1SDimitry Andric ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
8564df029ccSDimitry Andric Status &error, bool honor_array) {
857e81d9d49SDimitry Andric bool was_capped = false;
858205afe67SEd Maste StreamString s;
859f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
860f034231aSEd Maste Target *target = exe_ctx.GetTargetPtr();
861f034231aSEd Maste
86214f1b3e8SDimitry Andric if (!target) {
863f034231aSEd Maste s << "<no target to read from>";
864f034231aSEd Maste error.SetErrorString("no target to read from");
865205afe67SEd Maste CopyStringDataToBufferSP(s, buffer_sp);
866e81d9d49SDimitry Andric return {0, was_capped};
867f034231aSEd Maste }
868f034231aSEd Maste
8694df029ccSDimitry Andric const auto max_length = target->GetMaximumSizeOfStringSummary();
870f034231aSEd Maste
871f034231aSEd Maste size_t bytes_read = 0;
872f034231aSEd Maste size_t total_bytes_read = 0;
873f034231aSEd Maste
874e81d9d49SDimitry Andric CompilerType compiler_type = GetCompilerType();
875e81d9d49SDimitry Andric CompilerType elem_or_pointee_compiler_type;
876e81d9d49SDimitry Andric const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));
877205afe67SEd Maste if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
87814f1b3e8SDimitry Andric elem_or_pointee_compiler_type.IsCharType()) {
879f034231aSEd Maste addr_t cstr_address = LLDB_INVALID_ADDRESS;
880f034231aSEd Maste AddressType cstr_address_type = eAddressTypeInvalid;
881f034231aSEd Maste
882f034231aSEd Maste size_t cstr_len = 0;
883f034231aSEd Maste bool capped_data = false;
88414f1b3e8SDimitry Andric const bool is_array = type_flags.Test(eTypeIsArray);
88514f1b3e8SDimitry Andric if (is_array) {
886f034231aSEd Maste // We have an array
887f034231aSEd Maste uint64_t array_size = 0;
888344a3780SDimitry Andric if (compiler_type.IsArrayType(nullptr, &array_size)) {
889f034231aSEd Maste cstr_len = array_size;
89014f1b3e8SDimitry Andric if (cstr_len > max_length) {
891f034231aSEd Maste capped_data = true;
892f034231aSEd Maste cstr_len = max_length;
893f034231aSEd Maste }
894f034231aSEd Maste }
895f034231aSEd Maste cstr_address = GetAddressOf(true, &cstr_address_type);
89614f1b3e8SDimitry Andric } else {
897f034231aSEd Maste // We have a pointer
898f034231aSEd Maste cstr_address = GetPointerValue(&cstr_address_type);
899f034231aSEd Maste }
900f034231aSEd Maste
90114f1b3e8SDimitry Andric if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {
90214f1b3e8SDimitry Andric if (cstr_address_type == eAddressTypeHost && is_array) {
90314f1b3e8SDimitry Andric const char *cstr = GetDataExtractor().PeekCStr(0);
90414f1b3e8SDimitry Andric if (cstr == nullptr) {
905f034231aSEd Maste s << "<invalid address>";
906f034231aSEd Maste error.SetErrorString("invalid address");
907205afe67SEd Maste CopyStringDataToBufferSP(s, buffer_sp);
908e81d9d49SDimitry Andric return {0, was_capped};
909f034231aSEd Maste }
910c0981da4SDimitry Andric s << llvm::StringRef(cstr, cstr_len);
911c0981da4SDimitry Andric CopyStringDataToBufferSP(s, buffer_sp);
91214f1b3e8SDimitry Andric return {cstr_len, was_capped};
91314f1b3e8SDimitry Andric } else {
91414f1b3e8SDimitry Andric s << "<invalid address>";
91514f1b3e8SDimitry Andric error.SetErrorString("invalid address");
91614f1b3e8SDimitry Andric CopyStringDataToBufferSP(s, buffer_sp);
91714f1b3e8SDimitry Andric return {0, was_capped};
91814f1b3e8SDimitry Andric }
91914f1b3e8SDimitry Andric }
920f034231aSEd Maste
921f034231aSEd Maste Address cstr_so_addr(cstr_address);
922f034231aSEd Maste DataExtractor data;
92314f1b3e8SDimitry Andric if (cstr_len > 0 && honor_array) {
92414f1b3e8SDimitry Andric // I am using GetPointeeData() here to abstract the fact that some
925f73363f1SDimitry Andric // ValueObjects are actually frozen pointers in the host but the pointed-
926f73363f1SDimitry Andric // to data lives in the debuggee, and GetPointeeData() automatically
927f73363f1SDimitry Andric // takes care of this
928f034231aSEd Maste GetPointeeData(data, 0, cstr_len);
929f034231aSEd Maste
93014f1b3e8SDimitry Andric if ((bytes_read = data.GetByteSize()) > 0) {
931f034231aSEd Maste total_bytes_read = bytes_read;
932205afe67SEd Maste for (size_t offset = 0; offset < bytes_read; offset++)
933205afe67SEd Maste s.Printf("%c", *data.PeekData(offset, 1));
934f034231aSEd Maste if (capped_data)
935e81d9d49SDimitry Andric was_capped = true;
936f034231aSEd Maste }
93714f1b3e8SDimitry Andric } else {
938f034231aSEd Maste cstr_len = max_length;
939f034231aSEd Maste const size_t k_max_buf_size = 64;
940f034231aSEd Maste
941f034231aSEd Maste size_t offset = 0;
942f034231aSEd Maste
943f034231aSEd Maste int cstr_len_displayed = -1;
944f034231aSEd Maste bool capped_cstr = false;
94514f1b3e8SDimitry Andric // I am using GetPointeeData() here to abstract the fact that some
946f73363f1SDimitry Andric // ValueObjects are actually frozen pointers in the host but the pointed-
947f73363f1SDimitry Andric // to data lives in the debuggee, and GetPointeeData() automatically
948f73363f1SDimitry Andric // takes care of this
94914f1b3e8SDimitry Andric while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
950f034231aSEd Maste total_bytes_read += bytes_read;
951f034231aSEd Maste const char *cstr = data.PeekCStr(0);
952e81d9d49SDimitry Andric size_t len = strnlen(cstr, k_max_buf_size);
953f034231aSEd Maste if (cstr_len_displayed < 0)
954f034231aSEd Maste cstr_len_displayed = len;
955f034231aSEd Maste
956f034231aSEd Maste if (len == 0)
957f034231aSEd Maste break;
958f034231aSEd Maste cstr_len_displayed += len;
959f034231aSEd Maste if (len > bytes_read)
960f034231aSEd Maste len = bytes_read;
961f034231aSEd Maste if (len > cstr_len)
962f034231aSEd Maste len = cstr_len;
963f034231aSEd Maste
964205afe67SEd Maste for (size_t offset = 0; offset < bytes_read; offset++)
965205afe67SEd Maste s.Printf("%c", *data.PeekData(offset, 1));
966f034231aSEd Maste
967f034231aSEd Maste if (len < k_max_buf_size)
968f034231aSEd Maste break;
969f034231aSEd Maste
97014f1b3e8SDimitry Andric if (len >= cstr_len) {
971f034231aSEd Maste capped_cstr = true;
972f034231aSEd Maste break;
973f034231aSEd Maste }
974f034231aSEd Maste
975f034231aSEd Maste cstr_len -= len;
976f034231aSEd Maste offset += len;
977f034231aSEd Maste }
978f034231aSEd Maste
97914f1b3e8SDimitry Andric if (cstr_len_displayed >= 0) {
980f034231aSEd Maste if (capped_cstr)
981e81d9d49SDimitry Andric was_capped = true;
982f034231aSEd Maste }
983f034231aSEd Maste }
98414f1b3e8SDimitry Andric } else {
985f034231aSEd Maste error.SetErrorString("not a string object");
986f034231aSEd Maste s << "<not a string object>";
987f034231aSEd Maste }
988205afe67SEd Maste CopyStringDataToBufferSP(s, buffer_sp);
989e81d9d49SDimitry Andric return {total_bytes_read, was_capped};
990f034231aSEd Maste }
991f034231aSEd Maste
GetObjectDescription()992ac9a064cSDimitry Andric llvm::Expected<std::string> ValueObject::GetObjectDescription() {
993f034231aSEd Maste if (!UpdateValueIfNeeded(true))
994ac9a064cSDimitry Andric return llvm::createStringError("could not update value");
995f034231aSEd Maste
9965f29bb8aSDimitry Andric // Return cached value.
997f034231aSEd Maste if (!m_object_desc_str.empty())
998ac9a064cSDimitry Andric return m_object_desc_str;
999f034231aSEd Maste
1000f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
1001f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
10025f29bb8aSDimitry Andric if (!process)
1003ac9a064cSDimitry Andric return llvm::createStringError("no process");
1004f034231aSEd Maste
10055f29bb8aSDimitry Andric // Returns the object description produced by one language runtime.
1006ac9a064cSDimitry Andric auto get_object_description =
1007ac9a064cSDimitry Andric [&](LanguageType language) -> llvm::Expected<std::string> {
10085f29bb8aSDimitry Andric if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
1009f034231aSEd Maste StreamString s;
1010ac9a064cSDimitry Andric if (llvm::Error error = runtime->GetObjectDescription(s, *this))
1011ac9a064cSDimitry Andric return error;
1012ac9a064cSDimitry Andric m_object_desc_str = s.GetString();
1013ac9a064cSDimitry Andric return m_object_desc_str;
1014f034231aSEd Maste }
1015ac9a064cSDimitry Andric return llvm::createStringError("no native language runtime");
10165f29bb8aSDimitry Andric };
10175f29bb8aSDimitry Andric
10185f29bb8aSDimitry Andric // Try the native language runtime first.
10195f29bb8aSDimitry Andric LanguageType native_language = GetObjectRuntimeLanguage();
1020ac9a064cSDimitry Andric llvm::Expected<std::string> desc = get_object_description(native_language);
1021ac9a064cSDimitry Andric if (desc)
10225f29bb8aSDimitry Andric return desc;
10235f29bb8aSDimitry Andric
10245f29bb8aSDimitry Andric // Try the Objective-C language runtime. This fallback is necessary
10255f29bb8aSDimitry Andric // for Objective-C++ and mixed Objective-C / C++ programs.
1026ac9a064cSDimitry Andric if (Language::LanguageIsCFamily(native_language)) {
1027ac9a064cSDimitry Andric // We're going to try again, so let's drop the first error.
1028ac9a064cSDimitry Andric llvm::consumeError(desc.takeError());
10295f29bb8aSDimitry Andric return get_object_description(eLanguageTypeObjC);
1030ac9a064cSDimitry Andric }
1031ac9a064cSDimitry Andric return desc;
10325f29bb8aSDimitry Andric }
1033f034231aSEd Maste
GetValueAsCString(const lldb_private::TypeFormatImpl & format,std::string & destination)103414f1b3e8SDimitry Andric bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
103514f1b3e8SDimitry Andric std::string &destination) {
1036866dcdacSEd Maste if (UpdateValueIfNeeded(false))
1037866dcdacSEd Maste return format.FormatObject(this, destination);
1038866dcdacSEd Maste else
1039866dcdacSEd Maste return false;
1040866dcdacSEd Maste }
1041866dcdacSEd Maste
GetValueAsCString(lldb::Format format,std::string & destination)104214f1b3e8SDimitry Andric bool ValueObject::GetValueAsCString(lldb::Format format,
104314f1b3e8SDimitry Andric std::string &destination) {
1044866dcdacSEd Maste return GetValueAsCString(TypeFormatImpl_Format(format), destination);
1045f034231aSEd Maste }
1046f034231aSEd Maste
GetValueAsCString()104714f1b3e8SDimitry Andric const char *ValueObject::GetValueAsCString() {
104814f1b3e8SDimitry Andric if (UpdateValueIfNeeded(true)) {
1049866dcdacSEd Maste lldb::TypeFormatImplSP format_sp;
1050f034231aSEd Maste lldb::Format my_format = GetFormat();
105114f1b3e8SDimitry Andric if (my_format == lldb::eFormatDefault) {
1052f034231aSEd Maste if (m_type_format_sp)
1053866dcdacSEd Maste format_sp = m_type_format_sp;
105414f1b3e8SDimitry Andric else {
1055344a3780SDimitry Andric if (m_flags.m_is_bitfield_for_scalar)
1056f034231aSEd Maste my_format = eFormatUnsigned;
105714f1b3e8SDimitry Andric else {
1058344a3780SDimitry Andric if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
1059f034231aSEd Maste const RegisterInfo *reg_info = m_value.GetRegisterInfo();
1060f034231aSEd Maste if (reg_info)
1061f034231aSEd Maste my_format = reg_info->format;
106214f1b3e8SDimitry Andric } else {
1063e81d9d49SDimitry Andric my_format = GetValue().GetCompilerType().GetFormat();
1064f034231aSEd Maste }
1065f034231aSEd Maste }
1066f034231aSEd Maste }
1067f034231aSEd Maste }
106814f1b3e8SDimitry Andric if (my_format != m_last_format || m_value_str.empty()) {
1069f034231aSEd Maste m_last_format = my_format;
1070866dcdacSEd Maste if (!format_sp)
10715f29bb8aSDimitry Andric format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
107214f1b3e8SDimitry Andric if (GetValueAsCString(*format_sp.get(), m_value_str)) {
1073344a3780SDimitry Andric if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
1074f73363f1SDimitry Andric // The value was gotten successfully, so we consider the value as
1075f73363f1SDimitry Andric // changed if the value string differs
1076f034231aSEd Maste SetValueDidChange(m_old_value_str != m_value_str);
1077f034231aSEd Maste }
1078f034231aSEd Maste }
1079f034231aSEd Maste }
1080f034231aSEd Maste }
1081f034231aSEd Maste if (m_value_str.empty())
10825f29bb8aSDimitry Andric return nullptr;
1083f034231aSEd Maste return m_value_str.c_str();
1084f034231aSEd Maste }
1085f034231aSEd Maste
1086f73363f1SDimitry Andric // if > 8bytes, 0 is returned. this method should mostly be used to read
1087f73363f1SDimitry Andric // address values out of pointers
GetValueAsUnsigned(uint64_t fail_value,bool * success)108814f1b3e8SDimitry Andric uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
1089f034231aSEd Maste // If our byte size is zero this is an aggregate type that has children
109014f1b3e8SDimitry Andric if (CanProvideValue()) {
1091f034231aSEd Maste Scalar scalar;
109214f1b3e8SDimitry Andric if (ResolveValue(scalar)) {
1093f034231aSEd Maste if (success)
1094f034231aSEd Maste *success = true;
1095cfca06d7SDimitry Andric scalar.MakeUnsigned();
1096f034231aSEd Maste return scalar.ULongLong(fail_value);
1097f034231aSEd Maste }
1098f034231aSEd Maste // fallthrough, otherwise...
1099f034231aSEd Maste }
1100f034231aSEd Maste
1101f034231aSEd Maste if (success)
1102f034231aSEd Maste *success = false;
1103f034231aSEd Maste return fail_value;
1104f034231aSEd Maste }
1105f034231aSEd Maste
GetValueAsSigned(int64_t fail_value,bool * success)110614f1b3e8SDimitry Andric int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
1107f21a844fSEd Maste // If our byte size is zero this is an aggregate type that has children
110814f1b3e8SDimitry Andric if (CanProvideValue()) {
1109f21a844fSEd Maste Scalar scalar;
111014f1b3e8SDimitry Andric if (ResolveValue(scalar)) {
1111f21a844fSEd Maste if (success)
1112f21a844fSEd Maste *success = true;
1113cfca06d7SDimitry Andric scalar.MakeSigned();
1114f21a844fSEd Maste return scalar.SLongLong(fail_value);
1115f21a844fSEd Maste }
1116f21a844fSEd Maste // fallthrough, otherwise...
1117f21a844fSEd Maste }
1118f21a844fSEd Maste
1119f21a844fSEd Maste if (success)
1120f21a844fSEd Maste *success = false;
1121f21a844fSEd Maste return fail_value;
1122f21a844fSEd Maste }
1123f21a844fSEd Maste
GetValueAsAPSInt()1124ac9a064cSDimitry Andric llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {
1125ac9a064cSDimitry Andric // Make sure the type can be converted to an APSInt.
1126ac9a064cSDimitry Andric if (!GetCompilerType().IsInteger() &&
1127ac9a064cSDimitry Andric !GetCompilerType().IsScopedEnumerationType() &&
1128ac9a064cSDimitry Andric !GetCompilerType().IsEnumerationType() &&
1129ac9a064cSDimitry Andric !GetCompilerType().IsPointerType() &&
1130ac9a064cSDimitry Andric !GetCompilerType().IsNullPtrType() &&
1131ac9a064cSDimitry Andric !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())
1132ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
1133ac9a064cSDimitry Andric "type cannot be converted to APSInt", llvm::inconvertibleErrorCode());
1134ac9a064cSDimitry Andric
1135ac9a064cSDimitry Andric if (CanProvideValue()) {
1136ac9a064cSDimitry Andric Scalar scalar;
1137ac9a064cSDimitry Andric if (ResolveValue(scalar))
1138ac9a064cSDimitry Andric return scalar.GetAPSInt();
1139ac9a064cSDimitry Andric }
1140ac9a064cSDimitry Andric
1141ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
1142ac9a064cSDimitry Andric "error occurred; unable to convert to APSInt",
1143ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
1144ac9a064cSDimitry Andric }
1145ac9a064cSDimitry Andric
GetValueAsAPFloat()1146ac9a064cSDimitry Andric llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {
1147ac9a064cSDimitry Andric if (!GetCompilerType().IsFloat())
1148ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
1149ac9a064cSDimitry Andric "type cannot be converted to APFloat", llvm::inconvertibleErrorCode());
1150ac9a064cSDimitry Andric
1151ac9a064cSDimitry Andric if (CanProvideValue()) {
1152ac9a064cSDimitry Andric Scalar scalar;
1153ac9a064cSDimitry Andric if (ResolveValue(scalar))
1154ac9a064cSDimitry Andric return scalar.GetAPFloat();
1155ac9a064cSDimitry Andric }
1156ac9a064cSDimitry Andric
1157ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
1158ac9a064cSDimitry Andric "error occurred; unable to convert to APFloat",
1159ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
1160ac9a064cSDimitry Andric }
1161ac9a064cSDimitry Andric
GetValueAsBool()1162ac9a064cSDimitry Andric llvm::Expected<bool> ValueObject::GetValueAsBool() {
1163ac9a064cSDimitry Andric CompilerType val_type = GetCompilerType();
1164ac9a064cSDimitry Andric if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
1165ac9a064cSDimitry Andric val_type.IsPointerType()) {
1166ac9a064cSDimitry Andric auto value_or_err = GetValueAsAPSInt();
1167ac9a064cSDimitry Andric if (value_or_err)
1168ac9a064cSDimitry Andric return value_or_err->getBoolValue();
1169ac9a064cSDimitry Andric }
1170ac9a064cSDimitry Andric if (val_type.IsFloat()) {
1171ac9a064cSDimitry Andric auto value_or_err = GetValueAsAPFloat();
1172ac9a064cSDimitry Andric if (value_or_err)
1173ac9a064cSDimitry Andric return value_or_err->isNonZero();
1174ac9a064cSDimitry Andric }
1175ac9a064cSDimitry Andric if (val_type.IsArrayType())
1176ac9a064cSDimitry Andric return GetAddressOf() != 0;
1177ac9a064cSDimitry Andric
1178ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>("type cannot be converted to bool",
1179ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
1180ac9a064cSDimitry Andric }
1181ac9a064cSDimitry Andric
SetValueFromInteger(const llvm::APInt & value,Status & error)1182ac9a064cSDimitry Andric void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
1183ac9a064cSDimitry Andric // Verify the current object is an integer object
1184ac9a064cSDimitry Andric CompilerType val_type = GetCompilerType();
1185ac9a064cSDimitry Andric if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
1186ac9a064cSDimitry Andric !val_type.IsFloat() && !val_type.IsPointerType() &&
1187ac9a064cSDimitry Andric !val_type.IsScalarType()) {
1188ac9a064cSDimitry Andric error.SetErrorString("current value object is not an integer objet");
1189ac9a064cSDimitry Andric return;
1190ac9a064cSDimitry Andric }
1191ac9a064cSDimitry Andric
1192ac9a064cSDimitry Andric // Verify the current object is not actually associated with any program
1193ac9a064cSDimitry Andric // variable.
1194ac9a064cSDimitry Andric if (GetVariable()) {
1195ac9a064cSDimitry Andric error.SetErrorString("current value object is not a temporary object");
1196ac9a064cSDimitry Andric return;
1197ac9a064cSDimitry Andric }
1198ac9a064cSDimitry Andric
1199ac9a064cSDimitry Andric // Verify the proposed new value is the right size.
1200ac9a064cSDimitry Andric lldb::TargetSP target = GetTargetSP();
1201ac9a064cSDimitry Andric uint64_t byte_size = 0;
1202ac9a064cSDimitry Andric if (auto temp = GetCompilerType().GetByteSize(target.get()))
1203ac9a064cSDimitry Andric byte_size = temp.value();
1204ac9a064cSDimitry Andric if (value.getBitWidth() != byte_size * CHAR_BIT) {
1205ac9a064cSDimitry Andric error.SetErrorString(
1206ac9a064cSDimitry Andric "illegal argument: new value should be of the same size");
1207ac9a064cSDimitry Andric return;
1208ac9a064cSDimitry Andric }
1209ac9a064cSDimitry Andric
1210ac9a064cSDimitry Andric lldb::DataExtractorSP data_sp;
1211ac9a064cSDimitry Andric data_sp->SetData(value.getRawData(), byte_size,
1212ac9a064cSDimitry Andric target->GetArchitecture().GetByteOrder());
1213ac9a064cSDimitry Andric data_sp->SetAddressByteSize(
1214ac9a064cSDimitry Andric static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));
1215ac9a064cSDimitry Andric SetData(*data_sp, error);
1216ac9a064cSDimitry Andric }
1217ac9a064cSDimitry Andric
SetValueFromInteger(lldb::ValueObjectSP new_val_sp,Status & error)1218ac9a064cSDimitry Andric void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
1219ac9a064cSDimitry Andric Status &error) {
1220ac9a064cSDimitry Andric // Verify the current object is an integer object
1221ac9a064cSDimitry Andric CompilerType val_type = GetCompilerType();
1222ac9a064cSDimitry Andric if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
1223ac9a064cSDimitry Andric !val_type.IsFloat() && !val_type.IsPointerType() &&
1224ac9a064cSDimitry Andric !val_type.IsScalarType()) {
1225ac9a064cSDimitry Andric error.SetErrorString("current value object is not an integer objet");
1226ac9a064cSDimitry Andric return;
1227ac9a064cSDimitry Andric }
1228ac9a064cSDimitry Andric
1229ac9a064cSDimitry Andric // Verify the current object is not actually associated with any program
1230ac9a064cSDimitry Andric // variable.
1231ac9a064cSDimitry Andric if (GetVariable()) {
1232ac9a064cSDimitry Andric error.SetErrorString("current value object is not a temporary object");
1233ac9a064cSDimitry Andric return;
1234ac9a064cSDimitry Andric }
1235ac9a064cSDimitry Andric
1236ac9a064cSDimitry Andric // Verify the proposed new value is the right type.
1237ac9a064cSDimitry Andric CompilerType new_val_type = new_val_sp->GetCompilerType();
1238ac9a064cSDimitry Andric if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&
1239ac9a064cSDimitry Andric !new_val_type.IsPointerType()) {
1240ac9a064cSDimitry Andric error.SetErrorString(
1241ac9a064cSDimitry Andric "illegal argument: new value should be of the same size");
1242ac9a064cSDimitry Andric return;
1243ac9a064cSDimitry Andric }
1244ac9a064cSDimitry Andric
1245ac9a064cSDimitry Andric if (new_val_type.IsInteger()) {
1246ac9a064cSDimitry Andric auto value_or_err = new_val_sp->GetValueAsAPSInt();
1247ac9a064cSDimitry Andric if (value_or_err)
1248ac9a064cSDimitry Andric SetValueFromInteger(*value_or_err, error);
1249ac9a064cSDimitry Andric else
1250ac9a064cSDimitry Andric error.SetErrorString("error getting APSInt from new_val_sp");
1251ac9a064cSDimitry Andric } else if (new_val_type.IsFloat()) {
1252ac9a064cSDimitry Andric auto value_or_err = new_val_sp->GetValueAsAPFloat();
1253ac9a064cSDimitry Andric if (value_or_err)
1254ac9a064cSDimitry Andric SetValueFromInteger(value_or_err->bitcastToAPInt(), error);
1255ac9a064cSDimitry Andric else
1256ac9a064cSDimitry Andric error.SetErrorString("error getting APFloat from new_val_sp");
1257ac9a064cSDimitry Andric } else if (new_val_type.IsPointerType()) {
1258ac9a064cSDimitry Andric bool success = true;
1259ac9a064cSDimitry Andric uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);
1260ac9a064cSDimitry Andric if (success) {
1261ac9a064cSDimitry Andric lldb::TargetSP target = GetTargetSP();
1262ac9a064cSDimitry Andric uint64_t num_bits = 0;
1263ac9a064cSDimitry Andric if (auto temp = new_val_sp->GetCompilerType().GetBitSize(target.get()))
1264ac9a064cSDimitry Andric num_bits = temp.value();
1265ac9a064cSDimitry Andric SetValueFromInteger(llvm::APInt(num_bits, int_val), error);
1266ac9a064cSDimitry Andric } else
1267ac9a064cSDimitry Andric error.SetErrorString("error converting new_val_sp to integer");
1268ac9a064cSDimitry Andric }
1269ac9a064cSDimitry Andric }
1270ac9a064cSDimitry Andric
127114f1b3e8SDimitry Andric // if any more "special cases" are added to
1272f73363f1SDimitry Andric // ValueObject::DumpPrintableRepresentation() please keep this call up to date
1273f73363f1SDimitry Andric // by returning true for your new special cases. We will eventually move to
1274f73363f1SDimitry Andric // checking this call result before trying to display special cases
HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,Format custom_format)127514f1b3e8SDimitry Andric bool ValueObject::HasSpecialPrintableRepresentation(
127614f1b3e8SDimitry Andric ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
1277f034231aSEd Maste Flags flags(GetTypeInfo());
127814f1b3e8SDimitry Andric if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
127914f1b3e8SDimitry Andric val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
1280f034231aSEd Maste if (IsCStringContainer(true) &&
128114f1b3e8SDimitry Andric (custom_format == eFormatCString || custom_format == eFormatCharArray ||
128214f1b3e8SDimitry Andric custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
1283f034231aSEd Maste return true;
1284f034231aSEd Maste
128514f1b3e8SDimitry Andric if (flags.Test(eTypeIsArray)) {
1286f034231aSEd Maste if ((custom_format == eFormatBytes) ||
1287f034231aSEd Maste (custom_format == eFormatBytesWithASCII))
1288f034231aSEd Maste return true;
1289f034231aSEd Maste
1290f034231aSEd Maste if ((custom_format == eFormatVectorOfChar) ||
1291f034231aSEd Maste (custom_format == eFormatVectorOfFloat32) ||
1292f034231aSEd Maste (custom_format == eFormatVectorOfFloat64) ||
1293f034231aSEd Maste (custom_format == eFormatVectorOfSInt16) ||
1294f034231aSEd Maste (custom_format == eFormatVectorOfSInt32) ||
1295f034231aSEd Maste (custom_format == eFormatVectorOfSInt64) ||
1296f034231aSEd Maste (custom_format == eFormatVectorOfSInt8) ||
1297f034231aSEd Maste (custom_format == eFormatVectorOfUInt128) ||
1298f034231aSEd Maste (custom_format == eFormatVectorOfUInt16) ||
1299f034231aSEd Maste (custom_format == eFormatVectorOfUInt32) ||
1300f034231aSEd Maste (custom_format == eFormatVectorOfUInt64) ||
1301f034231aSEd Maste (custom_format == eFormatVectorOfUInt8))
1302f034231aSEd Maste return true;
1303f034231aSEd Maste }
1304f034231aSEd Maste }
1305f034231aSEd Maste return false;
1306f034231aSEd Maste }
1307f034231aSEd Maste
DumpPrintableRepresentation(Stream & s,ValueObjectRepresentationStyle val_obj_display,Format custom_format,PrintableRepresentationSpecialCases special,bool do_dump_error)130814f1b3e8SDimitry Andric bool ValueObject::DumpPrintableRepresentation(
130914f1b3e8SDimitry Andric Stream &s, ValueObjectRepresentationStyle val_obj_display,
131014f1b3e8SDimitry Andric Format custom_format, PrintableRepresentationSpecialCases special,
131114f1b3e8SDimitry Andric bool do_dump_error) {
1312f034231aSEd Maste
13137fa27ce4SDimitry Andric // If the ValueObject has an error, we might end up dumping the type, which
13147fa27ce4SDimitry Andric // is useful, but if we don't even have a type, then don't examine the object
13157fa27ce4SDimitry Andric // further as that's not meaningful, only the error is.
13167fa27ce4SDimitry Andric if (m_error.Fail() && !GetCompilerType().IsValid()) {
13177fa27ce4SDimitry Andric if (do_dump_error)
13187fa27ce4SDimitry Andric s.Printf("<%s>", m_error.AsCString());
13197fa27ce4SDimitry Andric return false;
13207fa27ce4SDimitry Andric }
13217fa27ce4SDimitry Andric
1322f034231aSEd Maste Flags flags(GetTypeInfo());
1323f034231aSEd Maste
132414f1b3e8SDimitry Andric bool allow_special =
132514f1b3e8SDimitry Andric (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
132614f1b3e8SDimitry Andric const bool only_special = false;
1327f034231aSEd Maste
132814f1b3e8SDimitry Andric if (allow_special) {
132914f1b3e8SDimitry Andric if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
133014f1b3e8SDimitry Andric val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
133114f1b3e8SDimitry Andric // when being asked to get a printable display an array or pointer type
1332f73363f1SDimitry Andric // directly, try to "do the right thing"
1333f034231aSEd Maste
1334f034231aSEd Maste if (IsCStringContainer(true) &&
1335f034231aSEd Maste (custom_format == eFormatCString ||
133614f1b3e8SDimitry Andric custom_format == eFormatCharArray || custom_format == eFormatChar ||
133714f1b3e8SDimitry Andric custom_format ==
133814f1b3e8SDimitry Andric eFormatVectorOfChar)) // print char[] & char* directly
1339f034231aSEd Maste {
1340b76161e4SDimitry Andric Status error;
1341145449b1SDimitry Andric lldb::WritableDataBufferSP buffer_sp;
13424df029ccSDimitry Andric std::pair<size_t, bool> read_string =
13434df029ccSDimitry Andric ReadPointedString(buffer_sp, error,
13444df029ccSDimitry Andric (custom_format == eFormatVectorOfChar) ||
1345f034231aSEd Maste (custom_format == eFormatCharArray));
134614f1b3e8SDimitry Andric lldb_private::formatters::StringPrinter::
134714f1b3e8SDimitry Andric ReadBufferAndDumpToStreamOptions options(*this);
134814f1b3e8SDimitry Andric options.SetData(DataExtractor(
134914f1b3e8SDimitry Andric buffer_sp, lldb::eByteOrderInvalid,
135014f1b3e8SDimitry Andric 8)); // none of this matters for a string - pass some defaults
1351205afe67SEd Maste options.SetStream(&s);
13525f29bb8aSDimitry Andric options.SetPrefixToken(nullptr);
1353205afe67SEd Maste options.SetQuote('"');
1354205afe67SEd Maste options.SetSourceSize(buffer_sp->GetByteSize());
1355e81d9d49SDimitry Andric options.SetIsTruncated(read_string.second);
1356c0981da4SDimitry Andric options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
135714f1b3e8SDimitry Andric formatters::StringPrinter::ReadBufferAndDumpToStream<
135814f1b3e8SDimitry Andric lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
135914f1b3e8SDimitry Andric options);
1360f034231aSEd Maste return !error.Fail();
1361f034231aSEd Maste }
1362f034231aSEd Maste
1363f034231aSEd Maste if (custom_format == eFormatEnum)
1364f034231aSEd Maste return false;
1365f034231aSEd Maste
1366f73363f1SDimitry Andric // this only works for arrays, because I have no way to know when the
1367f73363f1SDimitry Andric // pointed memory ends, and no special \0 end of data marker
136814f1b3e8SDimitry Andric if (flags.Test(eTypeIsArray)) {
1369f034231aSEd Maste if ((custom_format == eFormatBytes) ||
137014f1b3e8SDimitry Andric (custom_format == eFormatBytesWithASCII)) {
1371ac9a064cSDimitry Andric const size_t count = GetNumChildrenIgnoringErrors();
1372f034231aSEd Maste
1373f034231aSEd Maste s << '[';
137414f1b3e8SDimitry Andric for (size_t low = 0; low < count; low++) {
1375f034231aSEd Maste
1376f034231aSEd Maste if (low)
1377f034231aSEd Maste s << ',';
1378f034231aSEd Maste
13797fa27ce4SDimitry Andric ValueObjectSP child = GetChildAtIndex(low);
138014f1b3e8SDimitry Andric if (!child.get()) {
1381f034231aSEd Maste s << "<invalid child>";
1382f034231aSEd Maste continue;
1383f034231aSEd Maste }
138414f1b3e8SDimitry Andric child->DumpPrintableRepresentation(
138514f1b3e8SDimitry Andric s, ValueObject::eValueObjectRepresentationStyleValue,
138614f1b3e8SDimitry Andric custom_format);
1387f034231aSEd Maste }
1388f034231aSEd Maste
1389f034231aSEd Maste s << ']';
1390f034231aSEd Maste
1391f034231aSEd Maste return true;
1392f034231aSEd Maste }
1393f034231aSEd Maste
1394f034231aSEd Maste if ((custom_format == eFormatVectorOfChar) ||
1395f034231aSEd Maste (custom_format == eFormatVectorOfFloat32) ||
1396f034231aSEd Maste (custom_format == eFormatVectorOfFloat64) ||
1397f034231aSEd Maste (custom_format == eFormatVectorOfSInt16) ||
1398f034231aSEd Maste (custom_format == eFormatVectorOfSInt32) ||
1399f034231aSEd Maste (custom_format == eFormatVectorOfSInt64) ||
1400f034231aSEd Maste (custom_format == eFormatVectorOfSInt8) ||
1401f034231aSEd Maste (custom_format == eFormatVectorOfUInt128) ||
1402f034231aSEd Maste (custom_format == eFormatVectorOfUInt16) ||
1403f034231aSEd Maste (custom_format == eFormatVectorOfUInt32) ||
1404f034231aSEd Maste (custom_format == eFormatVectorOfUInt64) ||
140514f1b3e8SDimitry Andric (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
140614f1b3e8SDimitry Andric // with ASCII or any vector
140714f1b3e8SDimitry Andric // format should be printed
140814f1b3e8SDimitry Andric // directly
1409f034231aSEd Maste {
1410ac9a064cSDimitry Andric const size_t count = GetNumChildrenIgnoringErrors();
1411f034231aSEd Maste
1412f034231aSEd Maste Format format = FormatManager::GetSingleItemFormat(custom_format);
1413f034231aSEd Maste
1414f034231aSEd Maste s << '[';
141514f1b3e8SDimitry Andric for (size_t low = 0; low < count; low++) {
1416f034231aSEd Maste
1417f034231aSEd Maste if (low)
1418f034231aSEd Maste s << ',';
1419f034231aSEd Maste
14207fa27ce4SDimitry Andric ValueObjectSP child = GetChildAtIndex(low);
142114f1b3e8SDimitry Andric if (!child.get()) {
1422f034231aSEd Maste s << "<invalid child>";
1423f034231aSEd Maste continue;
1424f034231aSEd Maste }
142514f1b3e8SDimitry Andric child->DumpPrintableRepresentation(
142614f1b3e8SDimitry Andric s, ValueObject::eValueObjectRepresentationStyleValue, format);
1427f034231aSEd Maste }
1428f034231aSEd Maste
1429f034231aSEd Maste s << ']';
1430f034231aSEd Maste
1431f034231aSEd Maste return true;
1432f034231aSEd Maste }
1433f034231aSEd Maste }
1434f034231aSEd Maste
1435f034231aSEd Maste if ((custom_format == eFormatBoolean) ||
143614f1b3e8SDimitry Andric (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
1437f034231aSEd Maste (custom_format == eFormatCharPrintable) ||
1438f034231aSEd Maste (custom_format == eFormatComplexFloat) ||
143914f1b3e8SDimitry Andric (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
1440f034231aSEd Maste (custom_format == eFormatHexUppercase) ||
144114f1b3e8SDimitry Andric (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
1442f034231aSEd Maste (custom_format == eFormatOSType) ||
1443f034231aSEd Maste (custom_format == eFormatUnicode16) ||
1444f034231aSEd Maste (custom_format == eFormatUnicode32) ||
1445f034231aSEd Maste (custom_format == eFormatUnsigned) ||
1446f034231aSEd Maste (custom_format == eFormatPointer) ||
1447f034231aSEd Maste (custom_format == eFormatComplexInteger) ||
1448f034231aSEd Maste (custom_format == eFormatComplex) ||
1449f034231aSEd Maste (custom_format == eFormatDefault)) // use the [] operator
1450f034231aSEd Maste return false;
1451f034231aSEd Maste }
1452f034231aSEd Maste }
1453f034231aSEd Maste
1454f034231aSEd Maste if (only_special)
1455f034231aSEd Maste return false;
1456f034231aSEd Maste
1457f034231aSEd Maste bool var_success = false;
1458f034231aSEd Maste
1459f034231aSEd Maste {
146014f1b3e8SDimitry Andric llvm::StringRef str;
1461f034231aSEd Maste
146214f1b3e8SDimitry Andric // this is a local stream that we are using to ensure that the data pointed
1463f73363f1SDimitry Andric // to by cstr survives long enough for us to copy it to its destination -
1464f73363f1SDimitry Andric // it is necessary to have this temporary storage area for cases where our
146514f1b3e8SDimitry Andric // desired output is not backed by some other longer-term storage
1466f034231aSEd Maste StreamString strm;
1467f034231aSEd Maste
1468f034231aSEd Maste if (custom_format != eFormatInvalid)
1469f034231aSEd Maste SetFormat(custom_format);
1470f034231aSEd Maste
147114f1b3e8SDimitry Andric switch (val_obj_display) {
1472f034231aSEd Maste case eValueObjectRepresentationStyleValue:
147314f1b3e8SDimitry Andric str = GetValueAsCString();
1474f034231aSEd Maste break;
1475f034231aSEd Maste
1476f034231aSEd Maste case eValueObjectRepresentationStyleSummary:
147714f1b3e8SDimitry Andric str = GetSummaryAsCString();
1478f034231aSEd Maste break;
1479f034231aSEd Maste
1480ac9a064cSDimitry Andric case eValueObjectRepresentationStyleLanguageSpecific: {
1481ac9a064cSDimitry Andric llvm::Expected<std::string> desc = GetObjectDescription();
1482ac9a064cSDimitry Andric if (!desc) {
1483ac9a064cSDimitry Andric strm << "error: " << toString(desc.takeError());
1484ac9a064cSDimitry Andric str = strm.GetString();
1485ac9a064cSDimitry Andric } else {
1486ac9a064cSDimitry Andric strm << *desc;
1487ac9a064cSDimitry Andric str = strm.GetString();
1488ac9a064cSDimitry Andric }
1489ac9a064cSDimitry Andric } break;
1490f034231aSEd Maste
1491f034231aSEd Maste case eValueObjectRepresentationStyleLocation:
149214f1b3e8SDimitry Andric str = GetLocationAsCString();
1493f034231aSEd Maste break;
1494f034231aSEd Maste
1495f034231aSEd Maste case eValueObjectRepresentationStyleChildrenCount:
1496ac9a064cSDimitry Andric strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());
149714f1b3e8SDimitry Andric str = strm.GetString();
1498f034231aSEd Maste break;
1499f034231aSEd Maste
1500f034231aSEd Maste case eValueObjectRepresentationStyleType:
150114f1b3e8SDimitry Andric str = GetTypeName().GetStringRef();
1502f034231aSEd Maste break;
1503f034231aSEd Maste
1504f034231aSEd Maste case eValueObjectRepresentationStyleName:
150514f1b3e8SDimitry Andric str = GetName().GetStringRef();
1506f034231aSEd Maste break;
1507f034231aSEd Maste
1508f034231aSEd Maste case eValueObjectRepresentationStyleExpressionPath:
1509cfca06d7SDimitry Andric GetExpressionPath(strm);
151014f1b3e8SDimitry Andric str = strm.GetString();
1511f034231aSEd Maste break;
1512f034231aSEd Maste }
1513f034231aSEd Maste
1514ac9a064cSDimitry Andric // If the requested display style produced no output, try falling back to
1515ac9a064cSDimitry Andric // alternative presentations.
151614f1b3e8SDimitry Andric if (str.empty()) {
1517f034231aSEd Maste if (val_obj_display == eValueObjectRepresentationStyleValue)
151814f1b3e8SDimitry Andric str = GetSummaryAsCString();
151914f1b3e8SDimitry Andric else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
152014f1b3e8SDimitry Andric if (!CanProvideValue()) {
152114f1b3e8SDimitry Andric strm.Printf("%s @ %s", GetTypeName().AsCString(),
152214f1b3e8SDimitry Andric GetLocationAsCString());
152314f1b3e8SDimitry Andric str = strm.GetString();
152414f1b3e8SDimitry Andric } else
152514f1b3e8SDimitry Andric str = GetValueAsCString();
1526f034231aSEd Maste }
1527f034231aSEd Maste }
1528f034231aSEd Maste
152914f1b3e8SDimitry Andric if (!str.empty())
153014f1b3e8SDimitry Andric s << str;
153114f1b3e8SDimitry Andric else {
15327fa27ce4SDimitry Andric // We checked for errors at the start, but do it again here in case
15337fa27ce4SDimitry Andric // realizing the value for dumping produced an error.
153414f1b3e8SDimitry Andric if (m_error.Fail()) {
1535866dcdacSEd Maste if (do_dump_error)
1536f034231aSEd Maste s.Printf("<%s>", m_error.AsCString());
1537866dcdacSEd Maste else
1538866dcdacSEd Maste return false;
153914f1b3e8SDimitry Andric } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
1540f034231aSEd Maste s.PutCString("<no summary available>");
1541f034231aSEd Maste else if (val_obj_display == eValueObjectRepresentationStyleValue)
1542f034231aSEd Maste s.PutCString("<no value available>");
154314f1b3e8SDimitry Andric else if (val_obj_display ==
154414f1b3e8SDimitry Andric eValueObjectRepresentationStyleLanguageSpecific)
154514f1b3e8SDimitry Andric s.PutCString("<not a valid Objective-C object>"); // edit this if we
154614f1b3e8SDimitry Andric // have other runtimes
154714f1b3e8SDimitry Andric // that support a
154814f1b3e8SDimitry Andric // description
1549f034231aSEd Maste else
1550f034231aSEd Maste s.PutCString("<no printable representation>");
1551f034231aSEd Maste }
1552f034231aSEd Maste
1553f73363f1SDimitry Andric // we should only return false here if we could not do *anything* even if
1554f73363f1SDimitry Andric // we have an error message as output, that's a success from our callers'
1555f73363f1SDimitry Andric // perspective, so return true
1556f034231aSEd Maste var_success = true;
1557f034231aSEd Maste
1558f034231aSEd Maste if (custom_format != eFormatInvalid)
1559f034231aSEd Maste SetFormat(eFormatDefault);
1560f034231aSEd Maste }
1561f034231aSEd Maste
1562f034231aSEd Maste return var_success;
1563f034231aSEd Maste }
1564f034231aSEd Maste
GetAddressOf(bool scalar_is_load_address,AddressType * address_type)156514f1b3e8SDimitry Andric addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
156614f1b3e8SDimitry Andric AddressType *address_type) {
1567f3fbd1c0SDimitry Andric // Can't take address of a bitfield
1568f3fbd1c0SDimitry Andric if (IsBitfield())
1569f3fbd1c0SDimitry Andric return LLDB_INVALID_ADDRESS;
1570f3fbd1c0SDimitry Andric
1571f034231aSEd Maste if (!UpdateValueIfNeeded(false))
1572f034231aSEd Maste return LLDB_INVALID_ADDRESS;
1573f034231aSEd Maste
157414f1b3e8SDimitry Andric switch (m_value.GetValueType()) {
1575344a3780SDimitry Andric case Value::ValueType::Invalid:
1576344a3780SDimitry Andric return LLDB_INVALID_ADDRESS;
1577344a3780SDimitry Andric case Value::ValueType::Scalar:
157814f1b3e8SDimitry Andric if (scalar_is_load_address) {
1579f034231aSEd Maste if (address_type)
1580f034231aSEd Maste *address_type = eAddressTypeLoad;
1581f034231aSEd Maste return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1582f034231aSEd Maste }
1583f034231aSEd Maste break;
1584f034231aSEd Maste
1585344a3780SDimitry Andric case Value::ValueType::LoadAddress:
1586344a3780SDimitry Andric case Value::ValueType::FileAddress: {
1587f034231aSEd Maste if (address_type)
1588f034231aSEd Maste *address_type = m_value.GetValueAddressType();
1589f034231aSEd Maste return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
159014f1b3e8SDimitry Andric } break;
1591344a3780SDimitry Andric case Value::ValueType::HostAddress: {
15925e95aa85SEd Maste if (address_type)
15935e95aa85SEd Maste *address_type = m_value.GetValueAddressType();
15945e95aa85SEd Maste return LLDB_INVALID_ADDRESS;
159514f1b3e8SDimitry Andric } break;
1596f034231aSEd Maste }
1597f034231aSEd Maste if (address_type)
1598f034231aSEd Maste *address_type = eAddressTypeInvalid;
1599f034231aSEd Maste return LLDB_INVALID_ADDRESS;
1600f034231aSEd Maste }
1601f034231aSEd Maste
GetPointerValue(AddressType * address_type)160214f1b3e8SDimitry Andric addr_t ValueObject::GetPointerValue(AddressType *address_type) {
1603f034231aSEd Maste addr_t address = LLDB_INVALID_ADDRESS;
1604f034231aSEd Maste if (address_type)
1605f034231aSEd Maste *address_type = eAddressTypeInvalid;
1606f034231aSEd Maste
1607f034231aSEd Maste if (!UpdateValueIfNeeded(false))
1608f034231aSEd Maste return address;
1609f034231aSEd Maste
161014f1b3e8SDimitry Andric switch (m_value.GetValueType()) {
1611344a3780SDimitry Andric case Value::ValueType::Invalid:
1612344a3780SDimitry Andric return LLDB_INVALID_ADDRESS;
1613344a3780SDimitry Andric case Value::ValueType::Scalar:
1614f034231aSEd Maste address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1615f034231aSEd Maste break;
1616f034231aSEd Maste
1617344a3780SDimitry Andric case Value::ValueType::HostAddress:
1618344a3780SDimitry Andric case Value::ValueType::LoadAddress:
1619344a3780SDimitry Andric case Value::ValueType::FileAddress: {
1620f034231aSEd Maste lldb::offset_t data_offset = 0;
1621cfca06d7SDimitry Andric address = m_data.GetAddress(&data_offset);
162214f1b3e8SDimitry Andric } break;
1623f034231aSEd Maste }
1624f034231aSEd Maste
1625f034231aSEd Maste if (address_type)
1626f034231aSEd Maste *address_type = GetAddressTypeOfChildren();
1627f034231aSEd Maste
1628f034231aSEd Maste return address;
1629f034231aSEd Maste }
1630f034231aSEd Maste
SetValueFromCString(const char * value_str,Status & error)1631b76161e4SDimitry Andric bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
1632f034231aSEd Maste error.Clear();
1633f034231aSEd Maste // Make sure our value is up to date first so that our location and location
1634f034231aSEd Maste // type is valid.
163514f1b3e8SDimitry Andric if (!UpdateValueIfNeeded(false)) {
1636f034231aSEd Maste error.SetErrorString("unable to read value");
1637f034231aSEd Maste return false;
1638f034231aSEd Maste }
1639f034231aSEd Maste
1640f034231aSEd Maste uint64_t count = 0;
1641e81d9d49SDimitry Andric const Encoding encoding = GetCompilerType().GetEncoding(count);
1642f034231aSEd Maste
1643145449b1SDimitry Andric const size_t byte_size = GetByteSize().value_or(0);
1644f034231aSEd Maste
1645f034231aSEd Maste Value::ValueType value_type = m_value.GetValueType();
1646f034231aSEd Maste
1647344a3780SDimitry Andric if (value_type == Value::ValueType::Scalar) {
1648f034231aSEd Maste // If the value is already a scalar, then let the scalar change itself:
1649f034231aSEd Maste m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
165014f1b3e8SDimitry Andric } else if (byte_size <= 16) {
1651f034231aSEd Maste // If the value fits in a scalar, then make a new scalar and again let the
165214f1b3e8SDimitry Andric // scalar code do the conversion, then figure out where to put the new
165314f1b3e8SDimitry Andric // value.
1654f034231aSEd Maste Scalar new_scalar;
1655f034231aSEd Maste error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
165614f1b3e8SDimitry Andric if (error.Success()) {
165714f1b3e8SDimitry Andric switch (value_type) {
1658344a3780SDimitry Andric case Value::ValueType::LoadAddress: {
165914f1b3e8SDimitry Andric // If it is a load address, then the scalar value is the storage
1660f73363f1SDimitry Andric // location of the data, and we have to shove this value down to that
1661f73363f1SDimitry Andric // load location.
1662f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
1663f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
166414f1b3e8SDimitry Andric if (process) {
166514f1b3e8SDimitry Andric addr_t target_addr =
166614f1b3e8SDimitry Andric m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
166714f1b3e8SDimitry Andric size_t bytes_written = process->WriteScalarToMemory(
166814f1b3e8SDimitry Andric target_addr, new_scalar, byte_size, error);
1669f034231aSEd Maste if (!error.Success())
1670f034231aSEd Maste return false;
167114f1b3e8SDimitry Andric if (bytes_written != byte_size) {
1672f034231aSEd Maste error.SetErrorString("unable to write value to memory");
1673f034231aSEd Maste return false;
1674f034231aSEd Maste }
1675f034231aSEd Maste }
167614f1b3e8SDimitry Andric } break;
1677344a3780SDimitry Andric case Value::ValueType::HostAddress: {
167814f1b3e8SDimitry Andric // If it is a host address, then we stuff the scalar as a DataBuffer
167914f1b3e8SDimitry Andric // into the Value's data.
1680f034231aSEd Maste DataExtractor new_data;
1681f034231aSEd Maste new_data.SetByteOrder(m_data.GetByteOrder());
1682f034231aSEd Maste
1683f034231aSEd Maste DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
1684f034231aSEd Maste m_data.SetData(buffer_sp, 0);
1685f034231aSEd Maste bool success = new_scalar.GetData(new_data);
168614f1b3e8SDimitry Andric if (success) {
168714f1b3e8SDimitry Andric new_data.CopyByteOrderedData(
168814f1b3e8SDimitry Andric 0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),
168914f1b3e8SDimitry Andric byte_size, m_data.GetByteOrder());
1690f034231aSEd Maste }
1691f034231aSEd Maste m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
1692f034231aSEd Maste
169314f1b3e8SDimitry Andric } break;
1694344a3780SDimitry Andric case Value::ValueType::Invalid:
1695344a3780SDimitry Andric error.SetErrorString("invalid location");
1696344a3780SDimitry Andric return false;
1697344a3780SDimitry Andric case Value::ValueType::FileAddress:
1698344a3780SDimitry Andric case Value::ValueType::Scalar:
1699f034231aSEd Maste break;
1700f034231aSEd Maste }
170114f1b3e8SDimitry Andric } else {
1702f034231aSEd Maste return false;
1703f034231aSEd Maste }
170414f1b3e8SDimitry Andric } else {
1705f034231aSEd Maste // We don't support setting things bigger than a scalar at present.
1706f034231aSEd Maste error.SetErrorString("unable to write aggregate data type");
1707f034231aSEd Maste return false;
1708f034231aSEd Maste }
1709f034231aSEd Maste
1710f73363f1SDimitry Andric // If we have reached this point, then we have successfully changed the
1711f73363f1SDimitry Andric // value.
1712f034231aSEd Maste SetNeedsUpdate();
1713f034231aSEd Maste return true;
1714f034231aSEd Maste }
1715f034231aSEd Maste
GetDeclaration(Declaration & decl)171614f1b3e8SDimitry Andric bool ValueObject::GetDeclaration(Declaration &decl) {
1717f034231aSEd Maste decl.Clear();
1718f034231aSEd Maste return false;
1719f034231aSEd Maste }
1720f034231aSEd Maste
AddSyntheticChild(ConstString key,ValueObject * valobj)17215f29bb8aSDimitry Andric void ValueObject::AddSyntheticChild(ConstString key,
172214f1b3e8SDimitry Andric ValueObject *valobj) {
1723f034231aSEd Maste m_synthetic_children[key] = valobj;
1724f034231aSEd Maste }
1725f034231aSEd Maste
GetSyntheticChild(ConstString key) const17265f29bb8aSDimitry Andric ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
1727f034231aSEd Maste ValueObjectSP synthetic_child_sp;
172814f1b3e8SDimitry Andric std::map<ConstString, ValueObject *>::const_iterator pos =
172914f1b3e8SDimitry Andric m_synthetic_children.find(key);
1730f034231aSEd Maste if (pos != m_synthetic_children.end())
1731f034231aSEd Maste synthetic_child_sp = pos->second->GetSP();
1732f034231aSEd Maste return synthetic_child_sp;
1733f034231aSEd Maste }
1734f034231aSEd Maste
IsPossibleDynamicType()173514f1b3e8SDimitry Andric bool ValueObject::IsPossibleDynamicType() {
1736f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
1737f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
1738f034231aSEd Maste if (process)
1739f034231aSEd Maste return process->IsPossibleDynamicValue(*this);
1740f034231aSEd Maste else
17415f29bb8aSDimitry Andric return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);
1742f034231aSEd Maste }
1743f034231aSEd Maste
IsRuntimeSupportValue()174414f1b3e8SDimitry Andric bool ValueObject::IsRuntimeSupportValue() {
17455e95aa85SEd Maste Process *process(GetProcessSP().get());
17465f29bb8aSDimitry Andric if (!process)
17475e95aa85SEd Maste return false;
17485f29bb8aSDimitry Andric
1749344a3780SDimitry Andric // We trust that the compiler did the right thing and marked runtime support
17505f29bb8aSDimitry Andric // values as artificial.
17515f29bb8aSDimitry Andric if (!GetVariable() || !GetVariable()->IsArtificial())
17525f29bb8aSDimitry Andric return false;
17535f29bb8aSDimitry Andric
1754ead24645SDimitry Andric if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))
1755cfca06d7SDimitry Andric if (runtime->IsAllowedRuntimeValue(GetName()))
17565f29bb8aSDimitry Andric return false;
17575f29bb8aSDimitry Andric
17585f29bb8aSDimitry Andric return true;
17595e95aa85SEd Maste }
17605e95aa85SEd Maste
IsNilReference()176114f1b3e8SDimitry Andric bool ValueObject::IsNilReference() {
176214f1b3e8SDimitry Andric if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
1763e81d9d49SDimitry Andric return language->IsNilReference(*this);
1764e81d9d49SDimitry Andric }
1765f034231aSEd Maste return false;
1766e81d9d49SDimitry Andric }
1767e81d9d49SDimitry Andric
IsUninitializedReference()176814f1b3e8SDimitry Andric bool ValueObject::IsUninitializedReference() {
176914f1b3e8SDimitry Andric if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
1770e81d9d49SDimitry Andric return language->IsUninitializedReference(*this);
1771e81d9d49SDimitry Andric }
1772e81d9d49SDimitry Andric return false;
1773f034231aSEd Maste }
1774f034231aSEd Maste
1775f73363f1SDimitry Andric // This allows you to create an array member using and index that doesn't not
1776f73363f1SDimitry Andric // fall in the normal bounds of the array. Many times structure can be defined
1777f73363f1SDimitry Andric // as: struct Collection {
1778f034231aSEd Maste // uint32_t item_count;
1779f034231aSEd Maste // Item item_array[0];
1780f034231aSEd Maste // };
1781f73363f1SDimitry Andric // The size of the "item_array" is 1, but many times in practice there are more
1782f73363f1SDimitry Andric // items in "item_array".
1783f034231aSEd Maste
GetSyntheticArrayMember(size_t index,bool can_create)178414f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
178514f1b3e8SDimitry Andric bool can_create) {
1786ac9a064cSDimitry Andric ValueObjectSP synthetic_child_sp;
1787ac9a064cSDimitry Andric if (IsPointerType() || IsArrayType()) {
1788b60736ecSDimitry Andric std::string index_str = llvm::formatv("[{0}]", index);
1789f034231aSEd Maste ConstString index_const_str(index_str);
1790f73363f1SDimitry Andric // Check if we have already created a synthetic array member in this valid
1791f73363f1SDimitry Andric // object. If we have we will re-use it.
1792ac9a064cSDimitry Andric synthetic_child_sp = GetSyntheticChild(index_const_str);
1793ac9a064cSDimitry Andric if (!synthetic_child_sp) {
1794ac9a064cSDimitry Andric ValueObject *synthetic_child;
1795f73363f1SDimitry Andric // We haven't made a synthetic array member for INDEX yet, so lets make
1796f73363f1SDimitry Andric // one and cache it for any future reference.
1797ac9a064cSDimitry Andric synthetic_child = CreateSyntheticArrayMember(index);
1798f034231aSEd Maste
1799ac9a064cSDimitry Andric // Cache the value if we got one back...
1800ac9a064cSDimitry Andric if (synthetic_child) {
1801f034231aSEd Maste AddSyntheticChild(index_const_str, synthetic_child);
1802ac9a064cSDimitry Andric synthetic_child_sp = synthetic_child->GetSP();
1803f034231aSEd Maste synthetic_child_sp->SetName(ConstString(index_str));
1804344a3780SDimitry Andric synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
1805ac9a064cSDimitry Andric }
1806ac9a064cSDimitry Andric }
1807ac9a064cSDimitry Andric }
1808f034231aSEd Maste return synthetic_child_sp;
1809f034231aSEd Maste }
1810f034231aSEd Maste
GetSyntheticBitFieldChild(uint32_t from,uint32_t to,bool can_create)181114f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
181214f1b3e8SDimitry Andric bool can_create) {
1813ac9a064cSDimitry Andric ValueObjectSP synthetic_child_sp;
1814ac9a064cSDimitry Andric if (IsScalarType()) {
1815b60736ecSDimitry Andric std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
1816f034231aSEd Maste ConstString index_const_str(index_str);
1817f73363f1SDimitry Andric // Check if we have already created a synthetic array member in this valid
1818f73363f1SDimitry Andric // object. If we have we will re-use it.
1819ac9a064cSDimitry Andric synthetic_child_sp = GetSyntheticChild(index_const_str);
1820ac9a064cSDimitry Andric if (!synthetic_child_sp) {
1821f3fbd1c0SDimitry Andric uint32_t bit_field_size = to - from + 1;
1822f3fbd1c0SDimitry Andric uint32_t bit_field_offset = from;
1823f3fbd1c0SDimitry Andric if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
182414f1b3e8SDimitry Andric bit_field_offset =
1825145449b1SDimitry Andric GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
1826f73363f1SDimitry Andric // We haven't made a synthetic array member for INDEX yet, so lets make
1827f73363f1SDimitry Andric // one and cache it for any future reference.
182814f1b3e8SDimitry Andric ValueObjectChild *synthetic_child = new ValueObjectChild(
1829ac9a064cSDimitry Andric *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),
1830ac9a064cSDimitry Andric 0, bit_field_size, bit_field_offset, false, false,
1831ac9a064cSDimitry Andric eAddressTypeInvalid, 0);
1832f034231aSEd Maste
1833ac9a064cSDimitry Andric // Cache the value if we got one back...
1834ac9a064cSDimitry Andric if (synthetic_child) {
1835f034231aSEd Maste AddSyntheticChild(index_const_str, synthetic_child);
1836ac9a064cSDimitry Andric synthetic_child_sp = synthetic_child->GetSP();
1837f034231aSEd Maste synthetic_child_sp->SetName(ConstString(index_str));
1838344a3780SDimitry Andric synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
1839ac9a064cSDimitry Andric }
1840ac9a064cSDimitry Andric }
1841ac9a064cSDimitry Andric }
1842f034231aSEd Maste return synthetic_child_sp;
1843f034231aSEd Maste }
1844f034231aSEd Maste
GetSyntheticChildAtOffset(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)184514f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
184614f1b3e8SDimitry Andric uint32_t offset, const CompilerType &type, bool can_create,
184714f1b3e8SDimitry Andric ConstString name_const_str) {
1848f034231aSEd Maste
1849f034231aSEd Maste ValueObjectSP synthetic_child_sp;
1850f034231aSEd Maste
1851ac9a064cSDimitry Andric if (name_const_str.IsEmpty()) {
1852b60736ecSDimitry Andric name_const_str.SetString("@" + std::to_string(offset));
1853ac9a064cSDimitry Andric }
1854f034231aSEd Maste
1855f73363f1SDimitry Andric // Check if we have already created a synthetic array member in this valid
1856f73363f1SDimitry Andric // object. If we have we will re-use it.
1857f034231aSEd Maste synthetic_child_sp = GetSyntheticChild(name_const_str);
1858f034231aSEd Maste
1859f034231aSEd Maste if (synthetic_child_sp.get())
1860f034231aSEd Maste return synthetic_child_sp;
1861f034231aSEd Maste
1862f034231aSEd Maste if (!can_create)
1863ac9a064cSDimitry Andric return {};
1864f034231aSEd Maste
186512bd4897SEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
1866e3b55780SDimitry Andric std::optional<uint64_t> size =
186794994d37SDimitry Andric type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
186894994d37SDimitry Andric if (!size)
1869ac9a064cSDimitry Andric return {};
187094994d37SDimitry Andric ValueObjectChild *synthetic_child =
187194994d37SDimitry Andric new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
187214f1b3e8SDimitry Andric false, false, eAddressTypeInvalid, 0);
187314f1b3e8SDimitry Andric if (synthetic_child) {
1874f034231aSEd Maste AddSyntheticChild(name_const_str, synthetic_child);
1875f034231aSEd Maste synthetic_child_sp = synthetic_child->GetSP();
1876f034231aSEd Maste synthetic_child_sp->SetName(name_const_str);
1877344a3780SDimitry Andric synthetic_child_sp->m_flags.m_is_child_at_offset = true;
1878f034231aSEd Maste }
1879f034231aSEd Maste return synthetic_child_sp;
1880f034231aSEd Maste }
1881f034231aSEd Maste
GetSyntheticBase(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)188214f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
1883f3fbd1c0SDimitry Andric const CompilerType &type,
1884f3fbd1c0SDimitry Andric bool can_create,
188514f1b3e8SDimitry Andric ConstString name_const_str) {
18860cac4ca3SEd Maste ValueObjectSP synthetic_child_sp;
18870cac4ca3SEd Maste
188814f1b3e8SDimitry Andric if (name_const_str.IsEmpty()) {
1889f3fbd1c0SDimitry Andric char name_str[128];
189014f1b3e8SDimitry Andric snprintf(name_str, sizeof(name_str), "base%s@%i",
189114f1b3e8SDimitry Andric type.GetTypeName().AsCString("<unknown>"), offset);
1892f3fbd1c0SDimitry Andric name_const_str.SetCString(name_str);
1893f3fbd1c0SDimitry Andric }
18940cac4ca3SEd Maste
1895f73363f1SDimitry Andric // Check if we have already created a synthetic array member in this valid
1896f73363f1SDimitry Andric // object. If we have we will re-use it.
18970cac4ca3SEd Maste synthetic_child_sp = GetSyntheticChild(name_const_str);
18980cac4ca3SEd Maste
18990cac4ca3SEd Maste if (synthetic_child_sp.get())
19000cac4ca3SEd Maste return synthetic_child_sp;
19010cac4ca3SEd Maste
19020cac4ca3SEd Maste if (!can_create)
1903ac9a064cSDimitry Andric return {};
19040cac4ca3SEd Maste
19050cac4ca3SEd Maste const bool is_base_class = true;
19060cac4ca3SEd Maste
190712bd4897SEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
1908e3b55780SDimitry Andric std::optional<uint64_t> size =
190994994d37SDimitry Andric type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
191094994d37SDimitry Andric if (!size)
1911ac9a064cSDimitry Andric return {};
191294994d37SDimitry Andric ValueObjectChild *synthetic_child =
191394994d37SDimitry Andric new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
191414f1b3e8SDimitry Andric is_base_class, false, eAddressTypeInvalid, 0);
191514f1b3e8SDimitry Andric if (synthetic_child) {
19160cac4ca3SEd Maste AddSyntheticChild(name_const_str, synthetic_child);
19170cac4ca3SEd Maste synthetic_child_sp = synthetic_child->GetSP();
19180cac4ca3SEd Maste synthetic_child_sp->SetName(name_const_str);
19190cac4ca3SEd Maste }
19200cac4ca3SEd Maste return synthetic_child_sp;
19210cac4ca3SEd Maste }
19220cac4ca3SEd Maste
1923f73363f1SDimitry Andric // your expression path needs to have a leading . or -> (unless it somehow
1924f73363f1SDimitry Andric // "looks like" an array, in which case it has a leading [ symbol). while the [
1925f73363f1SDimitry Andric // is meaningful and should be shown to the user, . and -> are just parser
1926f73363f1SDimitry Andric // design, but by no means added information for the user.. strip them off
SkipLeadingExpressionPathSeparators(const char * expression)192714f1b3e8SDimitry Andric static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
1928f034231aSEd Maste if (!expression || !expression[0])
1929f034231aSEd Maste return expression;
1930f034231aSEd Maste if (expression[0] == '.')
1931f034231aSEd Maste return expression + 1;
1932f034231aSEd Maste if (expression[0] == '-' && expression[1] == '>')
1933f034231aSEd Maste return expression + 2;
1934f034231aSEd Maste return expression;
1935f034231aSEd Maste }
1936f034231aSEd Maste
1937f034231aSEd Maste ValueObjectSP
GetSyntheticExpressionPathChild(const char * expression,bool can_create)193814f1b3e8SDimitry Andric ValueObject::GetSyntheticExpressionPathChild(const char *expression,
193914f1b3e8SDimitry Andric bool can_create) {
1940ac9a064cSDimitry Andric ValueObjectSP synthetic_child_sp;
1941f034231aSEd Maste ConstString name_const_string(expression);
1942f73363f1SDimitry Andric // Check if we have already created a synthetic array member in this valid
1943f73363f1SDimitry Andric // object. If we have we will re-use it.
1944ac9a064cSDimitry Andric synthetic_child_sp = GetSyntheticChild(name_const_string);
1945ac9a064cSDimitry Andric if (!synthetic_child_sp) {
1946f73363f1SDimitry Andric // We haven't made a synthetic array member for expression yet, so lets
1947f73363f1SDimitry Andric // make one and cache it for any future reference.
1948ac9a064cSDimitry Andric synthetic_child_sp = GetValueForExpressionPath(
1949ac9a064cSDimitry Andric expression, nullptr, nullptr,
1950ac9a064cSDimitry Andric GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
1951ac9a064cSDimitry Andric GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
1952ac9a064cSDimitry Andric None));
1953f034231aSEd Maste
1954ac9a064cSDimitry Andric // Cache the value if we got one back...
1955ac9a064cSDimitry Andric if (synthetic_child_sp.get()) {
195614f1b3e8SDimitry Andric // FIXME: this causes a "real" child to end up with its name changed to
195714f1b3e8SDimitry Andric // the contents of expression
1958ac9a064cSDimitry Andric AddSyntheticChild(name_const_string, synthetic_child_sp.get());
1959ac9a064cSDimitry Andric synthetic_child_sp->SetName(
196014f1b3e8SDimitry Andric ConstString(SkipLeadingExpressionPathSeparators(expression)));
1961ac9a064cSDimitry Andric }
1962ac9a064cSDimitry Andric }
1963ac9a064cSDimitry Andric return synthetic_child_sp;
1964f034231aSEd Maste }
1965f034231aSEd Maste
CalculateSyntheticValue()1966cfca06d7SDimitry Andric void ValueObject::CalculateSyntheticValue() {
1967f034231aSEd Maste TargetSP target_sp(GetTargetSP());
196894994d37SDimitry Andric if (target_sp && !target_sp->GetEnableSyntheticValue()) {
19695f29bb8aSDimitry Andric m_synthetic_value = nullptr;
1970f034231aSEd Maste return;
1971f034231aSEd Maste }
1972f034231aSEd Maste
1973f034231aSEd Maste lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
1974f034231aSEd Maste
1975f034231aSEd Maste if (!UpdateFormatsIfNeeded() && m_synthetic_value)
1976f034231aSEd Maste return;
1977f034231aSEd Maste
19785f29bb8aSDimitry Andric if (m_synthetic_children_sp.get() == nullptr)
1979f034231aSEd Maste return;
1980f034231aSEd Maste
1981f034231aSEd Maste if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
1982f034231aSEd Maste return;
1983f034231aSEd Maste
1984f034231aSEd Maste m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
1985f034231aSEd Maste }
1986f034231aSEd Maste
CalculateDynamicValue(DynamicValueType use_dynamic)198714f1b3e8SDimitry Andric void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
1988f034231aSEd Maste if (use_dynamic == eNoDynamicValues)
1989f034231aSEd Maste return;
1990f034231aSEd Maste
199114f1b3e8SDimitry Andric if (!m_dynamic_value && !IsDynamic()) {
1992f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
1993f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
199414f1b3e8SDimitry Andric if (process && process->IsPossibleDynamicValue(*this)) {
1995f034231aSEd Maste ClearDynamicTypeInformation();
1996f034231aSEd Maste m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
1997f034231aSEd Maste }
1998f034231aSEd Maste }
1999f034231aSEd Maste }
2000f034231aSEd Maste
GetDynamicValue(DynamicValueType use_dynamic)200114f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
2002f034231aSEd Maste if (use_dynamic == eNoDynamicValues)
2003f034231aSEd Maste return ValueObjectSP();
2004f034231aSEd Maste
20055f29bb8aSDimitry Andric if (!IsDynamic() && m_dynamic_value == nullptr) {
2006f034231aSEd Maste CalculateDynamicValue(use_dynamic);
2007f034231aSEd Maste }
20087fa27ce4SDimitry Andric if (m_dynamic_value && m_dynamic_value->GetError().Success())
2009f034231aSEd Maste return m_dynamic_value->GetSP();
2010f034231aSEd Maste else
2011f034231aSEd Maste return ValueObjectSP();
2012f034231aSEd Maste }
2013f034231aSEd Maste
GetSyntheticValue()2014cfca06d7SDimitry Andric ValueObjectSP ValueObject::GetSyntheticValue() {
2015cfca06d7SDimitry Andric CalculateSyntheticValue();
2016f034231aSEd Maste
2017f034231aSEd Maste if (m_synthetic_value)
2018f034231aSEd Maste return m_synthetic_value->GetSP();
2019f034231aSEd Maste else
2020f034231aSEd Maste return ValueObjectSP();
2021f034231aSEd Maste }
2022f034231aSEd Maste
HasSyntheticValue()202314f1b3e8SDimitry Andric bool ValueObject::HasSyntheticValue() {
2024f034231aSEd Maste UpdateFormatsIfNeeded();
2025f034231aSEd Maste
20265f29bb8aSDimitry Andric if (m_synthetic_children_sp.get() == nullptr)
2027f034231aSEd Maste return false;
2028f034231aSEd Maste
2029cfca06d7SDimitry Andric CalculateSyntheticValue();
2030f034231aSEd Maste
203194994d37SDimitry Andric return m_synthetic_value != nullptr;
2032f034231aSEd Maste }
2033f034231aSEd Maste
GetNonBaseClassParent()203414f1b3e8SDimitry Andric ValueObject *ValueObject::GetNonBaseClassParent() {
203514f1b3e8SDimitry Andric if (GetParent()) {
2036f034231aSEd Maste if (GetParent()->IsBaseClass())
2037f034231aSEd Maste return GetParent()->GetNonBaseClassParent();
2038f034231aSEd Maste else
2039f034231aSEd Maste return GetParent();
2040f034231aSEd Maste }
20415f29bb8aSDimitry Andric return nullptr;
2042f034231aSEd Maste }
2043f034231aSEd Maste
IsBaseClass(uint32_t & depth)204414f1b3e8SDimitry Andric bool ValueObject::IsBaseClass(uint32_t &depth) {
204514f1b3e8SDimitry Andric if (!IsBaseClass()) {
20460cac4ca3SEd Maste depth = 0;
20470cac4ca3SEd Maste return false;
20480cac4ca3SEd Maste }
204914f1b3e8SDimitry Andric if (GetParent()) {
20500cac4ca3SEd Maste GetParent()->IsBaseClass(depth);
20510cac4ca3SEd Maste depth = depth + 1;
20520cac4ca3SEd Maste return true;
20530cac4ca3SEd Maste }
20540cac4ca3SEd Maste // TODO: a base of no parent? weird..
20550cac4ca3SEd Maste depth = 1;
20560cac4ca3SEd Maste return true;
20570cac4ca3SEd Maste }
20580cac4ca3SEd Maste
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)2059cfca06d7SDimitry Andric void ValueObject::GetExpressionPath(Stream &s,
206014f1b3e8SDimitry Andric GetExpressionPathFormat epformat) {
206114f1b3e8SDimitry Andric // synthetic children do not actually "exist" as part of the hierarchy, and
2062f73363f1SDimitry Andric // sometimes they are consed up in ways that don't make sense from an
2063f73363f1SDimitry Andric // underlying language/API standpoint. So, use a special code path here to
2064f73363f1SDimitry Andric // return something that can hopefully be used in expression
2065344a3780SDimitry Andric if (m_flags.m_is_synthetic_children_generated) {
2066205afe67SEd Maste UpdateValueIfNeeded();
2067205afe67SEd Maste
2068344a3780SDimitry Andric if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
206914f1b3e8SDimitry Andric if (IsPointerOrReferenceType()) {
207014f1b3e8SDimitry Andric s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
2071205afe67SEd Maste GetValueAsUnsigned(0));
2072205afe67SEd Maste return;
207314f1b3e8SDimitry Andric } else {
207414f1b3e8SDimitry Andric uint64_t load_addr =
207514f1b3e8SDimitry Andric m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
207614f1b3e8SDimitry Andric if (load_addr != LLDB_INVALID_ADDRESS) {
207714f1b3e8SDimitry Andric s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),
2078205afe67SEd Maste load_addr);
2079205afe67SEd Maste return;
2080205afe67SEd Maste }
2081205afe67SEd Maste }
2082205afe67SEd Maste }
2083205afe67SEd Maste
208414f1b3e8SDimitry Andric if (CanProvideValue()) {
208514f1b3e8SDimitry Andric s.Printf("((%s)%s)", GetTypeName().AsCString("void"),
2086205afe67SEd Maste GetValueAsCString());
2087205afe67SEd Maste return;
2088205afe67SEd Maste }
2089205afe67SEd Maste
2090205afe67SEd Maste return;
2091205afe67SEd Maste }
2092205afe67SEd Maste
2093f034231aSEd Maste const bool is_deref_of_parent = IsDereferenceOfParent();
2094f034231aSEd Maste
209514f1b3e8SDimitry Andric if (is_deref_of_parent &&
209614f1b3e8SDimitry Andric epformat == eGetExpressionPathFormatDereferencePointers) {
209714f1b3e8SDimitry Andric // this is the original format of GetExpressionPath() producing code like
2098f73363f1SDimitry Andric // *(a_ptr).memberName, which is entirely fine, until you put this into
209914f1b3e8SDimitry Andric // StackFrame::GetValueForVariableExpressionPath() which prefers to see
2100f73363f1SDimitry Andric // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
2101f73363f1SDimitry Andric // in this latter format
2102f034231aSEd Maste s.PutCString("*(");
2103f034231aSEd Maste }
2104f034231aSEd Maste
2105f034231aSEd Maste ValueObject *parent = GetParent();
2106f034231aSEd Maste
2107f034231aSEd Maste if (parent)
2108cfca06d7SDimitry Andric parent->GetExpressionPath(s, epformat);
2109f034231aSEd Maste
2110f73363f1SDimitry Andric // if we are a deref_of_parent just because we are synthetic array members
2111f73363f1SDimitry Andric // made up to allow ptr[%d] syntax to work in variable printing, then add our
2112f73363f1SDimitry Andric // name ([%d]) to the expression path
2113344a3780SDimitry Andric if (m_flags.m_is_array_item_for_pointer &&
211414f1b3e8SDimitry Andric epformat == eGetExpressionPathFormatHonorPointers)
2115cfca06d7SDimitry Andric s.PutCString(m_name.GetStringRef());
2116f034231aSEd Maste
211714f1b3e8SDimitry Andric if (!IsBaseClass()) {
211814f1b3e8SDimitry Andric if (!is_deref_of_parent) {
2119f034231aSEd Maste ValueObject *non_base_class_parent = GetNonBaseClassParent();
212014f1b3e8SDimitry Andric if (non_base_class_parent &&
212114f1b3e8SDimitry Andric !non_base_class_parent->GetName().IsEmpty()) {
212214f1b3e8SDimitry Andric CompilerType non_base_class_parent_compiler_type =
212314f1b3e8SDimitry Andric non_base_class_parent->GetCompilerType();
212414f1b3e8SDimitry Andric if (non_base_class_parent_compiler_type) {
212514f1b3e8SDimitry Andric if (parent && parent->IsDereferenceOfParent() &&
212614f1b3e8SDimitry Andric epformat == eGetExpressionPathFormatHonorPointers) {
2127f034231aSEd Maste s.PutCString("->");
212814f1b3e8SDimitry Andric } else {
212914f1b3e8SDimitry Andric const uint32_t non_base_class_parent_type_info =
213014f1b3e8SDimitry Andric non_base_class_parent_compiler_type.GetTypeInfo();
2131f034231aSEd Maste
213214f1b3e8SDimitry Andric if (non_base_class_parent_type_info & eTypeIsPointer) {
2133f034231aSEd Maste s.PutCString("->");
213414f1b3e8SDimitry Andric } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
213514f1b3e8SDimitry Andric !(non_base_class_parent_type_info & eTypeIsArray)) {
2136f034231aSEd Maste s.PutChar('.');
2137f034231aSEd Maste }
2138f034231aSEd Maste }
2139f034231aSEd Maste }
2140f034231aSEd Maste }
2141f034231aSEd Maste
2142f034231aSEd Maste const char *name = GetName().GetCString();
2143cfca06d7SDimitry Andric if (name)
2144f034231aSEd Maste s.PutCString(name);
2145f034231aSEd Maste }
2146f034231aSEd Maste }
2147f034231aSEd Maste
214814f1b3e8SDimitry Andric if (is_deref_of_parent &&
214914f1b3e8SDimitry Andric epformat == eGetExpressionPathFormatDereferencePointers) {
2150f034231aSEd Maste s.PutChar(')');
2151f034231aSEd Maste }
2152f034231aSEd Maste }
2153f034231aSEd Maste
GetValueForExpressionPath(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_value_type,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * final_task_on_target)215414f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath(
215514f1b3e8SDimitry Andric llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
2156f034231aSEd Maste ExpressionPathEndResultType *final_value_type,
2157f034231aSEd Maste const GetValueForExpressionPathOptions &options,
215814f1b3e8SDimitry Andric ExpressionPathAftermath *final_task_on_target) {
2159f034231aSEd Maste
2160ac9a064cSDimitry Andric ExpressionPathScanEndReason dummy_reason_to_stop =
2161ac9a064cSDimitry Andric ValueObject::eExpressionPathScanEndReasonUnknown;
2162ac9a064cSDimitry Andric ExpressionPathEndResultType dummy_final_value_type =
2163ac9a064cSDimitry Andric ValueObject::eExpressionPathEndResultTypeInvalid;
2164ac9a064cSDimitry Andric ExpressionPathAftermath dummy_final_task_on_target =
2165ac9a064cSDimitry Andric ValueObject::eExpressionPathAftermathNothing;
2166f034231aSEd Maste
2167ac9a064cSDimitry Andric ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
2168ac9a064cSDimitry Andric expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
2169ac9a064cSDimitry Andric final_value_type ? final_value_type : &dummy_final_value_type, options,
2170ac9a064cSDimitry Andric final_task_on_target ? final_task_on_target
2171ac9a064cSDimitry Andric : &dummy_final_task_on_target);
2172f034231aSEd Maste
2173ac9a064cSDimitry Andric if (!final_task_on_target ||
2174ac9a064cSDimitry Andric *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
2175ac9a064cSDimitry Andric return ret_val;
2176f034231aSEd Maste
2177ac9a064cSDimitry Andric if (ret_val.get() &&
2178ac9a064cSDimitry Andric ((final_value_type ? *final_value_type : dummy_final_value_type) ==
2179ac9a064cSDimitry Andric eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
2180ac9a064cSDimitry Andric // of plain objects
2181ac9a064cSDimitry Andric {
2182ac9a064cSDimitry Andric if ((final_task_on_target ? *final_task_on_target
2183ac9a064cSDimitry Andric : dummy_final_task_on_target) ==
2184ac9a064cSDimitry Andric ValueObject::eExpressionPathAftermathDereference) {
2185b76161e4SDimitry Andric Status error;
2186ac9a064cSDimitry Andric ValueObjectSP final_value = ret_val->Dereference(error);
2187ac9a064cSDimitry Andric if (error.Fail() || !final_value.get()) {
2188f034231aSEd Maste if (reason_to_stop)
2189ac9a064cSDimitry Andric *reason_to_stop =
2190ac9a064cSDimitry Andric ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2191f034231aSEd Maste if (final_value_type)
2192ac9a064cSDimitry Andric *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2193f034231aSEd Maste return ValueObjectSP();
2194ac9a064cSDimitry Andric } else {
2195ac9a064cSDimitry Andric if (final_task_on_target)
2196ac9a064cSDimitry Andric *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2197ac9a064cSDimitry Andric return final_value;
2198ac9a064cSDimitry Andric }
2199ac9a064cSDimitry Andric }
2200ac9a064cSDimitry Andric if (*final_task_on_target ==
2201ac9a064cSDimitry Andric ValueObject::eExpressionPathAftermathTakeAddress) {
2202ac9a064cSDimitry Andric Status error;
2203ac9a064cSDimitry Andric ValueObjectSP final_value = ret_val->AddressOf(error);
2204ac9a064cSDimitry Andric if (error.Fail() || !final_value.get()) {
2205ac9a064cSDimitry Andric if (reason_to_stop)
2206ac9a064cSDimitry Andric *reason_to_stop =
2207ac9a064cSDimitry Andric ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
2208ac9a064cSDimitry Andric if (final_value_type)
2209ac9a064cSDimitry Andric *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2210ac9a064cSDimitry Andric return ValueObjectSP();
2211ac9a064cSDimitry Andric } else {
2212ac9a064cSDimitry Andric if (final_task_on_target)
2213ac9a064cSDimitry Andric *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2214ac9a064cSDimitry Andric return final_value;
2215ac9a064cSDimitry Andric }
2216ac9a064cSDimitry Andric }
2217ac9a064cSDimitry Andric }
2218ac9a064cSDimitry Andric return ret_val; // final_task_on_target will still have its original value, so
2219ac9a064cSDimitry Andric // you know I did not do it
2220f034231aSEd Maste }
2221f034231aSEd Maste
GetValueForExpressionPath_Impl(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_result,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * what_next)222214f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
222314f1b3e8SDimitry Andric llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
2224f034231aSEd Maste ExpressionPathEndResultType *final_result,
2225f034231aSEd Maste const GetValueForExpressionPathOptions &options,
222614f1b3e8SDimitry Andric ExpressionPathAftermath *what_next) {
2227f034231aSEd Maste ValueObjectSP root = GetSP();
2228f034231aSEd Maste
222914f1b3e8SDimitry Andric if (!root)
223014f1b3e8SDimitry Andric return nullptr;
2231f034231aSEd Maste
223214f1b3e8SDimitry Andric llvm::StringRef remainder = expression;
2233f034231aSEd Maste
223414f1b3e8SDimitry Andric while (true) {
223514f1b3e8SDimitry Andric llvm::StringRef temp_expression = remainder;
2236f034231aSEd Maste
2237e81d9d49SDimitry Andric CompilerType root_compiler_type = root->GetCompilerType();
2238e81d9d49SDimitry Andric CompilerType pointee_compiler_type;
2239e81d9d49SDimitry Andric Flags pointee_compiler_type_info;
2240f034231aSEd Maste
224114f1b3e8SDimitry Andric Flags root_compiler_type_info(
224214f1b3e8SDimitry Andric root_compiler_type.GetTypeInfo(&pointee_compiler_type));
2243e81d9d49SDimitry Andric if (pointee_compiler_type)
2244e81d9d49SDimitry Andric pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
2245f034231aSEd Maste
224614f1b3e8SDimitry Andric if (temp_expression.empty()) {
2247f034231aSEd Maste *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
2248f034231aSEd Maste return root;
2249f034231aSEd Maste }
2250f034231aSEd Maste
225114f1b3e8SDimitry Andric switch (temp_expression.front()) {
225214f1b3e8SDimitry Andric case '-': {
225314f1b3e8SDimitry Andric temp_expression = temp_expression.drop_front();
2254f034231aSEd Maste if (options.m_check_dot_vs_arrow_syntax &&
225514f1b3e8SDimitry Andric root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
225614f1b3e8SDimitry Andric // use -> on a
225714f1b3e8SDimitry Andric // non-pointer and I
225814f1b3e8SDimitry Andric // must catch the error
2259f034231aSEd Maste {
226014f1b3e8SDimitry Andric *reason_to_stop =
226114f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
2262f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2263f034231aSEd Maste return ValueObjectSP();
2264f034231aSEd Maste }
226514f1b3e8SDimitry Andric if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
226614f1b3e8SDimitry Andric // extract an ObjC IVar
226714f1b3e8SDimitry Andric // when this is forbidden
2268e81d9d49SDimitry Andric root_compiler_type_info.Test(eTypeIsPointer) &&
226914f1b3e8SDimitry Andric options.m_no_fragile_ivar) {
227014f1b3e8SDimitry Andric *reason_to_stop =
227114f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
2272f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2273f034231aSEd Maste return ValueObjectSP();
2274f034231aSEd Maste }
2275312c0ed1SDimitry Andric if (!temp_expression.starts_with(">")) {
227614f1b3e8SDimitry Andric *reason_to_stop =
227714f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2278f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2279f034231aSEd Maste return ValueObjectSP();
2280f034231aSEd Maste }
2281f034231aSEd Maste }
2282e3b55780SDimitry Andric [[fallthrough]];
2283f034231aSEd Maste case '.': // or fallthrough from ->
2284f034231aSEd Maste {
228514f1b3e8SDimitry Andric if (options.m_check_dot_vs_arrow_syntax &&
228614f1b3e8SDimitry Andric temp_expression.front() == '.' &&
228714f1b3e8SDimitry Andric root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
228814f1b3e8SDimitry Andric // use . on a pointer
228914f1b3e8SDimitry Andric // and I must catch the
229014f1b3e8SDimitry Andric // error
2291f034231aSEd Maste {
229214f1b3e8SDimitry Andric *reason_to_stop =
229314f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
2294f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
229514f1b3e8SDimitry Andric return nullptr;
2296f034231aSEd Maste }
229714f1b3e8SDimitry Andric temp_expression = temp_expression.drop_front(); // skip . or >
229814f1b3e8SDimitry Andric
229914f1b3e8SDimitry Andric size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
230014f1b3e8SDimitry Andric if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
230114f1b3e8SDimitry Andric // expand this last layer
2302f034231aSEd Maste {
2303b1c73532SDimitry Andric llvm::StringRef child_name = temp_expression;
230414f1b3e8SDimitry Andric ValueObjectSP child_valobj_sp =
23057fa27ce4SDimitry Andric root->GetChildMemberWithName(child_name);
2306f034231aSEd Maste
2307f034231aSEd Maste if (child_valobj_sp.get()) // we know we are done, so just return
2308f034231aSEd Maste {
230914f1b3e8SDimitry Andric *reason_to_stop =
231014f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString;
2311f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2312f034231aSEd Maste return child_valobj_sp;
231314f1b3e8SDimitry Andric } else {
231414f1b3e8SDimitry Andric switch (options.m_synthetic_children_traversal) {
231514f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
231614f1b3e8SDimitry Andric None:
23175e95aa85SEd Maste break;
231814f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
231914f1b3e8SDimitry Andric FromSynthetic:
232014f1b3e8SDimitry Andric if (root->IsSynthetic()) {
23215e95aa85SEd Maste child_valobj_sp = root->GetNonSyntheticValue();
23225e95aa85SEd Maste if (child_valobj_sp.get())
232314f1b3e8SDimitry Andric child_valobj_sp =
23247fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
2325f034231aSEd Maste }
23265e95aa85SEd Maste break;
232714f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
232814f1b3e8SDimitry Andric ToSynthetic:
232914f1b3e8SDimitry Andric if (!root->IsSynthetic()) {
2330f034231aSEd Maste child_valobj_sp = root->GetSyntheticValue();
2331f034231aSEd Maste if (child_valobj_sp.get())
233214f1b3e8SDimitry Andric child_valobj_sp =
23337fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
2334f034231aSEd Maste }
23355e95aa85SEd Maste break;
233614f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
233714f1b3e8SDimitry Andric Both:
233814f1b3e8SDimitry Andric if (root->IsSynthetic()) {
23395e95aa85SEd Maste child_valobj_sp = root->GetNonSyntheticValue();
23405e95aa85SEd Maste if (child_valobj_sp.get())
234114f1b3e8SDimitry Andric child_valobj_sp =
23427fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
234314f1b3e8SDimitry Andric } else {
23445e95aa85SEd Maste child_valobj_sp = root->GetSyntheticValue();
23455e95aa85SEd Maste if (child_valobj_sp.get())
234614f1b3e8SDimitry Andric child_valobj_sp =
23477fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
23485e95aa85SEd Maste }
23495e95aa85SEd Maste break;
23505e95aa85SEd Maste }
23515e95aa85SEd Maste }
2352f034231aSEd Maste
235314f1b3e8SDimitry Andric // if we are here and options.m_no_synthetic_children is true,
2354f73363f1SDimitry Andric // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2355f73363f1SDimitry Andric // branch, and return an error
2356f034231aSEd Maste if (child_valobj_sp.get()) // if it worked, just return
2357f034231aSEd Maste {
235814f1b3e8SDimitry Andric *reason_to_stop =
235914f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString;
2360f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2361f034231aSEd Maste return child_valobj_sp;
236214f1b3e8SDimitry Andric } else {
236314f1b3e8SDimitry Andric *reason_to_stop =
236414f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2365f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
236614f1b3e8SDimitry Andric return nullptr;
2367f034231aSEd Maste }
236814f1b3e8SDimitry Andric } else // other layers do expand
2369f034231aSEd Maste {
237014f1b3e8SDimitry Andric llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
2371b1c73532SDimitry Andric llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);
237214f1b3e8SDimitry Andric
237314f1b3e8SDimitry Andric ValueObjectSP child_valobj_sp =
23747fa27ce4SDimitry Andric root->GetChildMemberWithName(child_name);
2375f034231aSEd Maste if (child_valobj_sp.get()) // store the new root and move on
2376f034231aSEd Maste {
2377f034231aSEd Maste root = child_valobj_sp;
237814f1b3e8SDimitry Andric remainder = next_separator;
2379f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2380f034231aSEd Maste continue;
238114f1b3e8SDimitry Andric } else {
238214f1b3e8SDimitry Andric switch (options.m_synthetic_children_traversal) {
238314f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
238414f1b3e8SDimitry Andric None:
23855e95aa85SEd Maste break;
238614f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
238714f1b3e8SDimitry Andric FromSynthetic:
238814f1b3e8SDimitry Andric if (root->IsSynthetic()) {
23895e95aa85SEd Maste child_valobj_sp = root->GetNonSyntheticValue();
23905e95aa85SEd Maste if (child_valobj_sp.get())
239114f1b3e8SDimitry Andric child_valobj_sp =
23927fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
2393f034231aSEd Maste }
23945e95aa85SEd Maste break;
239514f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
239614f1b3e8SDimitry Andric ToSynthetic:
239714f1b3e8SDimitry Andric if (!root->IsSynthetic()) {
23985e95aa85SEd Maste child_valobj_sp = root->GetSyntheticValue();
23995e95aa85SEd Maste if (child_valobj_sp.get())
240014f1b3e8SDimitry Andric child_valobj_sp =
24017fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
24025e95aa85SEd Maste }
24035e95aa85SEd Maste break;
240414f1b3e8SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
240514f1b3e8SDimitry Andric Both:
240614f1b3e8SDimitry Andric if (root->IsSynthetic()) {
24075e95aa85SEd Maste child_valobj_sp = root->GetNonSyntheticValue();
24085e95aa85SEd Maste if (child_valobj_sp.get())
240914f1b3e8SDimitry Andric child_valobj_sp =
24107fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
241114f1b3e8SDimitry Andric } else {
24125e95aa85SEd Maste child_valobj_sp = root->GetSyntheticValue();
24135e95aa85SEd Maste if (child_valobj_sp.get())
241414f1b3e8SDimitry Andric child_valobj_sp =
24157fa27ce4SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name);
24165e95aa85SEd Maste }
24175e95aa85SEd Maste break;
24185e95aa85SEd Maste }
24195e95aa85SEd Maste }
2420f034231aSEd Maste
242114f1b3e8SDimitry Andric // if we are here and options.m_no_synthetic_children is true,
2422f73363f1SDimitry Andric // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2423f73363f1SDimitry Andric // branch, and return an error
2424f034231aSEd Maste if (child_valobj_sp.get()) // if it worked, move on
2425f034231aSEd Maste {
2426f034231aSEd Maste root = child_valobj_sp;
242714f1b3e8SDimitry Andric remainder = next_separator;
2428f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2429f034231aSEd Maste continue;
243014f1b3e8SDimitry Andric } else {
243114f1b3e8SDimitry Andric *reason_to_stop =
243214f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2433f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
243414f1b3e8SDimitry Andric return nullptr;
2435f034231aSEd Maste }
2436f034231aSEd Maste }
2437f034231aSEd Maste break;
2438f034231aSEd Maste }
243914f1b3e8SDimitry Andric case '[': {
244014f1b3e8SDimitry Andric if (!root_compiler_type_info.Test(eTypeIsArray) &&
244114f1b3e8SDimitry Andric !root_compiler_type_info.Test(eTypeIsPointer) &&
244214f1b3e8SDimitry Andric !root_compiler_type_info.Test(
244314f1b3e8SDimitry Andric eTypeIsVector)) // if this is not a T[] nor a T*
2444f034231aSEd Maste {
244514f1b3e8SDimitry Andric if (!root_compiler_type_info.Test(
244614f1b3e8SDimitry Andric eTypeIsScalar)) // if this is not even a scalar...
2447f034231aSEd Maste {
244814f1b3e8SDimitry Andric if (options.m_synthetic_children_traversal ==
244914f1b3e8SDimitry Andric GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
245014f1b3e8SDimitry Andric None) // ...only chance left is synthetic
2451f034231aSEd Maste {
245214f1b3e8SDimitry Andric *reason_to_stop =
245314f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
245414f1b3e8SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
245514f1b3e8SDimitry Andric return ValueObjectSP();
245614f1b3e8SDimitry Andric }
245714f1b3e8SDimitry Andric } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
245814f1b3e8SDimitry Andric // check that we can
245914f1b3e8SDimitry Andric // expand bitfields
2460f034231aSEd Maste {
246114f1b3e8SDimitry Andric *reason_to_stop =
246214f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
2463f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2464f034231aSEd Maste return ValueObjectSP();
2465f034231aSEd Maste }
2466f034231aSEd Maste }
246714f1b3e8SDimitry Andric if (temp_expression[1] ==
246814f1b3e8SDimitry Andric ']') // if this is an unbounded range it only works for arrays
2469f034231aSEd Maste {
247014f1b3e8SDimitry Andric if (!root_compiler_type_info.Test(eTypeIsArray)) {
247114f1b3e8SDimitry Andric *reason_to_stop =
247214f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
2473f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
247414f1b3e8SDimitry Andric return nullptr;
247514f1b3e8SDimitry Andric } else // even if something follows, we cannot expand unbounded ranges,
247614f1b3e8SDimitry Andric // just let the caller do it
2477f034231aSEd Maste {
247814f1b3e8SDimitry Andric *reason_to_stop =
247914f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
248014f1b3e8SDimitry Andric *final_result =
248114f1b3e8SDimitry Andric ValueObject::eExpressionPathEndResultTypeUnboundedRange;
2482f034231aSEd Maste return root;
2483f034231aSEd Maste }
2484f034231aSEd Maste }
248514f1b3e8SDimitry Andric
248614f1b3e8SDimitry Andric size_t close_bracket_position = temp_expression.find(']', 1);
248714f1b3e8SDimitry Andric if (close_bracket_position ==
248814f1b3e8SDimitry Andric llvm::StringRef::npos) // if there is no ], this is a syntax error
2489f034231aSEd Maste {
249014f1b3e8SDimitry Andric *reason_to_stop =
249114f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2492f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
249314f1b3e8SDimitry Andric return nullptr;
2494f034231aSEd Maste }
249514f1b3e8SDimitry Andric
249614f1b3e8SDimitry Andric llvm::StringRef bracket_expr =
249714f1b3e8SDimitry Andric temp_expression.slice(1, close_bracket_position);
249814f1b3e8SDimitry Andric
249914f1b3e8SDimitry Andric // If this was an empty expression it would have been caught by the if
250014f1b3e8SDimitry Andric // above.
250114f1b3e8SDimitry Andric assert(!bracket_expr.empty());
250214f1b3e8SDimitry Andric
250314f1b3e8SDimitry Andric if (!bracket_expr.contains('-')) {
2504f73363f1SDimitry Andric // if no separator, this is of the form [N]. Note that this cannot be
2505f73363f1SDimitry Andric // an unbounded range of the form [], because that case was handled
250614f1b3e8SDimitry Andric // above with an unconditional return.
250714f1b3e8SDimitry Andric unsigned long index = 0;
250814f1b3e8SDimitry Andric if (bracket_expr.getAsInteger(0, index)) {
250914f1b3e8SDimitry Andric *reason_to_stop =
251014f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2511f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
251214f1b3e8SDimitry Andric return nullptr;
2513f034231aSEd Maste }
251414f1b3e8SDimitry Andric
2515f034231aSEd Maste // from here on we do have a valid index
251614f1b3e8SDimitry Andric if (root_compiler_type_info.Test(eTypeIsArray)) {
25177fa27ce4SDimitry Andric ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);
2518f034231aSEd Maste if (!child_valobj_sp)
25195e95aa85SEd Maste child_valobj_sp = root->GetSyntheticArrayMember(index, true);
2520f034231aSEd Maste if (!child_valobj_sp)
252114f1b3e8SDimitry Andric if (root->HasSyntheticValue() &&
2522ac9a064cSDimitry Andric llvm::expectedToStdOptional(
2523ac9a064cSDimitry Andric root->GetSyntheticValue()->GetNumChildren())
2524ac9a064cSDimitry Andric .value_or(0) > index)
252514f1b3e8SDimitry Andric child_valobj_sp =
25267fa27ce4SDimitry Andric root->GetSyntheticValue()->GetChildAtIndex(index);
252714f1b3e8SDimitry Andric if (child_valobj_sp) {
2528f034231aSEd Maste root = child_valobj_sp;
252914f1b3e8SDimitry Andric remainder =
253014f1b3e8SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ]
2531f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2532f034231aSEd Maste continue;
253314f1b3e8SDimitry Andric } else {
253414f1b3e8SDimitry Andric *reason_to_stop =
253514f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2536f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
253714f1b3e8SDimitry Andric return nullptr;
2538f034231aSEd Maste }
253914f1b3e8SDimitry Andric } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
254014f1b3e8SDimitry Andric if (*what_next ==
254114f1b3e8SDimitry Andric ValueObject::
254214f1b3e8SDimitry Andric eExpressionPathAftermathDereference && // if this is a
254314f1b3e8SDimitry Andric // ptr-to-scalar, I
254414f1b3e8SDimitry Andric // am accessing it
254514f1b3e8SDimitry Andric // by index and I
254614f1b3e8SDimitry Andric // would have
254714f1b3e8SDimitry Andric // deref'ed anyway,
254814f1b3e8SDimitry Andric // then do it now
254914f1b3e8SDimitry Andric // and use this as
255014f1b3e8SDimitry Andric // a bitfield
255114f1b3e8SDimitry Andric pointee_compiler_type_info.Test(eTypeIsScalar)) {
2552b76161e4SDimitry Andric Status error;
2553f034231aSEd Maste root = root->Dereference(error);
255414f1b3e8SDimitry Andric if (error.Fail() || !root) {
255514f1b3e8SDimitry Andric *reason_to_stop =
255614f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2557f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
255814f1b3e8SDimitry Andric return nullptr;
255914f1b3e8SDimitry Andric } else {
2560f034231aSEd Maste *what_next = eExpressionPathAftermathNothing;
2561f034231aSEd Maste continue;
2562f034231aSEd Maste }
256314f1b3e8SDimitry Andric } else {
256414f1b3e8SDimitry Andric if (root->GetCompilerType().GetMinimumLanguage() ==
256514f1b3e8SDimitry Andric eLanguageTypeObjC &&
256614f1b3e8SDimitry Andric pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
256714f1b3e8SDimitry Andric root->HasSyntheticValue() &&
256814f1b3e8SDimitry Andric (options.m_synthetic_children_traversal ==
256914f1b3e8SDimitry Andric GetValueForExpressionPathOptions::
257014f1b3e8SDimitry Andric SyntheticChildrenTraversal::ToSynthetic ||
257114f1b3e8SDimitry Andric options.m_synthetic_children_traversal ==
257214f1b3e8SDimitry Andric GetValueForExpressionPathOptions::
257314f1b3e8SDimitry Andric SyntheticChildrenTraversal::Both)) {
25747fa27ce4SDimitry Andric root = root->GetSyntheticValue()->GetChildAtIndex(index);
257514f1b3e8SDimitry Andric } else
25765e95aa85SEd Maste root = root->GetSyntheticArrayMember(index, true);
257714f1b3e8SDimitry Andric if (!root) {
257814f1b3e8SDimitry Andric *reason_to_stop =
257914f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2580f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
258114f1b3e8SDimitry Andric return nullptr;
258214f1b3e8SDimitry Andric } else {
258314f1b3e8SDimitry Andric remainder =
258414f1b3e8SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ]
2585f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2586f034231aSEd Maste continue;
2587f034231aSEd Maste }
2588f034231aSEd Maste }
258914f1b3e8SDimitry Andric } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
2590f034231aSEd Maste root = root->GetSyntheticBitFieldChild(index, index, true);
259114f1b3e8SDimitry Andric if (!root) {
259214f1b3e8SDimitry Andric *reason_to_stop =
259314f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2594f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
259514f1b3e8SDimitry Andric return nullptr;
259614f1b3e8SDimitry Andric } else // we do not know how to expand members of bitfields, so we
259714f1b3e8SDimitry Andric // just return and let the caller do any further processing
2598f034231aSEd Maste {
259914f1b3e8SDimitry Andric *reason_to_stop = ValueObject::
260014f1b3e8SDimitry Andric eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2601f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2602f034231aSEd Maste return root;
2603f034231aSEd Maste }
260414f1b3e8SDimitry Andric } else if (root_compiler_type_info.Test(eTypeIsVector)) {
26057fa27ce4SDimitry Andric root = root->GetChildAtIndex(index);
260614f1b3e8SDimitry Andric if (!root) {
260714f1b3e8SDimitry Andric *reason_to_stop =
260814f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2609f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2610f034231aSEd Maste return ValueObjectSP();
261114f1b3e8SDimitry Andric } else {
261214f1b3e8SDimitry Andric remainder =
261314f1b3e8SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ]
2614f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2615f034231aSEd Maste continue;
2616f034231aSEd Maste }
261714f1b3e8SDimitry Andric } else if (options.m_synthetic_children_traversal ==
261814f1b3e8SDimitry Andric GetValueForExpressionPathOptions::
261914f1b3e8SDimitry Andric SyntheticChildrenTraversal::ToSynthetic ||
262014f1b3e8SDimitry Andric options.m_synthetic_children_traversal ==
262114f1b3e8SDimitry Andric GetValueForExpressionPathOptions::
262214f1b3e8SDimitry Andric SyntheticChildrenTraversal::Both) {
2623f034231aSEd Maste if (root->HasSyntheticValue())
2624f034231aSEd Maste root = root->GetSyntheticValue();
262514f1b3e8SDimitry Andric else if (!root->IsSynthetic()) {
262614f1b3e8SDimitry Andric *reason_to_stop =
262714f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2628f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
262914f1b3e8SDimitry Andric return nullptr;
2630f034231aSEd Maste }
2631f73363f1SDimitry Andric // if we are here, then root itself is a synthetic VO.. should be
2632f73363f1SDimitry Andric // good to go
2633f034231aSEd Maste
263414f1b3e8SDimitry Andric if (!root) {
263514f1b3e8SDimitry Andric *reason_to_stop =
263614f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2637f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
263814f1b3e8SDimitry Andric return nullptr;
2639f034231aSEd Maste }
26407fa27ce4SDimitry Andric root = root->GetChildAtIndex(index);
264114f1b3e8SDimitry Andric if (!root) {
264214f1b3e8SDimitry Andric *reason_to_stop =
264314f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2644f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
264514f1b3e8SDimitry Andric return nullptr;
264614f1b3e8SDimitry Andric } else {
264714f1b3e8SDimitry Andric remainder =
264814f1b3e8SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ]
2649f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2650f034231aSEd Maste continue;
2651f034231aSEd Maste }
265214f1b3e8SDimitry Andric } else {
265314f1b3e8SDimitry Andric *reason_to_stop =
265414f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2655f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
265614f1b3e8SDimitry Andric return nullptr;
2657f034231aSEd Maste }
265814f1b3e8SDimitry Andric } else {
265914f1b3e8SDimitry Andric // we have a low and a high index
266014f1b3e8SDimitry Andric llvm::StringRef sleft, sright;
266114f1b3e8SDimitry Andric unsigned long low_index, high_index;
266214f1b3e8SDimitry Andric std::tie(sleft, sright) = bracket_expr.split('-');
266314f1b3e8SDimitry Andric if (sleft.getAsInteger(0, low_index) ||
266414f1b3e8SDimitry Andric sright.getAsInteger(0, high_index)) {
266514f1b3e8SDimitry Andric *reason_to_stop =
266614f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2667f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
266814f1b3e8SDimitry Andric return nullptr;
2669f034231aSEd Maste }
267014f1b3e8SDimitry Andric
267114f1b3e8SDimitry Andric if (low_index > high_index) // swap indices if required
267214f1b3e8SDimitry Andric std::swap(low_index, high_index);
267314f1b3e8SDimitry Andric
267414f1b3e8SDimitry Andric if (root_compiler_type_info.Test(
267514f1b3e8SDimitry Andric eTypeIsScalar)) // expansion only works for scalars
2676f034231aSEd Maste {
267714f1b3e8SDimitry Andric root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
267814f1b3e8SDimitry Andric if (!root) {
267914f1b3e8SDimitry Andric *reason_to_stop =
268014f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2681f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
268214f1b3e8SDimitry Andric return nullptr;
268314f1b3e8SDimitry Andric } else {
268414f1b3e8SDimitry Andric *reason_to_stop = ValueObject::
268514f1b3e8SDimitry Andric eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2686f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2687f034231aSEd Maste return root;
2688f034231aSEd Maste }
268914f1b3e8SDimitry Andric } else if (root_compiler_type_info.Test(
269014f1b3e8SDimitry Andric eTypeIsPointer) && // if this is a ptr-to-scalar, I am
269114f1b3e8SDimitry Andric // accessing it by index and I would
269214f1b3e8SDimitry Andric // have deref'ed anyway, then do it
269314f1b3e8SDimitry Andric // now and use this as a bitfield
269414f1b3e8SDimitry Andric *what_next ==
269514f1b3e8SDimitry Andric ValueObject::eExpressionPathAftermathDereference &&
269614f1b3e8SDimitry Andric pointee_compiler_type_info.Test(eTypeIsScalar)) {
2697b76161e4SDimitry Andric Status error;
2698f034231aSEd Maste root = root->Dereference(error);
269914f1b3e8SDimitry Andric if (error.Fail() || !root) {
270014f1b3e8SDimitry Andric *reason_to_stop =
270114f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2702f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
270314f1b3e8SDimitry Andric return nullptr;
270414f1b3e8SDimitry Andric } else {
2705f034231aSEd Maste *what_next = ValueObject::eExpressionPathAftermathNothing;
2706f034231aSEd Maste continue;
2707f034231aSEd Maste }
270814f1b3e8SDimitry Andric } else {
270914f1b3e8SDimitry Andric *reason_to_stop =
271014f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
2711f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
2712f034231aSEd Maste return root;
2713f034231aSEd Maste }
2714f034231aSEd Maste }
2715f034231aSEd Maste break;
2716f034231aSEd Maste }
2717f034231aSEd Maste default: // some non-separator is in the way
2718f034231aSEd Maste {
271914f1b3e8SDimitry Andric *reason_to_stop =
272014f1b3e8SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2721f034231aSEd Maste *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
272214f1b3e8SDimitry Andric return nullptr;
2723f034231aSEd Maste }
2724f034231aSEd Maste }
2725f034231aSEd Maste }
2726f034231aSEd Maste }
2727f034231aSEd Maste
Dump(Stream & s)2728ac9a064cSDimitry Andric llvm::Error ValueObject::Dump(Stream &s) {
2729ac9a064cSDimitry Andric return Dump(s, DumpValueObjectOptions(*this));
2730ac9a064cSDimitry Andric }
2731f034231aSEd Maste
Dump(Stream & s,const DumpValueObjectOptions & options)2732ac9a064cSDimitry Andric llvm::Error ValueObject::Dump(Stream &s,
2733ac9a064cSDimitry Andric const DumpValueObjectOptions &options) {
2734ac9a064cSDimitry Andric ValueObjectPrinter printer(*this, &s, options);
2735ac9a064cSDimitry Andric return printer.PrintValueObject();
2736f034231aSEd Maste }
2737f034231aSEd Maste
CreateConstantValue(ConstString name)27385f29bb8aSDimitry Andric ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
2739f034231aSEd Maste ValueObjectSP valobj_sp;
2740f034231aSEd Maste
274114f1b3e8SDimitry Andric if (UpdateValueIfNeeded(false) && m_error.Success()) {
2742f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
2743f034231aSEd Maste
2744f034231aSEd Maste DataExtractor data;
2745f034231aSEd Maste data.SetByteOrder(m_data.GetByteOrder());
2746f034231aSEd Maste data.SetAddressByteSize(m_data.GetAddressByteSize());
2747f034231aSEd Maste
274814f1b3e8SDimitry Andric if (IsBitfield()) {
2749f034231aSEd Maste Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
2750ead24645SDimitry Andric m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());
275114f1b3e8SDimitry Andric } else
2752ead24645SDimitry Andric m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
2753f034231aSEd Maste
275414f1b3e8SDimitry Andric valobj_sp = ValueObjectConstResult::Create(
275514f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
2756f034231aSEd Maste GetAddressOf());
2757f034231aSEd Maste }
2758f034231aSEd Maste
275914f1b3e8SDimitry Andric if (!valobj_sp) {
2760866dcdacSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
276114f1b3e8SDimitry Andric valobj_sp = ValueObjectConstResult::Create(
276214f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope(), m_error);
2763f034231aSEd Maste }
2764f034231aSEd Maste return valobj_sp;
2765f034231aSEd Maste }
2766f034231aSEd Maste
GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,bool synthValue)276714f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
276814f1b3e8SDimitry Andric lldb::DynamicValueType dynValue, bool synthValue) {
2769b1c73532SDimitry Andric ValueObjectSP result_sp;
277014f1b3e8SDimitry Andric switch (dynValue) {
2771205afe67SEd Maste case lldb::eDynamicCanRunTarget:
277214f1b3e8SDimitry Andric case lldb::eDynamicDontRunTarget: {
2773b1c73532SDimitry Andric if (!IsDynamic())
2774b1c73532SDimitry Andric result_sp = GetDynamicValue(dynValue);
277514f1b3e8SDimitry Andric } break;
277614f1b3e8SDimitry Andric case lldb::eNoDynamicValues: {
2777b1c73532SDimitry Andric if (IsDynamic())
2778b1c73532SDimitry Andric result_sp = GetStaticValue();
277914f1b3e8SDimitry Andric } break;
2780205afe67SEd Maste }
2781b1c73532SDimitry Andric if (!result_sp)
2782b1c73532SDimitry Andric result_sp = GetSP();
2783b1c73532SDimitry Andric assert(result_sp);
2784205afe67SEd Maste
2785b1c73532SDimitry Andric bool is_synthetic = result_sp->IsSynthetic();
2786b1c73532SDimitry Andric if (synthValue && !is_synthetic) {
2787b1c73532SDimitry Andric if (auto synth_sp = result_sp->GetSyntheticValue())
2788b1c73532SDimitry Andric return synth_sp;
2789205afe67SEd Maste }
2790b1c73532SDimitry Andric if (!synthValue && is_synthetic) {
2791b1c73532SDimitry Andric if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
2792b1c73532SDimitry Andric return non_synth_sp;
2793205afe67SEd Maste }
2794205afe67SEd Maste
2795205afe67SEd Maste return result_sp;
2796205afe67SEd Maste }
2797205afe67SEd Maste
Dereference(Status & error)2798b76161e4SDimitry Andric ValueObjectSP ValueObject::Dereference(Status &error) {
2799f034231aSEd Maste if (m_deref_valobj)
2800f034231aSEd Maste return m_deref_valobj->GetSP();
2801f034231aSEd Maste
2802e81d9d49SDimitry Andric const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
280314f1b3e8SDimitry Andric if (is_pointer_or_reference_type) {
2804f034231aSEd Maste bool omit_empty_base_classes = true;
2805f034231aSEd Maste bool ignore_array_bounds = false;
2806f034231aSEd Maste
2807f034231aSEd Maste std::string child_name_str;
2808f034231aSEd Maste uint32_t child_byte_size = 0;
2809f034231aSEd Maste int32_t child_byte_offset = 0;
2810f034231aSEd Maste uint32_t child_bitfield_bit_size = 0;
2811f034231aSEd Maste uint32_t child_bitfield_bit_offset = 0;
2812f034231aSEd Maste bool child_is_base_class = false;
2813f034231aSEd Maste bool child_is_deref_of_parent = false;
2814f034231aSEd Maste const bool transparent_pointers = false;
2815e81d9d49SDimitry Andric CompilerType compiler_type = GetCompilerType();
2816cfca06d7SDimitry Andric uint64_t language_flags = 0;
2817f034231aSEd Maste
2818f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
2819f034231aSEd Maste
2820ac9a064cSDimitry Andric CompilerType child_compiler_type;
2821ac9a064cSDimitry Andric auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(
282214f1b3e8SDimitry Andric &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
282314f1b3e8SDimitry Andric ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
282414f1b3e8SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
282514f1b3e8SDimitry Andric child_is_deref_of_parent, this, language_flags);
2826ac9a064cSDimitry Andric if (!child_compiler_type_or_err)
2827ac9a064cSDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
2828ac9a064cSDimitry Andric child_compiler_type_or_err.takeError(),
2829ac9a064cSDimitry Andric "could not find child: {0}");
2830ac9a064cSDimitry Andric else
2831ac9a064cSDimitry Andric child_compiler_type = *child_compiler_type_or_err;
2832ac9a064cSDimitry Andric
283314f1b3e8SDimitry Andric if (child_compiler_type && child_byte_size) {
2834f034231aSEd Maste ConstString child_name;
2835f034231aSEd Maste if (!child_name_str.empty())
2836f034231aSEd Maste child_name.SetCString(child_name_str.c_str());
2837f034231aSEd Maste
283814f1b3e8SDimitry Andric m_deref_valobj = new ValueObjectChild(
283914f1b3e8SDimitry Andric *this, child_compiler_type, child_name, child_byte_size,
284014f1b3e8SDimitry Andric child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
284114f1b3e8SDimitry Andric child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
2842e81d9d49SDimitry Andric language_flags);
2843f034231aSEd Maste }
2844cfca06d7SDimitry Andric
2845cfca06d7SDimitry Andric // In case of incomplete child compiler type, use the pointee type and try
2846cfca06d7SDimitry Andric // to recreate a new ValueObjectChild using it.
2847cfca06d7SDimitry Andric if (!m_deref_valobj) {
2848e3b55780SDimitry Andric // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
2849e3b55780SDimitry Andric // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
2850e3b55780SDimitry Andric if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
2851e3b55780SDimitry Andric HasSyntheticValue()) {
2852cfca06d7SDimitry Andric child_compiler_type = compiler_type.GetPointeeType();
2853cfca06d7SDimitry Andric
2854cfca06d7SDimitry Andric if (child_compiler_type) {
2855cfca06d7SDimitry Andric ConstString child_name;
2856cfca06d7SDimitry Andric if (!child_name_str.empty())
2857cfca06d7SDimitry Andric child_name.SetCString(child_name_str.c_str());
2858cfca06d7SDimitry Andric
2859cfca06d7SDimitry Andric m_deref_valobj = new ValueObjectChild(
2860cfca06d7SDimitry Andric *this, child_compiler_type, child_name, child_byte_size,
2861cfca06d7SDimitry Andric child_byte_offset, child_bitfield_bit_size,
2862cfca06d7SDimitry Andric child_bitfield_bit_offset, child_is_base_class,
2863cfca06d7SDimitry Andric child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
2864cfca06d7SDimitry Andric }
2865cfca06d7SDimitry Andric }
2866cfca06d7SDimitry Andric }
2867cfca06d7SDimitry Andric
286874a628f7SDimitry Andric } else if (HasSyntheticValue()) {
286974a628f7SDimitry Andric m_deref_valobj =
28707fa27ce4SDimitry Andric GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();
2871cfca06d7SDimitry Andric } else if (IsSynthetic()) {
28727fa27ce4SDimitry Andric m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
2873f034231aSEd Maste }
2874f034231aSEd Maste
287514f1b3e8SDimitry Andric if (m_deref_valobj) {
2876f034231aSEd Maste error.Clear();
2877f034231aSEd Maste return m_deref_valobj->GetSP();
287814f1b3e8SDimitry Andric } else {
2879f034231aSEd Maste StreamString strm;
2880cfca06d7SDimitry Andric GetExpressionPath(strm);
2881f034231aSEd Maste
2882e81d9d49SDimitry Andric if (is_pointer_or_reference_type)
288314f1b3e8SDimitry Andric error.SetErrorStringWithFormat("dereference failed: (%s) %s",
288414f1b3e8SDimitry Andric GetTypeName().AsCString("<invalid type>"),
288514f1b3e8SDimitry Andric strm.GetData());
2886f034231aSEd Maste else
288714f1b3e8SDimitry Andric error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
288814f1b3e8SDimitry Andric GetTypeName().AsCString("<invalid type>"),
288914f1b3e8SDimitry Andric strm.GetData());
2890f034231aSEd Maste return ValueObjectSP();
2891f034231aSEd Maste }
2892f034231aSEd Maste }
2893f034231aSEd Maste
AddressOf(Status & error)2894b76161e4SDimitry Andric ValueObjectSP ValueObject::AddressOf(Status &error) {
2895f034231aSEd Maste if (m_addr_of_valobj_sp)
2896f034231aSEd Maste return m_addr_of_valobj_sp;
2897f034231aSEd Maste
2898f034231aSEd Maste AddressType address_type = eAddressTypeInvalid;
2899f034231aSEd Maste const bool scalar_is_load_address = false;
2900f034231aSEd Maste addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
2901f034231aSEd Maste error.Clear();
2902ac9a064cSDimitry Andric if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
2903ac9a064cSDimitry Andric switch (address_type) {
2904ac9a064cSDimitry Andric case eAddressTypeInvalid: {
2905f034231aSEd Maste StreamString expr_path_strm;
2906cfca06d7SDimitry Andric GetExpressionPath(expr_path_strm);
2907ac9a064cSDimitry Andric error.SetErrorStringWithFormat("'%s' is not in memory",
2908ac9a064cSDimitry Andric expr_path_strm.GetData());
2909ac9a064cSDimitry Andric } break;
2910f034231aSEd Maste
2911f034231aSEd Maste case eAddressTypeFile:
291214f1b3e8SDimitry Andric case eAddressTypeLoad: {
2913e81d9d49SDimitry Andric CompilerType compiler_type = GetCompilerType();
2914ac9a064cSDimitry Andric if (compiler_type) {
29154df029ccSDimitry Andric std::string name(1, '&');
29164df029ccSDimitry Andric name.append(m_name.AsCString(""));
2917ac9a064cSDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
29184df029ccSDimitry Andric m_addr_of_valobj_sp = ValueObjectConstResult::Create(
2919ac9a064cSDimitry Andric exe_ctx.GetBestExecutionContextScope(),
2920ac9a064cSDimitry Andric compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
29214df029ccSDimitry Andric eAddressTypeInvalid, m_data.GetAddressByteSize());
2922ac9a064cSDimitry Andric }
2923ac9a064cSDimitry Andric } break;
2924ac9a064cSDimitry Andric default:
2925ac9a064cSDimitry Andric break;
2926ac9a064cSDimitry Andric }
2927ac9a064cSDimitry Andric } else {
2928ac9a064cSDimitry Andric StreamString expr_path_strm;
2929ac9a064cSDimitry Andric GetExpressionPath(expr_path_strm);
2930ac9a064cSDimitry Andric error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
2931ac9a064cSDimitry Andric expr_path_strm.GetData());
2932ac9a064cSDimitry Andric }
2933ac9a064cSDimitry Andric
2934f034231aSEd Maste return m_addr_of_valobj_sp;
2935f034231aSEd Maste }
2936f034231aSEd Maste
DoCast(const CompilerType & compiler_type)29377fa27ce4SDimitry Andric ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
2938e81d9d49SDimitry Andric return ValueObjectCast::Create(*this, GetName(), compiler_type);
2939f034231aSEd Maste }
2940f034231aSEd Maste
Cast(const CompilerType & compiler_type)29417fa27ce4SDimitry Andric ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
29427fa27ce4SDimitry Andric // Only allow casts if the original type is equal or larger than the cast
2943ac9a064cSDimitry Andric // type, unless we know this is a load address. Getting the size wrong for
2944ac9a064cSDimitry Andric // a host side storage could leak lldb memory, so we absolutely want to
2945ac9a064cSDimitry Andric // prevent that. We may not always get the right value, for instance if we
2946ac9a064cSDimitry Andric // have an expression result value that's copied into a storage location in
2947ac9a064cSDimitry Andric // the target may not have copied enough memory. I'm not trying to fix that
2948ac9a064cSDimitry Andric // here, I'm just making Cast from a smaller to a larger possible in all the
2949ac9a064cSDimitry Andric // cases where that doesn't risk making a Value out of random lldb memory.
2950ac9a064cSDimitry Andric // You have to check the ValueObject's Value for the address types, since
2951ac9a064cSDimitry Andric // ValueObjects that use live addresses will tell you they fetch data from the
2952ac9a064cSDimitry Andric // live address, but once they are made, they actually don't.
2953ac9a064cSDimitry Andric // FIXME: Can we make ValueObject's with a live address fetch "more data" from
2954ac9a064cSDimitry Andric // the live address if it is still valid?
2955ac9a064cSDimitry Andric
29567fa27ce4SDimitry Andric Status error;
29577fa27ce4SDimitry Andric CompilerType my_type = GetCompilerType();
29587fa27ce4SDimitry Andric
29597fa27ce4SDimitry Andric ExecutionContextScope *exe_scope
29607fa27ce4SDimitry Andric = ExecutionContext(GetExecutionContextRef())
29617fa27ce4SDimitry Andric .GetBestExecutionContextScope();
29627fa27ce4SDimitry Andric if (compiler_type.GetByteSize(exe_scope)
2963ac9a064cSDimitry Andric <= GetCompilerType().GetByteSize(exe_scope)
2964ac9a064cSDimitry Andric || m_value.GetValueType() == Value::ValueType::LoadAddress)
29657fa27ce4SDimitry Andric return DoCast(compiler_type);
2966ac9a064cSDimitry Andric
29677fa27ce4SDimitry Andric error.SetErrorString("Can only cast to a type that is equal to or smaller "
29687fa27ce4SDimitry Andric "than the orignal type.");
29697fa27ce4SDimitry Andric
29707fa27ce4SDimitry Andric return ValueObjectConstResult::Create(
29717fa27ce4SDimitry Andric ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
29727fa27ce4SDimitry Andric error);
29737fa27ce4SDimitry Andric }
29747fa27ce4SDimitry Andric
Clone(ConstString new_name)29755f29bb8aSDimitry Andric lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
297674a628f7SDimitry Andric return ValueObjectCast::Create(*this, new_name, GetCompilerType());
297774a628f7SDimitry Andric }
297874a628f7SDimitry Andric
CastPointerType(const char * name,CompilerType & compiler_type)297914f1b3e8SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name,
298014f1b3e8SDimitry Andric CompilerType &compiler_type) {
2981f034231aSEd Maste ValueObjectSP valobj_sp;
2982f034231aSEd Maste AddressType address_type;
2983f034231aSEd Maste addr_t ptr_value = GetPointerValue(&address_type);
2984f034231aSEd Maste
298514f1b3e8SDimitry Andric if (ptr_value != LLDB_INVALID_ADDRESS) {
2986f034231aSEd Maste Address ptr_addr(ptr_value);
2987f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
298814f1b3e8SDimitry Andric valobj_sp = ValueObjectMemory::Create(
298914f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
2990f034231aSEd Maste }
2991f034231aSEd Maste return valobj_sp;
2992f034231aSEd Maste }
2993f034231aSEd Maste
CastPointerType(const char * name,TypeSP & type_sp)299414f1b3e8SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
2995f034231aSEd Maste ValueObjectSP valobj_sp;
2996f034231aSEd Maste AddressType address_type;
2997f034231aSEd Maste addr_t ptr_value = GetPointerValue(&address_type);
2998f034231aSEd Maste
299914f1b3e8SDimitry Andric if (ptr_value != LLDB_INVALID_ADDRESS) {
3000f034231aSEd Maste Address ptr_addr(ptr_value);
3001f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
300214f1b3e8SDimitry Andric valobj_sp = ValueObjectMemory::Create(
300314f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
3004f034231aSEd Maste }
3005f034231aSEd Maste return valobj_sp;
3006f034231aSEd Maste }
3007f034231aSEd Maste
GetLoadAddress()3008ac9a064cSDimitry Andric lldb::addr_t ValueObject::GetLoadAddress() {
3009ac9a064cSDimitry Andric lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
3010ac9a064cSDimitry Andric if (auto target_sp = GetTargetSP()) {
3011ac9a064cSDimitry Andric const bool scalar_is_load_address = true;
3012ac9a064cSDimitry Andric AddressType addr_type;
3013ac9a064cSDimitry Andric addr_value = GetAddressOf(scalar_is_load_address, &addr_type);
3014ac9a064cSDimitry Andric if (addr_type == eAddressTypeFile) {
3015ac9a064cSDimitry Andric lldb::ModuleSP module_sp(GetModule());
3016ac9a064cSDimitry Andric if (!module_sp)
3017ac9a064cSDimitry Andric addr_value = LLDB_INVALID_ADDRESS;
3018ac9a064cSDimitry Andric else {
3019ac9a064cSDimitry Andric Address tmp_addr;
3020ac9a064cSDimitry Andric module_sp->ResolveFileAddress(addr_value, tmp_addr);
3021ac9a064cSDimitry Andric addr_value = tmp_addr.GetLoadAddress(target_sp.get());
3022ac9a064cSDimitry Andric }
3023ac9a064cSDimitry Andric } else if (addr_type == eAddressTypeHost ||
3024ac9a064cSDimitry Andric addr_type == eAddressTypeInvalid)
3025ac9a064cSDimitry Andric addr_value = LLDB_INVALID_ADDRESS;
3026ac9a064cSDimitry Andric }
3027ac9a064cSDimitry Andric return addr_value;
3028ac9a064cSDimitry Andric }
3029ac9a064cSDimitry Andric
CastDerivedToBaseType(CompilerType type,const llvm::ArrayRef<uint32_t> & base_type_indices)3030ac9a064cSDimitry Andric llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(
3031ac9a064cSDimitry Andric CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {
3032ac9a064cSDimitry Andric // Make sure the starting type and the target type are both valid for this
3033ac9a064cSDimitry Andric // type of cast; otherwise return the shared pointer to the original
3034ac9a064cSDimitry Andric // (unchanged) ValueObject.
3035ac9a064cSDimitry Andric if (!type.IsPointerType() && !type.IsReferenceType())
3036ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3037ac9a064cSDimitry Andric "Invalid target type: should be a pointer or a reference",
3038ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3039ac9a064cSDimitry Andric
3040ac9a064cSDimitry Andric CompilerType start_type = GetCompilerType();
3041ac9a064cSDimitry Andric if (start_type.IsReferenceType())
3042ac9a064cSDimitry Andric start_type = start_type.GetNonReferenceType();
3043ac9a064cSDimitry Andric
3044ac9a064cSDimitry Andric auto target_record_type =
3045ac9a064cSDimitry Andric type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
3046ac9a064cSDimitry Andric auto start_record_type =
3047ac9a064cSDimitry Andric start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
3048ac9a064cSDimitry Andric
3049ac9a064cSDimitry Andric if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
3050ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3051ac9a064cSDimitry Andric "Underlying start & target types should be record types",
3052ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3053ac9a064cSDimitry Andric
3054ac9a064cSDimitry Andric if (target_record_type.CompareTypes(start_record_type))
3055ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3056ac9a064cSDimitry Andric "Underlying start & target types should be different",
3057ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3058ac9a064cSDimitry Andric
3059ac9a064cSDimitry Andric if (base_type_indices.empty())
3060ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3061ac9a064cSDimitry Andric "Children sequence must be non-empty", llvm::inconvertibleErrorCode());
3062ac9a064cSDimitry Andric
3063ac9a064cSDimitry Andric // Both the starting & target types are valid for the cast, and the list of
3064ac9a064cSDimitry Andric // base class indices is non-empty, so we can proceed with the cast.
3065ac9a064cSDimitry Andric
3066ac9a064cSDimitry Andric lldb::TargetSP target = GetTargetSP();
3067ac9a064cSDimitry Andric // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
3068ac9a064cSDimitry Andric lldb::ValueObjectSP inner_value = GetSP();
3069ac9a064cSDimitry Andric
3070ac9a064cSDimitry Andric for (const uint32_t i : base_type_indices)
3071ac9a064cSDimitry Andric // Create synthetic value if needed.
3072ac9a064cSDimitry Andric inner_value =
3073ac9a064cSDimitry Andric inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);
3074ac9a064cSDimitry Andric
3075ac9a064cSDimitry Andric // At this point type of `inner_value` should be the dereferenced target
3076ac9a064cSDimitry Andric // type.
3077ac9a064cSDimitry Andric CompilerType inner_value_type = inner_value->GetCompilerType();
3078ac9a064cSDimitry Andric if (type.IsPointerType()) {
3079ac9a064cSDimitry Andric if (!inner_value_type.CompareTypes(type.GetPointeeType()))
3080ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3081ac9a064cSDimitry Andric "casted value doesn't match the desired type",
3082ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3083ac9a064cSDimitry Andric
3084ac9a064cSDimitry Andric uintptr_t addr = inner_value->GetLoadAddress();
3085ac9a064cSDimitry Andric llvm::StringRef name = "";
3086ac9a064cSDimitry Andric ExecutionContext exe_ctx(target.get(), false);
3087ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,
3088ac9a064cSDimitry Andric /* do deref */ false);
3089ac9a064cSDimitry Andric }
3090ac9a064cSDimitry Andric
3091ac9a064cSDimitry Andric // At this point the target type should be a reference.
3092ac9a064cSDimitry Andric if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))
3093ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3094ac9a064cSDimitry Andric "casted value doesn't match the desired type",
3095ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3096ac9a064cSDimitry Andric
3097ac9a064cSDimitry Andric return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
3098ac9a064cSDimitry Andric }
3099ac9a064cSDimitry Andric
3100ac9a064cSDimitry Andric llvm::Expected<lldb::ValueObjectSP>
CastBaseToDerivedType(CompilerType type,uint64_t offset)3101ac9a064cSDimitry Andric ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
3102ac9a064cSDimitry Andric // Make sure the starting type and the target type are both valid for this
3103ac9a064cSDimitry Andric // type of cast; otherwise return the shared pointer to the original
3104ac9a064cSDimitry Andric // (unchanged) ValueObject.
3105ac9a064cSDimitry Andric if (!type.IsPointerType() && !type.IsReferenceType())
3106ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3107ac9a064cSDimitry Andric "Invalid target type: should be a pointer or a reference",
3108ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3109ac9a064cSDimitry Andric
3110ac9a064cSDimitry Andric CompilerType start_type = GetCompilerType();
3111ac9a064cSDimitry Andric if (start_type.IsReferenceType())
3112ac9a064cSDimitry Andric start_type = start_type.GetNonReferenceType();
3113ac9a064cSDimitry Andric
3114ac9a064cSDimitry Andric auto target_record_type =
3115ac9a064cSDimitry Andric type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
3116ac9a064cSDimitry Andric auto start_record_type =
3117ac9a064cSDimitry Andric start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
3118ac9a064cSDimitry Andric
3119ac9a064cSDimitry Andric if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
3120ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3121ac9a064cSDimitry Andric "Underlying start & target types should be record types",
3122ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3123ac9a064cSDimitry Andric
3124ac9a064cSDimitry Andric if (target_record_type.CompareTypes(start_record_type))
3125ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3126ac9a064cSDimitry Andric "Underlying start & target types should be different",
3127ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3128ac9a064cSDimitry Andric
3129ac9a064cSDimitry Andric CompilerType virtual_base;
3130ac9a064cSDimitry Andric if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {
3131ac9a064cSDimitry Andric if (!virtual_base.IsValid())
3132ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3133ac9a064cSDimitry Andric "virtual base should be valid", llvm::inconvertibleErrorCode());
3134ac9a064cSDimitry Andric return llvm::make_error<llvm::StringError>(
3135ac9a064cSDimitry Andric llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +
3136ac9a064cSDimitry Andric type.TypeDescription() + " via virtual base " +
3137ac9a064cSDimitry Andric virtual_base.TypeDescription()),
3138ac9a064cSDimitry Andric llvm::inconvertibleErrorCode());
3139ac9a064cSDimitry Andric }
3140ac9a064cSDimitry Andric
3141ac9a064cSDimitry Andric // Both the starting & target types are valid for the cast, so we can
3142ac9a064cSDimitry Andric // proceed with the cast.
3143ac9a064cSDimitry Andric
3144ac9a064cSDimitry Andric lldb::TargetSP target = GetTargetSP();
3145ac9a064cSDimitry Andric auto pointer_type =
3146ac9a064cSDimitry Andric type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();
3147ac9a064cSDimitry Andric
3148ac9a064cSDimitry Andric uintptr_t addr =
3149ac9a064cSDimitry Andric type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();
3150ac9a064cSDimitry Andric
3151ac9a064cSDimitry Andric llvm::StringRef name = "";
3152ac9a064cSDimitry Andric ExecutionContext exe_ctx(target.get(), false);
3153ac9a064cSDimitry Andric lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(
3154ac9a064cSDimitry Andric name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);
3155ac9a064cSDimitry Andric
3156ac9a064cSDimitry Andric if (type.IsPointerType())
3157ac9a064cSDimitry Andric return value;
3158ac9a064cSDimitry Andric
3159ac9a064cSDimitry Andric // At this point the target type is a reference. Since `value` is a pointer,
3160ac9a064cSDimitry Andric // it has to be dereferenced.
3161ac9a064cSDimitry Andric Status error;
3162ac9a064cSDimitry Andric return value->Dereference(error);
3163ac9a064cSDimitry Andric }
3164ac9a064cSDimitry Andric
CastToBasicType(CompilerType type)3165ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
3166ac9a064cSDimitry Andric bool is_scalar = GetCompilerType().IsScalarType();
3167ac9a064cSDimitry Andric bool is_enum = GetCompilerType().IsEnumerationType();
3168ac9a064cSDimitry Andric bool is_pointer =
3169ac9a064cSDimitry Andric GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();
3170ac9a064cSDimitry Andric bool is_float = GetCompilerType().IsFloat();
3171ac9a064cSDimitry Andric bool is_integer = GetCompilerType().IsInteger();
3172ac9a064cSDimitry Andric
3173ac9a064cSDimitry Andric if (!type.IsScalarType()) {
3174ac9a064cSDimitry Andric m_error.SetErrorString("target type must be a scalar");
3175ac9a064cSDimitry Andric return GetSP();
3176ac9a064cSDimitry Andric }
3177ac9a064cSDimitry Andric
3178ac9a064cSDimitry Andric if (!is_scalar && !is_enum && !is_pointer) {
3179ac9a064cSDimitry Andric m_error.SetErrorString("argument must be a scalar, enum, or pointer");
3180ac9a064cSDimitry Andric return GetSP();
3181ac9a064cSDimitry Andric }
3182ac9a064cSDimitry Andric
3183ac9a064cSDimitry Andric lldb::TargetSP target = GetTargetSP();
3184ac9a064cSDimitry Andric uint64_t type_byte_size = 0;
3185ac9a064cSDimitry Andric uint64_t val_byte_size = 0;
3186ac9a064cSDimitry Andric if (auto temp = type.GetByteSize(target.get()))
3187ac9a064cSDimitry Andric type_byte_size = temp.value();
3188ac9a064cSDimitry Andric if (auto temp = GetCompilerType().GetByteSize(target.get()))
3189ac9a064cSDimitry Andric val_byte_size = temp.value();
3190ac9a064cSDimitry Andric
3191ac9a064cSDimitry Andric if (is_pointer) {
3192ac9a064cSDimitry Andric if (!type.IsInteger() && !type.IsBoolean()) {
3193ac9a064cSDimitry Andric m_error.SetErrorString("target type must be an integer or boolean");
3194ac9a064cSDimitry Andric return GetSP();
3195ac9a064cSDimitry Andric }
3196ac9a064cSDimitry Andric if (!type.IsBoolean() && type_byte_size < val_byte_size) {
3197ac9a064cSDimitry Andric m_error.SetErrorString(
3198ac9a064cSDimitry Andric "target type cannot be smaller than the pointer type");
3199ac9a064cSDimitry Andric return GetSP();
3200ac9a064cSDimitry Andric }
3201ac9a064cSDimitry Andric }
3202ac9a064cSDimitry Andric
3203ac9a064cSDimitry Andric if (type.IsBoolean()) {
3204ac9a064cSDimitry Andric if (!is_scalar || is_integer)
3205ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromBool(
3206ac9a064cSDimitry Andric target, GetValueAsUnsigned(0) != 0, "result");
3207ac9a064cSDimitry Andric else if (is_scalar && is_float) {
3208ac9a064cSDimitry Andric auto float_value_or_err = GetValueAsAPFloat();
3209ac9a064cSDimitry Andric if (float_value_or_err)
3210ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromBool(
3211ac9a064cSDimitry Andric target, !float_value_or_err->isZero(), "result");
3212ac9a064cSDimitry Andric else {
3213ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3214ac9a064cSDimitry Andric "cannot get value as APFloat: %s",
3215ac9a064cSDimitry Andric llvm::toString(float_value_or_err.takeError()).c_str());
3216ac9a064cSDimitry Andric return GetSP();
3217ac9a064cSDimitry Andric }
3218ac9a064cSDimitry Andric }
3219ac9a064cSDimitry Andric }
3220ac9a064cSDimitry Andric
3221ac9a064cSDimitry Andric if (type.IsInteger()) {
3222ac9a064cSDimitry Andric if (!is_scalar || is_integer) {
3223ac9a064cSDimitry Andric auto int_value_or_err = GetValueAsAPSInt();
3224ac9a064cSDimitry Andric if (int_value_or_err) {
3225ac9a064cSDimitry Andric // Get the value as APSInt and extend or truncate it to the requested
3226ac9a064cSDimitry Andric // size.
3227ac9a064cSDimitry Andric llvm::APSInt ext =
3228ac9a064cSDimitry Andric int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
3229ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
3230ac9a064cSDimitry Andric "result");
3231ac9a064cSDimitry Andric } else {
3232ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3233ac9a064cSDimitry Andric "cannot get value as APSInt: %s",
3234ac9a064cSDimitry Andric llvm::toString(int_value_or_err.takeError()).c_str());
3235ac9a064cSDimitry Andric ;
3236ac9a064cSDimitry Andric return GetSP();
3237ac9a064cSDimitry Andric }
3238ac9a064cSDimitry Andric } else if (is_scalar && is_float) {
3239ac9a064cSDimitry Andric llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
3240ac9a064cSDimitry Andric bool is_exact;
3241ac9a064cSDimitry Andric auto float_value_or_err = GetValueAsAPFloat();
3242ac9a064cSDimitry Andric if (float_value_or_err) {
3243ac9a064cSDimitry Andric llvm::APFloatBase::opStatus status =
3244ac9a064cSDimitry Andric float_value_or_err->convertToInteger(
3245ac9a064cSDimitry Andric integer, llvm::APFloat::rmTowardZero, &is_exact);
3246ac9a064cSDimitry Andric
3247ac9a064cSDimitry Andric // Casting floating point values that are out of bounds of the target
3248ac9a064cSDimitry Andric // type is undefined behaviour.
3249ac9a064cSDimitry Andric if (status & llvm::APFloatBase::opInvalidOp) {
3250ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3251ac9a064cSDimitry Andric "invalid type cast detected: %s",
3252ac9a064cSDimitry Andric llvm::toString(float_value_or_err.takeError()).c_str());
3253ac9a064cSDimitry Andric return GetSP();
3254ac9a064cSDimitry Andric }
3255ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
3256ac9a064cSDimitry Andric "result");
3257ac9a064cSDimitry Andric }
3258ac9a064cSDimitry Andric }
3259ac9a064cSDimitry Andric }
3260ac9a064cSDimitry Andric
3261ac9a064cSDimitry Andric if (type.IsFloat()) {
3262ac9a064cSDimitry Andric if (!is_scalar) {
3263ac9a064cSDimitry Andric auto int_value_or_err = GetValueAsAPSInt();
3264ac9a064cSDimitry Andric if (int_value_or_err) {
3265ac9a064cSDimitry Andric llvm::APSInt ext =
3266ac9a064cSDimitry Andric int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
3267ac9a064cSDimitry Andric Scalar scalar_int(ext);
3268ac9a064cSDimitry Andric llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
3269ac9a064cSDimitry Andric type.GetCanonicalType().GetBasicTypeEnumeration());
3270ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3271ac9a064cSDimitry Andric "result");
3272ac9a064cSDimitry Andric } else {
3273ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3274ac9a064cSDimitry Andric "cannot get value as APSInt: %s",
3275ac9a064cSDimitry Andric llvm::toString(int_value_or_err.takeError()).c_str());
3276ac9a064cSDimitry Andric return GetSP();
3277ac9a064cSDimitry Andric }
3278ac9a064cSDimitry Andric } else {
3279ac9a064cSDimitry Andric if (is_integer) {
3280ac9a064cSDimitry Andric auto int_value_or_err = GetValueAsAPSInt();
3281ac9a064cSDimitry Andric if (int_value_or_err) {
3282ac9a064cSDimitry Andric Scalar scalar_int(*int_value_or_err);
3283ac9a064cSDimitry Andric llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
3284ac9a064cSDimitry Andric type.GetCanonicalType().GetBasicTypeEnumeration());
3285ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3286ac9a064cSDimitry Andric "result");
3287ac9a064cSDimitry Andric } else {
3288ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3289ac9a064cSDimitry Andric "cannot get value as APSInt: %s",
3290ac9a064cSDimitry Andric llvm::toString(int_value_or_err.takeError()).c_str());
3291ac9a064cSDimitry Andric return GetSP();
3292ac9a064cSDimitry Andric }
3293ac9a064cSDimitry Andric }
3294ac9a064cSDimitry Andric if (is_float) {
3295ac9a064cSDimitry Andric auto float_value_or_err = GetValueAsAPFloat();
3296ac9a064cSDimitry Andric if (float_value_or_err) {
3297ac9a064cSDimitry Andric Scalar scalar_float(*float_value_or_err);
3298ac9a064cSDimitry Andric llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
3299ac9a064cSDimitry Andric type.GetCanonicalType().GetBasicTypeEnumeration());
3300ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3301ac9a064cSDimitry Andric "result");
3302ac9a064cSDimitry Andric } else {
3303ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3304ac9a064cSDimitry Andric "cannot get value as APFloat: %s",
3305ac9a064cSDimitry Andric llvm::toString(float_value_or_err.takeError()).c_str());
3306ac9a064cSDimitry Andric return GetSP();
3307ac9a064cSDimitry Andric }
3308ac9a064cSDimitry Andric }
3309ac9a064cSDimitry Andric }
3310ac9a064cSDimitry Andric }
3311ac9a064cSDimitry Andric
3312ac9a064cSDimitry Andric m_error.SetErrorString("Unable to perform requested cast");
3313ac9a064cSDimitry Andric return GetSP();
3314ac9a064cSDimitry Andric }
3315ac9a064cSDimitry Andric
CastToEnumType(CompilerType type)3316ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
3317ac9a064cSDimitry Andric bool is_enum = GetCompilerType().IsEnumerationType();
3318ac9a064cSDimitry Andric bool is_integer = GetCompilerType().IsInteger();
3319ac9a064cSDimitry Andric bool is_float = GetCompilerType().IsFloat();
3320ac9a064cSDimitry Andric
3321ac9a064cSDimitry Andric if (!is_enum && !is_integer && !is_float) {
3322ac9a064cSDimitry Andric m_error.SetErrorString("argument must be an integer, a float, or an enum");
3323ac9a064cSDimitry Andric return GetSP();
3324ac9a064cSDimitry Andric }
3325ac9a064cSDimitry Andric
3326ac9a064cSDimitry Andric if (!type.IsEnumerationType()) {
3327ac9a064cSDimitry Andric m_error.SetErrorString("target type must be an enum");
3328ac9a064cSDimitry Andric return GetSP();
3329ac9a064cSDimitry Andric }
3330ac9a064cSDimitry Andric
3331ac9a064cSDimitry Andric lldb::TargetSP target = GetTargetSP();
3332ac9a064cSDimitry Andric uint64_t byte_size = 0;
3333ac9a064cSDimitry Andric if (auto temp = type.GetByteSize(target.get()))
3334ac9a064cSDimitry Andric byte_size = temp.value();
3335ac9a064cSDimitry Andric
3336ac9a064cSDimitry Andric if (is_float) {
3337ac9a064cSDimitry Andric llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
3338ac9a064cSDimitry Andric bool is_exact;
3339ac9a064cSDimitry Andric auto value_or_err = GetValueAsAPFloat();
3340ac9a064cSDimitry Andric if (value_or_err) {
3341ac9a064cSDimitry Andric llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(
3342ac9a064cSDimitry Andric integer, llvm::APFloat::rmTowardZero, &is_exact);
3343ac9a064cSDimitry Andric
3344ac9a064cSDimitry Andric // Casting floating point values that are out of bounds of the target
3345ac9a064cSDimitry Andric // type is undefined behaviour.
3346ac9a064cSDimitry Andric if (status & llvm::APFloatBase::opInvalidOp) {
3347ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3348ac9a064cSDimitry Andric "invalid type cast detected: %s",
3349ac9a064cSDimitry Andric llvm::toString(value_or_err.takeError()).c_str());
3350ac9a064cSDimitry Andric return GetSP();
3351ac9a064cSDimitry Andric }
3352ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
3353ac9a064cSDimitry Andric "result");
3354ac9a064cSDimitry Andric } else {
3355ac9a064cSDimitry Andric m_error.SetErrorString("cannot get value as APFloat");
3356ac9a064cSDimitry Andric return GetSP();
3357ac9a064cSDimitry Andric }
3358ac9a064cSDimitry Andric } else {
3359ac9a064cSDimitry Andric // Get the value as APSInt and extend or truncate it to the requested size.
3360ac9a064cSDimitry Andric auto value_or_err = GetValueAsAPSInt();
3361ac9a064cSDimitry Andric if (value_or_err) {
3362ac9a064cSDimitry Andric llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);
3363ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
3364ac9a064cSDimitry Andric "result");
3365ac9a064cSDimitry Andric } else {
3366ac9a064cSDimitry Andric m_error.SetErrorStringWithFormat(
3367ac9a064cSDimitry Andric "cannot get value as APSInt: %s",
3368ac9a064cSDimitry Andric llvm::toString(value_or_err.takeError()).c_str());
3369ac9a064cSDimitry Andric return GetSP();
3370ac9a064cSDimitry Andric }
3371ac9a064cSDimitry Andric }
3372ac9a064cSDimitry Andric m_error.SetErrorString("Cannot perform requested cast");
3373ac9a064cSDimitry Andric return GetSP();
3374ac9a064cSDimitry Andric }
3375ac9a064cSDimitry Andric
EvaluationPoint()3376344a3780SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
3377f034231aSEd Maste
EvaluationPoint(ExecutionContextScope * exe_scope,bool use_selected)337814f1b3e8SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
337914f1b3e8SDimitry Andric bool use_selected)
3380145449b1SDimitry Andric : m_mod_id(), m_exe_ctx_ref() {
3381f034231aSEd Maste ExecutionContext exe_ctx(exe_scope);
3382f034231aSEd Maste TargetSP target_sp(exe_ctx.GetTargetSP());
338314f1b3e8SDimitry Andric if (target_sp) {
3384f034231aSEd Maste m_exe_ctx_ref.SetTargetSP(target_sp);
3385f034231aSEd Maste ProcessSP process_sp(exe_ctx.GetProcessSP());
3386f034231aSEd Maste if (!process_sp)
3387f034231aSEd Maste process_sp = target_sp->GetProcessSP();
3388f034231aSEd Maste
338914f1b3e8SDimitry Andric if (process_sp) {
3390f034231aSEd Maste m_mod_id = process_sp->GetModID();
3391f034231aSEd Maste m_exe_ctx_ref.SetProcessSP(process_sp);
3392f034231aSEd Maste
3393f034231aSEd Maste ThreadSP thread_sp(exe_ctx.GetThreadSP());
3394f034231aSEd Maste
339514f1b3e8SDimitry Andric if (!thread_sp) {
3396f034231aSEd Maste if (use_selected)
3397f034231aSEd Maste thread_sp = process_sp->GetThreadList().GetSelectedThread();
3398f034231aSEd Maste }
3399f034231aSEd Maste
340014f1b3e8SDimitry Andric if (thread_sp) {
3401f034231aSEd Maste m_exe_ctx_ref.SetThreadSP(thread_sp);
3402f034231aSEd Maste
3403f034231aSEd Maste StackFrameSP frame_sp(exe_ctx.GetFrameSP());
340414f1b3e8SDimitry Andric if (!frame_sp) {
3405f034231aSEd Maste if (use_selected)
34067fa27ce4SDimitry Andric frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
3407f034231aSEd Maste }
3408f034231aSEd Maste if (frame_sp)
3409f034231aSEd Maste m_exe_ctx_ref.SetFrameSP(frame_sp);
3410f034231aSEd Maste }
3411f034231aSEd Maste }
3412f034231aSEd Maste }
3413f034231aSEd Maste }
3414f034231aSEd Maste
EvaluationPoint(const ValueObject::EvaluationPoint & rhs)341514f1b3e8SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(
341614f1b3e8SDimitry Andric const ValueObject::EvaluationPoint &rhs)
3417145449b1SDimitry Andric : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}
3418f034231aSEd Maste
3419344a3780SDimitry Andric ValueObject::EvaluationPoint::~EvaluationPoint() = default;
3420f034231aSEd Maste
342114f1b3e8SDimitry Andric // This function checks the EvaluationPoint against the current process state.
3422f73363f1SDimitry Andric // If the current state matches the evaluation point, or the evaluation point
3423f73363f1SDimitry Andric // is already invalid, then we return false, meaning "no change". If the
3424f73363f1SDimitry Andric // current state is different, we update our state, and return true meaning
3425f73363f1SDimitry Andric // "yes, change". If we did see a change, we also set m_needs_update to true,
3426f73363f1SDimitry Andric // so future calls to NeedsUpdate will return true. exe_scope will be set to
3427f73363f1SDimitry Andric // the current execution context scope.
3428f034231aSEd Maste
SyncWithProcessState(bool accept_invalid_exe_ctx)342914f1b3e8SDimitry Andric bool ValueObject::EvaluationPoint::SyncWithProcessState(
343014f1b3e8SDimitry Andric bool accept_invalid_exe_ctx) {
3431f73363f1SDimitry Andric // Start with the target, if it is NULL, then we're obviously not going to
3432f73363f1SDimitry Andric // get any further:
3433866dcdacSEd Maste const bool thread_and_frame_only_if_stopped = true;
343414f1b3e8SDimitry Andric ExecutionContext exe_ctx(
343514f1b3e8SDimitry Andric m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
3436f034231aSEd Maste
34375f29bb8aSDimitry Andric if (exe_ctx.GetTargetPtr() == nullptr)
3438f034231aSEd Maste return false;
3439f034231aSEd Maste
3440f034231aSEd Maste // If we don't have a process nothing can change.
3441f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
34425f29bb8aSDimitry Andric if (process == nullptr)
3443f034231aSEd Maste return false;
3444f034231aSEd Maste
3445f034231aSEd Maste // If our stop id is the current stop ID, nothing has changed:
3446f034231aSEd Maste ProcessModID current_mod_id = process->GetModID();
3447f034231aSEd Maste
344814f1b3e8SDimitry Andric // If the current stop id is 0, either we haven't run yet, or the process
3449f73363f1SDimitry Andric // state has been cleared. In either case, we aren't going to be able to sync
3450f73363f1SDimitry Andric // with the process state.
3451f034231aSEd Maste if (current_mod_id.GetStopID() == 0)
3452f034231aSEd Maste return false;
3453f034231aSEd Maste
3454f034231aSEd Maste bool changed = false;
3455f034231aSEd Maste const bool was_valid = m_mod_id.IsValid();
345614f1b3e8SDimitry Andric if (was_valid) {
345714f1b3e8SDimitry Andric if (m_mod_id == current_mod_id) {
3458f73363f1SDimitry Andric // Everything is already up to date in this object, no need to update the
3459f73363f1SDimitry Andric // execution context scope.
3460f034231aSEd Maste changed = false;
346114f1b3e8SDimitry Andric } else {
3462f034231aSEd Maste m_mod_id = current_mod_id;
3463f034231aSEd Maste m_needs_update = true;
3464f034231aSEd Maste changed = true;
3465f034231aSEd Maste }
3466f034231aSEd Maste }
3467f034231aSEd Maste
346814f1b3e8SDimitry Andric // Now re-look up the thread and frame in case the underlying objects have
3469f73363f1SDimitry Andric // gone away & been recreated. That way we'll be sure to return a valid
3470f73363f1SDimitry Andric // exe_scope. If we used to have a thread or a frame but can't find it
3471f73363f1SDimitry Andric // anymore, then mark ourselves as invalid.
3472f034231aSEd Maste
347314f1b3e8SDimitry Andric if (!accept_invalid_exe_ctx) {
347414f1b3e8SDimitry Andric if (m_exe_ctx_ref.HasThreadRef()) {
3475f034231aSEd Maste ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
347614f1b3e8SDimitry Andric if (thread_sp) {
347714f1b3e8SDimitry Andric if (m_exe_ctx_ref.HasFrameRef()) {
3478f034231aSEd Maste StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
347914f1b3e8SDimitry Andric if (!frame_sp) {
3480f034231aSEd Maste // We used to have a frame, but now it is gone
3481f034231aSEd Maste SetInvalid();
3482f034231aSEd Maste changed = was_valid;
3483f034231aSEd Maste }
3484f034231aSEd Maste }
348514f1b3e8SDimitry Andric } else {
3486f034231aSEd Maste // We used to have a thread, but now it is gone
3487f034231aSEd Maste SetInvalid();
3488f034231aSEd Maste changed = was_valid;
3489f034231aSEd Maste }
3490f034231aSEd Maste }
34915e95aa85SEd Maste }
34925e95aa85SEd Maste
3493f034231aSEd Maste return changed;
3494f034231aSEd Maste }
3495f034231aSEd Maste
SetUpdated()349614f1b3e8SDimitry Andric void ValueObject::EvaluationPoint::SetUpdated() {
3497f034231aSEd Maste ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
3498f034231aSEd Maste if (process_sp)
3499f034231aSEd Maste m_mod_id = process_sp->GetModID();
3500f034231aSEd Maste m_needs_update = false;
3501f034231aSEd Maste }
3502f034231aSEd Maste
ClearUserVisibleData(uint32_t clear_mask)350314f1b3e8SDimitry Andric void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
350414f1b3e8SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsValue) ==
350514f1b3e8SDimitry Andric eClearUserVisibleDataItemsValue)
3506f034231aSEd Maste m_value_str.clear();
3507f034231aSEd Maste
350814f1b3e8SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
350914f1b3e8SDimitry Andric eClearUserVisibleDataItemsLocation)
3510f034231aSEd Maste m_location_str.clear();
3511f034231aSEd Maste
351214f1b3e8SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
351314f1b3e8SDimitry Andric eClearUserVisibleDataItemsSummary)
3514f034231aSEd Maste m_summary_str.clear();
3515f034231aSEd Maste
351614f1b3e8SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
351714f1b3e8SDimitry Andric eClearUserVisibleDataItemsDescription)
3518f034231aSEd Maste m_object_desc_str.clear();
3519f034231aSEd Maste
352014f1b3e8SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
352114f1b3e8SDimitry Andric eClearUserVisibleDataItemsSyntheticChildren) {
3522f034231aSEd Maste if (m_synthetic_value)
35235f29bb8aSDimitry Andric m_synthetic_value = nullptr;
3524f034231aSEd Maste }
3525f034231aSEd Maste }
3526f034231aSEd Maste
GetSymbolContextScope()352714f1b3e8SDimitry Andric SymbolContextScope *ValueObject::GetSymbolContextScope() {
352814f1b3e8SDimitry Andric if (m_parent) {
3529f034231aSEd Maste if (!m_parent->IsPointerOrReferenceType())
3530f034231aSEd Maste return m_parent->GetSymbolContextScope();
3531f034231aSEd Maste }
35325f29bb8aSDimitry Andric return nullptr;
3533f034231aSEd Maste }
3534f034231aSEd Maste
3535f034231aSEd Maste lldb::ValueObjectSP
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx)353614f1b3e8SDimitry Andric ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
353714f1b3e8SDimitry Andric llvm::StringRef expression,
353814f1b3e8SDimitry Andric const ExecutionContext &exe_ctx) {
353914f1b3e8SDimitry Andric return CreateValueObjectFromExpression(name, expression, exe_ctx,
354014f1b3e8SDimitry Andric EvaluateExpressionOptions());
3541205afe67SEd Maste }
3542205afe67SEd Maste
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options)354314f1b3e8SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
354414f1b3e8SDimitry Andric llvm::StringRef name, llvm::StringRef expression,
354514f1b3e8SDimitry Andric const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
3546f034231aSEd Maste lldb::ValueObjectSP retval_sp;
3547f034231aSEd Maste lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
3548f034231aSEd Maste if (!target_sp)
3549f034231aSEd Maste return retval_sp;
355014f1b3e8SDimitry Andric if (expression.empty())
3551f034231aSEd Maste return retval_sp;
355214f1b3e8SDimitry Andric target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
355314f1b3e8SDimitry Andric retval_sp, options);
355414f1b3e8SDimitry Andric if (retval_sp && !name.empty())
3555f034231aSEd Maste retval_sp->SetName(ConstString(name));
3556f034231aSEd Maste return retval_sp;
3557f034231aSEd Maste }
3558f034231aSEd Maste
CreateValueObjectFromAddress(llvm::StringRef name,uint64_t address,const ExecutionContext & exe_ctx,CompilerType type,bool do_deref)355914f1b3e8SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
356014f1b3e8SDimitry Andric llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
3561ac9a064cSDimitry Andric CompilerType type, bool do_deref) {
356214f1b3e8SDimitry Andric if (type) {
3563e81d9d49SDimitry Andric CompilerType pointer_type(type.GetPointerType());
3564ac9a064cSDimitry Andric if (!do_deref)
3565ac9a064cSDimitry Andric pointer_type = type;
356614f1b3e8SDimitry Andric if (pointer_type) {
356714f1b3e8SDimitry Andric lldb::DataBufferSP buffer(
356814f1b3e8SDimitry Andric new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
356914f1b3e8SDimitry Andric lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
357014f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope(), pointer_type,
357114f1b3e8SDimitry Andric ConstString(name), buffer, exe_ctx.GetByteOrder(),
3572f034231aSEd Maste exe_ctx.GetAddressByteSize()));
357314f1b3e8SDimitry Andric if (ptr_result_valobj_sp) {
3574ac9a064cSDimitry Andric if (do_deref)
357514f1b3e8SDimitry Andric ptr_result_valobj_sp->GetValue().SetValueType(
3576344a3780SDimitry Andric Value::ValueType::LoadAddress);
3577b76161e4SDimitry Andric Status err;
3578ac9a064cSDimitry Andric if (do_deref)
3579f034231aSEd Maste ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
358014f1b3e8SDimitry Andric if (ptr_result_valobj_sp && !name.empty())
3581f034231aSEd Maste ptr_result_valobj_sp->SetName(ConstString(name));
3582f034231aSEd Maste }
3583f034231aSEd Maste return ptr_result_valobj_sp;
3584f034231aSEd Maste }
3585f034231aSEd Maste }
3586f034231aSEd Maste return lldb::ValueObjectSP();
3587f034231aSEd Maste }
3588f034231aSEd Maste
CreateValueObjectFromData(llvm::StringRef name,const DataExtractor & data,const ExecutionContext & exe_ctx,CompilerType type)358914f1b3e8SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
359014f1b3e8SDimitry Andric llvm::StringRef name, const DataExtractor &data,
359114f1b3e8SDimitry Andric const ExecutionContext &exe_ctx, CompilerType type) {
3592f034231aSEd Maste lldb::ValueObjectSP new_value_sp;
359314f1b3e8SDimitry Andric new_value_sp = ValueObjectConstResult::Create(
359414f1b3e8SDimitry Andric exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
3595f034231aSEd Maste LLDB_INVALID_ADDRESS);
3596f034231aSEd Maste new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
359714f1b3e8SDimitry Andric if (new_value_sp && !name.empty())
3598f034231aSEd Maste new_value_sp->SetName(ConstString(name));
3599f034231aSEd Maste return new_value_sp;
3600f034231aSEd Maste }
3601f034231aSEd Maste
3602ac9a064cSDimitry Andric lldb::ValueObjectSP
CreateValueObjectFromAPInt(lldb::TargetSP target,const llvm::APInt & v,CompilerType type,llvm::StringRef name)3603ac9a064cSDimitry Andric ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
3604ac9a064cSDimitry Andric const llvm::APInt &v, CompilerType type,
3605ac9a064cSDimitry Andric llvm::StringRef name) {
3606ac9a064cSDimitry Andric ExecutionContext exe_ctx(target.get(), false);
3607ac9a064cSDimitry Andric uint64_t byte_size = 0;
3608ac9a064cSDimitry Andric if (auto temp = type.GetByteSize(target.get()))
3609ac9a064cSDimitry Andric byte_size = temp.value();
3610ac9a064cSDimitry Andric lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3611ac9a064cSDimitry Andric reinterpret_cast<const void *>(v.getRawData()), byte_size,
3612ac9a064cSDimitry Andric exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());
3613ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
3614ac9a064cSDimitry Andric }
3615ac9a064cSDimitry Andric
CreateValueObjectFromAPFloat(lldb::TargetSP target,const llvm::APFloat & v,CompilerType type,llvm::StringRef name)3616ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
3617ac9a064cSDimitry Andric lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,
3618ac9a064cSDimitry Andric llvm::StringRef name) {
3619ac9a064cSDimitry Andric return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
3620ac9a064cSDimitry Andric }
3621ac9a064cSDimitry Andric
3622ac9a064cSDimitry Andric lldb::ValueObjectSP
CreateValueObjectFromBool(lldb::TargetSP target,bool value,llvm::StringRef name)3623ac9a064cSDimitry Andric ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
3624ac9a064cSDimitry Andric llvm::StringRef name) {
3625ac9a064cSDimitry Andric CompilerType target_type;
3626ac9a064cSDimitry Andric if (target) {
3627ac9a064cSDimitry Andric for (auto type_system_sp : target->GetScratchTypeSystems())
3628ac9a064cSDimitry Andric if (auto compiler_type =
3629ac9a064cSDimitry Andric type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {
3630ac9a064cSDimitry Andric target_type = compiler_type;
3631ac9a064cSDimitry Andric break;
3632ac9a064cSDimitry Andric }
3633ac9a064cSDimitry Andric }
3634ac9a064cSDimitry Andric ExecutionContext exe_ctx(target.get(), false);
3635ac9a064cSDimitry Andric uint64_t byte_size = 0;
3636ac9a064cSDimitry Andric if (auto temp = target_type.GetByteSize(target.get()))
3637ac9a064cSDimitry Andric byte_size = temp.value();
3638ac9a064cSDimitry Andric lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3639ac9a064cSDimitry Andric reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),
3640ac9a064cSDimitry Andric exe_ctx.GetAddressByteSize());
3641ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,
3642ac9a064cSDimitry Andric target_type);
3643ac9a064cSDimitry Andric }
3644ac9a064cSDimitry Andric
CreateValueObjectFromNullptr(lldb::TargetSP target,CompilerType type,llvm::StringRef name)3645ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(
3646ac9a064cSDimitry Andric lldb::TargetSP target, CompilerType type, llvm::StringRef name) {
3647ac9a064cSDimitry Andric if (!type.IsNullPtrType()) {
3648ac9a064cSDimitry Andric lldb::ValueObjectSP ret_val;
3649ac9a064cSDimitry Andric return ret_val;
3650ac9a064cSDimitry Andric }
3651ac9a064cSDimitry Andric uintptr_t zero = 0;
3652ac9a064cSDimitry Andric ExecutionContext exe_ctx(target.get(), false);
3653ac9a064cSDimitry Andric uint64_t byte_size = 0;
3654ac9a064cSDimitry Andric if (auto temp = type.GetByteSize(target.get()))
3655ac9a064cSDimitry Andric byte_size = temp.value();
3656ac9a064cSDimitry Andric lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3657ac9a064cSDimitry Andric reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),
3658ac9a064cSDimitry Andric exe_ctx.GetAddressByteSize());
3659ac9a064cSDimitry Andric return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
3660ac9a064cSDimitry Andric }
3661ac9a064cSDimitry Andric
GetModule()366214f1b3e8SDimitry Andric ModuleSP ValueObject::GetModule() {
3663f034231aSEd Maste ValueObject *root(GetRoot());
3664f034231aSEd Maste if (root != this)
3665f034231aSEd Maste return root->GetModule();
3666f034231aSEd Maste return lldb::ModuleSP();
3667f034231aSEd Maste }
3668f034231aSEd Maste
GetRoot()366914f1b3e8SDimitry Andric ValueObject *ValueObject::GetRoot() {
3670f034231aSEd Maste if (m_root)
3671f034231aSEd Maste return m_root;
367212bd4897SEd Maste return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
367312bd4897SEd Maste return (vo->m_parent != nullptr);
367412bd4897SEd Maste }));
3675f034231aSEd Maste }
367612bd4897SEd Maste
367712bd4897SEd Maste ValueObject *
FollowParentChain(std::function<bool (ValueObject *)> f)367814f1b3e8SDimitry Andric ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
367912bd4897SEd Maste ValueObject *vo = this;
368014f1b3e8SDimitry Andric while (vo) {
368194994d37SDimitry Andric if (!f(vo))
368212bd4897SEd Maste break;
368312bd4897SEd Maste vo = vo->m_parent;
368412bd4897SEd Maste }
368512bd4897SEd Maste return vo;
3686f034231aSEd Maste }
3687f034231aSEd Maste
GetAddressTypeOfChildren()368814f1b3e8SDimitry Andric AddressType ValueObject::GetAddressTypeOfChildren() {
368914f1b3e8SDimitry Andric if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
3690f034231aSEd Maste ValueObject *root(GetRoot());
3691f034231aSEd Maste if (root != this)
3692f034231aSEd Maste return root->GetAddressTypeOfChildren();
3693f034231aSEd Maste }
3694f034231aSEd Maste return m_address_type_of_ptr_or_ref_children;
3695f034231aSEd Maste }
3696f034231aSEd Maste
GetDynamicValueType()369714f1b3e8SDimitry Andric lldb::DynamicValueType ValueObject::GetDynamicValueType() {
3698f034231aSEd Maste ValueObject *with_dv_info = this;
369914f1b3e8SDimitry Andric while (with_dv_info) {
3700f034231aSEd Maste if (with_dv_info->HasDynamicValueTypeInfo())
3701f034231aSEd Maste return with_dv_info->GetDynamicValueTypeImpl();
3702f034231aSEd Maste with_dv_info = with_dv_info->m_parent;
3703f034231aSEd Maste }
3704f034231aSEd Maste return lldb::eNoDynamicValues;
3705f034231aSEd Maste }
3706f034231aSEd Maste
GetFormat() const370714f1b3e8SDimitry Andric lldb::Format ValueObject::GetFormat() const {
3708f034231aSEd Maste const ValueObject *with_fmt_info = this;
370914f1b3e8SDimitry Andric while (with_fmt_info) {
3710f034231aSEd Maste if (with_fmt_info->m_format != lldb::eFormatDefault)
3711f034231aSEd Maste return with_fmt_info->m_format;
3712f034231aSEd Maste with_fmt_info = with_fmt_info->m_parent;
3713f034231aSEd Maste }
3714f034231aSEd Maste return m_format;
3715f034231aSEd Maste }
3716205afe67SEd Maste
GetPreferredDisplayLanguage()371714f1b3e8SDimitry Andric lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
371812bd4897SEd Maste lldb::LanguageType type = m_preferred_display_language;
371914f1b3e8SDimitry Andric if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
372014f1b3e8SDimitry Andric if (GetRoot()) {
372114f1b3e8SDimitry Andric if (GetRoot() == this) {
372214f1b3e8SDimitry Andric if (StackFrameSP frame_sp = GetFrameSP()) {
372314f1b3e8SDimitry Andric const SymbolContext &sc(
372414f1b3e8SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextCompUnit));
3725205afe67SEd Maste if (CompileUnit *cu = sc.comp_unit)
3726205afe67SEd Maste type = cu->GetLanguage();
3727205afe67SEd Maste }
372814f1b3e8SDimitry Andric } else {
3729205afe67SEd Maste type = GetRoot()->GetPreferredDisplayLanguage();
3730205afe67SEd Maste }
3731205afe67SEd Maste }
373212bd4897SEd Maste }
373312bd4897SEd Maste return (m_preferred_display_language = type); // only compute it once
373412bd4897SEd Maste }
373512bd4897SEd Maste
SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt)373614f1b3e8SDimitry Andric void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
3737e81d9d49SDimitry Andric if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
3738e81d9d49SDimitry Andric SetPreferredDisplayLanguage(lt);
3739e81d9d49SDimitry Andric }
3740e81d9d49SDimitry Andric
CanProvideValue()374114f1b3e8SDimitry Andric bool ValueObject::CanProvideValue() {
3742f73363f1SDimitry Andric // we need to support invalid types as providers of values because some bare-
3743f73363f1SDimitry Andric // board debugging scenarios have no notion of types, but still manage to
3744f73363f1SDimitry Andric // have raw numeric values for things like registers. sigh.
3745b60736ecSDimitry Andric CompilerType type = GetCompilerType();
374694994d37SDimitry Andric return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
3747205afe67SEd Maste }
3748205afe67SEd Maste
3749344a3780SDimitry Andric
3750205afe67SEd Maste
Persist()375114f1b3e8SDimitry Andric ValueObjectSP ValueObject::Persist() {
3752205afe67SEd Maste if (!UpdateValueIfNeeded())
3753205afe67SEd Maste return nullptr;
3754205afe67SEd Maste
3755205afe67SEd Maste TargetSP target_sp(GetTargetSP());
3756205afe67SEd Maste if (!target_sp)
3757205afe67SEd Maste return nullptr;
3758205afe67SEd Maste
375914f1b3e8SDimitry Andric PersistentExpressionState *persistent_state =
376014f1b3e8SDimitry Andric target_sp->GetPersistentExpressionStateForLanguage(
376114f1b3e8SDimitry Andric GetPreferredDisplayLanguage());
3762205afe67SEd Maste
3763e81d9d49SDimitry Andric if (!persistent_state)
3764e81d9d49SDimitry Andric return nullptr;
3765e81d9d49SDimitry Andric
3766cfca06d7SDimitry Andric ConstString name = persistent_state->GetNextPersistentVariableName();
3767e81d9d49SDimitry Andric
376814f1b3e8SDimitry Andric ValueObjectSP const_result_sp =
376914f1b3e8SDimitry Andric ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);
3770e81d9d49SDimitry Andric
3771cfca06d7SDimitry Andric ExpressionVariableSP persistent_var_sp =
377214f1b3e8SDimitry Andric persistent_state->CreatePersistentVariable(const_result_sp);
3773cfca06d7SDimitry Andric persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
3774cfca06d7SDimitry Andric persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
3775205afe67SEd Maste
3776cfca06d7SDimitry Andric return persistent_var_sp->GetValueObject();
3777205afe67SEd Maste }
3778b1c73532SDimitry Andric
GetVTable()3779b1c73532SDimitry Andric lldb::ValueObjectSP ValueObject::GetVTable() {
3780b1c73532SDimitry Andric return ValueObjectVTable::Create(*this);
3781b1c73532SDimitry Andric }
3782