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

#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Stream.h"
#include "lldb/Expression/ClangASTSource.h"
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/IRForTarget.h"
#include "lldb/Expression/IRToDWARF.h"
#include "lldb/Expression/RecordingMemoryManager.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Checker/FrontendActions.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Driver/CC1Options.h"
#include "clang/Driver/OptTable.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/VerifyDiagnosticsClient.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/FrontendActions.h"
#include "clang/Sema/ParseAST.h"
#include "clang/Sema/SemaConsumer.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Module.h"
#include "llvm/LLVMContext.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/System/Host.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetSelect.h"

using namespace clang;
using namespace llvm;
using namespace lldb_private;

//===----------------------------------------------------------------------===//
// Utility Methods for Clang
//===----------------------------------------------------------------------===//

std::string GetBuiltinIncludePath(const char *Argv0) {
    llvm::sys::Path P =
    llvm::sys::Path::GetMainExecutable(Argv0,
                                       (void*)(intptr_t) GetBuiltinIncludePath);
    
    if (!P.isEmpty()) {
        P.eraseComponent();  // Remove /clang from foo/bin/clang
        P.eraseComponent();  // Remove /bin   from foo/bin
        
        // Get foo/lib/clang/<version>/include
        P.appendComponent("lib");
        P.appendComponent("clang");
        P.appendComponent(CLANG_VERSION_STRING);
        P.appendComponent("include");
    }
    
    return P.str();
}


//===----------------------------------------------------------------------===//
// Main driver for Clang
//===----------------------------------------------------------------------===//

static void LLVMErrorHandler(void *UserData, const std::string &Message) {
    Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
    
    Diags.Report(diag::err_fe_error_backend) << Message;
    
    // We cannot recover from llvm errors.
    exit(1);
}

static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
    using namespace clang::frontend;
    
    switch (CI.getFrontendOpts().ProgramAction) {
        default:
            llvm_unreachable("Invalid program action!");
            
        case ASTDump:                return new ASTDumpAction();
        case ASTPrint:               return new ASTPrintAction();
        case ASTPrintXML:            return new ASTPrintXMLAction();
        case ASTView:                return new ASTViewAction();
        case BoostCon:               return new BoostConAction();
        case DumpRawTokens:          return new DumpRawTokensAction();
        case DumpTokens:             return new DumpTokensAction();
        case EmitAssembly:           return new EmitAssemblyAction();
        case EmitBC:                 return new EmitBCAction();
        case EmitHTML:               return new HTMLPrintAction();
        case EmitLLVM:               return new EmitLLVMAction();
        case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
        case EmitCodeGenOnly:        return new EmitCodeGenOnlyAction();
        case EmitObj:                return new EmitObjAction();
        case FixIt:                  return new FixItAction();
        case GeneratePCH:            return new GeneratePCHAction();
        case GeneratePTH:            return new GeneratePTHAction();
        case InheritanceView:        return new InheritanceViewAction();
        case InitOnly:               return new InitOnlyAction();
        case ParseSyntaxOnly:        return new SyntaxOnlyAction();
            
        case PluginAction: {
            for (FrontendPluginRegistry::iterator it =
                 FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
                 it != ie; ++it) {
                if (it->getName() == CI.getFrontendOpts().ActionName) {
                    llvm::OwningPtr<PluginASTAction> P(it->instantiate());
                    if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
                        return 0;
                    return P.take();
                }
            }
            
            CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
            << CI.getFrontendOpts().ActionName;
            return 0;
        }
            
        case PrintDeclContext:       return new DeclContextPrintAction();
        case PrintPreamble:          return new PrintPreambleAction();
        case PrintPreprocessedInput: return new PrintPreprocessedAction();
        case RewriteMacros:          return new RewriteMacrosAction();
        case RewriteObjC:            return new RewriteObjCAction();
        case RewriteTest:            return new RewriteTestAction();
        case RunAnalysis:            return new AnalysisAction();
        case RunPreprocessorOnly:    return new PreprocessOnlyAction();
    }
}

static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
    // Create the underlying action.
    FrontendAction *Act = CreateFrontendBaseAction(CI);
    if (!Act)
        return 0;
    
    // If there are any AST files to merge, create a frontend action
    // adaptor to perform the merge.
    if (!CI.getFrontendOpts().ASTMergeFiles.empty())
        Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
                                 CI.getFrontendOpts().ASTMergeFiles.size());
    
    return Act;
}

//===----------------------------------------------------------------------===//
// Implementation of ClangExpressionParser
//===----------------------------------------------------------------------===//

ClangExpressionParser::ClangExpressionParser(const char *target_triple,
                                             ClangExpression &expr) :
    m_expr(expr),
    m_target_triple (),
    m_compiler (),
    m_code_generator (NULL),
    m_execution_engine (),
    m_jitted_functions ()
{
    // Initialize targets first, so that --version shows registered targets.
    static struct InitializeLLVM {
        InitializeLLVM() {
            llvm::InitializeAllTargets();
            llvm::InitializeAllAsmPrinters();
        }
    } InitializeLLVM;
    
    if (target_triple && target_triple[0])
        m_target_triple = target_triple;
    else
        m_target_triple = llvm::sys::getHostTriple();
    
    // 1. Create a new compiler instance.
    m_compiler.reset(new CompilerInstance());    
    m_compiler->setLLVMContext(new LLVMContext());
    
    // 2. Set options.
    
    // Parse expressions as Objective C++ regardless of context.
    // Our hook into Clang's lookup mechanism only works in C++.
    m_compiler->getLangOpts().CPlusPlus = true;
    m_compiler->getLangOpts().ObjC1 = true;
    m_compiler->getLangOpts().ThreadsafeStatics = false;
    m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
    m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
    
    // Set CodeGen options
    m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
    m_compiler->getCodeGenOpts().InstrumentFunctions = false;
    
    // Disable some warnings.
    m_compiler->getDiagnosticOpts().Warnings.push_back("no-unused-value");
    
    // Set the target triple.
    m_compiler->getTargetOpts().Triple = m_target_triple;
    
    // 3. Set up various important bits of infrastructure.
    m_compiler->createDiagnostics(0, 0);
    
    // Create the target instance.
    m_compiler->setTarget(TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(),
                                                       m_compiler->getTargetOpts()));
    
    assert (m_compiler->hasTarget());
    
    // Inform the target of the language options
    //
    // FIXME: We shouldn't need to do this, the target should be immutable once
    // created. This complexity should be lifted elsewhere.
    m_compiler->getTarget().setForcedLangOptions(m_compiler->getLangOpts());
    
    // 4. Set up the diagnostic buffer for reporting errors
    
    m_diagnostic_buffer.reset(new clang::TextDiagnosticBuffer);
    m_compiler->getDiagnostics().setClient(m_diagnostic_buffer.get());
    
    // 5. Set up the source management objects inside the compiler
    
    if (!m_compiler->hasSourceManager())
        m_compiler->createSourceManager();
    
    m_compiler->createFileManager();
    m_compiler->createPreprocessor();
    
    // 6. Most of this we get from the CompilerInstance, but we 
    // also want to give the context an ExternalASTSource.
    SelectorTable selector_table;
    m_builtin_context.reset(new Builtin::Context(m_compiler->getTarget()));
    
    std::auto_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
                                                                m_compiler->getSourceManager(),
                                                                m_compiler->getTarget(),
                                                                m_compiler->getPreprocessor().getIdentifierTable(),
                                                                selector_table,
                                                                *m_builtin_context.get(),
                                                                0));
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
    
    if (decl_map)
    {
        OwningPtr<clang::ExternalASTSource> ast_source(new ClangASTSource(*ast_context, *decl_map));
        ast_context->setExternalSource(ast_source);
    }
    
    m_compiler->setASTContext(ast_context.release());
    
    std::string module_name("___clang_module");

    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
                                             module_name,
                                             m_compiler->getCodeGenOpts(),
                                             m_compiler->getLLVMContext()));
}

ClangExpressionParser::~ClangExpressionParser()
{
}

unsigned
ClangExpressionParser::Parse (Stream &stream)
{
    m_diagnostic_buffer->FlushDiagnostics (m_compiler->getDiagnostics());
    
    MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(m_expr.Text(), __FUNCTION__);
    FileID memory_buffer_file_id = m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
    
    m_diagnostic_buffer->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
    
    ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
    
    if (ast_transformer)
        ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
    else 
        ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());    
    
    m_diagnostic_buffer->EndSourceFile();
    
    TextDiagnosticBuffer::const_iterator diag_iterator;
    
    int num_errors = 0;
        
    for (diag_iterator = m_diagnostic_buffer->warn_begin();
         diag_iterator != m_diagnostic_buffer->warn_end();
         ++diag_iterator)
        stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
    
    num_errors = 0;
    
    for (diag_iterator = m_diagnostic_buffer->err_begin();
         diag_iterator != m_diagnostic_buffer->err_end();
         ++diag_iterator)
    {
        num_errors++;
        stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
    }
    
    return num_errors;
}

Error
ClangExpressionParser::MakeDWARF ()
{
    Error err;
    
    llvm::Module *module = m_code_generator->GetModule();
    
    if (!module)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }
    
    ClangExpressionVariableStore *local_variables = m_expr.LocalVariables();
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
    
    if (!local_variables)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Can't convert an expression without a VariableList to DWARF");
        return err;
    }
    
    if (!decl_map)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Can't convert an expression without a DeclMap to DWARF");
        return err;
    }
    
    IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream());
    
    if (!ir_to_dwarf.runOnModule(*module))
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Couldn't convert the expression to DWARF");
        return err;
    }
    
    err.Clear();
    return err;
}

Error
ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr, 
                                lldb::addr_t &func_end, 
                                ExecutionContext &exe_ctx)
{
    Error err;
    
    llvm::Module *module = m_code_generator->ReleaseModule();

    if (!module)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
    
    if (decl_map)
    {
        std::string target_error;
        
        const llvm::Target *target = llvm::TargetRegistry::lookupTarget(m_target_triple, target_error);
        
        if (!target)
        {
            err.SetErrorToGenericError();
            err.SetErrorStringWithFormat("Couldn't find a target for %s", m_target_triple.c_str());
            return err;
        }
        
        std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
        
        IRForTarget ir_for_target(decl_map, target_machine->getTargetData(), m_expr.FunctionName());
        
        if (!ir_for_target.runOnModule(*module))
        {
            err.SetErrorToGenericError();
            err.SetErrorString("Couldn't convert the expression to DWARF");
            return err;
        }
    }
    
    m_jit_mm = new RecordingMemoryManager();
    
    std::string error_string;
    
    m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, 
                                                               &error_string, 
                                                               m_jit_mm,
                                                               CodeGenOpt::Default,
                                                               true,
                                                               CodeModel::Small));
    
    if (!m_execution_engine.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return err;
    }
    
    m_execution_engine->DisableLazyCompilation();
    
    llvm::Function *function = module->getFunction (m_expr.FunctionName());
    
    // We don't actually need the function pointer here, this just forces it to get resolved.
    
    void *fun_ptr = m_execution_engine->getPointerToFunction(function);
    
    // Errors usually cause failures in the JIT, but if we're lucky we get here.
    
    if (!fun_ptr)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Couldn't JIT the function");
        return err;
    }
    
    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(m_expr.FunctionName(), (lldb::addr_t)fun_ptr));
    
    ExecutionContext &exc_context(exe_ctx);
    
    if (exc_context.process == NULL)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
        return err;
    }
    
    // Look over the regions allocated for the function compiled.  The JIT
    // tries to allocate the functions & stubs close together, so we should try to
    // write them that way too...
    // For now I only write functions with no stubs, globals, exception tables,
    // etc.  So I only need to write the functions.
    
    size_t alloc_size = 0;
    
    std::map<uint8_t *, uint8_t *>::iterator fun_pos = m_jit_mm->m_functions.begin();
    std::map<uint8_t *, uint8_t *>::iterator fun_end = m_jit_mm->m_functions.end();
    
    for (; fun_pos != fun_end; ++fun_pos)
        alloc_size += (*fun_pos).second - (*fun_pos).first;
    
    Error alloc_error;
    lldb::addr_t target_addr = exc_context.process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, alloc_error);
    
    if (target_addr == LLDB_INVALID_ADDRESS)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error"));
        return err;
    }
    
    lldb::addr_t cursor = target_addr;
        
    for (fun_pos = m_jit_mm->m_functions.begin(); fun_pos != fun_end; fun_pos++)
    {
        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
        size_t size = lend - lstart;
        
        Error write_error;
        
        if (exc_context.process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
        {
            err.SetErrorToGenericError();
            err.SetErrorStringWithFormat("Couldn't copy JITted function into the target: %s", write_error.AsCString("unknown error"));
            return err;
        }
            
        m_jit_mm->AddToLocalToRemoteMap (lstart, size, cursor);
        cursor += size;
    }
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos != end; pos++)
    {
        (*pos).m_remote_addr = m_jit_mm->GetRemoteAddressForLocal ((*pos).m_local_addr);
    
        if (!(*pos).m_name.compare(m_expr.FunctionName()))
        {
            func_end = m_jit_mm->GetRemoteRangeForLocal ((*pos).m_local_addr).second;
            func_addr = (*pos).m_remote_addr;
        }
    }
    
    err.Clear();
    return err;
}

Error
ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
    
    const char *name = m_expr.FunctionName();
    
    Error ret;
    
    ret.Clear();
    
    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos < end; pos++)
    {
        if (strcmp(pos->m_name.c_str(), name) == 0)
        {
            func_local_addr = pos->m_local_addr;
            func_remote_addr = pos->m_remote_addr;
        }
    }
    
    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
        return ret;
    }
    
    if(log)
        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
    
    std::pair <lldb::addr_t, lldb::addr_t> func_range;
    
    func_range = m_jit_mm->GetRemoteRangeForLocal(func_local_addr);
    
    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
        return ret;
    }
    
    if(log)
        log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
    
    if (!exe_ctx.target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
    }
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
    
    Error err;
    exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
    
    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }
    
    ArchSpec arch(exe_ctx.target->GetArchitecture());
    
    Disassembler *disassembler = Disassembler::FindPlugin(arch);
    
    if (disassembler == NULL)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString());
        return ret;
    }
    
    if (!exe_ctx.process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }
    
    DataExtractor extractor(buffer_sp, 
                            exe_ctx.process->GetByteOrder(),
                            exe_ctx.target->GetArchitecture().GetAddressByteSize());
    
    if(log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log,
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }
    
    disassembler->DecodeInstructions(extractor, 0, UINT32_MAX);
    
    Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList();
    
    uint32_t bytes_offset = 0;
    
    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
         instruction_index < num_instructions; 
         ++instruction_index)
    {
        Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index);
        Address addr(NULL, func_remote_addr + bytes_offset);
        instruction->Dump (&stream,
                           &addr,
                           &extractor, 
                           bytes_offset, 
                           exe_ctx, 
                           true);
        stream.PutChar('\n');
        bytes_offset += instruction->GetByteSize();
    }
    
    return ret;
}
