xref: /llvm-project/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp (revision e103ae92ef2336854587778bd3ae88a87e409a5e)
1 //===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/ThreadPlanCallOnFunctionExit.h"
11 
12 using namespace lldb;
13 using namespace lldb_private;
14 
15 ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(
16     Thread &thread, const Callback &callback)
17     : ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit", thread,
18                  eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these
19                  ),
20       m_callback(callback) {
21   // We are not a user-generated plan.
22   SetIsMasterPlan(false);
23 }
24 
25 void ThreadPlanCallOnFunctionExit::DidPush() {
26   // We now want to queue the "step out" thread plan so it executes and
27   // completes.
28 
29   // Set stop vote to eVoteNo.
30   Status status;
31   m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
32       false,             // abort other plans
33       nullptr,           // addr_context
34       true,              // first instruction
35       true,              // stop other threads
36       eVoteNo,           // do not say "we're stopping"
37       eVoteNoOpinion,    // don't care about run state broadcasting
38       0,                 // frame_idx
39       status,            // status
40       eLazyBoolCalculate // avoid code w/o debinfo
41   );
42 }
43 
44 // -------------------------------------------------------------------------
45 // ThreadPlan API
46 // -------------------------------------------------------------------------
47 
48 void ThreadPlanCallOnFunctionExit::GetDescription(
49     Stream *s, lldb::DescriptionLevel level) {
50   if (!s)
51     return;
52   s->Printf("Running until completion of current function, then making "
53             "callback.");
54 }
55 
56 bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) {
57   // We'll say we're always good since I don't know what would make this
58   // invalid.
59   return true;
60 }
61 
62 bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
63   // If this is where we find out that an internal stop came in, then: Check if
64   // the step-out plan completed.  If it did, then we want to run the callback
65   // here (our reason for living...)
66   if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) {
67     m_callback();
68 
69     // We no longer need the pointer to the step-out thread plan.
70     m_step_out_threadplan_sp.reset();
71 
72     // Indicate that this plan is done and can be discarded.
73     SetPlanComplete();
74 
75     // We're done now, but we want to return false so that we don't cause the
76     // thread to really stop.
77   }
78 
79   return false;
80 }
81 
82 bool ThreadPlanCallOnFunctionExit::WillStop() {
83   // The code looks like the return value is ignored via ThreadList::
84   // ShouldStop(). This is called when we really are going to stop.  We don't
85   // care and don't need to do anything here.
86   return false;
87 }
88 
89 bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) {
90   // We don't ever explain a stop.  The only stop that is relevant to us
91   // directly is the step_out plan we added to do the heavy lifting of getting
92   // us past the current method.
93   return false;
94 }
95 
96 lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() {
97   // This value doesn't matter - we'll never be the top thread plan, so nobody
98   // will ask us this question.
99   return eStateRunning;
100 }
101