From bfd263a34df5d3916eb8425bb070618324acabfa Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Sat, 22 Jun 2024 07:20:13 +0100 Subject: [lldb][ExpressionParser][NFCI] Add new DoPrepareForExecution interface to be implemented by language plugins (#96290) This patch adds a new `DoPrepareForExecution` API, which can be implemented by the Clang and Swift language plugins. This also moves `RunStaticInitializers` into `ExpressionParser::PrepareForExecution`, so we call it consistently between language plugins. This *should* be mostly NFC (the static initializers will still only run after we finished parsing). We've been living on this patch downstream for sometime now. rdar://130267058 --- lldb/include/lldb/Expression/ExpressionParser.h | 25 +++++++- lldb/source/Expression/CMakeLists.txt | 1 + lldb/source/Expression/ExpressionParser.cpp | 72 ++++++++++++++++++++++ .../Clang/ClangExpressionParser.cpp | 46 +------------- .../ExpressionParser/Clang/ClangExpressionParser.h | 23 ++----- .../ExpressionParser/Clang/ClangUserExpression.cpp | 15 ----- 6 files changed, 102 insertions(+), 80 deletions(-) create mode 100644 lldb/source/Expression/ExpressionParser.cpp diff --git a/lldb/include/lldb/Expression/ExpressionParser.h b/lldb/include/lldb/Expression/ExpressionParser.h index ab5223c..2ef7e03 100644 --- a/lldb/include/lldb/Expression/ExpressionParser.h +++ b/lldb/include/lldb/Expression/ExpressionParser.h @@ -119,15 +119,36 @@ public: /// \return /// An error code indicating the success or failure of the operation. /// Test with Success(). - virtual Status + Status PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, - lldb_private::ExecutionPolicy execution_policy) = 0; + lldb_private::ExecutionPolicy execution_policy); bool GetGenerateDebugInfo() const { return m_generate_debug_info; } protected: + virtual Status + DoPrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, + std::shared_ptr &execution_unit_sp, + ExecutionContext &exe_ctx, bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) = 0; + +private: + /// Run all static initializers for an execution unit. + /// + /// \param[in] execution_unit_sp + /// The execution unit. + /// + /// \param[in] exe_ctx + /// The execution context to use when running them. Thread can't be null. + /// + /// \return + /// The error code indicating the + Status RunStaticInitializers(lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx); + +protected: Expression &m_expr; ///< The expression to be parsed bool m_generate_debug_info; }; diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index 9ba5fef..be1e132 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -3,6 +3,7 @@ add_lldb_library(lldbExpression NO_PLUGIN_DEPENDENCIES DWARFExpression.cpp DWARFExpressionList.cpp Expression.cpp + ExpressionParser.cpp ExpressionTypeSystemHelper.cpp ExpressionVariable.cpp FunctionCaller.cpp diff --git a/lldb/source/Expression/ExpressionParser.cpp b/lldb/source/Expression/ExpressionParser.cpp new file mode 100644 index 0000000..e9f7121 --- /dev/null +++ b/lldb/source/Expression/ExpressionParser.cpp @@ -0,0 +1,72 @@ +//===-- ExpressionParser.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Expression/ExpressionParser.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb; +using namespace lldb_private; + +Status ExpressionParser::PrepareForExecution( + addr_t &func_addr, addr_t &func_end, + std::shared_ptr &execution_unit_sp, + ExecutionContext &exe_ctx, bool &can_interpret, + ExecutionPolicy execution_policy) { + Status status = + DoPrepareForExecution(func_addr, func_end, execution_unit_sp, exe_ctx, + can_interpret, execution_policy); + if (status.Success() && exe_ctx.GetProcessPtr() && exe_ctx.HasThreadScope()) + status = RunStaticInitializers(execution_unit_sp, exe_ctx); + + return status; +} + +Status +ExpressionParser::RunStaticInitializers(IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx) { + Status err; + + if (!execution_unit_sp.get()) { + err.SetErrorString( + "can't run static initializers for a NULL execution unit"); + return err; + } + + if (!exe_ctx.HasThreadScope()) { + err.SetErrorString("can't run static initializers without a thread"); + return err; + } + + std::vector static_initializers; + + execution_unit_sp->GetStaticInitializers(static_initializers); + + for (addr_t static_initializer : static_initializers) { + EvaluateExpressionOptions options; + + ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction( + exe_ctx.GetThreadRef(), Address(static_initializer), CompilerType(), + llvm::ArrayRef(), options)); + + DiagnosticManager execution_errors; + ExpressionResults results = + exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan( + exe_ctx, call_static_initializer, options, execution_errors); + + if (results != eExpressionCompleted) { + err.SetErrorStringWithFormat("couldn't run static initializer: %s", + execution_errors.GetString().c_str()); + return err; + } + } + + return err; +} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 1dd9856..303e88f 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -1296,7 +1296,7 @@ static bool FindFunctionInModule(ConstString &mangled_name, return false; } -lldb_private::Status ClangExpressionParser::PrepareForExecution( +lldb_private::Status ClangExpressionParser::DoPrepareForExecution( lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { @@ -1472,47 +1472,3 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( return err; } - -lldb_private::Status ClangExpressionParser::RunStaticInitializers( - lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx) { - lldb_private::Status err; - - lldbassert(execution_unit_sp.get()); - lldbassert(exe_ctx.HasThreadScope()); - - if (!execution_unit_sp.get()) { - err.SetErrorString( - "can't run static initializers for a NULL execution unit"); - return err; - } - - if (!exe_ctx.HasThreadScope()) { - err.SetErrorString("can't run static initializers without a thread"); - return err; - } - - std::vector static_initializers; - - execution_unit_sp->GetStaticInitializers(static_initializers); - - for (lldb::addr_t static_initializer : static_initializers) { - EvaluateExpressionOptions options; - - lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction( - exe_ctx.GetThreadRef(), Address(static_initializer), CompilerType(), - llvm::ArrayRef(), options)); - - DiagnosticManager execution_errors; - lldb::ExpressionResults results = - exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan( - exe_ctx, call_static_initializer, options, execution_errors); - - if (results != lldb::eExpressionCompleted) { - err.SetErrorStringWithFormat("couldn't run static initializer: %s", - execution_errors.GetString().c_str()); - return err; - } - } - - return err; -} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 185a5a3..0852e92 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -113,24 +113,11 @@ public: /// \return /// An error code indicating the success or failure of the operation. /// Test with Success(). - Status - PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, - lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx, bool &can_interpret, - lldb_private::ExecutionPolicy execution_policy) override; - - /// Run all static initializers for an execution unit. - /// - /// \param[in] execution_unit_sp - /// The execution unit. - /// - /// \param[in] exe_ctx - /// The execution context to use when running them. Thread can't be null. - /// - /// \return - /// The error code indicating the - Status RunStaticInitializers(lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx); + Status DoPrepareForExecution( + lldb::addr_t &func_addr, lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) override; /// Returns a string representing current ABI. /// diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index c7e98d1..35038a5 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -698,21 +698,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, if (!parse_success) return false; - if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) { - Status static_init_error = - m_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(lldb::eSeverityError, "%s\n", error_cstr); - else - diagnostic_manager.PutString(lldb::eSeverityError, - "couldn't run static initializers\n"); - return false; - } - } - if (m_execution_unit_sp) { bool register_execution_unit = false; -- cgit v1.1