1435933ddSDimitry Andric //===-- ThreadPlanCallUserExpression.cpp -------------------------*- C++-*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanCallUserExpression.h"
11ac7ddfbfSEd Maste 
120127ef0fSEd Maste 
13ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
14ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
15ac7ddfbfSEd Maste #include "lldb/Core/Address.h"
164bb0738eSEd Maste #include "lldb/Expression/DiagnosticManager.h"
171c3bbb01SEd Maste #include "lldb/Expression/IRDynamicChecks.h"
184bb0738eSEd Maste #include "lldb/Expression/UserExpression.h"
190127ef0fSEd Maste #include "lldb/Host/HostInfo.h"
20ac7ddfbfSEd Maste #include "lldb/Target/LanguageRuntime.h"
21ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
22ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
23ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
24ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
25ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
26ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h"
27f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
28f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
29ac7ddfbfSEd Maste 
30ac7ddfbfSEd Maste using namespace lldb;
31ac7ddfbfSEd Maste using namespace lldb_private;
32ac7ddfbfSEd Maste 
33ac7ddfbfSEd Maste //----------------------------------------------------------------------
34ac7ddfbfSEd Maste // ThreadPlanCallUserExpression: Plan to call a single function
35ac7ddfbfSEd Maste //----------------------------------------------------------------------
36ac7ddfbfSEd Maste 
ThreadPlanCallUserExpression(Thread & thread,Address & function,llvm::ArrayRef<lldb::addr_t> args,const EvaluateExpressionOptions & options,lldb::UserExpressionSP & user_expression_sp)37435933ddSDimitry Andric ThreadPlanCallUserExpression::ThreadPlanCallUserExpression(
38435933ddSDimitry Andric     Thread &thread, Address &function, llvm::ArrayRef<lldb::addr_t> args,
39b952cd58SEd Maste     const EvaluateExpressionOptions &options,
40435933ddSDimitry Andric     lldb::UserExpressionSP &user_expression_sp)
41435933ddSDimitry Andric     : ThreadPlanCallFunction(thread, function, CompilerType(), args, options),
42435933ddSDimitry Andric       m_user_expression_sp(user_expression_sp) {
43*4ba319b5SDimitry Andric   // User expressions are generally "User generated" so we should set them up
44*4ba319b5SDimitry Andric   // to stop when done.
45ac7ddfbfSEd Maste   SetIsMasterPlan(true);
46ac7ddfbfSEd Maste   SetOkayToDiscard(false);
47ac7ddfbfSEd Maste }
48ac7ddfbfSEd Maste 
~ThreadPlanCallUserExpression()49435933ddSDimitry Andric ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() {}
50ac7ddfbfSEd Maste 
GetDescription(Stream * s,lldb::DescriptionLevel level)51435933ddSDimitry Andric void ThreadPlanCallUserExpression::GetDescription(
52435933ddSDimitry Andric     Stream *s, lldb::DescriptionLevel level) {
530127ef0fSEd Maste   if (level == eDescriptionLevelBrief)
540127ef0fSEd Maste     s->Printf("User Expression thread plan");
550127ef0fSEd Maste   else
56ac7ddfbfSEd Maste     ThreadPlanCallFunction::GetDescription(s, level);
57ac7ddfbfSEd Maste }
58ac7ddfbfSEd Maste 
DidPush()590f5676f4SDimitry Andric void ThreadPlanCallUserExpression::DidPush() {
600f5676f4SDimitry Andric   ThreadPlanCallFunction::DidPush();
610f5676f4SDimitry Andric   if (m_user_expression_sp)
620f5676f4SDimitry Andric     m_user_expression_sp->WillStartExecuting();
630f5676f4SDimitry Andric }
640f5676f4SDimitry Andric 
WillPop()65435933ddSDimitry Andric void ThreadPlanCallUserExpression::WillPop() {
660127ef0fSEd Maste   ThreadPlanCallFunction::WillPop();
670127ef0fSEd Maste   if (m_user_expression_sp)
680127ef0fSEd Maste     m_user_expression_sp.reset();
690127ef0fSEd Maste }
700127ef0fSEd Maste 
MischiefManaged()71435933ddSDimitry Andric bool ThreadPlanCallUserExpression::MischiefManaged() {
720127ef0fSEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
730127ef0fSEd Maste 
74435933ddSDimitry Andric   if (IsPlanComplete()) {
750127ef0fSEd Maste     if (log)
760127ef0fSEd Maste       log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.",
770127ef0fSEd Maste                   static_cast<void *>(this));
780127ef0fSEd Maste 
79435933ddSDimitry Andric     if (m_manage_materialization && PlanSucceeded() && m_user_expression_sp) {
800127ef0fSEd Maste       lldb::addr_t function_stack_top;
810127ef0fSEd Maste       lldb::addr_t function_stack_bottom;
820127ef0fSEd Maste       lldb::addr_t function_stack_pointer = GetFunctionStackPointer();
830127ef0fSEd Maste 
840127ef0fSEd Maste       function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
850127ef0fSEd Maste       function_stack_top = function_stack_pointer;
860127ef0fSEd Maste 
874bb0738eSEd Maste       DiagnosticManager diagnostics;
880127ef0fSEd Maste 
890127ef0fSEd Maste       ExecutionContext exe_ctx(GetThread());
900127ef0fSEd Maste 
91435933ddSDimitry Andric       m_user_expression_sp->FinalizeJITExecution(
92435933ddSDimitry Andric           diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom,
934bb0738eSEd Maste           function_stack_top);
940127ef0fSEd Maste     }
950127ef0fSEd Maste 
960127ef0fSEd Maste     ThreadPlan::MischiefManaged();
970127ef0fSEd Maste     return true;
98435933ddSDimitry Andric   } else {
990127ef0fSEd Maste     return false;
1000127ef0fSEd Maste   }
1010127ef0fSEd Maste }
1020127ef0fSEd Maste 
GetRealStopInfo()103435933ddSDimitry Andric StopInfoSP ThreadPlanCallUserExpression::GetRealStopInfo() {
104ac7ddfbfSEd Maste   StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo();
105ac7ddfbfSEd Maste 
106435933ddSDimitry Andric   if (stop_info_sp) {
107ac7ddfbfSEd Maste     lldb::addr_t addr = GetStopAddress();
108435933ddSDimitry Andric     DynamicCheckerFunctions *checkers =
109435933ddSDimitry Andric         m_thread.GetProcess()->GetDynamicCheckers();
110ac7ddfbfSEd Maste     StreamString s;
111ac7ddfbfSEd Maste 
112ac7ddfbfSEd Maste     if (checkers && checkers->DoCheckersExplainStop(addr, s))
113ac7ddfbfSEd Maste       stop_info_sp->SetDescription(s.GetData());
114ac7ddfbfSEd Maste   }
115ac7ddfbfSEd Maste 
116ac7ddfbfSEd Maste   return stop_info_sp;
117ac7ddfbfSEd Maste }
1180f5676f4SDimitry Andric 
DoTakedown(bool success)1190f5676f4SDimitry Andric void ThreadPlanCallUserExpression::DoTakedown(bool success) {
1200f5676f4SDimitry Andric   ThreadPlanCallFunction::DoTakedown(success);
1210f5676f4SDimitry Andric   m_user_expression_sp->DidFinishExecuting();
1220f5676f4SDimitry Andric }
123