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