Index: include/lldb/Expression/LLVMUserExpression.h =================================================================== --- include/lldb/Expression/LLVMUserExpression.h +++ include/lldb/Expression/LLVMUserExpression.h @@ -16,6 +16,9 @@ #include #include +// Other libraries and framework includes +#include "llvm/IR/LegacyPassManager.h" + // Project includes #include "lldb/Expression/UserExpression.h" @@ -35,6 +38,17 @@ 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 EarlyPasses; + std::shared_ptr LatePasses; + }; + LLVMUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); Index: include/lldb/Target/LanguageRuntime.h =================================================================== --- include/lldb/Target/LanguageRuntime.h +++ include/lldb/Target/LanguageRuntime.h @@ -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 @@ 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 Index: source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -837,6 +837,30 @@ 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 @@ 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); + } } }