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

#include "RegisterContextMacOSXFrameBackchain.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Target/Thread.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// RegisterContextMacOSXFrameBackchain constructor
//----------------------------------------------------------------------
RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain
(
    Thread &thread,
    uint32_t concrete_frame_idx,
    const UnwindMacOSXFrameBackchain::Cursor &cursor
) :
    RegisterContext (thread, concrete_frame_idx),
    m_cursor (cursor),
    m_cursor_is_valid (true)
{
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain()
{
}

void
RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters ()
{
    m_cursor_is_valid = false;
}

size_t
RegisterContextMacOSXFrameBackchain::GetRegisterCount ()
{
    return m_thread.GetRegisterContext()->GetRegisterCount();
}

const RegisterInfo *
RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg)
{
    return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
}

size_t
RegisterContextMacOSXFrameBackchain::GetRegisterSetCount ()
{
    return m_thread.GetRegisterContext()->GetRegisterSetCount();
}



const RegisterSet *
RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set)
{
    return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
}



bool
RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
                                                   RegisterValue &value)
{
    if (!m_cursor_is_valid)
        return false;

    uint64_t reg_value = LLDB_INVALID_ADDRESS;
    
    switch (reg_info->kinds[eRegisterKindGeneric])
    {
    case LLDB_REGNUM_GENERIC_PC:
        if (m_cursor.pc == LLDB_INVALID_ADDRESS)
            return false;
        reg_value = m_cursor.pc;
        break;
    
    case LLDB_REGNUM_GENERIC_FP:
        if (m_cursor.fp == LLDB_INVALID_ADDRESS)
            return false;
        reg_value = m_cursor.fp;
        break;
    
    default:
        return false;    
    }
    
    switch (reg_info->encoding)
    {
    case eEncodingInvalid:
    case eEncodingVector:
        break;

    case eEncodingUint:
    case eEncodingSint:
        value.SetUInt(reg_value, reg_info->byte_size);
        return true;

    case eEncodingIEEE754:
        switch (reg_info->byte_size)
        {
        case sizeof (float):
            if (sizeof (float) == sizeof(uint32_t))
            {
                value.SetUInt32(reg_value, RegisterValue::eTypeFloat);
                return true;
            }
            else if (sizeof (float) == sizeof(uint64_t))
            {
                value.SetUInt64(reg_value, RegisterValue::eTypeFloat);
                return true;
            }
            break;

        case sizeof (double):
            if (sizeof (double) == sizeof(uint32_t))
            {
                value.SetUInt32(reg_value, RegisterValue::eTypeDouble);
                return true;
            }
            else if (sizeof (double) == sizeof(uint64_t))
            {
                value.SetUInt64(reg_value, RegisterValue::eTypeDouble);
                return true;
            }
            break;

            // TOOD: need a better way to detect when "long double" types are
            // the same bytes size as "double"
#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && \
    !defined(__mips__) && !defined(__powerpc__) && !defined(__ANDROID_NDK__)
        case sizeof (long double):
            if (sizeof (long double) == sizeof(uint32_t))
            {
                value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble);
                return true;
            }
            else if (sizeof (long double) == sizeof(uint64_t))
            {
                value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble);
                return true;
            }
            break;
#endif
        }
        break;
    }
    return false;
}

bool
RegisterContextMacOSXFrameBackchain::WriteRegister (const RegisterInfo *reg_info,
                                                    const RegisterValue &value)
{
    // Not supported yet. We could easily add support for this by remembering
    // the address of each entry (it would need to be part of the cursor)
    return false;
}

bool
RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
{
    // libunwind frames can't handle this it doesn't always have all register
    // values. This call should only be called on frame zero anyway so there
    // shouldn't be any problem
    return false;
}

bool
RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
{
    // Since this class doesn't respond to "ReadAllRegisterValues()", it must
    // not have been the one that saved all the register values. So we just let
    // the thread's register context (the register context for frame zero) do
    // the writing.
    return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
}


uint32_t
RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
    return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
}

