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 
15 ThreadPlanCallOnFunctionExit::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 
28 void
29 ThreadPlanCallOnFunctionExit::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 
52 void
53 ThreadPlanCallOnFunctionExit::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 
62 bool
63 ThreadPlanCallOnFunctionExit::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 
70 bool
71 ThreadPlanCallOnFunctionExit::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 
94 bool
95 ThreadPlanCallOnFunctionExit::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 
104 bool
105 ThreadPlanCallOnFunctionExit::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 
113 lldb::StateType
114 ThreadPlanCallOnFunctionExit::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 }
120