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

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "clang/AST/ASTContext.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/Value.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"

using namespace lldb_private;
using namespace clang;

ClangExpressionVariable::ClangExpressionVariable()
{
    m_name = "";
    m_user_type = TypeFromUser(NULL, NULL);
    m_parser_vars.reset(NULL);
    m_jit_vars.reset(NULL);
    m_data_vars.reset(NULL);
}

void ClangExpressionVariable::DisableDataVars()
{
    if (m_data_vars.get() && m_data_vars->m_data)
        delete m_data_vars->m_data;
    m_data_vars.reset();
}

Error
ClangExpressionVariable::Print (Stream &output_stream,
                                ExecutionContext &exe_ctx,
                                lldb::Format format,
                                bool show_types,
                                bool show_summary,
                                bool verbose)
{
    Error err;
    
    Value val;
    if (!PointValueAtData (val, NULL))
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Variable doesn't contain a value");
        return err;
    }
    
    if (val.GetContextType () == Value::eContextTypeInvalid &&
        val.GetValueType () == Value::eValueTypeScalar &&
        format == lldb::eFormatDefault)
    {
        // The expression result is just a scalar with no special formatting
        val.GetScalar ().GetValue (&output_stream, show_types);
        output_stream.EOL ();
        return err;
    }
    
    clang::ASTContext *ast_context = m_user_type.GetASTContext();

    // The expression result is more complex and requires special handling
    DataExtractor data;
    Error expr_error = val.GetValueAsData (&exe_ctx, ast_context, data, 0);
    
    
    // Set byte order and pointer size to TARGET byte order and pointer size!
    
    data.SetByteOrder(exe_ctx.process->GetByteOrder());
    data.SetAddressByteSize(exe_ctx.process->GetAddressByteSize());
    
    if (!expr_error.Success ())
    {
        err.SetErrorToGenericError ();
        err.SetErrorStringWithFormat ("Couldn't resolve variable value: %s", expr_error.AsCString ());
        return err;
    }
    
    if (format == lldb::eFormatDefault)
        format = val.GetValueDefaultFormat ();
    
    void *clang_type = val.GetClangType ();
    
    output_stream.Printf("%s = ", m_name.c_str());
    
    if (clang_type)
    {
        if (show_types)
            output_stream.Printf("(%s) ", ClangASTType::GetClangTypeName (clang_type).GetCString());
        
        ClangASTType::DumpValue (ast_context,               // The ASTContext that the clang type belongs to
                                 clang_type,                // The opaque clang type we want to dump that value of
                                 &exe_ctx,                  // The execution context for memory and variable access
                                 &output_stream,            // Stream to dump to
                                 format,                    // Format to use when dumping
                                 data,                      // A buffer containing the bytes for the clang type
                                 0,                         // Byte offset within "data" where value is
                                 data.GetByteSize (),       // Size in bytes of the value we are dumping
                                 0,                         // Bitfield bit size
                                 0,                         // Bitfield bit offset
                                 show_types,                // Show types?
                                 show_summary,              // Show summary?
                                 verbose,                   // Debug logging output?
                                 UINT32_MAX);               // Depth to dump in case this is an aggregate type
    }
    else
    {
        data.Dump (&output_stream,          // Stream to dump to
                   0,                       // Byte offset within "data"
                   format,                  // Format to use when dumping
                   data.GetByteSize (),     // Size in bytes of each item we are dumping
                   1,                       // Number of items to dump
                   UINT32_MAX,              // Number of items per line
                   LLDB_INVALID_ADDRESS,    // Invalid address, don't show any offset/address context
                   0,                       // Bitfield bit size
                   0);                      // Bitfield bit offset
    }
    
    output_stream.EOL();
    
    return err;
}

ClangExpressionVariable::ClangExpressionVariable(const ClangExpressionVariable &cev) :
    m_name(cev.m_name),
    m_user_type(cev.m_user_type),
    m_store(cev.m_store),
    m_index(cev.m_index)
{
    if (cev.m_parser_vars.get())
    {
        m_parser_vars.reset(new struct ParserVars);
        *m_parser_vars.get() = *cev.m_parser_vars.get();
    }
    
    if (cev.m_jit_vars.get())
    {
        m_jit_vars.reset(new struct JITVars);
        *m_jit_vars.get() = *cev.m_jit_vars.get();
    }
    
    if (cev.m_data_vars.get())
    {
        m_data_vars.reset(new struct DataVars);
        *m_data_vars.get() = *cev.m_data_vars.get();
    }
}

bool
ClangExpressionVariable::PointValueAtData(Value &value, ExecutionContext *exe_ctx)
{
    if (!m_data_vars.get() || !m_data_vars->m_data)
        return false;
    
    value.SetContext(Value::eContextTypeOpaqueClangQualType, m_user_type.GetOpaqueQualType());
    value.SetValueType(Value::eValueTypeHostAddress);
    value.GetScalar() = (uint64_t)m_data_vars->m_data->GetBytes();
    clang::ASTContext *ast_context = m_user_type.GetASTContext();

    if (exe_ctx)
        value.ResolveValue (exe_ctx, ast_context);
    
    return true;
}
