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