175930019STodd Fiala //===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===//
275930019STodd Fiala //
375930019STodd Fiala //                     The LLVM Compiler Infrastructure
475930019STodd Fiala //
575930019STodd Fiala // This file is distributed under the University of Illinois Open Source
675930019STodd Fiala // License. See LICENSE.TXT for details.
775930019STodd Fiala //
875930019STodd Fiala //===----------------------------------------------------------------------===//
975930019STodd Fiala 
1075930019STodd Fiala #include "lldb/Target/ThreadPlanCallOnFunctionExit.h"
1175930019STodd Fiala 
1275930019STodd Fiala using namespace lldb;
1375930019STodd Fiala using namespace lldb_private;
1475930019STodd Fiala 
15b9c1b51eSKate Stone ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(
16b9c1b51eSKate Stone     Thread &thread, const Callback &callback)
17b9c1b51eSKate Stone     : ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit", thread,
1875930019STodd Fiala                  eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these
1975930019STodd Fiala                  ),
20b9c1b51eSKate Stone       m_callback(callback) {
2175930019STodd Fiala   // We are not a user-generated plan.
2275930019STodd Fiala   SetIsMasterPlan(false);
2375930019STodd Fiala }
2475930019STodd Fiala 
25b9c1b51eSKate Stone void ThreadPlanCallOnFunctionExit::DidPush() {
26*05097246SAdrian Prantl   // We now want to queue the "step out" thread plan so it executes and
27*05097246SAdrian Prantl   // completes.
2875930019STodd Fiala 
2975930019STodd Fiala   // Set stop vote to eVoteNo.
30b9c1b51eSKate Stone   m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
31b9c1b51eSKate Stone       false,             // abort other plans
3275930019STodd Fiala       nullptr,           // addr_context
3375930019STodd Fiala       true,              // first instruction
3475930019STodd Fiala       true,              // stop other threads
3575930019STodd Fiala       eVoteNo,           // do not say "we're stopping"
3675930019STodd Fiala       eVoteNoOpinion,    // don't care about
3775930019STodd Fiala                          // run state broadcasting
3875930019STodd Fiala       0,                 // frame_idx
3975930019STodd Fiala       eLazyBoolCalculate // avoid code w/o debinfo
4075930019STodd Fiala       );
4175930019STodd Fiala }
4275930019STodd Fiala 
4375930019STodd Fiala // -------------------------------------------------------------------------
4475930019STodd Fiala // ThreadPlan API
4575930019STodd Fiala // -------------------------------------------------------------------------
4675930019STodd Fiala 
47b9c1b51eSKate Stone void ThreadPlanCallOnFunctionExit::GetDescription(
48b9c1b51eSKate Stone     Stream *s, lldb::DescriptionLevel level) {
4975930019STodd Fiala   if (!s)
5075930019STodd Fiala     return;
5175930019STodd Fiala   s->Printf("Running until completion of current function, then making "
5275930019STodd Fiala             "callback.");
5375930019STodd Fiala }
5475930019STodd Fiala 
55b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) {
5675930019STodd Fiala   // We'll say we're always good since I don't know what would make this
5775930019STodd Fiala   // invalid.
5875930019STodd Fiala   return true;
5975930019STodd Fiala }
6075930019STodd Fiala 
61b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
62*05097246SAdrian Prantl   // If this is where we find out that an internal stop came in, then: Check if
63*05097246SAdrian Prantl   // the step-out plan completed.  If it did, then we want to run the callback
64*05097246SAdrian Prantl   // here (our reason for living...)
65b9c1b51eSKate Stone   if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) {
6675930019STodd Fiala     m_callback();
6775930019STodd Fiala 
6875930019STodd Fiala     // We no longer need the pointer to the step-out thread plan.
6975930019STodd Fiala     m_step_out_threadplan_sp.reset();
7075930019STodd Fiala 
7175930019STodd Fiala     // Indicate that this plan is done and can be discarded.
7275930019STodd Fiala     SetPlanComplete();
7375930019STodd Fiala 
74*05097246SAdrian Prantl     // We're done now, but we want to return false so that we don't cause the
75*05097246SAdrian Prantl     // thread to really stop.
7675930019STodd Fiala   }
7775930019STodd Fiala 
7875930019STodd Fiala   return false;
7975930019STodd Fiala }
8075930019STodd Fiala 
81b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::WillStop() {
8275930019STodd Fiala   // The code looks like the return value is ignored via ThreadList::
83*05097246SAdrian Prantl   // ShouldStop(). This is called when we really are going to stop.  We don't
84*05097246SAdrian Prantl   // care and don't need to do anything here.
8575930019STodd Fiala   return false;
8675930019STodd Fiala }
8775930019STodd Fiala 
88b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) {
89*05097246SAdrian Prantl   // We don't ever explain a stop.  The only stop that is relevant to us
90*05097246SAdrian Prantl   // directly is the step_out plan we added to do the heavy lifting of getting
91*05097246SAdrian Prantl   // us past the current method.
9275930019STodd Fiala   return false;
9375930019STodd Fiala }
9475930019STodd Fiala 
95b9c1b51eSKate Stone lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() {
96*05097246SAdrian Prantl   // This value doesn't matter - we'll never be the top thread plan, so nobody
97*05097246SAdrian Prantl   // will ask us this question.
9875930019STodd Fiala   return eStateRunning;
9975930019STodd Fiala }
100