1435933ddSDimitry Andric //===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===//
2435933ddSDimitry Andric //
3435933ddSDimitry Andric //                     The LLVM Compiler Infrastructure
4435933ddSDimitry Andric //
5435933ddSDimitry Andric // This file is distributed under the University of Illinois Open Source
6435933ddSDimitry Andric // License. See LICENSE.TXT for details.
7435933ddSDimitry Andric //
8435933ddSDimitry Andric //===----------------------------------------------------------------------===//
9435933ddSDimitry Andric 
10435933ddSDimitry Andric #include "lldb/Target/ThreadPlanCallOnFunctionExit.h"
11435933ddSDimitry Andric 
12435933ddSDimitry Andric using namespace lldb;
13435933ddSDimitry Andric using namespace lldb_private;
14435933ddSDimitry Andric 
ThreadPlanCallOnFunctionExit(Thread & thread,const Callback & callback)15435933ddSDimitry Andric ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(
16435933ddSDimitry Andric     Thread &thread, const Callback &callback)
17435933ddSDimitry Andric     : ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit", thread,
18435933ddSDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these
19435933ddSDimitry Andric                  ),
20435933ddSDimitry Andric       m_callback(callback) {
21435933ddSDimitry Andric   // We are not a user-generated plan.
22435933ddSDimitry Andric   SetIsMasterPlan(false);
23435933ddSDimitry Andric }
24435933ddSDimitry Andric 
DidPush()25435933ddSDimitry Andric void ThreadPlanCallOnFunctionExit::DidPush() {
264ba319b5SDimitry Andric   // We now want to queue the "step out" thread plan so it executes and
274ba319b5SDimitry Andric   // completes.
28435933ddSDimitry Andric 
29435933ddSDimitry Andric   // Set stop vote to eVoteNo.
30*b5893f02SDimitry Andric   Status status;
31435933ddSDimitry Andric   m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
32435933ddSDimitry Andric       false,             // abort other plans
33435933ddSDimitry Andric       nullptr,           // addr_context
34435933ddSDimitry Andric       true,              // first instruction
35435933ddSDimitry Andric       true,              // stop other threads
36435933ddSDimitry Andric       eVoteNo,           // do not say "we're stopping"
37*b5893f02SDimitry Andric       eVoteNoOpinion,    // don't care about run state broadcasting
38435933ddSDimitry Andric       0,                 // frame_idx
39*b5893f02SDimitry Andric       status,            // status
40435933ddSDimitry Andric       eLazyBoolCalculate // avoid code w/o debinfo
41435933ddSDimitry Andric   );
42435933ddSDimitry Andric }
43435933ddSDimitry Andric 
44435933ddSDimitry Andric // -------------------------------------------------------------------------
45435933ddSDimitry Andric // ThreadPlan API
46435933ddSDimitry Andric // -------------------------------------------------------------------------
47435933ddSDimitry Andric 
GetDescription(Stream * s,lldb::DescriptionLevel level)48435933ddSDimitry Andric void ThreadPlanCallOnFunctionExit::GetDescription(
49435933ddSDimitry Andric     Stream *s, lldb::DescriptionLevel level) {
50435933ddSDimitry Andric   if (!s)
51435933ddSDimitry Andric     return;
52435933ddSDimitry Andric   s->Printf("Running until completion of current function, then making "
53435933ddSDimitry Andric             "callback.");
54435933ddSDimitry Andric }
55435933ddSDimitry Andric 
ValidatePlan(Stream * error)56435933ddSDimitry Andric bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) {
57435933ddSDimitry Andric   // We'll say we're always good since I don't know what would make this
58435933ddSDimitry Andric   // invalid.
59435933ddSDimitry Andric   return true;
60435933ddSDimitry Andric }
61435933ddSDimitry Andric 
ShouldStop(Event * event_ptr)62435933ddSDimitry Andric bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) {
634ba319b5SDimitry Andric   // If this is where we find out that an internal stop came in, then: Check if
644ba319b5SDimitry Andric   // the step-out plan completed.  If it did, then we want to run the callback
654ba319b5SDimitry Andric   // here (our reason for living...)
66435933ddSDimitry Andric   if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) {
67435933ddSDimitry Andric     m_callback();
68435933ddSDimitry Andric 
69435933ddSDimitry Andric     // We no longer need the pointer to the step-out thread plan.
70435933ddSDimitry Andric     m_step_out_threadplan_sp.reset();
71435933ddSDimitry Andric 
72435933ddSDimitry Andric     // Indicate that this plan is done and can be discarded.
73435933ddSDimitry Andric     SetPlanComplete();
74435933ddSDimitry Andric 
754ba319b5SDimitry Andric     // We're done now, but we want to return false so that we don't cause the
764ba319b5SDimitry Andric     // thread to really stop.
77435933ddSDimitry Andric   }
78435933ddSDimitry Andric 
79435933ddSDimitry Andric   return false;
80435933ddSDimitry Andric }
81435933ddSDimitry Andric 
WillStop()82435933ddSDimitry Andric bool ThreadPlanCallOnFunctionExit::WillStop() {
83435933ddSDimitry Andric   // The code looks like the return value is ignored via ThreadList::
844ba319b5SDimitry Andric   // ShouldStop(). This is called when we really are going to stop.  We don't
854ba319b5SDimitry Andric   // care and don't need to do anything here.
86435933ddSDimitry Andric   return false;
87435933ddSDimitry Andric }
88435933ddSDimitry Andric 
DoPlanExplainsStop(Event * event_ptr)89435933ddSDimitry Andric bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) {
904ba319b5SDimitry Andric   // We don't ever explain a stop.  The only stop that is relevant to us
914ba319b5SDimitry Andric   // directly is the step_out plan we added to do the heavy lifting of getting
924ba319b5SDimitry Andric   // us past the current method.
93435933ddSDimitry Andric   return false;
94435933ddSDimitry Andric }
95435933ddSDimitry Andric 
GetPlanRunState()96435933ddSDimitry Andric lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() {
974ba319b5SDimitry Andric   // This value doesn't matter - we'll never be the top thread plan, so nobody
984ba319b5SDimitry Andric   // will ask us this question.
99435933ddSDimitry Andric   return eStateRunning;
100435933ddSDimitry Andric }
101