//===-- ValueObjectRegister.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/ValueObjectRegister.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

using namespace lldb;
using namespace lldb_private;

#pragma mark ValueObjectRegisterContext

ValueObjectRegisterContext::ValueObjectRegisterContext (ValueObject *parent, RegisterContextSP &reg_ctx) :
    ValueObject (parent),
    m_reg_ctx (reg_ctx)
{
    assert (reg_ctx);
    m_name.SetCString("Registers");
    SetValueIsValid (true);
}

ValueObjectRegisterContext::~ValueObjectRegisterContext()
{
}

lldb::clang_type_t
ValueObjectRegisterContext::GetClangType ()
{
    return NULL;
}

ConstString
ValueObjectRegisterContext::GetTypeName()
{
    ConstString empty_type_name;
    return empty_type_name;
}

uint32_t
ValueObjectRegisterContext::CalculateNumChildren()
{
    return m_reg_ctx->GetRegisterSetCount();
}

clang::ASTContext *
ValueObjectRegisterContext::GetClangAST ()
{
    return NULL;
}

size_t
ValueObjectRegisterContext::GetByteSize()
{
    return 0;
}

void
ValueObjectRegisterContext::UpdateValue (ExecutionContextScope *exe_scope)
{
    m_error.Clear();
    StackFrame *frame = exe_scope->CalculateStackFrame();
    if (frame)
        m_reg_ctx = frame->GetRegisterContext();
    else
        m_reg_ctx.reset();

    SetValueIsValid (m_reg_ctx.get() != NULL);
}

ValueObjectSP
ValueObjectRegisterContext::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
{
    ValueObjectSP valobj_sp;

    const uint32_t num_children = GetNumChildren();
    if (idx < num_children)
        valobj_sp.reset (new ValueObjectRegisterSet(this, m_reg_ctx, idx));
    return valobj_sp;
}


#pragma mark -
#pragma mark ValueObjectRegisterSet

ValueObjectRegisterSet::ValueObjectRegisterSet (ValueObject *parent, lldb::RegisterContextSP &reg_ctx, uint32_t reg_set_idx) :
    ValueObject (parent),
    m_reg_ctx (reg_ctx),
    m_reg_set (NULL),
    m_reg_set_idx (reg_set_idx)
{
    assert (reg_ctx);
    m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
    if (m_reg_set)
    {
        m_name.SetCString (m_reg_set->name);
    }
}

ValueObjectRegisterSet::~ValueObjectRegisterSet()
{
}

lldb::clang_type_t
ValueObjectRegisterSet::GetClangType ()
{
    return NULL;
}

ConstString
ValueObjectRegisterSet::GetTypeName()
{
    return ConstString();
}

uint32_t
ValueObjectRegisterSet::CalculateNumChildren()
{
    const RegisterSet *reg_set = m_reg_ctx->GetRegisterSet(m_reg_set_idx);
    if (reg_set)
        return reg_set->num_registers;
    return 0;
}

clang::ASTContext *
ValueObjectRegisterSet::GetClangAST ()
{
    return NULL;
}

size_t
ValueObjectRegisterSet::GetByteSize()
{
    return 0;
}

void
ValueObjectRegisterSet::UpdateValue (ExecutionContextScope *exe_scope)
{
    m_error.Clear();
    SetValueDidChange (false);
    StackFrame *frame = exe_scope->CalculateStackFrame();
    if (frame == NULL)
        m_reg_ctx.reset();
    else
    {
        m_reg_ctx = frame->GetRegisterContext ();
        if (m_reg_ctx)
        {
            const RegisterSet *reg_set = m_reg_ctx->GetRegisterSet (m_reg_set_idx);
            if (reg_set == NULL)
                m_reg_ctx.reset();
            else if (m_reg_set != reg_set)
            {
                SetValueDidChange (true);
                m_name.SetCString(reg_set->name);
            }
        }
    }
    if (m_reg_ctx)
    {
        SetValueIsValid (true);
    }
    else
    {
        SetValueIsValid (false);
        m_children.clear();
    }
}


ValueObjectSP
ValueObjectRegisterSet::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
{
    ValueObjectSP valobj_sp;
    if (m_reg_ctx && m_reg_set)
    {
        const uint32_t num_children = GetNumChildren();
        if (idx < num_children)
            valobj_sp.reset (new ValueObjectRegister(this, m_reg_ctx, m_reg_set->registers[idx]));
    }
    return valobj_sp;
}


#pragma mark -
#pragma mark ValueObjectRegister

ValueObjectRegister::ValueObjectRegister (ValueObject *parent, lldb::RegisterContextSP &reg_ctx, uint32_t reg_num) :
    ValueObject (parent),
    m_reg_ctx (reg_ctx),
    m_reg_info (NULL),
    m_reg_num (reg_num),
    m_type_name (),
    m_clang_type (NULL)
{
    assert (reg_ctx);
    m_reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
    if (m_reg_info)
    {
        if (m_reg_info->name)
            m_name.SetCString(m_reg_info->name);
        else if (m_reg_info->alt_name)
            m_name.SetCString(m_reg_info->alt_name);
    }
}

ValueObjectRegister::~ValueObjectRegister()
{
}

lldb::clang_type_t
ValueObjectRegister::GetClangType ()
{
    if (m_clang_type == NULL && m_reg_info)
    {
        Process *process = m_reg_ctx->CalculateProcess ();
        if (process)
        {
            Module *exe_module = process->GetTarget().GetExecutableModule ().get();
            if (exe_module)
            {
                m_clang_type = exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info->encoding, m_reg_info->byte_size * 8);
            }
        }
    }
    return m_clang_type;
}

ConstString
ValueObjectRegister::GetTypeName()
{
    if (m_type_name.IsEmpty())
        m_type_name = ClangASTType::GetClangTypeName (GetClangType());
    return m_type_name;
}

uint32_t
ValueObjectRegister::CalculateNumChildren()
{
    return 0;
}

clang::ASTContext *
ValueObjectRegister::GetClangAST ()
{
    Process *process = m_reg_ctx->CalculateProcess ();
    if (process)
    {
        Module *exe_module = process->GetTarget().GetExecutableModule ().get();
        if (exe_module)
            return exe_module->GetClangASTContext().getASTContext();
    }
    return NULL;
}

size_t
ValueObjectRegister::GetByteSize()
{
    return m_reg_info->byte_size;
}

void
ValueObjectRegister::UpdateValue (ExecutionContextScope *exe_scope)
{
    m_error.Clear();
    StackFrame *frame = exe_scope->CalculateStackFrame();
    if (frame)
    {
        m_reg_ctx = frame->GetRegisterContext();
        if (m_reg_ctx)
        {
            const RegisterInfo *reg_info = m_reg_ctx->GetRegisterInfoAtIndex(m_reg_num);
            if (m_reg_info != reg_info)
            {
                m_reg_info = reg_info;
                if (m_reg_info)
                {
                    if (m_reg_info->name)
                        m_name.SetCString(m_reg_info->name);
                    else if (m_reg_info->alt_name)
                        m_name.SetCString(m_reg_info->alt_name);
                }
            }
        }
    }
    else
    {
        m_reg_ctx.reset();
        m_reg_info = NULL;
    }


    if (m_reg_ctx && m_reg_info)
    {
        if (m_reg_ctx->ReadRegisterBytes (m_reg_num, m_data))
        {
            m_value.SetContext(Value::eContextTypeRegisterInfo, (void *)m_reg_info);
            m_value.SetValueType(Value::eValueTypeHostAddress);
            m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
            SetValueIsValid (true);
            return;
        }
    }
    SetValueIsValid (false);
}


