Commit 694e2140 by Ben Clayton

Vulkan/Debug: Don't step for column updates

OpLine is produced for any line / column change. Column information may be useful for stack frame information (say two function calls on the same line), diagnosing a crash in a complex expression, or some other tooling. However, it's not so useful for IDE debugger stepping, unless you have a location for the span end (which we don't). Bug: b/155390706 Bug: b/148401179 Change-Id: Ic416c6e3c47044d707bfa36112e1153588669424 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/44549Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent cfc77602
...@@ -451,6 +451,7 @@ struct SpirvShader::Impl::Debugger ...@@ -451,6 +451,7 @@ struct SpirvShader::Impl::Debugger
void process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass); void process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass);
void setNextSetLocationIsStep();
void setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &, int line, int column); void setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &, int line, int column);
void setLocation(EmitState *state, const std::string &path, int line, int column); void setLocation(EmitState *state, const std::string &path, int line, int column);
...@@ -514,6 +515,8 @@ private: ...@@ -514,6 +515,8 @@ private:
void defineOrEmit(InsnIterator insn, Pass pass, F &&emit); void defineOrEmit(InsnIterator insn, Pass pass, F &&emit);
std::unordered_map<std::string, std::shared_ptr<vk::dbg::File>> files; std::unordered_map<std::string, std::shared_ptr<vk::dbg::File>> files;
bool nextSetLocationIsStep = true;
int lastSetLocationLine = 0;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -533,7 +536,7 @@ public: ...@@ -533,7 +536,7 @@ public:
void enter(vk::dbg::Context::Lock &lock, const char *name); void enter(vk::dbg::Context::Lock &lock, const char *name);
void exit(); void exit();
void updateActiveLaneMask(int lane, bool enabled); void updateActiveLaneMask(int lane, bool enabled);
void updateLocation(vk::dbg::File::ID file, int line, int column); void updateLocation(bool isStep, vk::dbg::File::ID file, int line, int column);
void createScope(const debug::Scope *); void createScope(const debug::Scope *);
void setScope(debug::SourceScope *newScope); void setScope(debug::SourceScope *newScope);
...@@ -595,7 +598,7 @@ SpirvShader::Impl::Debugger::State::State(const Debugger *debugger, const char * ...@@ -595,7 +598,7 @@ SpirvShader::Impl::Debugger::State::State(const Debugger *debugger, const char *
builtinsByLane[i] = lock.createVariableContainer(); builtinsByLane[i] = lock.createVariableContainer();
} }
thread->update([&](vk::dbg::Frame &frame) { thread->update(true, [&](vk::dbg::Frame &frame) {
rootScopes.locals = frame.locals; rootScopes.locals = frame.locals;
rootScopes.hovers = frame.hovers; rootScopes.hovers = frame.hovers;
for(int i = 0; i < sw::SIMD::Width; i++) for(int i = 0; i < sw::SIMD::Width; i++)
...@@ -631,10 +634,10 @@ void SpirvShader::Impl::Debugger::State::updateActiveLaneMask(int lane, bool ena ...@@ -631,10 +634,10 @@ void SpirvShader::Impl::Debugger::State::updateActiveLaneMask(int lane, bool ena
rootScopes.localsByLane[lane]->put("enabled", vk::dbg::make_constant(enabled)); rootScopes.localsByLane[lane]->put("enabled", vk::dbg::make_constant(enabled));
} }
void SpirvShader::Impl::Debugger::State::updateLocation(vk::dbg::File::ID fileID, int line, int column) void SpirvShader::Impl::Debugger::State::updateLocation(bool isStep, vk::dbg::File::ID fileID, int line, int column)
{ {
auto file = debugger->ctx->lock().get(fileID); auto file = debugger->ctx->lock().get(fileID);
thread->update([&](vk::dbg::Frame &frame) { thread->update(isStep, [&](vk::dbg::Frame &frame) {
frame.location = { file, line, column }; frame.location = { file, line, column };
}); });
} }
...@@ -735,7 +738,7 @@ void SpirvShader::Impl::Debugger::State::setScope(debug::SourceScope *newSrcScop ...@@ -735,7 +738,7 @@ void SpirvShader::Impl::Debugger::State::setScope(debug::SourceScope *newSrcScop
} }
auto dbgScope = getScopes(srcScope->scope); auto dbgScope = getScopes(srcScope->scope);
thread->update([&](vk::dbg::Frame &frame) { thread->update(true, [&](vk::dbg::Frame &frame) {
frame.locals = dbgScope.locals; frame.locals = dbgScope.locals;
frame.hovers = dbgScope.hovers; frame.hovers = dbgScope.hovers;
}); });
...@@ -1137,9 +1140,21 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI ...@@ -1137,9 +1140,21 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI
} }
} }
void SpirvShader::Impl::Debugger::setNextSetLocationIsStep()
{
nextSetLocationIsStep = true;
}
void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &file, int line, int column) void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &file, int line, int column)
{ {
rr::Call(&State::updateLocation, state->routine->dbgState, file->id, line, column); if(line != lastSetLocationLine)
{
// If the line number has changed, then this is always a step.
nextSetLocationIsStep = true;
lastSetLocationLine = line;
}
rr::Call(&State::updateLocation, state->routine->dbgState, nextSetLocationIsStep, file->id, line, column);
nextSetLocationIsStep = false;
} }
void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::string &path, int line, int column) void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::string &path, int line, int column)
...@@ -1579,6 +1594,16 @@ void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) c ...@@ -1579,6 +1594,16 @@ void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) c
if(auto dbg = impl.debugger) if(auto dbg = impl.debugger)
{ {
if(insn.opcode() == spv::OpLabel)
{
// Whenever we hit a label, force the next OpLine to be steppable.
// This handles the case where we have control flow on the same line
// For example:
// while(true) { foo(); }
// foo() should be repeatedly steppable.
dbg->setNextSetLocationIsStep();
}
if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0) if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0)
{ {
// We're emitting debugger logic for SPIR-V. // We're emitting debugger logic for SPIR-V.
......
...@@ -96,15 +96,22 @@ void Thread::exit() ...@@ -96,15 +96,22 @@ void Thread::exit()
frames.pop_back(); frames.pop_back();
} }
void Thread::update(std::function<void(Frame &)> f) void Thread::update(bool isStep, std::function<void(Frame &)> f)
{ {
marl::lock lock(mutex); marl::lock lock(mutex);
auto &frame = *frames.back(); auto &frame = *frames.back();
auto oldLocation = frame.location; if(isStep)
f(frame);
if(frame.location != oldLocation)
{ {
onLocationUpdate(lock); auto oldLocation = frame.location;
f(frame);
if(frame.location != oldLocation)
{
onLocationUpdate(lock);
}
}
else
{
f(frame);
} }
} }
......
...@@ -143,9 +143,14 @@ public: ...@@ -143,9 +143,14 @@ public:
State state() const; State state() const;
// update() calls f to modify the top most frame of the stack. // update() calls f to modify the top most frame of the stack.
// If the frame's location is changed, update() potentially blocks until the // If the frame's location is changed and isStep is true, update()
// thread is resumed with one of the methods below. // potentially blocks until the thread is resumed with one of the methods
void update(std::function<void(Frame &)> f); // below.
// isStep is used to distinguish same-statement column position updates
// from full line updates. Note that we cannot simply examine line position
// changes as single-line loops such as `while(true) { foo(); }` would not
// be correctly steppable.
void update(bool isStep, std::function<void(Frame &)> f);
// resume() resumes execution of the thread by unblocking a call to // resume() resumes execution of the thread by unblocking a call to
// update() and setting the thread's state to State::Running. // update() and setting the thread's state to State::Running.
......
...@@ -1805,7 +1805,7 @@ void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState) ...@@ -1805,7 +1805,7 @@ void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
#ifdef ENABLE_VK_DEBUGGER #ifdef ENABLE_VK_DEBUGGER
if(debuggerThread) if(debuggerThread)
{ {
debuggerThread->update([&](vk::dbg::Frame &frame) { debuggerThread->update(true, [&](vk::dbg::Frame &frame) {
frame.location = { debuggerFile, line++, 0 }; frame.location = { debuggerFile, line++, 0 };
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment