175930019STodd Fiala //===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===// 275930019STodd Fiala // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 675930019STodd Fiala // 775930019STodd Fiala //===----------------------------------------------------------------------===// 875930019STodd Fiala 975930019STodd Fiala #include "lldb/Target/ThreadPlanCallOnFunctionExit.h" 1075930019STodd Fiala 1175930019STodd Fiala using namespace lldb; 1275930019STodd Fiala using namespace lldb_private; 1375930019STodd Fiala 14b9c1b51eSKate Stone ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit( 15b9c1b51eSKate Stone Thread &thread, const Callback &callback) 16b9c1b51eSKate Stone : ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit", thread, 1775930019STodd Fiala eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these 1875930019STodd Fiala ), 19b9c1b51eSKate Stone m_callback(callback) { 2075930019STodd Fiala // We are not a user-generated plan. 2175930019STodd Fiala SetIsMasterPlan(false); 2275930019STodd Fiala } 2375930019STodd Fiala 24b9c1b51eSKate Stone void ThreadPlanCallOnFunctionExit::DidPush() { 2505097246SAdrian Prantl // We now want to queue the "step out" thread plan so it executes and 2605097246SAdrian Prantl // completes. 2775930019STodd Fiala 2875930019STodd Fiala // Set stop vote to eVoteNo. 29e103ae92SJonas Devlieghere Status status; 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" 36e103ae92SJonas Devlieghere eVoteNoOpinion, // don't care about run state broadcasting 3775930019STodd Fiala 0, // frame_idx 38e103ae92SJonas Devlieghere status, // status 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) { 6205097246SAdrian Prantl // If this is where we find out that an internal stop came in, then: Check if 6305097246SAdrian Prantl // the step-out plan completed. If it did, then we want to run the callback 6405097246SAdrian 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 7405097246SAdrian Prantl // We're done now, but we want to return false so that we don't cause the 7505097246SAdrian 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:: 8305097246SAdrian Prantl // ShouldStop(). This is called when we really are going to stop. We don't 8405097246SAdrian 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) { 8905097246SAdrian Prantl // We don't ever explain a stop. The only stop that is relevant to us 9005097246SAdrian Prantl // directly is the step_out plan we added to do the heavy lifting of getting 9105097246SAdrian Prantl // us past the current method. 9275930019STodd Fiala return false; 9375930019STodd Fiala } 9475930019STodd Fiala 95b9c1b51eSKate Stone lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() { 9605097246SAdrian Prantl // This value doesn't matter - we'll never be the top thread plan, so nobody 9705097246SAdrian Prantl // will ask us this question. 9875930019STodd Fiala return eStateRunning; 9975930019STodd Fiala } 100