ValueObjectConstResultImpl.cpp   [plain text]


//===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/ValueObjectConstResultImpl.h"

#include "lldb/Core/ValueObjectChild.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectConstResultChild.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObjectList.h"

#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"

#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"

using namespace lldb;
using namespace lldb_private;

// this macro enables a simpler implementation for some method calls in this object that relies only upon
// ValueObject knowning how to set the address type of its children correctly. the alternative implementation
// relies on being able to create a target copy of the frozen object, which makes it less bug-prone but less
// efficient as well. once we are confident the faster implementation is bug-free, this macro (and the slower
// implementations) can go
#define TRIVIAL_IMPL 1

ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj,
                                                        lldb::addr_t live_address) :
    m_impl_backend(valobj),
    m_live_address(live_address),
    m_live_address_type(eAddressTypeLoad),
    m_load_addr_backend(),
    m_address_of_backend()
{
}

lldb::ValueObjectSP
ValueObjectConstResultImpl::DerefOnTarget()
{
    if (m_load_addr_backend.get() == NULL)
    {
        lldb::addr_t tgt_address = m_impl_backend->GetPointerValue();
        ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
        m_load_addr_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
                                                              m_impl_backend->GetClangAST(),
                                                              m_impl_backend->GetClangType(),
                                                              m_impl_backend->GetName(),
                                                              tgt_address,
                                                              eAddressTypeLoad,
                                                              exe_ctx.GetAddressByteSize());
    }
    return m_load_addr_backend;
}

lldb::ValueObjectSP
ValueObjectConstResultImpl::Dereference (Error &error)
{
    if (m_impl_backend == NULL)
        return lldb::ValueObjectSP();
    
#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
    return m_impl_backend->ValueObject::Dereference(error);
#else
    m_impl_backend->UpdateValueIfNeeded(false);
        
    if (NeedsDerefOnTarget())
        return DerefOnTarget()->Dereference(error);
    else
        return m_impl_backend->ValueObject::Dereference(error);
#endif
}

ValueObject *
ValueObjectConstResultImpl::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
{
    if (m_impl_backend == NULL)
        return NULL;

    m_impl_backend->UpdateValueIfNeeded(false);
    
    ValueObjectConstResultChild *valobj = NULL;
    
    bool omit_empty_base_classes = true;
    bool ignore_array_bounds = synthetic_array_member;
    std::string child_name_str;
    uint32_t child_byte_size = 0;
    int32_t child_byte_offset = 0;
    uint32_t child_bitfield_bit_size = 0;
    uint32_t child_bitfield_bit_offset = 0;
    bool child_is_base_class = false;
    bool child_is_deref_of_parent = false;
    
    const bool transparent_pointers = synthetic_array_member == false;
    clang::ASTContext *clang_ast = m_impl_backend->GetClangAST();
    lldb::clang_type_t clang_type = m_impl_backend->GetClangType();
    lldb::clang_type_t child_clang_type;
    
    ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
    
    child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
                                                                  clang_ast,
                                                                  m_impl_backend->GetName().GetCString(),
                                                                  clang_type,
                                                                  idx,
                                                                  transparent_pointers,
                                                                  omit_empty_base_classes,
                                                                  ignore_array_bounds,
                                                                  child_name_str,
                                                                  child_byte_size,
                                                                  child_byte_offset,
                                                                  child_bitfield_bit_size,
                                                                  child_bitfield_bit_offset,
                                                                  child_is_base_class,
                                                                  child_is_deref_of_parent);
    if (child_clang_type && child_byte_size)
    {
        if (synthetic_index)
            child_byte_offset += child_byte_size * synthetic_index;
        
        ConstString child_name;
        if (!child_name_str.empty())
            child_name.SetCString (child_name_str.c_str());
        
        valobj = new ValueObjectConstResultChild (*m_impl_backend,
                                                  clang_ast,
                                                  child_clang_type,
                                                  child_name,
                                                  child_byte_size,
                                                  child_byte_offset,
                                                  child_bitfield_bit_size,
                                                  child_bitfield_bit_offset,
                                                  child_is_base_class,
                                                  child_is_deref_of_parent);
        valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset);
    }
    
    return valobj;
}

lldb::ValueObjectSP
ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create)
{
    if (m_impl_backend == NULL)
        return lldb::ValueObjectSP();

#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
    return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
#else
    m_impl_backend->UpdateValueIfNeeded(false);
    
    if (NeedsDerefOnTarget())
        return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create);
    else
        return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
#endif
}

lldb::ValueObjectSP
ValueObjectConstResultImpl::AddressOf (Error &error)
{
    if (m_address_of_backend.get() != NULL)
        return m_address_of_backend;
    
    if (m_impl_backend == NULL)
        return lldb::ValueObjectSP();
    if (m_live_address != LLDB_INVALID_ADDRESS)
    {
        ClangASTType type(m_impl_backend->GetClangAST(), m_impl_backend->GetClangType());
        
        lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t)));
        
        std::string new_name("&");
        new_name.append(m_impl_backend->GetName().AsCString(""));
        ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
        m_address_of_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
                                                               type.GetASTContext(),
                                                               type.GetPointerType(),
                                                               ConstString(new_name.c_str()),
                                                               buffer,
                                                               lldb::endian::InlHostByteOrder(), 
                                                               exe_ctx.GetAddressByteSize());
        
        m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar);
        m_address_of_backend->GetValue().GetScalar() = m_live_address;
        
        return m_address_of_backend;
    }
    else
        return lldb::ValueObjectSP();
}

lldb::addr_t
ValueObjectConstResultImpl::GetAddressOf (bool scalar_is_load_address,
                                          AddressType *address_type)
{
    
    if (m_impl_backend == NULL)
        return 0;
    
    if (m_live_address == LLDB_INVALID_ADDRESS)
    {
        return m_impl_backend->ValueObject::GetAddressOf (scalar_is_load_address,
                                                          address_type);
    }
    
    if (address_type)
        *address_type = m_live_address_type;
        
    return m_live_address;
}

size_t
ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data,
                                            uint32_t item_idx,
                                            uint32_t item_count)
{
    if (m_impl_backend == NULL)
        return 0;
#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
    return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
#else
    m_impl_backend->UpdateValueIfNeeded(false);
    
    if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType())
        return DerefOnTarget()->GetPointeeData(data, item_idx, item_count);
    else
        return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
#endif
}