reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
//===-- ThreadPlanCallOnFunctionExit.cpp ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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.
  Status status;
  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
      status,            // status
      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;
}