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