1//===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/ValueObjectConstResultImpl.h"
11
12#include "lldb/Core/ValueObjectChild.h"
13#include "lldb/Core/ValueObjectConstResult.h"
14#include "lldb/Core/ValueObjectConstResultChild.h"
15#include "lldb/Core/ValueObjectMemory.h"
16#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/ValueObjectList.h"
19
20#include "lldb/Symbol/ClangASTType.h"
21#include "lldb/Symbol/ObjectFile.h"
22#include "lldb/Symbol/SymbolContext.h"
23#include "lldb/Symbol/Type.h"
24#include "lldb/Symbol/Variable.h"
25
26#include "lldb/Target/ExecutionContext.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Target/Target.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33// this macro enables a simpler implementation for some method calls in this object that relies only upon
34// ValueObject knowning how to set the address type of its children correctly. the alternative implementation
35// relies on being able to create a target copy of the frozen object, which makes it less bug-prone but less
36// efficient as well. once we are confident the faster implementation is bug-free, this macro (and the slower
37// implementations) can go
38#define TRIVIAL_IMPL 1
39
40ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj,
41                                                        lldb::addr_t live_address) :
42    m_impl_backend(valobj),
43    m_live_address(live_address),
44    m_live_address_type(eAddressTypeLoad),
45    m_load_addr_backend(),
46    m_address_of_backend()
47{
48}
49
50lldb::ValueObjectSP
51ValueObjectConstResultImpl::DerefOnTarget()
52{
53    if (m_load_addr_backend.get() == NULL)
54    {
55        lldb::addr_t tgt_address = m_impl_backend->GetPointerValue();
56        ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
57        m_load_addr_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
58                                                              m_impl_backend->GetClangType(),
59                                                              m_impl_backend->GetName(),
60                                                              tgt_address,
61                                                              eAddressTypeLoad,
62                                                              exe_ctx.GetAddressByteSize());
63    }
64    return m_load_addr_backend;
65}
66
67lldb::ValueObjectSP
68ValueObjectConstResultImpl::Dereference (Error &error)
69{
70    if (m_impl_backend == NULL)
71        return lldb::ValueObjectSP();
72
73#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
74    return m_impl_backend->ValueObject::Dereference(error);
75#else
76    m_impl_backend->UpdateValueIfNeeded(false);
77
78    if (NeedsDerefOnTarget())
79        return DerefOnTarget()->Dereference(error);
80    else
81        return m_impl_backend->ValueObject::Dereference(error);
82#endif
83}
84
85ValueObject *
86ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index)
87{
88    if (m_impl_backend == NULL)
89        return NULL;
90
91    m_impl_backend->UpdateValueIfNeeded(false);
92
93    ValueObjectConstResultChild *valobj = NULL;
94
95    bool omit_empty_base_classes = true;
96    bool ignore_array_bounds = synthetic_array_member;
97    std::string child_name_str;
98    uint32_t child_byte_size = 0;
99    int32_t child_byte_offset = 0;
100    uint32_t child_bitfield_bit_size = 0;
101    uint32_t child_bitfield_bit_offset = 0;
102    bool child_is_base_class = false;
103    bool child_is_deref_of_parent = false;
104
105    const bool transparent_pointers = synthetic_array_member == false;
106    ClangASTType clang_type = m_impl_backend->GetClangType();
107    ClangASTType child_clang_type;
108
109    ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
110
111    child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
112                                                            m_impl_backend->GetName().GetCString(),
113                                                            idx,
114                                                            transparent_pointers,
115                                                            omit_empty_base_classes,
116                                                            ignore_array_bounds,
117                                                            child_name_str,
118                                                            child_byte_size,
119                                                            child_byte_offset,
120                                                            child_bitfield_bit_size,
121                                                            child_bitfield_bit_offset,
122                                                            child_is_base_class,
123                                                            child_is_deref_of_parent);
124    if (child_clang_type && child_byte_size)
125    {
126        if (synthetic_index)
127            child_byte_offset += child_byte_size * synthetic_index;
128
129        ConstString child_name;
130        if (!child_name_str.empty())
131            child_name.SetCString (child_name_str.c_str());
132
133        valobj = new ValueObjectConstResultChild (*m_impl_backend,
134                                                  child_clang_type,
135                                                  child_name,
136                                                  child_byte_size,
137                                                  child_byte_offset,
138                                                  child_bitfield_bit_size,
139                                                  child_bitfield_bit_offset,
140                                                  child_is_base_class,
141                                                  child_is_deref_of_parent);
142        valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset);
143    }
144
145    return valobj;
146}
147
148lldb::ValueObjectSP
149ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create)
150{
151    if (m_impl_backend == NULL)
152        return lldb::ValueObjectSP();
153
154#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
155    return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
156#else
157    m_impl_backend->UpdateValueIfNeeded(false);
158
159    if (NeedsDerefOnTarget())
160        return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create);
161    else
162        return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
163#endif
164}
165
166lldb::ValueObjectSP
167ValueObjectConstResultImpl::AddressOf (Error &error)
168{
169    if (m_address_of_backend.get() != NULL)
170        return m_address_of_backend;
171
172    if (m_impl_backend == NULL)
173        return lldb::ValueObjectSP();
174    if (m_live_address != LLDB_INVALID_ADDRESS)
175    {
176        ClangASTType clang_type(m_impl_backend->GetClangType());
177
178        lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t)));
179
180        std::string new_name("&");
181        new_name.append(m_impl_backend->GetName().AsCString(""));
182        ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
183        m_address_of_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
184                                                               clang_type.GetPointerType(),
185                                                               ConstString(new_name.c_str()),
186                                                               buffer,
187                                                               lldb::endian::InlHostByteOrder(),
188                                                               exe_ctx.GetAddressByteSize());
189
190        m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar);
191        m_address_of_backend->GetValue().GetScalar() = m_live_address;
192
193        return m_address_of_backend;
194    }
195    else
196        return lldb::ValueObjectSP();
197}
198
199lldb::addr_t
200ValueObjectConstResultImpl::GetAddressOf (bool scalar_is_load_address,
201                                          AddressType *address_type)
202{
203
204    if (m_impl_backend == NULL)
205        return 0;
206
207    if (m_live_address == LLDB_INVALID_ADDRESS)
208    {
209        return m_impl_backend->ValueObject::GetAddressOf (scalar_is_load_address,
210                                                          address_type);
211    }
212
213    if (address_type)
214        *address_type = m_live_address_type;
215
216    return m_live_address;
217}
218
219size_t
220ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data,
221                                            uint32_t item_idx,
222                                            uint32_t item_count)
223{
224    if (m_impl_backend == NULL)
225        return 0;
226#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
227    return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
228#else
229    m_impl_backend->UpdateValueIfNeeded(false);
230
231    if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType())
232        return DerefOnTarget()->GetPointeeData(data, item_idx, item_count);
233    else
234        return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
235#endif
236}
237