xref: /llvm-project/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp (revision 04cbfa950e0221ac334f802407a9b766df33eee5)
180814287SRaphael Isemann //===-- ThreadPlanCallOnFunctionExit.cpp ----------------------------------===//
275930019STodd Fiala //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler 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 
ThreadPlanCallOnFunctionExit(Thread & thread,const Callback & callback)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.
21*04cbfa95SQuinn Pham   SetIsControllingPlan(false);
2275930019STodd Fiala }
2375930019STodd Fiala 
DidPush()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 // ThreadPlan API
4475930019STodd Fiala 
GetDescription(Stream * s,lldb::DescriptionLevel level)45b9c1b51eSKate Stone void ThreadPlanCallOnFunctionExit::GetDescription(
46b9c1b51eSKate Stone     Stream *s, lldb::DescriptionLevel level) {
4775930019STodd Fiala   if (!s)
4875930019STodd Fiala     return;
4975930019STodd Fiala   s->Printf("Running until completion of current function, then making "
5075930019STodd Fiala             "callback.");
5175930019STodd Fiala }
5275930019STodd Fiala 
ValidatePlan(Stream * error)53b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) {
5475930019STodd Fiala   // We'll say we're always good since I don't know what would make this
5575930019STodd Fiala   // invalid.
5675930019STodd Fiala   return true;
5775930019STodd Fiala }
5875930019STodd Fiala 
ShouldStop(Event * event_ptr)59b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
6005097246SAdrian Prantl   // If this is where we find out that an internal stop came in, then: Check if
6105097246SAdrian Prantl   // the step-out plan completed.  If it did, then we want to run the callback
6205097246SAdrian Prantl   // here (our reason for living...)
63b9c1b51eSKate Stone   if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) {
6475930019STodd Fiala     m_callback();
6575930019STodd Fiala 
6675930019STodd Fiala     // We no longer need the pointer to the step-out thread plan.
6775930019STodd Fiala     m_step_out_threadplan_sp.reset();
6875930019STodd Fiala 
6975930019STodd Fiala     // Indicate that this plan is done and can be discarded.
7075930019STodd Fiala     SetPlanComplete();
7175930019STodd Fiala 
7205097246SAdrian Prantl     // We're done now, but we want to return false so that we don't cause the
7305097246SAdrian Prantl     // thread to really stop.
7475930019STodd Fiala   }
7575930019STodd Fiala 
7675930019STodd Fiala   return false;
7775930019STodd Fiala }
7875930019STodd Fiala 
WillStop()79b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::WillStop() {
8075930019STodd Fiala   // The code looks like the return value is ignored via ThreadList::
8105097246SAdrian Prantl   // ShouldStop(). This is called when we really are going to stop.  We don't
8205097246SAdrian Prantl   // care and don't need to do anything here.
8375930019STodd Fiala   return false;
8475930019STodd Fiala }
8575930019STodd Fiala 
DoPlanExplainsStop(Event * event_ptr)86b9c1b51eSKate Stone bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) {
8705097246SAdrian Prantl   // We don't ever explain a stop.  The only stop that is relevant to us
8805097246SAdrian Prantl   // directly is the step_out plan we added to do the heavy lifting of getting
8905097246SAdrian Prantl   // us past the current method.
9075930019STodd Fiala   return false;
9175930019STodd Fiala }
9275930019STodd Fiala 
GetPlanRunState()93b9c1b51eSKate Stone lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() {
9405097246SAdrian Prantl   // This value doesn't matter - we'll never be the top thread plan, so nobody
9505097246SAdrian Prantl   // will ask us this question.
9675930019STodd Fiala   return eStateRunning;
9775930019STodd Fiala }
98