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