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:
Luke Drummond 2016-06-15 16:19:46 +00:00
parent 194cb55f37
commit 9d4842251c
3 changed files with 58 additions and 1 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}
}