summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target/ThreadPlanCallOnFunctionExit.cpp
blob: b2383e4f122a3acbbfcf1313e6763eeabb18002c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ThreadPlanCallOnFunctionExit.h"

using namespace lldb;
using namespace lldb_private;

ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit(Thread &thread,
                                                           const Callback
                                                           &callback) :
    ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit",
               thread,
               eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these
               ),
    m_callback(callback)
{
    // We are not a user-generated plan.
    SetIsMasterPlan(false);
}

void
ThreadPlanCallOnFunctionExit::DidPush()
{
    // We now want to queue the "step out" thread plan so it executes
    // and completes.

    // Set stop vote to eVoteNo.
    m_step_out_threadplan_sp = GetThread()
        .QueueThreadPlanForStepOut(false,   // abort other plans
                                   nullptr, // addr_context
                                   true,    // first instruction
                                   true,    // stop other threads
                                   eVoteNo, // do not say "we're stopping"
                                   eVoteNoOpinion, // don't care about
                                                   // run state broadcasting
                                   0,       // frame_idx
                                   eLazyBoolCalculate // avoid code w/o debinfo
                                   );
}

// -------------------------------------------------------------------------
// ThreadPlan API
// -------------------------------------------------------------------------

void
ThreadPlanCallOnFunctionExit::GetDescription(Stream *s, lldb::DescriptionLevel
                                             level)
{
    if (!s)
        return;
    s->Printf("Running until completion of current function, then making "
              "callback.");
}

bool
ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error)
{
    // We'll say we're always good since I don't know what would make this
    // invalid.
    return true;
}

bool
ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr)
{
    // If this is where we find out that an internal stop came in, then:
    // Check if the step-out plan completed.  If it did, then we want to
    // run the callback here (our reason for living...)
    if (m_step_out_threadplan_sp &&
        m_step_out_threadplan_sp->IsPlanComplete())
    {
        m_callback();

        // We no longer need the pointer to the step-out thread plan.
        m_step_out_threadplan_sp.reset();

        // Indicate that this plan is done and can be discarded.
        SetPlanComplete();

        // We're done now, but we want to return false so that we
        // don't cause the thread to really stop.
    }

    return false;
}

bool
ThreadPlanCallOnFunctionExit::WillStop()
{
    // The code looks like the return value is ignored via ThreadList::
    // ShouldStop().
    // This is called when we really are going to stop.  We don't care
    // and don't need to do anything here.
    return false;
}

bool
ThreadPlanCallOnFunctionExit::DoPlanExplainsStop (Event *event_ptr)
{
    // We don't ever explain a stop.  The only stop that is relevant
    // to us directly is the step_out plan we added to do the heavy lifting
    // of getting us past the current method.
    return false;
}

lldb::StateType
ThreadPlanCallOnFunctionExit::GetPlanRunState()
{
    // This value doesn't matter - we'll never be the top thread plan, so
    // nobody will ask us this question.
    return eStateRunning;
}
OpenPOWER on IntegriCloud