15ffd83dbSDimitry Andric //===-- UserExpression.cpp ------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
9fe6060f1SDimitry Andric #include <cstdio>
100b57cec5SDimitry Andric #include <sys/types.h>
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric #include <cstdlib>
130b57cec5SDimitry Andric #include <map>
140b57cec5SDimitry Andric #include <string>
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #include "lldb/Core/Module.h"
170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
180b57cec5SDimitry Andric #include "lldb/Expression/DiagnosticManager.h"
190b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
200b57cec5SDimitry Andric #include "lldb/Expression/IRExecutionUnit.h"
210b57cec5SDimitry Andric #include "lldb/Expression/IRInterpreter.h"
220b57cec5SDimitry Andric #include "lldb/Expression/Materializer.h"
230b57cec5SDimitry Andric #include "lldb/Expression/UserExpression.h"
240b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
250b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
260b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
270b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
280b57cec5SDimitry Andric #include "lldb/Symbol/SymbolVendor.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h"
320b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
330b57cec5SDimitry Andric #include "lldb/Target/Process.h"
340b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
350b57cec5SDimitry Andric #include "lldb/Target/Target.h"
360b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
370b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallUserExpression.h"
3881ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
390b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
40fe013be4SDimitry Andric #include "lldb/Utility/State.h"
410b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric using namespace lldb_private;
440b57cec5SDimitry Andric
45480093f4SDimitry Andric char UserExpression::ID;
46480093f4SDimitry Andric
UserExpression(ExecutionContextScope & exe_scope,llvm::StringRef expr,llvm::StringRef prefix,lldb::LanguageType language,ResultType desired_type,const EvaluateExpressionOptions & options)470b57cec5SDimitry Andric UserExpression::UserExpression(ExecutionContextScope &exe_scope,
480b57cec5SDimitry Andric llvm::StringRef expr, llvm::StringRef prefix,
490b57cec5SDimitry Andric lldb::LanguageType language,
500b57cec5SDimitry Andric ResultType desired_type,
51480093f4SDimitry Andric const EvaluateExpressionOptions &options)
525ffd83dbSDimitry Andric : Expression(exe_scope), m_expr_text(std::string(expr)),
535ffd83dbSDimitry Andric m_expr_prefix(std::string(prefix)), m_language(language),
545ffd83dbSDimitry Andric m_desired_type(desired_type), m_options(options) {}
550b57cec5SDimitry Andric
56fe6060f1SDimitry Andric UserExpression::~UserExpression() = default;
570b57cec5SDimitry Andric
InstallContext(ExecutionContext & exe_ctx)580b57cec5SDimitry Andric void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
590b57cec5SDimitry Andric m_jit_process_wp = exe_ctx.GetProcessSP();
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric if (frame_sp)
640b57cec5SDimitry Andric m_address = frame_sp->GetFrameCodeAddress();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
LockAndCheckContext(ExecutionContext & exe_ctx,lldb::TargetSP & target_sp,lldb::ProcessSP & process_sp,lldb::StackFrameSP & frame_sp)670b57cec5SDimitry Andric bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
680b57cec5SDimitry Andric lldb::TargetSP &target_sp,
690b57cec5SDimitry Andric lldb::ProcessSP &process_sp,
700b57cec5SDimitry Andric lldb::StackFrameSP &frame_sp) {
710b57cec5SDimitry Andric lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
720b57cec5SDimitry Andric process_sp = exe_ctx.GetProcessSP();
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric if (process_sp != expected_process_sp)
750b57cec5SDimitry Andric return false;
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric process_sp = exe_ctx.GetProcessSP();
780b57cec5SDimitry Andric target_sp = exe_ctx.GetTargetSP();
790b57cec5SDimitry Andric frame_sp = exe_ctx.GetFrameSP();
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric if (m_address.IsValid()) {
820b57cec5SDimitry Andric if (!frame_sp)
830b57cec5SDimitry Andric return false;
84480093f4SDimitry Andric return (Address::CompareLoadAddress(m_address,
850b57cec5SDimitry Andric frame_sp->GetFrameCodeAddress(),
86480093f4SDimitry Andric target_sp.get()) == 0);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric return true;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
MatchesContext(ExecutionContext & exe_ctx)920b57cec5SDimitry Andric bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) {
930b57cec5SDimitry Andric lldb::TargetSP target_sp;
940b57cec5SDimitry Andric lldb::ProcessSP process_sp;
950b57cec5SDimitry Andric lldb::StackFrameSP frame_sp;
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric
GetObjectPointerValueObject(lldb::StackFrameSP frame_sp,llvm::StringRef object_name,Status & err)100fcaf7f86SDimitry Andric lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject(
101*c9157d92SDimitry Andric lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) {
1020b57cec5SDimitry Andric err.Clear();
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric if (!frame_sp) {
105*c9157d92SDimitry Andric err.SetErrorStringWithFormatv(
106*c9157d92SDimitry Andric "Couldn't load '{0}' because the context is incomplete", object_name);
107fcaf7f86SDimitry Andric return {};
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric lldb::VariableSP var_sp;
1110b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp;
1120b57cec5SDimitry Andric
113fcaf7f86SDimitry Andric return frame_sp->GetValueForVariableExpressionPath(
114*c9157d92SDimitry Andric object_name, lldb::eNoDynamicValues,
1150b57cec5SDimitry Andric StackFrame::eExpressionPathOptionCheckPtrVsMember |
1160b57cec5SDimitry Andric StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
1170b57cec5SDimitry Andric StackFrame::eExpressionPathOptionsNoSyntheticChildren |
1180b57cec5SDimitry Andric StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
1190b57cec5SDimitry Andric var_sp, err);
120fcaf7f86SDimitry Andric }
121fcaf7f86SDimitry Andric
GetObjectPointer(lldb::StackFrameSP frame_sp,llvm::StringRef object_name,Status & err)122fcaf7f86SDimitry Andric lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
123*c9157d92SDimitry Andric llvm::StringRef object_name,
124fcaf7f86SDimitry Andric Status &err) {
125fcaf7f86SDimitry Andric auto valobj_sp =
126fcaf7f86SDimitry Andric GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric if (!err.Success() || !valobj_sp.get())
1290b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS;
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric if (ret == LLDB_INVALID_ADDRESS) {
134*c9157d92SDimitry Andric err.SetErrorStringWithFormatv(
135*c9157d92SDimitry Andric "Couldn't load '{0}' because its value couldn't be evaluated",
136*c9157d92SDimitry Andric object_name);
1370b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS;
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric return ret;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
1435ffd83dbSDimitry Andric lldb::ExpressionResults
Evaluate(ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options,llvm::StringRef expr,llvm::StringRef prefix,lldb::ValueObjectSP & result_valobj_sp,Status & error,std::string * fixed_expression,ValueObject * ctx_obj)1445ffd83dbSDimitry Andric UserExpression::Evaluate(ExecutionContext &exe_ctx,
1455ffd83dbSDimitry Andric const EvaluateExpressionOptions &options,
1460b57cec5SDimitry Andric llvm::StringRef expr, llvm::StringRef prefix,
1470b57cec5SDimitry Andric lldb::ValueObjectSP &result_valobj_sp, Status &error,
1485ffd83dbSDimitry Andric std::string *fixed_expression, ValueObject *ctx_obj) {
14981ad6265SDimitry Andric Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric if (ctx_obj) {
15281ad6265SDimitry Andric static unsigned const ctx_type_mask = lldb::TypeFlags::eTypeIsClass |
15381ad6265SDimitry Andric lldb::TypeFlags::eTypeIsStructUnion |
15481ad6265SDimitry Andric lldb::TypeFlags::eTypeIsReference;
1550b57cec5SDimitry Andric if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) {
1560b57cec5SDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
1570b57cec5SDimitry Andric "an invalid type, can't run expressions.");
1580b57cec5SDimitry Andric error.SetErrorString("a context object of an invalid type passed");
1590b57cec5SDimitry Andric return lldb::eExpressionSetupError;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
16381ad6265SDimitry Andric if (ctx_obj && ctx_obj->GetTypeInfo() & lldb::TypeFlags::eTypeIsReference) {
16481ad6265SDimitry Andric Status error;
16581ad6265SDimitry Andric lldb::ValueObjectSP deref_ctx_sp = ctx_obj->Dereference(error);
16681ad6265SDimitry Andric if (!error.Success()) {
16781ad6265SDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
16881ad6265SDimitry Andric "a reference type that can't be dereferenced, can't run "
16981ad6265SDimitry Andric "expressions.");
17081ad6265SDimitry Andric error.SetErrorString(
17181ad6265SDimitry Andric "passed context object of an reference type cannot be deferenced");
17281ad6265SDimitry Andric return lldb::eExpressionSetupError;
17381ad6265SDimitry Andric }
17481ad6265SDimitry Andric
17581ad6265SDimitry Andric ctx_obj = deref_ctx_sp.get();
17681ad6265SDimitry Andric }
17781ad6265SDimitry Andric
1780b57cec5SDimitry Andric lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
1790b57cec5SDimitry Andric lldb::LanguageType language = options.GetLanguage();
1800b57cec5SDimitry Andric const ResultType desired_type = options.DoesCoerceToId()
1810b57cec5SDimitry Andric ? UserExpression::eResultTypeId
1820b57cec5SDimitry Andric : UserExpression::eResultTypeAny;
1830b57cec5SDimitry Andric lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr();
1860b57cec5SDimitry Andric if (!target) {
1875ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a NULL target, can't "
1880b57cec5SDimitry Andric "run expressions.");
1890b57cec5SDimitry Andric error.SetErrorString("expression passed a null target");
1900b57cec5SDimitry Andric return lldb::eExpressionSetupError;
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr();
1940b57cec5SDimitry Andric
195bdd1243dSDimitry Andric if (process == nullptr && execution_policy == eExecutionPolicyAlways) {
196bdd1243dSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] No process, but the policy is "
197bdd1243dSDimitry Andric "eExecutionPolicyAlways");
1980b57cec5SDimitry Andric
199bdd1243dSDimitry Andric error.SetErrorString("expression needed to run but couldn't: no process");
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric return execution_results;
2020b57cec5SDimitry Andric }
203fe013be4SDimitry Andric
204fe013be4SDimitry Andric // Since we might need to allocate memory, we need to be stopped to run
205fe013be4SDimitry Andric // an expression.
206bdd1243dSDimitry Andric if (process != nullptr && process->GetState() != lldb::eStateStopped) {
207fe013be4SDimitry Andric error.SetErrorStringWithFormatv(
208fe013be4SDimitry Andric "unable to evaluate expression while the process is {0}: the process "
209fe013be4SDimitry Andric "must be stopped because the expression might require allocating "
210fe013be4SDimitry Andric "memory.",
211fe013be4SDimitry Andric StateAsCString(process->GetState()));
212bdd1243dSDimitry Andric return execution_results;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
215fe6060f1SDimitry Andric // Explicitly force the IR interpreter to evaluate the expression when the
216fe6060f1SDimitry Andric // there is no process that supports running the expression for us. Don't
217fe6060f1SDimitry Andric // change the execution policy if we have the special top-level policy that
218fe6060f1SDimitry Andric // doesn't contain any expression and there is nothing to interpret.
219fe6060f1SDimitry Andric if (execution_policy != eExecutionPolicyTopLevel &&
220fe6060f1SDimitry Andric (process == nullptr || !process->CanJIT()))
2210b57cec5SDimitry Andric execution_policy = eExecutionPolicyNever;
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric // We need to set the expression execution thread here, turns out parse can
2240b57cec5SDimitry Andric // call functions in the process of looking up symbols, which will escape the
2250b57cec5SDimitry Andric // context set by exe_ctx passed to Execute.
2260b57cec5SDimitry Andric lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
2270b57cec5SDimitry Andric ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
2280b57cec5SDimitry Andric thread_sp);
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric llvm::StringRef full_prefix;
2310b57cec5SDimitry Andric llvm::StringRef option_prefix(options.GetPrefix());
2320b57cec5SDimitry Andric std::string full_prefix_storage;
2330b57cec5SDimitry Andric if (!prefix.empty() && !option_prefix.empty()) {
2345ffd83dbSDimitry Andric full_prefix_storage = std::string(prefix);
2355ffd83dbSDimitry Andric full_prefix_storage.append(std::string(option_prefix));
2360b57cec5SDimitry Andric full_prefix = full_prefix_storage;
2370b57cec5SDimitry Andric } else if (!prefix.empty())
2380b57cec5SDimitry Andric full_prefix = prefix;
2390b57cec5SDimitry Andric else
2400b57cec5SDimitry Andric full_prefix = option_prefix;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric // If the language was not specified in the expression command, set it to the
2430b57cec5SDimitry Andric // language in the target's properties if specified, else default to the
2440b57cec5SDimitry Andric // langage for the frame.
2450b57cec5SDimitry Andric if (language == lldb::eLanguageTypeUnknown) {
2460b57cec5SDimitry Andric if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
2470b57cec5SDimitry Andric language = target->GetLanguage();
2480b57cec5SDimitry Andric else if (StackFrame *frame = exe_ctx.GetFramePtr())
2490b57cec5SDimitry Andric language = frame->GetLanguage();
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric lldb::UserExpressionSP user_expression_sp(
2530b57cec5SDimitry Andric target->GetUserExpressionForLanguage(expr, full_prefix, language,
2540b57cec5SDimitry Andric desired_type, options, ctx_obj,
2550b57cec5SDimitry Andric error));
256*c9157d92SDimitry Andric if (error.Fail() || !user_expression_sp) {
2575ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==",
2580b57cec5SDimitry Andric error.AsCString());
2590b57cec5SDimitry Andric return lldb::eExpressionSetupError;
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric
2625ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Parsing expression {0} ==",
2635ffd83dbSDimitry Andric expr.str());
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric const bool keep_expression_in_memory = true;
2660b57cec5SDimitry Andric const bool generate_debug_info = options.GetGenerateDebugInfo();
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) {
2690b57cec5SDimitry Andric error.SetErrorString("expression interrupted by callback before parse");
2700b57cec5SDimitry Andric result_valobj_sp = ValueObjectConstResult::Create(
2710b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), error);
2720b57cec5SDimitry Andric return lldb::eExpressionInterrupted;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric DiagnosticManager diagnostic_manager;
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric bool parse_success =
2780b57cec5SDimitry Andric user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
2790b57cec5SDimitry Andric keep_expression_in_memory, generate_debug_info);
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric // Calculate the fixed expression always, since we need it for errors.
2820b57cec5SDimitry Andric std::string tmp_fixed_expression;
2830b57cec5SDimitry Andric if (fixed_expression == nullptr)
2840b57cec5SDimitry Andric fixed_expression = &tmp_fixed_expression;
2850b57cec5SDimitry Andric
2860eae32dcSDimitry Andric *fixed_expression = user_expression_sp->GetFixedText().str();
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric // If there is a fixed expression, try to parse it:
2890b57cec5SDimitry Andric if (!parse_success) {
2905ffd83dbSDimitry Andric // Delete the expression that failed to parse before attempting to parse
2915ffd83dbSDimitry Andric // the next expression.
2925ffd83dbSDimitry Andric user_expression_sp.reset();
2935ffd83dbSDimitry Andric
2940b57cec5SDimitry Andric execution_results = lldb::eExpressionParseError;
2950eae32dcSDimitry Andric if (!fixed_expression->empty() && options.GetAutoApplyFixIts()) {
2965ffd83dbSDimitry Andric const uint64_t max_fix_retries = options.GetRetriesWithFixIts();
2975ffd83dbSDimitry Andric for (uint64_t i = 0; i < max_fix_retries; ++i) {
2985ffd83dbSDimitry Andric // Try parsing the fixed expression.
2990b57cec5SDimitry Andric lldb::UserExpressionSP fixed_expression_sp(
3005ffd83dbSDimitry Andric target->GetUserExpressionForLanguage(
3015ffd83dbSDimitry Andric fixed_expression->c_str(), full_prefix, language, desired_type,
3025ffd83dbSDimitry Andric options, ctx_obj, error));
3030b57cec5SDimitry Andric DiagnosticManager fixed_diagnostic_manager;
3040b57cec5SDimitry Andric parse_success = fixed_expression_sp->Parse(
3050b57cec5SDimitry Andric fixed_diagnostic_manager, exe_ctx, execution_policy,
3060b57cec5SDimitry Andric keep_expression_in_memory, generate_debug_info);
3070b57cec5SDimitry Andric if (parse_success) {
3080b57cec5SDimitry Andric diagnostic_manager.Clear();
3090b57cec5SDimitry Andric user_expression_sp = fixed_expression_sp;
3105ffd83dbSDimitry Andric break;
3110b57cec5SDimitry Andric } else {
3125ffd83dbSDimitry Andric // The fixed expression also didn't parse. Let's check for any new
3135ffd83dbSDimitry Andric // Fix-Its we could try.
3140eae32dcSDimitry Andric if (!fixed_expression_sp->GetFixedText().empty()) {
3150eae32dcSDimitry Andric *fixed_expression = fixed_expression_sp->GetFixedText().str();
3165ffd83dbSDimitry Andric } else {
3175ffd83dbSDimitry Andric // Fixed expression didn't compile without a fixit, don't retry and
3185ffd83dbSDimitry Andric // don't tell the user about it.
3190b57cec5SDimitry Andric fixed_expression->clear();
3205ffd83dbSDimitry Andric break;
3215ffd83dbSDimitry Andric }
3225ffd83dbSDimitry Andric }
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric if (!parse_success) {
327fe6060f1SDimitry Andric std::string msg;
328fe6060f1SDimitry Andric {
329fe6060f1SDimitry Andric llvm::raw_string_ostream os(msg);
330fe6060f1SDimitry Andric if (!diagnostic_manager.Diagnostics().empty())
331fe6060f1SDimitry Andric os << diagnostic_manager.GetString();
3320b57cec5SDimitry Andric else
333fe013be4SDimitry Andric os << "expression failed to parse (no further compiler diagnostics)";
334fe6060f1SDimitry Andric if (target->GetEnableNotifyAboutFixIts() && fixed_expression &&
335fe6060f1SDimitry Andric !fixed_expression->empty())
336fe6060f1SDimitry Andric os << "\nfixed expression suggested:\n " << *fixed_expression;
3370b57cec5SDimitry Andric }
338fe6060f1SDimitry Andric error.SetExpressionError(execution_results, msg.c_str());
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric if (parse_success) {
3430b57cec5SDimitry Andric lldb::ExpressionVariableSP expr_result;
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric if (execution_policy == eExecutionPolicyNever &&
3460b57cec5SDimitry Andric !user_expression_sp->CanInterpret()) {
3475ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
3480b57cec5SDimitry Andric "is not constant ==");
3490b57cec5SDimitry Andric
3500b57cec5SDimitry Andric if (!diagnostic_manager.Diagnostics().size())
3510b57cec5SDimitry Andric error.SetExpressionError(lldb::eExpressionSetupError,
3520b57cec5SDimitry Andric "expression needed to run but couldn't");
3530b57cec5SDimitry Andric } else if (execution_policy == eExecutionPolicyTopLevel) {
3540b57cec5SDimitry Andric error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
3550b57cec5SDimitry Andric return lldb::eExpressionCompleted;
3560b57cec5SDimitry Andric } else {
3570b57cec5SDimitry Andric if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
3580b57cec5SDimitry Andric error.SetExpressionError(
3590b57cec5SDimitry Andric lldb::eExpressionInterrupted,
3600b57cec5SDimitry Andric "expression interrupted by callback before execution");
3610b57cec5SDimitry Andric result_valobj_sp = ValueObjectConstResult::Create(
3620b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), error);
3630b57cec5SDimitry Andric return lldb::eExpressionInterrupted;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric diagnostic_manager.Clear();
3670b57cec5SDimitry Andric
3685ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression ==");
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric execution_results =
3710b57cec5SDimitry Andric user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
3720b57cec5SDimitry Andric user_expression_sp, expr_result);
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric if (execution_results != lldb::eExpressionCompleted) {
3755ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
3760b57cec5SDimitry Andric "abnormally ==");
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andric if (!diagnostic_manager.Diagnostics().size())
3790b57cec5SDimitry Andric error.SetExpressionError(
3800b57cec5SDimitry Andric execution_results, "expression failed to execute, unknown error");
3810b57cec5SDimitry Andric else
3820b57cec5SDimitry Andric error.SetExpressionError(execution_results,
3830b57cec5SDimitry Andric diagnostic_manager.GetString().c_str());
3840b57cec5SDimitry Andric } else {
3850b57cec5SDimitry Andric if (expr_result) {
3860b57cec5SDimitry Andric result_valobj_sp = expr_result->GetValueObject();
387e8d8bef9SDimitry Andric result_valobj_sp->SetPreferredDisplayLanguage(language);
3880b57cec5SDimitry Andric
3895ffd83dbSDimitry Andric LLDB_LOG(log,
3909dba64beSDimitry Andric "== [UserExpression::Evaluate] Execution completed "
391fe6060f1SDimitry Andric "normally with result {0} ==",
3920b57cec5SDimitry Andric result_valobj_sp->GetValueAsCString());
3930b57cec5SDimitry Andric } else {
3945ffd83dbSDimitry Andric LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
3950b57cec5SDimitry Andric "normally with no result ==");
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andric error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
4040b57cec5SDimitry Andric error.SetExpressionError(
4050b57cec5SDimitry Andric lldb::eExpressionInterrupted,
4060b57cec5SDimitry Andric "expression interrupted by callback after complete");
4070b57cec5SDimitry Andric return lldb::eExpressionInterrupted;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric if (result_valobj_sp.get() == nullptr) {
4110b57cec5SDimitry Andric result_valobj_sp = ValueObjectConstResult::Create(
4120b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), error);
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
4150b57cec5SDimitry Andric return execution_results;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric lldb::ExpressionResults
Execute(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options,lldb::UserExpressionSP & shared_ptr_to_me,lldb::ExpressionVariableSP & result_var)4190b57cec5SDimitry Andric UserExpression::Execute(DiagnosticManager &diagnostic_manager,
4200b57cec5SDimitry Andric ExecutionContext &exe_ctx,
4210b57cec5SDimitry Andric const EvaluateExpressionOptions &options,
4220b57cec5SDimitry Andric lldb::UserExpressionSP &shared_ptr_to_me,
4230b57cec5SDimitry Andric lldb::ExpressionVariableSP &result_var) {
4240b57cec5SDimitry Andric lldb::ExpressionResults expr_result = DoExecute(
4250b57cec5SDimitry Andric diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
4260b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr();
427fe013be4SDimitry Andric if (options.GetSuppressPersistentResult() && result_var && target) {
428480093f4SDimitry Andric if (auto *persistent_state =
429480093f4SDimitry Andric target->GetPersistentExpressionStateForLanguage(m_language))
430480093f4SDimitry Andric persistent_state->RemovePersistentVariable(result_var);
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric return expr_result;
4330b57cec5SDimitry Andric }
434