Skip to content

Commit

Permalink
Allow runtimes to execute custom LLVM ModulePasses over the expressio…
Browse files Browse the repository at this point in the history
…n 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
  • Loading branch information
ldrumm committed Jun 15, 2016
1 parent 194cb55 commit 9d48422
Showing 3 changed files with 58 additions and 1 deletion.
14 changes: 14 additions & 0 deletions lldb/include/lldb/Expression/LLVMUserExpression.h
Original file line number Diff line number Diff line change
@@ -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);
9 changes: 9 additions & 0 deletions lldb/include/lldb/Target/LanguageRuntime.h
Original file line number Diff line number Diff line change
@@ -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 @@ class LanguageRuntime :
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
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

0 comments on commit 9d48422

Please sign in to comment.