forked from OSchip/llvm-project
Allow runtimes to execute custom LLVM ModulePasses over the expression IR
During expression evaluation, the ClangExpressionParser preforms a number of hard-coded fixups on the expression's IR before the module is assembled and dispatched to be run in a ThreadPlan. This patch allows the runtimes to register LLVM passes to be run over the generated IR, that they may perform language or architecture-specfic fixups or analyses over the generated expression. This makes expression evaluation for plugins more flexible and allows language-specific fixes to reside in their own module, rather than littering the expression evaluator itself with language-specific fixes. llvm-svn: 272800
This commit is contained in:
parent
194cb55f37
commit
9d4842251c
|
@ -16,6 +16,9 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
// Other libraries and framework includes
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
|
||||
// Project includes
|
||||
#include "lldb/Expression/UserExpression.h"
|
||||
|
||||
|
@ -35,6 +38,17 @@ namespace lldb_private
|
|||
class LLVMUserExpression : public UserExpression
|
||||
{
|
||||
public:
|
||||
// The IRPasses struct is filled in by a runtime after an expression is compiled and can be used to to run
|
||||
// fixups/analysis passes as required. EarlyPasses are run on the generated module before lldb runs its own IR
|
||||
// fixups and inserts instrumentation code/pointer checks. LatePasses are run after the module has been processed by
|
||||
// llvm, before the module is assembled and run in the ThreadPlan.
|
||||
struct IRPasses
|
||||
{
|
||||
IRPasses() : EarlyPasses(nullptr), LatePasses(nullptr){};
|
||||
std::shared_ptr<llvm::legacy::PassManager> EarlyPasses;
|
||||
std::shared_ptr<llvm::legacy::PassManager> LatePasses;
|
||||
};
|
||||
|
||||
LLVMUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
|
||||
lldb::LanguageType language, ResultType desired_type,
|
||||
const EvaluateExpressionOptions &options);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Core/Value.h"
|
||||
#include "lldb/Target/ExecutionContextScope.h"
|
||||
#include "lldb/Expression/LLVMUserExpression.h"
|
||||
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -157,6 +159,13 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
// Called by ClangExpressionParser::PrepareForExecution to query for any custom LLVM IR passes
|
||||
// that need to be run before an expression is assembled and run.
|
||||
virtual bool
|
||||
GetIRPasses(LLVMUserExpression::IRPasses &custom_passes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Classes that inherit from LanguageRuntime can see and modify these
|
||||
|
|
|
@ -837,6 +837,30 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
sc.target_sp = target_sp;
|
||||
}
|
||||
|
||||
LLVMUserExpression::IRPasses custom_passes;
|
||||
{
|
||||
auto lang = m_expr.Language();
|
||||
if (log)
|
||||
log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__,
|
||||
Language::GetNameForLanguageType(lang));
|
||||
|
||||
if (lang != lldb::eLanguageTypeUnknown)
|
||||
{
|
||||
auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang);
|
||||
if (runtime)
|
||||
runtime->GetIRPasses(custom_passes);
|
||||
}
|
||||
}
|
||||
|
||||
if (custom_passes.EarlyPasses)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__,
|
||||
m_expr.FunctionName());
|
||||
|
||||
custom_passes.EarlyPasses->run(*llvm_module_ap);
|
||||
}
|
||||
|
||||
execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
|
||||
llvm_module_ap, // handed off here
|
||||
function_name,
|
||||
|
@ -925,12 +949,22 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
|
||||
IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
|
||||
|
||||
if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
|
||||
llvm::Module *module = execution_unit_sp->GetModule();
|
||||
if (!module || !ir_dynamic_checks.runOnModule(*module))
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString("Couldn't add dynamic checks to the expression");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (custom_passes.LatePasses)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'",
|
||||
__FUNCTION__, m_expr.FunctionName());
|
||||
|
||||
custom_passes.LatePasses->run(*module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue