blob: 9facfdcb95c9755d7ec0247b9479aeb88b0850d1 [file] [log] [blame]
Jim Inghamd1686902010-10-14 23:45:03 +00001//===-- ThreadPlanTestCondition.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/ThreadPlanTestCondition.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16
17#include "lldb/lldb-private-log.h"
18#include "lldb/Breakpoint/BreakpointLocation.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Core/Stream.h"
21#include "lldb/Core/Value.h"
22#include "lldb/Core/ValueObject.h"
23#include "lldb/Symbol/Function.h"
24#include "lldb/Symbol/Symbol.h"
25#include "lldb/Target/Process.h"
26#include "lldb/Target/RegisterContext.h"
27#include "lldb/Target/StopInfo.h"
28#include "lldb/Target/Thread.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33
34//----------------------------------------------------------------------
35// ThreadPlanTestCondition: Step through a stack range, either stepping over or into
36// based on the value of \a type.
37//----------------------------------------------------------------------
38
39ThreadPlanTestCondition::ThreadPlanTestCondition (
40 Thread& thread,
41 ExecutionContext &exe_ctx,
42 ClangUserExpression *expression,
43 lldb::BreakpointLocationSP break_loc_sp,
44 bool stop_others) :
45 ThreadPlan (ThreadPlan::eKindTestCondition, "test condition", thread, eVoteNoOpinion, eVoteNoOpinion),
Jim Inghamd1686902010-10-14 23:45:03 +000046 m_expression (expression),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000047 m_exe_ctx (exe_ctx),
Jim Inghamd1686902010-10-14 23:45:03 +000048 m_break_loc_sp (break_loc_sp),
49 m_did_stop (false),
50 m_stop_others (stop_others)
51{
52}
53
54ThreadPlanTestCondition::~ThreadPlanTestCondition ()
55{
56}
57
58bool
59ThreadPlanTestCondition::ValidatePlan (Stream *error)
60{
61 return true;
62}
63
64void
65ThreadPlanTestCondition::GetDescription (Stream *s, lldb::DescriptionLevel level)
66{
Jim Ingham360f53f2010-11-30 02:22:11 +000067 if (m_expression)
68 s->Printf("Thread plan to test condition: \"%s\".", m_expression->GetUserText());
69 else
70 s->Printf("Thread plan to test unspecified condition.");
Jim Inghamd1686902010-10-14 23:45:03 +000071}
72
73bool
74ThreadPlanTestCondition::ShouldStop (Event *event_ptr)
75{
Greg Claytone005f2c2010-11-06 01:53:30 +000076 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamd1686902010-10-14 23:45:03 +000077 if (m_thread.IsThreadPlanDone(m_expression_plan_sp.get()))
78 {
Greg Clayton427f2902010-12-14 02:59:59 +000079 lldb::ClangExpressionVariableSP expr_result;
Jim Inghamd1686902010-10-14 23:45:03 +000080 StreamString error_stream;
81 m_expression->FinalizeJITExecution(error_stream, m_exe_ctx, expr_result);
82
Greg Clayton427f2902010-12-14 02:59:59 +000083 ValueObjectSP result_sp (expr_result->GetValueObject());
Jim Inghamd1686902010-10-14 23:45:03 +000084 if (result_sp)
85 {
86 // FIXME: This is not the right answer, we should have a "GetValueAsBoolean..."
87 Scalar scalar_value = result_sp->GetValue().ResolveValue (&m_exe_ctx, result_sp->GetClangAST());
88 if (scalar_value.IsValid())
89 {
90 if (scalar_value.ULongLong(1) == 0)
91 m_did_stop = false;
92 else
93 m_did_stop = true;
94 }
95 if (log)
96 log->Printf("Condition successfully evaluated, result is %s.\n", m_did_stop ? "true" : "false");
97 }
98 else
99 {
100 if (log)
101 log->Printf("Failed to get a result from the expression, error: \"%s\"\n", error_stream.GetData());
102 m_did_stop = true;
103 }
104 }
105 else if (m_exe_ctx.thread->WasThreadPlanDiscarded (m_expression_plan_sp.get()))
106 {
107 if (log)
108 log->Printf("ExecuteExpression thread plan was discarded.\n");
109 m_did_stop = true;
110 }
111
112 // Now we have to change the event to a breakpoint event and mark it up appropriately:
113 Process::ProcessEventData *new_data = new Process::ProcessEventData (m_thread.GetProcess().GetSP(), eStateStopped);
114 event_ptr->SetData(new_data);
115 event_ptr->SetType(Process::eBroadcastBitStateChanged);
Jim Ingham6297a3a2010-10-20 00:39:53 +0000116 SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID (m_thread,
117 m_break_loc_sp->GetBreakpointSite()->GetID(),
118 m_did_stop));
Jim Inghamd1686902010-10-14 23:45:03 +0000119 if (m_did_stop)
120 {
121 Process::ProcessEventData::SetRestartedInEvent (event_ptr, false);
122 }
123 else
124 {
125 Process::ProcessEventData::SetRestartedInEvent (event_ptr, true);
126 }
127
128 SetPlanComplete();
129 return m_did_stop;
130}
131
132bool
133ThreadPlanTestCondition::PlanExplainsStop ()
134{
135 // We explain all stops, and we just can the execution and return true if we stop for any
136 // reason other than that our expression execution is done.
137 return true;
138}
139
140Vote
141ThreadPlanTestCondition::ShouldReportStop (Event *event_ptr)
142{
143 if (m_did_stop)
144 {
145 return eVoteYes;
146 }
147 else
148 {
149 return eVoteNo;
150 }
151}
152
153void
154ThreadPlanTestCondition::DidPush()
155{
156 StreamString error_stream;
157 m_expression_plan_sp.reset(m_expression->GetThreadPlanToExecuteJITExpression (error_stream, m_exe_ctx));
158 m_thread.QueueThreadPlan (m_expression_plan_sp, false);
159}
160
161bool
162ThreadPlanTestCondition::StopOthers ()
163{
164 return m_stop_others;
165}
166
167bool
168ThreadPlanTestCondition::WillStop ()
169{
170 return true;
171}
172
173StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000174ThreadPlanTestCondition::GetPlanRunState ()
Jim Inghamd1686902010-10-14 23:45:03 +0000175{
176 return eStateRunning;
177}
178
179bool
180ThreadPlanTestCondition::MischiefManaged ()
181{
182 // If we get a stop we're done, we don't puase in the middle of
183 // condition execution.
184 return true;
185}