blob: b2383e4f122a3acbbfcf1313e6763eeabb18002c [file] [log] [blame]
Todd Fiala75930012016-08-19 04:21:48 +00001//===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Target/ThreadPlanCallOnFunctionExit.h"
11
12using namespace lldb;
13using namespace lldb_private;
14
15ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(Thread &thread,
16 const Callback
17 &callback) :
18 ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit",
19 thread,
20 eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these
21 ),
22 m_callback(callback)
23{
24 // We are not a user-generated plan.
25 SetIsMasterPlan(false);
26}
27
28void
29ThreadPlanCallOnFunctionExit::DidPush()
30{
31 // We now want to queue the "step out" thread plan so it executes
32 // and completes.
33
34 // Set stop vote to eVoteNo.
35 m_step_out_threadplan_sp = GetThread()
36 .QueueThreadPlanForStepOut(false, // abort other plans
37 nullptr, // addr_context
38 true, // first instruction
39 true, // stop other threads
40 eVoteNo, // do not say "we're stopping"
41 eVoteNoOpinion, // don't care about
42 // run state broadcasting
43 0, // frame_idx
44 eLazyBoolCalculate // avoid code w/o debinfo
45 );
46}
47
48// -------------------------------------------------------------------------
49// ThreadPlan API
50// -------------------------------------------------------------------------
51
52void
53ThreadPlanCallOnFunctionExit::GetDescription(Stream *s, lldb::DescriptionLevel
54 level)
55{
56 if (!s)
57 return;
58 s->Printf("Running until completion of current function, then making "
59 "callback.");
60}
61
62bool
63ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error)
64{
65 // We'll say we're always good since I don't know what would make this
66 // invalid.
67 return true;
68}
69
70bool
71ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr)
72{
73 // If this is where we find out that an internal stop came in, then:
74 // Check if the step-out plan completed. If it did, then we want to
75 // run the callback here (our reason for living...)
76 if (m_step_out_threadplan_sp &&
77 m_step_out_threadplan_sp->IsPlanComplete())
78 {
79 m_callback();
80
81 // We no longer need the pointer to the step-out thread plan.
82 m_step_out_threadplan_sp.reset();
83
84 // Indicate that this plan is done and can be discarded.
85 SetPlanComplete();
86
87 // We're done now, but we want to return false so that we
88 // don't cause the thread to really stop.
89 }
90
91 return false;
92}
93
94bool
95ThreadPlanCallOnFunctionExit::WillStop()
96{
97 // The code looks like the return value is ignored via ThreadList::
98 // ShouldStop().
99 // This is called when we really are going to stop. We don't care
100 // and don't need to do anything here.
101 return false;
102}
103
104bool
105ThreadPlanCallOnFunctionExit::DoPlanExplainsStop (Event *event_ptr)
106{
107 // We don't ever explain a stop. The only stop that is relevant
108 // to us directly is the step_out plan we added to do the heavy lifting
109 // of getting us past the current method.
110 return false;
111}
112
113lldb::StateType
114ThreadPlanCallOnFunctionExit::GetPlanRunState()
115{
116 // This value doesn't matter - we'll never be the top thread plan, so
117 // nobody will ask us this question.
118 return eStateRunning;
119}