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

#include "GoLanguageRuntime.h"

#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Symbol/GoASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "llvm/ADT/Twine.h"

#include <vector>

using namespace lldb;
using namespace lldb_private;

namespace {
ValueObjectSP GetChild(ValueObject& obj, const char* name, bool dereference = true) {
    ConstString name_const_str(name);
    ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
    if (dereference && result && result->IsPointerType()) {
        Error err;
        result = result->Dereference(err);
        if (err.Fail())
            result.reset();
    }
    return result;
}

ConstString ReadString(ValueObject& str, Process* process) {
    ConstString result;
    ValueObjectSP data = GetChild(str, "str", false);
    ValueObjectSP len = GetChild(str, "len");
    if (len && data)
    {
        Error err;
        lldb::addr_t addr = data->GetPointerValue();
        if (addr == LLDB_INVALID_ADDRESS)
            return result;
        uint64_t byte_size = len->GetValueAsUnsigned(0);
        char* buf = new char[byte_size + 1];
        buf[byte_size] = 0;
        size_t bytes_read = process->ReadMemory (addr,
                                                 buf,
                                                 byte_size,
                                                 err);
        if (!(err.Fail() || bytes_read != byte_size))
            result = ConstString(buf, bytes_read);
        delete[] buf;
    }
    return result;
}

ConstString
ReadTypeName(ValueObjectSP type, Process* process)
{
    if (ValueObjectSP uncommon = GetChild(*type, "x"))
    {
        ValueObjectSP name = GetChild(*uncommon, "name");
        ValueObjectSP package = GetChild(*uncommon, "pkgpath");
        if (name && name->GetPointerValue() != 0 && package && package->GetPointerValue() != 0)
        {
            ConstString package_const_str = ReadString(*package, process);
            ConstString name_const_str = ReadString(*name, process);
            if (package_const_str.GetLength() == 0)
                return name_const_str;
            return ConstString((package_const_str.GetStringRef() + "." + name_const_str.GetStringRef()).str());
        }
    }
    ValueObjectSP name = GetChild(*type, "_string");
    if (name)
        return ReadString(*name, process);
    return ConstString("");
}

CompilerType
LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct)
{
    uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
    *is_direct = GoASTContext::IsDirectIface(kind);
    if (GoASTContext::IsPointerKind(kind))
    {
        CompilerType type_ptr = type->GetCompilerType().GetPointerType();
        Error err;
        ValueObjectSP elem = type->CreateValueObjectFromAddress("elem", type->GetAddressOf() + type->GetByteSize(), *exe_ctx, type_ptr)->Dereference(err);
        if (err.Fail())
            return CompilerType();
        bool tmp_direct;
        return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
    }
    Target *target = exe_ctx->GetTargetPtr();
    Process *process = exe_ctx->GetProcessPtr();
    
    ConstString const_typename = ReadTypeName(type, process);
    if (const_typename.GetLength() == 0)
        return CompilerType();
    
    SymbolContext sc;
    TypeList type_list;
    llvm::DenseSet<SymbolFile *> searched_symbol_files;
    uint32_t num_matches = target->GetImages().FindTypes (sc,
                                                          const_typename,
                                                          false,
                                                          2,
                                                          searched_symbol_files,
                                                          type_list);
    if (num_matches > 0) {
        return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
    }
    return CompilerType();
}

}

bool
GoLanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{
    return GoASTContext::IsGoInterface(in_value.GetCompilerType());
}

bool
GoLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
                                            TypeAndOrName &class_type_or_name, Address &dynamic_address,
                                            Value::ValueType &value_type)
{
    value_type = Value::eValueTypeScalar;
    class_type_or_name.Clear();
    if (CouldHaveDynamicValue (in_value))
    {
        Error err;
        ValueObjectSP iface = in_value.GetStaticValue();
        ValueObjectSP data_sp = GetChild(*iface, "data", false);
        if (!data_sp)
            return false;

        if (ValueObjectSP tab = GetChild(*iface, "tab"))
            iface = tab;
        ValueObjectSP type = GetChild(*iface, "_type");
        if (!type)
        {
            return false;
        }
        
        bool direct;
        ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
        CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
        if (!final_type)
            return false;
        if (direct)
        {
            class_type_or_name.SetCompilerType(final_type);
        }
        else
        {
            // TODO: implement reference types or fix caller to support dynamic types that aren't pointers
            // so we don't have to introduce this extra pointer.
            class_type_or_name.SetCompilerType(final_type.GetPointerType());
        }

        dynamic_address.SetLoadAddress(data_sp->GetPointerValue(), exe_ctx.GetTargetPtr());

        return true;
    }
    return false;
}

TypeAndOrName
GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
{
    return type_and_or_name;
}

//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
GoLanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
{
    if (language == eLanguageTypeGo)
        return new GoLanguageRuntime (process);
    else
        return NULL;
}

void
GoLanguageRuntime::Initialize()
{
    PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                   "Go Language Runtime",
                                   CreateInstance);
}

void
GoLanguageRuntime::Terminate()
{
    PluginManager::UnregisterPlugin (CreateInstance);
}

lldb_private::ConstString
GoLanguageRuntime::GetPluginNameStatic()
{
    static ConstString g_name("golang");
    return g_name;
}

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString
GoLanguageRuntime::GetPluginName()
{
    return GetPluginNameStatic();
}

uint32_t
GoLanguageRuntime::GetPluginVersion()
{
    return 1;
}

