xref: /freebsd-src/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
4006c3fb27SDimitry Andric #include "lldb/Utility/State.h"
410b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
42*0fca6ea1SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric using namespace lldb_private;
450b57cec5SDimitry Andric 
46480093f4SDimitry Andric char UserExpression::ID;
47480093f4SDimitry Andric 
480b57cec5SDimitry Andric UserExpression::UserExpression(ExecutionContextScope &exe_scope,
490b57cec5SDimitry Andric                                llvm::StringRef expr, llvm::StringRef prefix,
50*0fca6ea1SDimitry Andric                                SourceLanguage language, 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 
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 
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 
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 
100fcaf7f86SDimitry Andric lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject(
1015f757f3fSDimitry Andric     lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) {
1020b57cec5SDimitry Andric   err.Clear();
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   if (!frame_sp) {
1055f757f3fSDimitry Andric     err.SetErrorStringWithFormatv(
1065f757f3fSDimitry 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(
1145f757f3fSDimitry 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 
122fcaf7f86SDimitry Andric lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
1235f757f3fSDimitry 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) {
1345f757f3fSDimitry Andric     err.SetErrorStringWithFormatv(
1355f757f3fSDimitry Andric         "Couldn't load '{0}' because its value couldn't be evaluated",
1365f757f3fSDimitry 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
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();
179*0fca6ea1SDimitry Andric   SourceLanguage 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   }
20306c3fb27SDimitry Andric 
20406c3fb27SDimitry Andric   // Since we might need to allocate memory, we need to be stopped to run
20506c3fb27SDimitry Andric   // an expression.
206bdd1243dSDimitry Andric   if (process != nullptr && process->GetState() != lldb::eStateStopped) {
20706c3fb27SDimitry Andric     error.SetErrorStringWithFormatv(
20806c3fb27SDimitry Andric         "unable to evaluate expression while the process is {0}: the process "
20906c3fb27SDimitry Andric         "must be stopped because the expression might require allocating "
21006c3fb27SDimitry Andric         "memory.",
21106c3fb27SDimitry 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.
245*0fca6ea1SDimitry Andric   if (!language) {
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));
2565f757f3fSDimitry 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));
303*0fca6ea1SDimitry Andric         if (!fixed_expression_sp)
304*0fca6ea1SDimitry Andric           break;
3050b57cec5SDimitry Andric         DiagnosticManager fixed_diagnostic_manager;
3060b57cec5SDimitry Andric         parse_success = fixed_expression_sp->Parse(
3070b57cec5SDimitry Andric             fixed_diagnostic_manager, exe_ctx, execution_policy,
3080b57cec5SDimitry Andric             keep_expression_in_memory, generate_debug_info);
3090b57cec5SDimitry Andric         if (parse_success) {
3100b57cec5SDimitry Andric           diagnostic_manager.Clear();
3110b57cec5SDimitry Andric           user_expression_sp = fixed_expression_sp;
3125ffd83dbSDimitry Andric           break;
313*0fca6ea1SDimitry Andric         }
3145ffd83dbSDimitry Andric         // The fixed expression also didn't parse. Let's check for any new
315*0fca6ea1SDimitry Andric         // fixits we could try.
3160eae32dcSDimitry Andric         if (!fixed_expression_sp->GetFixedText().empty()) {
3170eae32dcSDimitry Andric           *fixed_expression = fixed_expression_sp->GetFixedText().str();
3185ffd83dbSDimitry Andric         } else {
3195ffd83dbSDimitry Andric           // Fixed expression didn't compile without a fixit, don't retry and
3205ffd83dbSDimitry Andric           // don't tell the user about it.
3210b57cec5SDimitry Andric           fixed_expression->clear();
3225ffd83dbSDimitry Andric           break;
3235ffd83dbSDimitry Andric         }
3245ffd83dbSDimitry Andric       }
3250b57cec5SDimitry Andric     }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric     if (!parse_success) {
328fe6060f1SDimitry Andric       std::string msg;
329fe6060f1SDimitry Andric       {
330fe6060f1SDimitry Andric         llvm::raw_string_ostream os(msg);
331fe6060f1SDimitry Andric         if (!diagnostic_manager.Diagnostics().empty())
332fe6060f1SDimitry Andric           os << diagnostic_manager.GetString();
3330b57cec5SDimitry Andric         else
33406c3fb27SDimitry Andric           os << "expression failed to parse (no further compiler diagnostics)";
335fe6060f1SDimitry Andric         if (target->GetEnableNotifyAboutFixIts() && fixed_expression &&
336fe6060f1SDimitry Andric             !fixed_expression->empty())
337fe6060f1SDimitry Andric           os << "\nfixed expression suggested:\n  " << *fixed_expression;
3380b57cec5SDimitry Andric       }
339fe6060f1SDimitry Andric       error.SetExpressionError(execution_results, msg.c_str());
3400b57cec5SDimitry Andric     }
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   if (parse_success) {
3440b57cec5SDimitry Andric     lldb::ExpressionVariableSP expr_result;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric     if (execution_policy == eExecutionPolicyNever &&
3470b57cec5SDimitry Andric         !user_expression_sp->CanInterpret()) {
3485ffd83dbSDimitry Andric       LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
3490b57cec5SDimitry Andric                     "is not constant ==");
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric       if (!diagnostic_manager.Diagnostics().size())
3520b57cec5SDimitry Andric         error.SetExpressionError(lldb::eExpressionSetupError,
3530b57cec5SDimitry Andric                                  "expression needed to run but couldn't");
3540b57cec5SDimitry Andric     } else if (execution_policy == eExecutionPolicyTopLevel) {
3550b57cec5SDimitry Andric       error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
3560b57cec5SDimitry Andric       return lldb::eExpressionCompleted;
3570b57cec5SDimitry Andric     } else {
3580b57cec5SDimitry Andric       if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
3590b57cec5SDimitry Andric         error.SetExpressionError(
3600b57cec5SDimitry Andric             lldb::eExpressionInterrupted,
3610b57cec5SDimitry Andric             "expression interrupted by callback before execution");
3620b57cec5SDimitry Andric         result_valobj_sp = ValueObjectConstResult::Create(
3630b57cec5SDimitry Andric             exe_ctx.GetBestExecutionContextScope(), error);
3640b57cec5SDimitry Andric         return lldb::eExpressionInterrupted;
3650b57cec5SDimitry Andric       }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric       diagnostic_manager.Clear();
3680b57cec5SDimitry Andric 
3695ffd83dbSDimitry Andric       LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression ==");
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric       execution_results =
3720b57cec5SDimitry Andric           user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
3730b57cec5SDimitry Andric                                       user_expression_sp, expr_result);
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric       if (execution_results != lldb::eExpressionCompleted) {
3765ffd83dbSDimitry Andric         LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
3770b57cec5SDimitry Andric                       "abnormally ==");
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric         if (!diagnostic_manager.Diagnostics().size())
3800b57cec5SDimitry Andric           error.SetExpressionError(
3810b57cec5SDimitry Andric               execution_results, "expression failed to execute, unknown error");
3820b57cec5SDimitry Andric         else
3830b57cec5SDimitry Andric           error.SetExpressionError(execution_results,
3840b57cec5SDimitry Andric                                    diagnostic_manager.GetString().c_str());
3850b57cec5SDimitry Andric       } else {
3860b57cec5SDimitry Andric         if (expr_result) {
3870b57cec5SDimitry Andric           result_valobj_sp = expr_result->GetValueObject();
388*0fca6ea1SDimitry Andric           result_valobj_sp->SetPreferredDisplayLanguage(
389*0fca6ea1SDimitry Andric               language.AsLanguageType());
3900b57cec5SDimitry Andric 
3915ffd83dbSDimitry Andric           LLDB_LOG(log,
3929dba64beSDimitry Andric                    "== [UserExpression::Evaluate] Execution completed "
393fe6060f1SDimitry Andric                    "normally with result {0} ==",
3940b57cec5SDimitry Andric                    result_valobj_sp->GetValueAsCString());
3950b57cec5SDimitry Andric         } else {
3965ffd83dbSDimitry Andric           LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
3970b57cec5SDimitry Andric                         "normally with no result ==");
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric           error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
4000b57cec5SDimitry Andric         }
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric     }
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
4060b57cec5SDimitry Andric     error.SetExpressionError(
4070b57cec5SDimitry Andric         lldb::eExpressionInterrupted,
4080b57cec5SDimitry Andric         "expression interrupted by callback after complete");
4090b57cec5SDimitry Andric     return lldb::eExpressionInterrupted;
4100b57cec5SDimitry Andric   }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   if (result_valobj_sp.get() == nullptr) {
4130b57cec5SDimitry Andric     result_valobj_sp = ValueObjectConstResult::Create(
4140b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), error);
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   return execution_results;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric lldb::ExpressionResults
4210b57cec5SDimitry Andric UserExpression::Execute(DiagnosticManager &diagnostic_manager,
4220b57cec5SDimitry Andric                         ExecutionContext &exe_ctx,
4230b57cec5SDimitry Andric                         const EvaluateExpressionOptions &options,
4240b57cec5SDimitry Andric                         lldb::UserExpressionSP &shared_ptr_to_me,
4250b57cec5SDimitry Andric                         lldb::ExpressionVariableSP &result_var) {
4260b57cec5SDimitry Andric   lldb::ExpressionResults expr_result = DoExecute(
4270b57cec5SDimitry Andric       diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
4280b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
42906c3fb27SDimitry Andric   if (options.GetSuppressPersistentResult() && result_var && target) {
430480093f4SDimitry Andric     if (auto *persistent_state =
431*0fca6ea1SDimitry Andric             target->GetPersistentExpressionStateForLanguage(
432*0fca6ea1SDimitry Andric                 m_language.AsLanguageType()))
433480093f4SDimitry Andric       persistent_state->RemovePersistentVariable(result_var);
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric   return expr_result;
4360b57cec5SDimitry Andric }
437