Backend support for top-level Clang epxressions

This patch adds a new ExecutionPolicy, eExecutionPolicyTopLevel, which
tells the expression parser that the expression should be JITted as top
level code but nothing (except static initializers) should be run.  I
have modified the Clang expression parser to recognize this execution
policy.  On top of the existing patches that support storing IR and
maintaining a map of arbitrary Decls, this is mainly just patching up a
few places in the expression parser.

I intend to submit a patch for review that exposes this functionality
through the "expression" command and through the SB API.  That patch
also includes a testcase for all of this.

<rdar://problem/22864976>

llvm-svn: 264095
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 25ac0e2..3066384 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -55,28 +55,25 @@
 
 using namespace lldb_private;
 
-ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
-                                          const char *expr,
-                                          const char *expr_prefix,
-                                          lldb::LanguageType language,
-                                          ResultType desired_type,
-                                          const EvaluateExpressionOptions &options) :
-    LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options),
-    m_type_system_helper(*m_target_wp.lock().get())
+ClangUserExpression::ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                                         lldb::LanguageType language, ResultType desired_type,
+                                         const EvaluateExpressionOptions &options)
+    : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type, options),
+      m_type_system_helper(*m_target_wp.lock().get(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
 {
     switch (m_language)
     {
-    case lldb::eLanguageTypeC_plus_plus:
-        m_allow_cxx = true;
-        break;
-    case lldb::eLanguageTypeObjC:
-        m_allow_objc = true;
-        break;
-    case lldb::eLanguageTypeObjC_plus_plus:
-    default:
-        m_allow_cxx = true;
-        m_allow_objc = true;
-        break;
+        case lldb::eLanguageTypeC_plus_plus:
+            m_allow_cxx = true;
+            break;
+        case lldb::eLanguageTypeObjC:
+            m_allow_objc = true;
+            break;
+        case lldb::eLanguageTypeObjC_plus_plus:
+        default:
+            m_allow_cxx = true;
+            m_allow_objc = true;
+            break;
     }
 }
 
@@ -402,22 +399,30 @@
             }
         }
     }
-    
-    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
-    
-    lldb::LanguageType lang_type;
 
-    if (m_in_cplusplus_method)
-        lang_type = lldb::eLanguageTypeC_plus_plus;
-    else if (m_in_objectivec_method)
-        lang_type = lldb::eLanguageTypeObjC;
-    else
-        lang_type = lldb::eLanguageTypeC;
-
-    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
+    if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
     {
-        diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body");
-        return false;
+        m_transformed_text = m_expr_text;
+    }
+    else
+    {
+        std::unique_ptr<ExpressionSourceCode> source_code(
+            ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
+
+        lldb::LanguageType lang_type;
+
+        if (m_in_cplusplus_method)
+            lang_type = lldb::eLanguageTypeC_plus_plus;
+        else if (m_in_objectivec_method)
+            lang_type = lldb::eLanguageTypeObjC;
+        else
+            lang_type = lldb::eLanguageTypeC;
+
+        if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
+        {
+            diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body");
+            return false;
+        }
     }
 
     if (log)
@@ -473,6 +478,11 @@
         return false;
     }
 
+    if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+    {
+        DeclMap()->SetLookupsEnabled(true);
+    }
+
     Process *process = exe_ctx.GetProcessPtr();
     ExecutionContextScope *exe_scope = process;
 
@@ -497,16 +507,60 @@
     // Prepare the output of the parser for execution, evaluating it statically if possible
     //
 
-    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
-                                                  m_jit_end_addr,
-                                                  m_execution_unit_sp,
-                                                  exe_ctx,
-                                                  m_can_interpret,
-                                                  execution_policy);
+    {
+        Error jit_error = parser.PrepareForExecution(m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
+                                                     m_can_interpret, execution_policy);
+
+        if (!jit_error.Success())
+        {
+            const char *error_cstr = jit_error.AsCString();
+            if (error_cstr && error_cstr[0])
+                diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
+            else
+                diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run");
+            return false;
+        }
+    }
+
+    if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel)
+    {
+        Error static_init_error = parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx);
+
+        if (!static_init_error.Success())
+        {
+            const char *error_cstr = static_init_error.AsCString();
+            if (error_cstr && error_cstr[0])
+                diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n",
+                                          error_cstr);
+            else
+                diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't run static initializers\n");
+            return false;
+        }
+    }
+
+    if (m_execution_unit_sp)
+    {
+        bool register_execution_unit = false;
+
+        if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+        {
+            register_execution_unit = true;
+        }
+
+        if (register_execution_unit)
+        {
+            // We currently key off there being more than one external function in the execution
+            // unit to determine whether it needs to live in the process.
+
+            llvm::cast<PersistentExpressionState>(
+                exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(m_language))
+                ->RegisterExecutionUnit(m_execution_unit_sp);
+        }
+    }
 
     if (generate_debug_info)
     {
-        lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+        lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
 
         if (jit_module_sp)
         {
@@ -517,41 +571,14 @@
             m_jit_module_wp = jit_module_sp;
             target->GetImages().Append(jit_module_sp);
         }
-//        lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
-//        StreamFile strm (stdout, false);
-//        if (jit_obj_file)
-//        {
-//            jit_obj_file->GetSectionList();
-//            jit_obj_file->GetSymtab();
-//            jit_obj_file->Dump(&strm);
-//        }
-//        lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
-//        if (jit_sym_vendor)
-//        {
-//            lldb_private::SymbolContextList sc_list;
-//            jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
-//            sc_list.Dump(&strm, target);
-//            jit_sym_vendor->Dump(&strm);
-//        }
     }
 
-    ResetDeclMap(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any ClangASTImporter::Minions.
+    ResetDeclMap(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any
+                    // ClangASTImporter::Minions.
 
-    if (jit_error.Success())
-    {
-        if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
-            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
-        return true;
-    }
-    else
-    {
-        const char *error_cstr = jit_error.AsCString();
-        if (error_cstr && error_cstr[0])
-            diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
-        else
-            diagnostic_manager.Printf(eDiagnosticSeverityError, "expression can't be interpreted or run");
-        return false;
-    }
+    if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
+        m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
+    return true;
 }
 
 bool
@@ -637,14 +664,22 @@
 }
 
 clang::ASTConsumer *
-ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(clang::ASTConsumer *passthrough)
 {
-    m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough,
-                                                           m_target));
+    m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, m_top_level, m_target));
 
     return m_result_synthesizer_up.get();
 }
 
+void
+ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls()
+{
+    if (m_result_synthesizer_up.get())
+    {
+        m_result_synthesizer_up->CommitPersistentDecls();
+    }
+}
+
 ClangUserExpression::ResultDelegate::ResultDelegate()
 {
 }