//===-- SBAddress.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/API/SBAddress.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBSection.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Target/Target.h"


using namespace lldb;
using namespace lldb_private;


SBAddress::SBAddress () :
    m_opaque_ap (new Address())
{
}

SBAddress::SBAddress (const Address *lldb_object_ptr) :
    m_opaque_ap (new Address())
{
    if (lldb_object_ptr)
        ref() = *lldb_object_ptr;
}

SBAddress::SBAddress (const SBAddress &rhs) :
    m_opaque_ap (new Address())
{
    if (rhs.IsValid())
        ref() = rhs.ref();
}


SBAddress::SBAddress (lldb::SBSection section, lldb::addr_t offset) :
    m_opaque_ap(new Address (section.GetSP(), offset))
{
}

// Create an address by resolving a load address using the supplied target
SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
    m_opaque_ap(new Address())
{    
    SetLoadAddress (load_addr, target);
}



SBAddress::~SBAddress ()
{
}

const SBAddress &
SBAddress::operator = (const SBAddress &rhs)
{
    if (this != &rhs)
    {
        if (rhs.IsValid())
            ref() = rhs.ref();
        else
            m_opaque_ap.reset (new Address());
    }
    return *this;
}

bool
SBAddress::IsValid () const
{
    return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
}

void
SBAddress::Clear ()
{
    m_opaque_ap.reset (new Address());
}

void
SBAddress::SetAddress (lldb::SBSection section, lldb::addr_t offset)
{
    Address &addr = ref();
    addr.SetSection (section.GetSP());
    addr.SetOffset (offset);
}


void
SBAddress::SetAddress (const Address *lldb_object_ptr)
{
    if (lldb_object_ptr)
        ref() =  *lldb_object_ptr;
    else
        m_opaque_ap.reset (new Address());
}

lldb::addr_t
SBAddress::GetFileAddress () const
{
    if (m_opaque_ap->IsValid())
        return m_opaque_ap->GetFileAddress();
    else
        return LLDB_INVALID_ADDRESS;
}

lldb::addr_t
SBAddress::GetLoadAddress (const SBTarget &target) const
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    lldb::addr_t addr = LLDB_INVALID_ADDRESS;
    TargetSP target_sp (target.GetSP());
    if (target_sp)
    {
        if (m_opaque_ap->IsValid())
        {
            std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
            addr = m_opaque_ap->GetLoadAddress (target_sp.get());
        }
    }

    if (log)
    {
        if (addr == LLDB_INVALID_ADDRESS)
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS",
                         static_cast<void*>(target_sp.get()));
        else
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%" PRIx64,
                         static_cast<void*>(target_sp.get()), addr);
    }

    return addr;
}

void
SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target)
{
    // Create the address object if we don't already have one
    ref();
    if (target.IsValid())
        *this = target.ResolveLoadAddress(load_addr);
    else
        m_opaque_ap->Clear();

    // Check if we weren't were able to resolve a section offset address.
    // If we weren't it is ok, the load address might be a location on the
    // stack or heap, so we should just have an address with no section and
    // a valid offset
    if (!m_opaque_ap->IsValid())
        m_opaque_ap->SetOffset(load_addr);
}

bool
SBAddress::OffsetAddress (addr_t offset)
{
    if (m_opaque_ap->IsValid())
    {
        addr_t addr_offset = m_opaque_ap->GetOffset();
        if (addr_offset != LLDB_INVALID_ADDRESS)
        {
            m_opaque_ap->SetOffset(addr_offset + offset);
            return true;
        }
    }
    return false;
}

lldb::SBSection
SBAddress::GetSection ()
{
    lldb::SBSection sb_section;
    if (m_opaque_ap->IsValid())
        sb_section.SetSP (m_opaque_ap->GetSection());
    return sb_section;
}

lldb::addr_t
SBAddress::GetOffset ()
{
    if (m_opaque_ap->IsValid())
        return m_opaque_ap->GetOffset();
    return 0;
}

Address *
SBAddress::operator->()
{
    return m_opaque_ap.get();
}

const Address *
SBAddress::operator->() const
{
    return m_opaque_ap.get();
}

Address &
SBAddress::ref ()
{
    if (m_opaque_ap.get() == NULL)
        m_opaque_ap.reset (new Address());
    return *m_opaque_ap;
}

const Address &
SBAddress::ref () const
{
    // This object should already have checked with "IsValid()" 
    // prior to calling this function. In case you didn't we will assert
    // and die to let you know.
    assert (m_opaque_ap.get());
    return *m_opaque_ap;
}

Address *
SBAddress::get ()
{
    return m_opaque_ap.get();
}

bool
SBAddress::GetDescription (SBStream &description)
{
    // Call "ref()" on the stream to make sure it creates a backing stream in
    // case there isn't one already...
    Stream &strm = description.ref();
    if (m_opaque_ap->IsValid())
    {
        m_opaque_ap->Dump (&strm,
                           NULL,
                           Address::DumpStyleResolvedDescription,
                           Address::DumpStyleModuleWithFileAddress,
                           4);
        StreamString sstrm;
//        m_opaque_ap->Dump (&sstrm, NULL, Address::DumpStyleResolvedDescription, Address::DumpStyleInvalid, 4);
//        if (sstrm.GetData())
//            strm.Printf (" (%s)", sstrm.GetData());
    }
    else
        strm.PutCString ("No value");

    return true;
}

SBModule
SBAddress::GetModule ()
{
    SBModule sb_module;
    if (m_opaque_ap->IsValid())
        sb_module.SetSP (m_opaque_ap->GetModule());
    return sb_module;
}

SBSymbolContext
SBAddress::GetSymbolContext (uint32_t resolve_scope)
{
    SBSymbolContext sb_sc;
    if (m_opaque_ap->IsValid())
        m_opaque_ap->CalculateSymbolContext (&sb_sc.ref(), resolve_scope);
    return sb_sc;
}

SBCompileUnit
SBAddress::GetCompileUnit ()
{
    SBCompileUnit sb_comp_unit;
    if (m_opaque_ap->IsValid())
        sb_comp_unit.reset(m_opaque_ap->CalculateSymbolContextCompileUnit());
    return sb_comp_unit;
}

SBFunction
SBAddress::GetFunction ()
{
    SBFunction sb_function;
    if (m_opaque_ap->IsValid())
        sb_function.reset(m_opaque_ap->CalculateSymbolContextFunction());
    return sb_function;
}

SBBlock
SBAddress::GetBlock ()
{
    SBBlock sb_block;
    if (m_opaque_ap->IsValid())
        sb_block.SetPtr(m_opaque_ap->CalculateSymbolContextBlock());
    return sb_block;
}

SBSymbol
SBAddress::GetSymbol ()
{
    SBSymbol sb_symbol;
    if (m_opaque_ap->IsValid())
        sb_symbol.reset(m_opaque_ap->CalculateSymbolContextSymbol());
    return sb_symbol;
}

SBLineEntry
SBAddress::GetLineEntry ()
{
    SBLineEntry sb_line_entry;
    if (m_opaque_ap->IsValid())
    {
        LineEntry line_entry;
        if (m_opaque_ap->CalculateSymbolContextLineEntry (line_entry))
            sb_line_entry.SetLineEntry (line_entry);
    }
    return sb_line_entry;
}

AddressClass
SBAddress::GetAddressClass ()
{
    if (m_opaque_ap->IsValid())
        return m_opaque_ap->GetAddressClass();
    return eAddressClassInvalid;
}

