15ffd83dbSDimitry Andric //===-- ValueObjectConstResultImpl.cpp ------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultImpl.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Value.h"
120b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
130b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
140b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultCast.h"
150b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultChild.h"
160b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
170b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
180b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
200b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric #include <string>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace lldb_private {
250b57cec5SDimitry Andric class DataExtractor;
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric namespace lldb_private {
280b57cec5SDimitry Andric class Status;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb;
320b57cec5SDimitry Andric using namespace lldb_private;
330b57cec5SDimitry Andric 
ValueObjectConstResultImpl(ValueObject * valobj,lldb::addr_t live_address)340b57cec5SDimitry Andric ValueObjectConstResultImpl::ValueObjectConstResultImpl(
350b57cec5SDimitry Andric     ValueObject *valobj, lldb::addr_t live_address)
360b57cec5SDimitry Andric     : m_impl_backend(valobj), m_live_address(live_address),
370b57cec5SDimitry Andric       m_live_address_type(eAddressTypeLoad), m_load_addr_backend(),
380b57cec5SDimitry Andric       m_address_of_backend() {}
390b57cec5SDimitry Andric 
Dereference(Status & error)400b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {
410b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
420b57cec5SDimitry Andric     return lldb::ValueObjectSP();
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   return m_impl_backend->ValueObject::Dereference(error);
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)470b57cec5SDimitry Andric ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(
480b57cec5SDimitry Andric     size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
490b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
500b57cec5SDimitry Andric     return nullptr;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   m_impl_backend->UpdateValueIfNeeded(false);
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   ValueObjectConstResultChild *valobj = nullptr;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
570b57cec5SDimitry Andric   bool ignore_array_bounds = synthetic_array_member;
580b57cec5SDimitry Andric   std::string child_name_str;
590b57cec5SDimitry Andric   uint32_t child_byte_size = 0;
600b57cec5SDimitry Andric   int32_t child_byte_offset = 0;
610b57cec5SDimitry Andric   uint32_t child_bitfield_bit_size = 0;
620b57cec5SDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
630b57cec5SDimitry Andric   bool child_is_base_class = false;
640b57cec5SDimitry Andric   bool child_is_deref_of_parent = false;
650b57cec5SDimitry Andric   uint64_t language_flags;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   const bool transparent_pointers = !synthetic_array_member;
680b57cec5SDimitry Andric   CompilerType compiler_type = m_impl_backend->GetCompilerType();
690b57cec5SDimitry Andric   CompilerType child_compiler_type;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex(
740b57cec5SDimitry Andric       &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
750b57cec5SDimitry Andric       ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
760b57cec5SDimitry Andric       child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
770b57cec5SDimitry Andric       child_is_deref_of_parent, m_impl_backend, language_flags);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   // One might think we should check that the size of the children
800b57cec5SDimitry Andric   // is always strictly positive, hence we could avoid creating a
810b57cec5SDimitry Andric   // ValueObject if that's not the case, but it turns out there
820b57cec5SDimitry Andric   // are languages out there which allow zero-size types with
830b57cec5SDimitry Andric   // children (e.g. Swift).
840b57cec5SDimitry Andric   if (child_compiler_type) {
850b57cec5SDimitry Andric     if (synthetic_index)
860b57cec5SDimitry Andric       child_byte_offset += child_byte_size * synthetic_index;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     ConstString child_name;
890b57cec5SDimitry Andric     if (!child_name_str.empty())
900b57cec5SDimitry Andric       child_name.SetCString(child_name_str.c_str());
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric     valobj = new ValueObjectConstResultChild(
930b57cec5SDimitry Andric         *m_impl_backend, child_compiler_type, child_name, child_byte_size,
940b57cec5SDimitry Andric         child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
950b57cec5SDimitry Andric         child_is_base_class, child_is_deref_of_parent,
960b57cec5SDimitry Andric         m_live_address == LLDB_INVALID_ADDRESS
970b57cec5SDimitry Andric             ? m_live_address
980b57cec5SDimitry Andric             : m_live_address + child_byte_offset,
990b57cec5SDimitry Andric         language_flags);
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   return valobj;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
GetSyntheticChildAtOffset(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)1050b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(
1060b57cec5SDimitry Andric     uint32_t offset, const CompilerType &type, bool can_create,
1070b57cec5SDimitry Andric     ConstString name_const_str) {
1080b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1090b57cec5SDimitry Andric     return lldb::ValueObjectSP();
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(
1120b57cec5SDimitry Andric       offset, type, can_create, name_const_str);
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
AddressOf(Status & error)1150b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
1160b57cec5SDimitry Andric   if (m_address_of_backend.get() != nullptr)
1170b57cec5SDimitry Andric     return m_address_of_backend;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1200b57cec5SDimitry Andric     return lldb::ValueObjectSP();
1210b57cec5SDimitry Andric   if (m_live_address != LLDB_INVALID_ADDRESS) {
1220b57cec5SDimitry Andric     CompilerType compiler_type(m_impl_backend->GetCompilerType());
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(
1250b57cec5SDimitry Andric         &m_live_address, sizeof(lldb::addr_t)));
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     std::string new_name("&");
1280b57cec5SDimitry Andric     new_name.append(m_impl_backend->GetName().AsCString(""));
1290b57cec5SDimitry Andric     ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());
1300b57cec5SDimitry Andric     m_address_of_backend = ValueObjectConstResult::Create(
1310b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(),
1320b57cec5SDimitry Andric         ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),
1330b57cec5SDimitry Andric         exe_ctx.GetAddressByteSize());
1340b57cec5SDimitry Andric 
135*5f7ddb14SDimitry Andric     m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);
1360b57cec5SDimitry Andric     m_address_of_backend->GetValue().GetScalar() = m_live_address;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     return m_address_of_backend;
1390b57cec5SDimitry Andric   } else
1400b57cec5SDimitry Andric     return m_impl_backend->ValueObject::AddressOf(error);
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric lldb::ValueObjectSP
Cast(const CompilerType & compiler_type)1440b57cec5SDimitry Andric ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {
1450b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1460b57cec5SDimitry Andric     return lldb::ValueObjectSP();
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   ValueObjectConstResultCast *result_cast =
1490b57cec5SDimitry Andric       new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(),
1500b57cec5SDimitry Andric                                      compiler_type, m_live_address);
1510b57cec5SDimitry Andric   return result_cast->GetSP();
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric lldb::addr_t
GetAddressOf(bool scalar_is_load_address,AddressType * address_type)1550b57cec5SDimitry Andric ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address,
1560b57cec5SDimitry Andric                                          AddressType *address_type) {
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1590b57cec5SDimitry Andric     return 0;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   if (m_live_address == LLDB_INVALID_ADDRESS) {
1620b57cec5SDimitry Andric     return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address,
1630b57cec5SDimitry Andric                                                      address_type);
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   if (address_type)
1670b57cec5SDimitry Andric     *address_type = m_live_address_type;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   return m_live_address;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
GetPointeeData(DataExtractor & data,uint32_t item_idx,uint32_t item_count)1720b57cec5SDimitry Andric size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data,
1730b57cec5SDimitry Andric                                                   uint32_t item_idx,
1740b57cec5SDimitry Andric                                                   uint32_t item_count) {
1750b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1760b57cec5SDimitry Andric     return 0;
1770b57cec5SDimitry Andric   return m_impl_backend->ValueObject::GetPointeeData(data, item_idx,
1780b57cec5SDimitry Andric                                                      item_count);
1790b57cec5SDimitry Andric }
180