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