[Lldb-commits] [lldb] r264095 - Backend support for top-level Clang epxressions

Sean Callanan via lldb-commits lldb-commits at lists.llvm.org
Tue Mar 22 14:05:51 PDT 2016


Author: spyffe
Date: Tue Mar 22 16:05:51 2016
New Revision: 264095

URL: http://llvm.org/viewvc/llvm-project?rev=264095&view=rev
Log:
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>

Modified:
    lldb/trunk/include/lldb/lldb-private-enumerations.h
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
    lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.h

Modified: lldb/trunk/include/lldb/lldb-private-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-enumerations.h?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-private-enumerations.h Tue Mar 22 16:05:51 2016
@@ -164,11 +164,12 @@ typedef enum FormatCategoryItem
 
 //------------------------------------------------------------------
 /// Expression execution policies
-//------------------------------------------------------------------  
+//------------------------------------------------------------------
 typedef enum {
     eExecutionPolicyOnlyWhenNeeded,
     eExecutionPolicyNever,
-    eExecutionPolicyAlways
+    eExecutionPolicyAlways,
+    eExecutionPolicyTopLevel // used for top-level code
 } ExecutionPolicy;
 
 //----------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp Tue Mar 22 16:05:51 2016
@@ -11,6 +11,11 @@
 
 #include "ClangPersistentVariables.h"
 
+#include "lldb/Core/Log.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/LLDBAssert.h"
 #include "stdlib.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
@@ -23,22 +28,18 @@
 #include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/raw_ostream.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Target/Target.h"
 
 using namespace llvm;
 using namespace clang;
 using namespace lldb_private;
 
-ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
-                                           Target &target) :
-    m_ast_context (NULL),
-    m_passthrough (passthrough),
-    m_passthrough_sema (NULL),
-    m_target (target),
-    m_sema (NULL)
+ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, bool top_level, Target &target)
+    : m_ast_context(NULL),
+      m_passthrough(passthrough),
+      m_passthrough_sema(NULL),
+      m_target(target),
+      m_sema(NULL),
+      m_top_level(top_level)
 {
     if (!m_passthrough)
         return;
@@ -76,6 +77,10 @@ ASTResultSynthesizer::TransformTopLevelD
                 log->Printf("TransformTopLevelDecl(<complex>)");
         }
 
+        if (m_top_level)
+        {
+            RecordPersistentDecl(named_decl);
+        }
     }
 
     if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
@@ -89,22 +94,23 @@ ASTResultSynthesizer::TransformTopLevelD
             TransformTopLevelDecl(*decl_iterator);
         }
     }
-    else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
+    else if (!m_top_level)
     {
-        if (m_ast_context &&
-            !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
+        if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
         {
-            RecordPersistentTypes(method_decl);
-            SynthesizeObjCMethodResult(method_decl);
+            if (m_ast_context && !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
+            {
+                RecordPersistentTypes(method_decl);
+                SynthesizeObjCMethodResult(method_decl);
+            }
         }
-    }
-    else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
-    {
-        if (m_ast_context &&
-            !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
+        else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
         {
-            RecordPersistentTypes(function_decl);
-            SynthesizeFunctionResult(function_decl);
+            if (m_ast_context && !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
+            {
+                RecordPersistentTypes(function_decl);
+                SynthesizeFunctionResult(function_decl);
+            }
         }
     }
 }
@@ -457,14 +463,66 @@ ASTResultSynthesizer::MaybeRecordPersist
     ConstString name_cs(name.str().c_str());
 
     if (log)
-        log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
+        log->Printf("Recording persistent type %s\n", name_cs.GetCString());
+
+    m_decls.push_back(D);
+}
+
+void
+ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D)
+{
+    lldbassert(m_top_level);
+
+    if (!D->getIdentifier())
+        return;
+
+    StringRef name = D->getName();
+
+    if (name.size() == 0)
+        return;
+
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+    ConstString name_cs(name.str().c_str());
+
+    if (log)
+        log->Printf("Recording persistent decl %s\n", name_cs.GetCString());
 
-    Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
-                                                                 m_ast_context,
-                                                                 D);
+    m_decls.push_back(D);
+}
 
-    if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
-        llvm::cast<ClangPersistentVariables>(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentDecl(name_cs, TypeDecl_scratch);
+void
+ASTResultSynthesizer::CommitPersistentDecls()
+{
+    for (clang::NamedDecl *decl : m_decls)
+    {
+        StringRef name = decl->getName();
+        ConstString name_cs(name.str().c_str());
+
+        Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(
+            m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context, decl);
+
+        if (!D_scratch)
+        {
+            Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+            if (log)
+            {
+                std::string s;
+                llvm::raw_string_ostream ss(s);
+                decl->dump(ss);
+                ss.flush();
+
+                log->Printf("Couldn't commit persistent  decl: %s\n", s.c_str());
+            }
+
+            continue;
+        }
+
+        if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch))
+            llvm::cast<ClangPersistentVariables>(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
+                ->RegisterPersistentDecl(name_cs, NamedDecl_scratch);
+    }
 }
 
 void

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h Tue Mar 22 16:05:51 2016
@@ -41,13 +41,16 @@ public:
     ///     pass to the next step in the chain after processing.  Passthrough is
     ///     the next ASTConsumer, or NULL if none is required.
     ///
+    /// @param[in] top_level
+    ///     If true, register all top-level Decls and don't try to handle the
+    ///     main function.
+    ///
     /// @param[in] target
     ///     The target, which contains the persistent variable store and the
     ///     AST importer.
     //----------------------------------------------------------------------
-    ASTResultSynthesizer(clang::ASTConsumer *passthrough,
-                         Target &target);
-    
+    ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level, Target &target);
+
     //----------------------------------------------------------------------
     /// Destructor
     //----------------------------------------------------------------------
@@ -106,11 +109,18 @@ public:
     ///     casts it to an Action for actual use.
     //----------------------------------------------------------------------
     void InitializeSema(clang::Sema &S) override;
-    
+
     //----------------------------------------------------------------------
     /// Reset the Sema to NULL now that transformations are done
     //----------------------------------------------------------------------
-    void ForgetSema() override;
+    void
+    ForgetSema() override;
+
+    //----------------------------------------------------------------------
+    /// The parse has succeeded, so record its persistent decls
+    //----------------------------------------------------------------------
+    void
+    CommitPersistentDecls();
 
 private:
     //----------------------------------------------------------------------
@@ -171,13 +181,30 @@ private:
     /// @param[in] Body
     ///     The body of the function.
     //----------------------------------------------------------------------
-    void MaybeRecordPersistentType(clang::TypeDecl *D);
-    
-    clang::ASTContext *m_ast_context;           ///< The AST context to use for identifiers and types.
-    clang::ASTConsumer *m_passthrough;          ///< The ASTConsumer down the chain, for passthrough.  NULL if it's a SemaConsumer.
-    clang::SemaConsumer *m_passthrough_sema;    ///< The SemaConsumer down the chain, for passthrough.  NULL if it's an ASTConsumer.
-    Target &m_target;                           ///< The target, which contains the persistent variable store and the
-    clang::Sema *m_sema;                        ///< The Sema to use.
+    void
+    MaybeRecordPersistentType(clang::TypeDecl *D);
+
+    //----------------------------------------------------------------------
+    /// Given a NamedDecl, register it as a pointer type in the target's scratch
+    /// AST context.
+    ///
+    /// @param[in] Body
+    ///     The body of the function.
+    //----------------------------------------------------------------------
+    void
+    RecordPersistentDecl(clang::NamedDecl *D);
+
+    clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types.
+    clang::ASTConsumer
+        *m_passthrough; ///< The ASTConsumer down the chain, for passthrough.  NULL if it's a SemaConsumer.
+    clang::SemaConsumer
+        *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough.  NULL if it's an ASTConsumer.
+
+    std::vector<clang::NamedDecl *> m_decls; ///< Persistent declarations to register assuming the expression succeeds.
+
+    Target &m_target;    ///< The target, which contains the persistent variable store and the
+    clang::Sema *m_sema; ///< The Sema to use.
+    bool m_top_level;
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h Tue Mar 22 16:05:51 2016
@@ -67,11 +67,14 @@ public:
     ///     the ASTs to after transformation.
     //------------------------------------------------------------------
     virtual clang::ASTConsumer *
-    ASTTransformer (clang::ASTConsumer *passthrough) = 0;
-    
+    ASTTransformer(clang::ASTConsumer *passthrough) = 0;
 
-protected:
+    virtual void
+    CommitPersistentDecls()
+    {
+    }
 
+protected:
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp Tue Mar 22 16:05:51 2016
@@ -652,6 +652,11 @@ ClangExpressionParser::Parse(DiagnosticM
         }
     }
 
+    if (!num_errors)
+    {
+        type_system_helper->CommitPersistentDecls();
+    }
+
     adapter->ResetManager();
 
     return num_errors;
@@ -697,24 +702,27 @@ ClangExpressionParser::PrepareForExecuti
         return err;
     }
 
-    // Find the actual name of the function (it's often mangled somehow)
-
     ConstString function_name;
 
-    if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
-    {
-        err.SetErrorToGenericError();
-        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
-        return err;
-    }
-    else
+    if (execution_policy != eExecutionPolicyTopLevel)
     {
-        if (log)
-            log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
+        // Find the actual name of the function (it's often mangled somehow)
+
+        if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
+        {
+            err.SetErrorToGenericError();
+            err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
+            return err;
+        }
+        else
+        {
+            if (log)
+                log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
+        }
     }
-    
+
     SymbolContext sc;
-    
+
     if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP())
     {
         sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
@@ -741,20 +749,28 @@ ClangExpressionParser::PrepareForExecuti
         if (target)
             error_stream = target->GetDebugger().GetErrorFile().get();
 
-        IRForTarget ir_for_target(decl_map,
-                                  m_expr.NeedsVariableResolution(),
-                                  *execution_unit_sp,
-                                  error_stream,
+        IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream,
                                   function_name.AsCString());
 
         bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
 
-        Error interpret_error;
         Process *process = exe_ctx.GetProcessPtr();
 
-        bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
-        can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls);
+        if (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel)
+        {
+            Error interpret_error;
+
+            bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
+            can_interpret =
+                IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
+                                            interpret_error, interpret_function_calls);
 
+            if (!can_interpret && execution_policy == eExecutionPolicyNever)
+            {
+                err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
+                return err;
+            }
+        }
 
         if (!ir_can_run)
         {
@@ -762,19 +778,21 @@ ClangExpressionParser::PrepareForExecuti
             return err;
         }
 
-        if (!can_interpret && execution_policy == eExecutionPolicyNever)
+        if (!process && execution_policy == eExecutionPolicyAlways)
         {
-            err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
+            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
             return err;
         }
 
-        if (!process && execution_policy == eExecutionPolicyAlways)
+        if (!process && execution_policy == eExecutionPolicyTopLevel)
         {
-            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
+            err.SetErrorString(
+                "Top-level code needs to be inserted into a runnable target, but the target can't be run");
             return err;
         }
 
-        if (execution_policy == eExecutionPolicyAlways || !can_interpret)
+        if (execution_policy == eExecutionPolicyAlways ||
+            (execution_policy != eExecutionPolicyTopLevel && !can_interpret))
         {
             if (m_expr.NeedsValidation() && process)
             {
@@ -809,7 +827,11 @@ ClangExpressionParser::PrepareForExecuti
                     return err;
                 }
             }
+        }
 
+        if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel ||
+            !can_interpret)
+        {
             execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
         }
     }

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp Tue Mar 22 16:05:51 2016
@@ -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 @@ ClangUserExpression::Parse(DiagnosticMan
             }
         }
     }
-    
-    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;
+    if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+    {
+        m_transformed_text = m_expr_text;
+    }
     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;
+        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 @@ ClangUserExpression::Parse(DiagnosticMan
         return false;
     }
 
+    if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+    {
+        DeclMap()->SetLookupsEnabled(true);
+    }
+
     Process *process = exe_ctx.GetProcessPtr();
     ExecutionContextScope *exe_scope = process;
 
@@ -497,16 +507,60 @@ ClangUserExpression::Parse(DiagnosticMan
     // 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 @@ ClangUserExpression::Parse(DiagnosticMan
             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.
-
-    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;
     }
+
+    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 (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 @@ ClangUserExpression::ClangUserExpression
 }
 
 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()
 {
 }

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h Tue Mar 22 16:05:51 2016
@@ -51,13 +51,10 @@ public:
     class ClangUserExpressionHelper : public ClangExpressionHelper
     {
     public:
-        ClangUserExpressionHelper (Target &target) :
-            m_target(target)
-        {
-        }
-        
+        ClangUserExpressionHelper(Target &target, bool top_level) : m_target(target), m_top_level(top_level) {}
+
         ~ClangUserExpressionHelper() override = default;
-        
+
         //------------------------------------------------------------------
         /// Return the object that the parser should use when resolving external
         /// values.  May be NULL if everything should be self-contained.
@@ -88,11 +85,16 @@ public:
         clang::ASTConsumer *
         ASTTransformer(clang::ASTConsumer *passthrough) override;
 
+        void
+        CommitPersistentDecls() override;
+
     private:
-        Target                                  &m_target;
+        Target &m_target;
         std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
-        std::unique_ptr<ASTStructExtractor> m_struct_extractor_up;         ///< The class that generates the argument struct layout.
+        std::unique_ptr<ASTStructExtractor>
+            m_struct_extractor_up; ///< The class that generates the argument struct layout.
         std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up;
+        bool m_top_level;
     };
 
     //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp Tue Mar 22 16:05:51 2016
@@ -1957,25 +1957,29 @@ IRForTarget::runOnModule (Module &llvm_m
         log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str());
     }
 
-    Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str()));
+    Function *const main_function = m_func_name.IsEmpty() ? nullptr : m_module->getFunction(m_func_name.GetStringRef());
 
-    if (!main_function)
+    if (!m_func_name.IsEmpty() && !main_function)
     {
         if (log)
-            log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
+            log->Printf("Couldn't find \"%s()\" in the module", m_func_name.AsCString());
 
         if (m_error_stream)
-            m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str());
+            m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module",
+                                   m_func_name.AsCString());
 
         return false;
     }
 
-    if (!FixFunctionLinkage (*main_function))
+    if (main_function)
     {
-        if (log)
-            log->Printf("Couldn't fix the linkage for the function");
+        if (!FixFunctionLinkage(*main_function))
+        {
+            if (log)
+                log->Printf("Couldn't fix the linkage for the function");
 
-        return false;
+            return false;
+        }
     }
 
     llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
@@ -1994,14 +1998,17 @@ IRForTarget::runOnModule (Module &llvm_m
     // Replace $__lldb_expr_result with a persistent variable
     //
 
-    if (!CreateResultVariable(*main_function))
+    if (main_function)
     {
-        if (log)
-            log->Printf("CreateResultVariable() failed");
+        if (!CreateResultVariable(*main_function))
+        {
+            if (log)
+                log->Printf("CreateResultVariable() failed");
 
-        // CreateResultVariable() reports its own errors, so we don't do so here
+            // CreateResultVariable() reports its own errors, so we don't do so here
 
-        return false;
+            return false;
+        }
     }
 
     if (log && log->GetVerbose())
@@ -2125,24 +2132,27 @@ IRForTarget::runOnModule (Module &llvm_m
     // Run function-level passes that only make sense on the main function
     //
 
-    if (!ResolveExternals(*main_function))
+    if (main_function)
     {
-        if (log)
-            log->Printf("ResolveExternals() failed");
+        if (!ResolveExternals(*main_function))
+        {
+            if (log)
+                log->Printf("ResolveExternals() failed");
 
-        // ResolveExternals() reports its own errors, so we don't do so here
+            // ResolveExternals() reports its own errors, so we don't do so here
 
-        return false;
-    }
+            return false;
+        }
 
-    if (!ReplaceVariables(*main_function))
-    {
-        if (log)
-            log->Printf("ReplaceVariables() failed");
+        if (!ReplaceVariables(*main_function))
+        {
+            if (log)
+                log->Printf("ReplaceVariables() failed");
 
-        // ReplaceVariables() reports its own errors, so we don't do so here
+            // ReplaceVariables() reports its own errors, so we don't do so here
 
-        return false;
+            return false;
+        }
     }
 
     if (log && log->GetVerbose())

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.h?rev=264095&r1=264094&r2=264095&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.h (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/IRForTarget.h Tue Mar 22 16:05:51 2016
@@ -546,40 +546,45 @@ private:
     /// @return
     ///     True on success; false otherwise
     //------------------------------------------------------------------
-    bool 
-    ReplaceVariables (llvm::Function &llvm_function);
-    
-    
+    bool
+    ReplaceVariables(llvm::Function &llvm_function);
+
     /// Flags
-    bool                                    m_resolve_vars;             ///< True if external variable references and persistent variable references should be resolved
-    std::string                             m_func_name;                ///< The name of the function to translate
-    lldb_private::ConstString               m_result_name;              ///< The name of the result variable ($0, $1, ...)
-    lldb_private::TypeFromParser            m_result_type;              ///< The type of the result variable.
-    llvm::Module                           *m_module;                   ///< The module being processed, or NULL if that has not been determined yet.
-    std::unique_ptr<llvm::DataLayout>       m_target_data;              ///< The target data for the module being processed, or NULL if there is no module.
-    lldb_private::ClangExpressionDeclMap   *m_decl_map;                 ///< The DeclMap containing the Decls 
-    llvm::Constant                         *m_CFStringCreateWithBytes;  ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
-    llvm::Constant                         *m_sel_registerName;         ///< The address of the function sel_registerName, cast to the appropriate function pointer type
-    llvm::IntegerType                      *m_intptr_ty;                ///< The type of an integer large enough to hold a pointer.
-    lldb_private::Stream                   *m_error_stream;             ///< If non-NULL, the stream on which errors should be printed
-    lldb_private::IRExecutionUnit          &m_execution_unit;           ///< The execution unit containing the IR being created.
-    
-    llvm::StoreInst                        *m_result_store;             ///< If non-NULL, the store instruction that writes to the result variable.  If m_has_side_effects is true, this is NULL.
-    bool                                    m_result_is_pointer;        ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult)
-    
-    llvm::GlobalVariable                   *m_reloc_placeholder;        ///< A placeholder that will be replaced by a pointer to the final location of the static allocation.
-    
+    bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved
+    lldb_private::ConstString m_func_name;      ///< The name of the function to translate
+    lldb_private::ConstString m_result_name;    ///< The name of the result variable ($0, $1, ...)
+    lldb_private::TypeFromParser m_result_type; ///< The type of the result variable.
+    llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet.
+    std::unique_ptr<llvm::DataLayout>
+        m_target_data; ///< The target data for the module being processed, or NULL if there is no module.
+    lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
+    llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the
+                                               ///appropriate function pointer type
+    llvm::Constant *m_sel_registerName;   ///< The address of the function sel_registerName, cast to the appropriate
+                                          ///function pointer type
+    llvm::IntegerType *m_intptr_ty;       ///< The type of an integer large enough to hold a pointer.
+    lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed
+    lldb_private::IRExecutionUnit &m_execution_unit; ///< The execution unit containing the IR being created.
+
+    llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable.  If
+                                     ///m_has_side_effects is true, this is NULL.
+    bool m_result_is_pointer;        ///< True if the function's result in the AST is a pointer (see comments in
+                                     ///ASTResultSynthesizer::SynthesizeBodyResult)
+
+    llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final
+                                               ///location of the static allocation.
+
     //------------------------------------------------------------------
-    /// UnfoldConstant operates on a constant [Old] which has just been 
-    /// replaced with a value [New].  We assume that new_value has 
-    /// been properly placed early in the function, in front of the 
-    /// first instruction in the entry basic block 
-    /// [FirstEntryInstruction].  
+    /// UnfoldConstant operates on a constant [Old] which has just been
+    /// replaced with a value [New].  We assume that new_value has
+    /// been properly placed early in the function, in front of the
+    /// first instruction in the entry basic block
+    /// [FirstEntryInstruction].
     ///
-    /// UnfoldConstant reads through the uses of Old and replaces Old 
-    /// in those uses with New.  Where those uses are constants, the 
-    /// function generates new instructions to compute the result of the 
-    /// new, non-constant expression and places them before 
+    /// UnfoldConstant reads through the uses of Old and replaces Old
+    /// in those uses with New.  Where those uses are constants, the
+    /// function generates new instructions to compute the result of the
+    /// new, non-constant expression and places them before
     /// FirstEntryInstruction.  These instructions replace the constant
     /// uses, so UnfoldConstant calls itself recursively for those.
     ///
@@ -589,7 +594,7 @@ private:
     /// @return
     ///     True on success; false otherwise
     //------------------------------------------------------------------
-    
+
     class FunctionValueCache {
     public:
         typedef std::function <llvm::Value *(llvm::Function *)> Maker;




More information about the lldb-commits mailing list