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 
15*b9c1b51eSKate Stone ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(
16*b9c1b51eSKate Stone     Thread &thread, const Callback &callback)
17*b9c1b51eSKate Stone     : ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit", thread,
1875930019STodd Fiala                  eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these
1975930019STodd Fiala                  ),
20*b9c1b51eSKate Stone       m_callback(callback) {
2175930019STodd Fiala   // We are not a user-generated plan.
2275930019STodd Fiala   SetIsMasterPlan(false);
2375930019STodd Fiala }
2475930019STodd Fiala 
25*b9c1b51eSKate Stone void ThreadPlanCallOnFunctionExit::DidPush() {
2675930019STodd Fiala   // We now want to queue the "step out" thread plan so it executes
2775930019STodd Fiala   // and completes.
2875930019STodd Fiala 
2975930019STodd Fiala   // Set stop vote to eVoteNo.
30*b9c1b51eSKate Stone   m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
31*b9c1b51eSKate 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 
47*b9c1b51eSKate Stone void ThreadPlanCallOnFunctionExit::GetDescription(
48*b9c1b51eSKate 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 
55*b9c1b51eSKate 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 
61*b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
6275930019STodd Fiala   // If this is where we find out that an internal stop came in, then:
6375930019STodd Fiala   // Check if the step-out plan completed.  If it did, then we want to
6475930019STodd Fiala   // run the callback here (our reason for living...)
65*b9c1b51eSKate 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 
7475930019STodd Fiala     // We're done now, but we want to return false so that we
7575930019STodd Fiala     // don't cause the thread to really stop.
7675930019STodd Fiala   }
7775930019STodd Fiala 
7875930019STodd Fiala   return false;
7975930019STodd Fiala }
8075930019STodd Fiala 
81*b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::WillStop() {
8275930019STodd Fiala   // The code looks like the return value is ignored via ThreadList::
8375930019STodd Fiala   // ShouldStop().
8475930019STodd Fiala   // This is called when we really are going to stop.  We don't care
8575930019STodd Fiala   // and don't need to do anything here.
8675930019STodd Fiala   return false;
8775930019STodd Fiala }
8875930019STodd Fiala 
89*b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) {
9075930019STodd Fiala   // We don't ever explain a stop.  The only stop that is relevant
9175930019STodd Fiala   // to us directly is the step_out plan we added to do the heavy lifting
9275930019STodd Fiala   // of getting us past the current method.
9375930019STodd Fiala   return false;
9475930019STodd Fiala }
9575930019STodd Fiala 
96*b9c1b51eSKate Stone lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() {
9775930019STodd Fiala   // This value doesn't matter - we'll never be the top thread plan, so
9875930019STodd Fiala   // nobody will ask us this question.
9975930019STodd Fiala   return eStateRunning;
10075930019STodd Fiala }
101