[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