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