1435933ddSDimitry Andric //===-- ThreadPlanPython.cpp ------------------------------------*- C++ -*-===//
27aa51b79SEd Maste //
37aa51b79SEd Maste //                     The LLVM Compiler Infrastructure
47aa51b79SEd Maste //
57aa51b79SEd Maste // This file is distributed under the University of Illinois Open Source
67aa51b79SEd Maste // License. See LICENSE.TXT for details.
77aa51b79SEd Maste //
87aa51b79SEd Maste //===----------------------------------------------------------------------===//
97aa51b79SEd Maste 
107aa51b79SEd Maste #include "lldb/Target/ThreadPlan.h"
117aa51b79SEd Maste 
127aa51b79SEd Maste // C Includes
137aa51b79SEd Maste // C++ Includes
147aa51b79SEd Maste // Other libraries and framework includes
157aa51b79SEd Maste // Project includes
167aa51b79SEd Maste #include "lldb/Core/Debugger.h"
177aa51b79SEd Maste #include "lldb/Core/State.h"
187aa51b79SEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
197aa51b79SEd Maste #include "lldb/Interpreter/ScriptInterpreter.h"
20435933ddSDimitry Andric #include "lldb/Target/Process.h"
217aa51b79SEd Maste #include "lldb/Target/RegisterContext.h"
22435933ddSDimitry Andric #include "lldb/Target/Target.h"
237aa51b79SEd Maste #include "lldb/Target/Thread.h"
247aa51b79SEd Maste #include "lldb/Target/ThreadPlan.h"
257aa51b79SEd Maste #include "lldb/Target/ThreadPlanPython.h"
26f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
277aa51b79SEd Maste 
287aa51b79SEd Maste using namespace lldb;
297aa51b79SEd Maste using namespace lldb_private;
307aa51b79SEd Maste 
317aa51b79SEd Maste //----------------------------------------------------------------------
327aa51b79SEd Maste // ThreadPlanPython
337aa51b79SEd Maste //----------------------------------------------------------------------
347aa51b79SEd Maste 
35435933ddSDimitry Andric ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
36435933ddSDimitry Andric     : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
37435933ddSDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
38435933ddSDimitry Andric       m_class_name(class_name) {
397aa51b79SEd Maste   SetIsMasterPlan(true);
407aa51b79SEd Maste   SetOkayToDiscard(true);
417aa51b79SEd Maste   SetPrivate(false);
427aa51b79SEd Maste }
437aa51b79SEd Maste 
44435933ddSDimitry Andric ThreadPlanPython::~ThreadPlanPython() {
45435933ddSDimitry Andric   // FIXME, do I need to decrement the ref count on this implementation object
46435933ddSDimitry Andric   // to make it go away?
477aa51b79SEd Maste }
487aa51b79SEd Maste 
49435933ddSDimitry Andric bool ThreadPlanPython::ValidatePlan(Stream *error) {
50435933ddSDimitry Andric   // I have to postpone setting up the implementation till after the constructor
51435933ddSDimitry Andric   // because I need to call
52435933ddSDimitry Andric   // shared_from_this, which you can't do in the constructor.  So I'll do it
53435933ddSDimitry Andric   // here.
547aa51b79SEd Maste   if (m_implementation_sp)
557aa51b79SEd Maste     return true;
567aa51b79SEd Maste   else
577aa51b79SEd Maste     return false;
587aa51b79SEd Maste }
597aa51b79SEd Maste 
60435933ddSDimitry Andric void ThreadPlanPython::DidPush() {
61435933ddSDimitry Andric   // We set up the script side in DidPush, so that it can push other plans in
62435933ddSDimitry Andric   // the constructor,
637aa51b79SEd Maste   // and doesn't have to care about the details of DidPush.
647aa51b79SEd Maste 
65435933ddSDimitry Andric   if (!m_class_name.empty()) {
66435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
67435933ddSDimitry Andric                                            ->GetTarget()
68435933ddSDimitry Andric                                            .GetDebugger()
69435933ddSDimitry Andric                                            .GetCommandInterpreter()
70435933ddSDimitry Andric                                            .GetScriptInterpreter();
71435933ddSDimitry Andric     if (script_interp) {
72435933ddSDimitry Andric       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
73435933ddSDimitry Andric           m_class_name.c_str(), this->shared_from_this());
747aa51b79SEd Maste     }
757aa51b79SEd Maste   }
767aa51b79SEd Maste }
777aa51b79SEd Maste 
78435933ddSDimitry Andric bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
797aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
807aa51b79SEd Maste   if (log)
81435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
82435933ddSDimitry Andric                 m_class_name.c_str());
837aa51b79SEd Maste 
847aa51b79SEd Maste   bool should_stop = true;
85435933ddSDimitry Andric   if (m_implementation_sp) {
86435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
87435933ddSDimitry Andric                                            ->GetTarget()
88435933ddSDimitry Andric                                            .GetDebugger()
89435933ddSDimitry Andric                                            .GetCommandInterpreter()
90435933ddSDimitry Andric                                            .GetScriptInterpreter();
91435933ddSDimitry Andric     if (script_interp) {
927aa51b79SEd Maste       bool script_error;
93435933ddSDimitry Andric       should_stop = script_interp->ScriptedThreadPlanShouldStop(
94435933ddSDimitry Andric           m_implementation_sp, event_ptr, script_error);
957aa51b79SEd Maste       if (script_error)
967aa51b79SEd Maste         SetPlanComplete(false);
977aa51b79SEd Maste     }
987aa51b79SEd Maste   }
997aa51b79SEd Maste   return should_stop;
1007aa51b79SEd Maste }
1017aa51b79SEd Maste 
102435933ddSDimitry Andric bool ThreadPlanPython::IsPlanStale() {
1037aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1047aa51b79SEd Maste   if (log)
105435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
106435933ddSDimitry Andric                 m_class_name.c_str());
107435933ddSDimitry Andric 
108435933ddSDimitry Andric   bool is_stale = true;
109435933ddSDimitry Andric   if (m_implementation_sp) {
110435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
111435933ddSDimitry Andric                                            ->GetTarget()
112435933ddSDimitry Andric                                            .GetDebugger()
113435933ddSDimitry Andric                                            .GetCommandInterpreter()
114435933ddSDimitry Andric                                            .GetScriptInterpreter();
115435933ddSDimitry Andric     if (script_interp) {
116435933ddSDimitry Andric       bool script_error;
117435933ddSDimitry Andric       is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
118435933ddSDimitry Andric                                                           script_error);
119435933ddSDimitry Andric       if (script_error)
120435933ddSDimitry Andric         SetPlanComplete(false);
121435933ddSDimitry Andric     }
122435933ddSDimitry Andric   }
123435933ddSDimitry Andric   return is_stale;
124435933ddSDimitry Andric }
125435933ddSDimitry Andric 
126435933ddSDimitry Andric bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
127435933ddSDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
128435933ddSDimitry Andric   if (log)
129435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
130435933ddSDimitry Andric                 m_class_name.c_str());
1317aa51b79SEd Maste 
1327aa51b79SEd Maste   bool explains_stop = true;
133435933ddSDimitry Andric   if (m_implementation_sp) {
134435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
135435933ddSDimitry Andric                                            ->GetTarget()
136435933ddSDimitry Andric                                            .GetDebugger()
137435933ddSDimitry Andric                                            .GetCommandInterpreter()
138435933ddSDimitry Andric                                            .GetScriptInterpreter();
139435933ddSDimitry Andric     if (script_interp) {
1407aa51b79SEd Maste       bool script_error;
141435933ddSDimitry Andric       explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
142435933ddSDimitry Andric           m_implementation_sp, event_ptr, script_error);
1437aa51b79SEd Maste       if (script_error)
1447aa51b79SEd Maste         SetPlanComplete(false);
1457aa51b79SEd Maste     }
1467aa51b79SEd Maste   }
1477aa51b79SEd Maste   return explains_stop;
1487aa51b79SEd Maste }
1497aa51b79SEd Maste 
150435933ddSDimitry Andric bool ThreadPlanPython::MischiefManaged() {
1517aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1527aa51b79SEd Maste   if (log)
153435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
154435933ddSDimitry Andric                 m_class_name.c_str());
1557aa51b79SEd Maste   bool mischief_managed = true;
156435933ddSDimitry Andric   if (m_implementation_sp) {
157435933ddSDimitry Andric     // I don't really need mischief_managed, since it's simpler to just call
158435933ddSDimitry Andric     // SetPlanComplete in should_stop.
1597aa51b79SEd Maste     mischief_managed = IsPlanComplete();
1607aa51b79SEd Maste     if (mischief_managed)
1617aa51b79SEd Maste       m_implementation_sp.reset();
1627aa51b79SEd Maste   }
1637aa51b79SEd Maste   return mischief_managed;
1647aa51b79SEd Maste }
1657aa51b79SEd Maste 
166435933ddSDimitry Andric lldb::StateType ThreadPlanPython::GetPlanRunState() {
1677aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1687aa51b79SEd Maste   if (log)
169435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
1707aa51b79SEd Maste                 m_class_name.c_str());
1717aa51b79SEd Maste   lldb::StateType run_state = eStateRunning;
172435933ddSDimitry Andric   if (m_implementation_sp) {
173435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
174435933ddSDimitry Andric                                            ->GetTarget()
175435933ddSDimitry Andric                                            .GetDebugger()
176435933ddSDimitry Andric                                            .GetCommandInterpreter()
177435933ddSDimitry Andric                                            .GetScriptInterpreter();
178435933ddSDimitry Andric     if (script_interp) {
1797aa51b79SEd Maste       bool script_error;
180435933ddSDimitry Andric       run_state = script_interp->ScriptedThreadPlanGetRunState(
181435933ddSDimitry Andric           m_implementation_sp, script_error);
1827aa51b79SEd Maste     }
1837aa51b79SEd Maste   }
1847aa51b79SEd Maste   return run_state;
1857aa51b79SEd Maste }
1867aa51b79SEd Maste 
1877aa51b79SEd Maste // The ones below are not currently exported to Python.
1887aa51b79SEd Maste 
189435933ddSDimitry Andric bool ThreadPlanPython::StopOthers() {
190435933ddSDimitry Andric   // For now Python plans run all threads, but we should add some controls for
191435933ddSDimitry Andric   // this.
1927aa51b79SEd Maste   return false;
1937aa51b79SEd Maste }
1947aa51b79SEd Maste 
195435933ddSDimitry Andric void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
196435933ddSDimitry Andric   s->Printf("Python thread plan implemented by class %s.",
197435933ddSDimitry Andric             m_class_name.c_str());
1987aa51b79SEd Maste }
1997aa51b79SEd Maste 
200435933ddSDimitry Andric bool ThreadPlanPython::WillStop() {
2017aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
2027aa51b79SEd Maste   if (log)
203435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
204435933ddSDimitry Andric                 m_class_name.c_str());
2057aa51b79SEd Maste   return true;
2067aa51b79SEd Maste }
207