ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
                                              ClangExpression &expr) :
    m_expr (expr),
    m_compiler (),
    m_code_generator ()
{
    // Initialize targets first, so that --version shows registered targets.
    static struct InitializeLLVM {
        InitializeLLVM() {
            llvm::InitializeAllTargets();
            llvm::InitializeAllAsmPrinters();
            llvm::InitializeAllTargetMCs();
            llvm::InitializeAllDisassemblers();
            
            llvm::DisablePrettyStackTrace = true;
        }
    } InitializeLLVM;
    
    // 1. Create a new compiler instance.
    m_compiler.reset(new CompilerInstance());    
    
    // 2. Install the target.

    lldb::TargetSP target_sp;
    if (exe_scope)
        target_sp = exe_scope->CalculateTarget();
    
    // TODO: figure out what to really do when we don't have a valid target.
    // Sometimes this will be ok to just use the host target triple (when we
    // evaluate say "2+3", but other expressions like breakpoint conditions
    // and other things that _are_ target specific really shouldn't just be
    // using the host triple. This needs to be fixed in a better way.
    if (target_sp && target_sp->GetArchitecture().IsValid())
    {
        std::string triple = target_sp->GetArchitecture().GetTriple().str();
        
        int dash_count = 0;
        for (size_t i = 0; i < triple.size(); ++i)
        {
            if (triple[i] == '-')
                dash_count++;
            if (dash_count == 3)
            {
                triple.resize(i);
                break;
            }
        }
        
        m_compiler->getTargetOpts().Triple = triple;
    }
    else
    {
        m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
    }
    
    if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
        target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
    {
        m_compiler->getTargetOpts().Features.push_back("+sse");
        m_compiler->getTargetOpts().Features.push_back("+sse2");
    }
    
    if (m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
        m_compiler->getTargetOpts().ABI = "apcs-gnu";
    
    m_compiler->createDiagnostics();
    
    // Create the target instance.
    m_compiler->setTarget(TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(),
                                                       &m_compiler->getTargetOpts()));
    
    assert (m_compiler->hasTarget());
    
    // 3. Set options.
    
    lldb::LanguageType language = expr.Language();
    
    switch (language)
    {
    case lldb::eLanguageTypeC:
        break;
    case lldb::eLanguageTypeObjC:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        break;
    case lldb::eLanguageTypeC_plus_plus:
        m_compiler->getLangOpts().CPlusPlus = true;
        m_compiler->getLangOpts().CPlusPlus11 = true;
        break;
    case lldb::eLanguageTypeObjC_plus_plus:
    default:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        m_compiler->getLangOpts().CPlusPlus = true;
        m_compiler->getLangOpts().CPlusPlus11 = true;
        break;
    }
    
    m_compiler->getLangOpts().Bool = true;
    m_compiler->getLangOpts().WChar = true;
    m_compiler->getLangOpts().Blocks = true;
    m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
    if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
        m_compiler->getLangOpts().DebuggerCastResultToId = true;
    
    // Spell checking is a nice feature, but it ends up completing a
    // lot of types that we didn't strictly speaking need to complete.
    // As a result, we spend a long time parsing and importing debug
    // information.
    m_compiler->getLangOpts().SpellChecking = false; 
    
    lldb::ProcessSP process_sp;
    if (exe_scope)
        process_sp = exe_scope->CalculateProcess();

    if (process_sp && m_compiler->getLangOpts().ObjC1)
    {
        if (process_sp->GetObjCLanguageRuntime())
        {
            if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2)
                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
            else
                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));
            
            if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing())
                m_compiler->getLangOpts().DebuggerObjCLiteral = 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->getDiagnostics().setDiagnosticGroupMapping("unused-value", clang::diag::MAP_IGNORE, SourceLocation());
    m_compiler->getDiagnostics().setDiagnosticGroupMapping("odr", clang::diag::MAP_IGNORE, SourceLocation());
    
    // 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_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);
    
    // 5. Set up the source management objects inside the compiler
    
    clang::FileSystemOptions file_system_options;
    m_file_manager.reset(new clang::FileManager(file_system_options));
    
    if (!m_compiler->hasSourceManager())
        m_compiler->createSourceManager(*m_file_manager.get());
    
    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.
    m_selector_table.reset(new SelectorTable());
    m_builtin_context.reset(new Builtin::Context());
    
    std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
                                                                 m_compiler->getSourceManager(),
                                                                 &m_compiler->getTarget(),
                                                                 m_compiler->getPreprocessor().getIdentifierTable(),
                                                                 *m_selector_table.get(),
                                                                 *m_builtin_context.get(),
                                                                 0));
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
    
    if (decl_map)
    {
        llvm::OwningPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
        decl_map->InstallASTContext(ast_context.get());
        ast_context->setExternalSource(ast_source);
    }
    
    m_compiler->setASTContext(ast_context.release());
    
    std::string module_name("$__lldb_module");

    m_llvm_context.reset(new LLVMContext());
    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
                                             module_name,
                                             m_compiler->getCodeGenOpts(),
                                             m_compiler->getTargetOpts(),
                                             *m_llvm_context));
}
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
                                              ClangExpression &expr,
                                              bool generate_debug_info) :
    m_expr (expr),
    m_compiler (),
    m_code_generator (),
    m_pp_callbacks(nullptr)
{
    // 1. Create a new compiler instance.
    m_compiler.reset(new CompilerInstance());

    // 2. Install the target.

    lldb::TargetSP target_sp;
    if (exe_scope)
        target_sp = exe_scope->CalculateTarget();

    // TODO: figure out what to really do when we don't have a valid target.
    // Sometimes this will be ok to just use the host target triple (when we
    // evaluate say "2+3", but other expressions like breakpoint conditions
    // and other things that _are_ target specific really shouldn't just be
    // using the host triple. This needs to be fixed in a better way.
    if (target_sp && target_sp->GetArchitecture().IsValid())
    {
        std::string triple = target_sp->GetArchitecture().GetTriple().str();
        m_compiler->getTargetOpts().Triple = triple;
    }
    else
    {
        m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
    }

    if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
        target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
    {
        m_compiler->getTargetOpts().Features.push_back("+sse");
        m_compiler->getTargetOpts().Features.push_back("+sse2");
    }

    // Any arm32 iOS environment, but not on arm64
    if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
        m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
        m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
    {
        m_compiler->getTargetOpts().ABI = "apcs-gnu";
    }

    m_compiler->createDiagnostics();

    // Create the target instance.
    m_compiler->setTarget(TargetInfo::CreateTargetInfo(
        m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts));

    assert (m_compiler->hasTarget());

    // 3. Set options.

    lldb::LanguageType language = expr.Language();

    switch (language)
    {
    case lldb::eLanguageTypeC:
        break;
    case lldb::eLanguageTypeObjC:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        break;
    case lldb::eLanguageTypeC_plus_plus:
        m_compiler->getLangOpts().CPlusPlus = true;
        m_compiler->getLangOpts().CPlusPlus11 = true;
        m_compiler->getHeaderSearchOpts().UseLibcxx = true;
        break;
    case lldb::eLanguageTypeObjC_plus_plus:
    default:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        m_compiler->getLangOpts().CPlusPlus = true;
        m_compiler->getLangOpts().CPlusPlus11 = true;
        m_compiler->getHeaderSearchOpts().UseLibcxx = true;
        break;
    }

    m_compiler->getLangOpts().Bool = true;
    m_compiler->getLangOpts().WChar = true;
    m_compiler->getLangOpts().Blocks = true;
    m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
    if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
        m_compiler->getLangOpts().DebuggerCastResultToId = true;

    // Spell checking is a nice feature, but it ends up completing a
    // lot of types that we didn't strictly speaking need to complete.
    // As a result, we spend a long time parsing and importing debug
    // information.
    m_compiler->getLangOpts().SpellChecking = false;

    lldb::ProcessSP process_sp;
    if (exe_scope)
        process_sp = exe_scope->CalculateProcess();

    if (process_sp && m_compiler->getLangOpts().ObjC1)
    {
        if (process_sp->GetObjCLanguageRuntime())
        {
            if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2)
                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
            else
                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));

            if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing())
                m_compiler->getLangOpts().DebuggerObjCLiteral = 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;
    m_compiler->getCodeGenOpts().DisableFPElim = true;
    m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
    if (generate_debug_info)
        m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo);
    else
        m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo);

    // Disable some warnings.
    m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
        "unused-value", clang::diag::Severity::Ignored, SourceLocation());
    m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
        "odr", clang::diag::Severity::Ignored, SourceLocation());

    // 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().adjust(m_compiler->getLangOpts());

    // 4. Set up the diagnostic buffer for reporting errors

    m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);

    // 5. Set up the source management objects inside the compiler

    clang::FileSystemOptions file_system_options;
    m_file_manager.reset(new clang::FileManager(file_system_options));

    if (!m_compiler->hasSourceManager())
        m_compiler->createSourceManager(*m_file_manager.get());

    m_compiler->createFileManager();
    m_compiler->createPreprocessor(TU_Complete);
    
    if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor())
    {
        std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor));
        m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get());
        m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
    }
        
    // 6. Most of this we get from the CompilerInstance, but we
    // also want to give the context an ExternalASTSource.
    m_selector_table.reset(new SelectorTable());
    m_builtin_context.reset(new Builtin::Context());

    std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
                                                                 m_compiler->getSourceManager(),
                                                                 m_compiler->getPreprocessor().getIdentifierTable(),
                                                                 *m_selector_table.get(),
                                                                 *m_builtin_context.get()));
    
    ast_context->InitBuiltinTypes(m_compiler->getTarget());

    ClangExpressionDeclMap *decl_map = m_expr.DeclMap();

    if (decl_map)
    {
        llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
        decl_map->InstallASTContext(ast_context.get());
        ast_context->setExternalSource(ast_source);
    }

    m_compiler->setASTContext(ast_context.release());

    std::string module_name("$__lldb_module");

    m_llvm_context.reset(new LLVMContext());
    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
                                             module_name,
                                             m_compiler->getCodeGenOpts(),
                                             m_compiler->getTargetOpts(),
                                             *m_llvm_context));
}
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
                                              ClangExpression &expr) :
    m_expr (expr),
    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();
            llvm::InitializeAllTargetMCs();
            llvm::InitializeAllDisassemblers();
        }
    } InitializeLLVM;
        
    // 1. Create a new compiler instance.
    m_compiler.reset(new CompilerInstance());    
    
    // 2. Set options.
    
    lldb::LanguageType language = expr.Language();
    
    switch (language)
    {
    case lldb::eLanguageTypeC:
        break;
    case lldb::eLanguageTypeObjC:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        break;
    case lldb::eLanguageTypeC_plus_plus:
        m_compiler->getLangOpts().CPlusPlus = true;
        break;
    case lldb::eLanguageTypeObjC_plus_plus:
    default:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        m_compiler->getLangOpts().CPlusPlus = true;
        break;
    }
    
    Process *process = NULL;
    if (exe_scope)
        process = exe_scope->CalculateProcess();

    if (process && m_compiler->getLangOpts().ObjC1)
    {
        if (process->GetObjCLanguageRuntime())
        {
            if (process->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2)
            {
                m_compiler->getLangOpts().ObjCNonFragileABI = true;     // NOT i386
                m_compiler->getLangOpts().ObjCNonFragileABI2 = true;    // NOT i386
            }
        }
    }

    m_compiler->getLangOpts().ThreadsafeStatics = false;
    m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
    m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
    m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
    
    // 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.
    Target *target = NULL;
    if (exe_scope)
        target = exe_scope->CalculateTarget();

    // TODO: figure out what to really do when we don't have a valid target.
    // Sometimes this will be ok to just use the host target triple (when we
    // evaluate say "2+3", but other expressions like breakpoint conditions
    // and other things that _are_ target specific really shouldn't just be 
    // using the host triple. This needs to be fixed in a better way.
    if (target && target->GetArchitecture().IsValid())
    {
        std::string triple = target->GetArchitecture().GetTriple().str();
        
        int dash_count = 0;
        for (size_t i = 0; i < triple.size(); ++i)
        {
            if (triple[i] == '-')
                dash_count++;
            if (dash_count == 3)
            {
                triple.resize(i);
                break;
            }
        }
        
        m_compiler->getTargetOpts().Triple = triple;
    }
    else
    {
        m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
    }
        
    // 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_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);
    
    // 5. Set up the source management objects inside the compiler
    
    clang::FileSystemOptions file_system_options;
    m_file_manager.reset(new clang::FileManager(file_system_options));
    
    if (!m_compiler->hasSourceManager())
        m_compiler->createSourceManager(*m_file_manager.get());
    
    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.
    m_selector_table.reset(new SelectorTable());
    m_builtin_context.reset(new Builtin::Context());
    
    std::auto_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
                                                                m_compiler->getSourceManager(),
                                                                &m_compiler->getTarget(),
                                                                m_compiler->getPreprocessor().getIdentifierTable(),
                                                                *m_selector_table.get(),
                                                                *m_builtin_context.get(),
                                                                0));
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
    
    if (decl_map)
    {
        llvm::OwningPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
        decl_map->InstallASTContext(ast_context.get());
        ast_context->setExternalSource(ast_source);
    }
    
    m_compiler->setASTContext(ast_context.release());
    
    std::string module_name("$__lldb_module");

    m_llvm_context.reset(new LLVMContext());
    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
                                             module_name,
                                             m_compiler->getCodeGenOpts(),
                                             *m_llvm_context));
}