SpirvShaderDebugger: Implement scope nesting Previously nested scopes would hide their parent variables. This is no longer the case. Bug: b/148401179 Change-Id: Icf2771a525524b8796ab12e295e141388bb5b399 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/42368 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com> Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Pipeline/SpirvShaderDebugger.cpp b/src/Pipeline/SpirvShaderDebugger.cpp index 41913d9..637dd80 100644 --- a/src/Pipeline/SpirvShaderDebugger.cpp +++ b/src/Pipeline/SpirvShaderDebugger.cpp
@@ -377,6 +377,12 @@ return scope->parent ? find<T>(scope->parent) : nullptr; } +bool hasDebuggerScope(debug::Scope *spirvScope) +{ + return debug::cast<debug::Function>(spirvScope) != nullptr || + debug::cast<debug::LexicalBlock>(spirvScope) != nullptr; +} + } // namespace debug } // anonymous namespace @@ -421,7 +427,8 @@ void process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass); - void setPosition(EmitState *state, const std::string &path, uint32_t line, uint32_t 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); // exposeVariable exposes the variable with the given ID to the debugger // using the specified key. @@ -469,8 +476,6 @@ // use get() and add() to access this std::unordered_map<debug::Object::ID, std::unique_ptr<debug::Object>> objects; - std::unordered_map<std::string, vk::dbg::File::ID> fileIDs; - // defineOrEmit() when called in Pass::Define, creates and stores a // zero-initialized object into the Debugger::objects map using the // object identifier held by second instruction operand. @@ -483,6 +488,8 @@ // The object type is automatically inferred from the function signature. template<typename F, typename T = typename std::remove_pointer<ArgTyT<F>>::type> void defineOrEmit(InsnIterator insn, Pass pass, F &&emit); + + std::unordered_map<std::string, std::shared_ptr<vk::dbg::File>> files; }; //////////////////////////////////////////////////////////////////////////////// @@ -502,7 +509,7 @@ void enter(vk::dbg::Context::Lock &lock, const char *name); void exit(); void updateActiveLaneMask(int lane, bool enabled); - void update(vk::dbg::File::ID file, int line, int column); + void updateLocation(vk::dbg::File::ID file, int line, int column); void createScope(const debug::Scope *); void setScope(debug::SourceScope *newScope); @@ -594,7 +601,7 @@ rootScopes.localsByLane[lane]->put("enabled", vk::dbg::make_constant(enabled)); } -void SpirvShader::Impl::Debugger::State::update(vk::dbg::File::ID fileID, int line, int column) +void SpirvShader::Impl::Debugger::State::updateLocation(vk::dbg::File::ID fileID, int line, int column) { auto file = debugger->ctx->lock().get(fileID); thread->update([&](vk::dbg::Frame &frame) { @@ -645,19 +652,35 @@ ASSERT(spirvScope != nullptr); - // TODO: Deal with scope nesting. - auto lock = debugger->ctx->lock(); Scopes s = {}; s.locals = lock.createScope(spirvScope->source->dbgFile); s.hovers = lock.createScope(spirvScope->source->dbgFile); + for(int i = 0; i < sw::SIMD::Width; i++) { auto locals = lock.createVariableContainer(); - locals->extend(builtinsByLane[i]); s.localsByLane[i] = locals; s.locals->variables->put(laneNames[i], locals); } + + if(hasDebuggerScope(spirvScope->parent)) + { + auto parent = getScopes(spirvScope->parent); + for(int i = 0; i < sw::SIMD::Width; i++) + { + s.localsByLane[i]->extend(parent.localsByLane[i]); + } + s.hovers->variables->extend(parent.hovers->variables); + } + else + { + for(int i = 0; i < sw::SIMD::Width; i++) + { + s.localsByLane[i]->extend(builtinsByLane[i]); + } + } + scopes.emplace(spirvScope, std::move(s)); } @@ -667,7 +690,7 @@ if(oldSrcScope == newSrcScope) { return; } srcScope = newSrcScope; - if(debug::cast<debug::LexicalBlock>(srcScope->scope)) + if(hasDebuggerScope(srcScope->scope)) { auto lock = debugger->ctx->lock(); auto thread = lock.currentThread(); @@ -1027,7 +1050,7 @@ auto file = dbg->ctx->lock().createVirtualFile(source->file.c_str(), source->source.c_str()); source->dbgFile = file; - fileIDs.emplace(source->file.c_str(), file->id); + files.emplace(source->file.c_str(), file); }); break; @@ -1057,12 +1080,17 @@ } } -void SpirvShader::Impl::Debugger::setPosition(EmitState *state, const std::string &path, uint32_t line, uint32_t column) +void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &file, int line, int column) { - auto it = fileIDs.find(path); - if(it != fileIDs.end()) + rr::Call(&State::updateLocation, state->routine->dbgState, file->id, line, column); +} + +void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::string &path, int line, int column) +{ + auto it = files.find(path); + if(it != files.end()) { - rr::Call(&State::update, state->routine->dbgState, it->second, line, column); + setLocation(state, it->second, line, column); } } @@ -1479,18 +1507,19 @@ } # endif // PRINT_EACH_EXECUTED_INSTRUCTION - if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0) - { - // We're emitting debugger logic for SPIR-V. - // Only single line step over statement instructions. - if(IsStatement(insn.opcode())) - { - auto dbg = impl.debugger; - if(!dbg) { return; } + // Only single line step over statement instructions. - auto line = dbg->spirvLineMappings.at(insn.wordPointer(0)); - auto column = 0; - rr::Call(&Impl::Debugger::State::update, state->routine->dbgState, dbg->spirvFile->id, line, column); + if(auto dbg = impl.debugger) + { + if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0) + { + // We're emitting debugger logic for SPIR-V. + if(IsStatement(insn.opcode())) + { + auto line = dbg->spirvLineMappings.at(insn.wordPointer(0)); + auto column = 0; + dbg->setLocation(state, dbg->spirvFile, line, column); + } } } } @@ -1542,7 +1571,7 @@ auto path = getString(insn.word(1)); auto line = insn.word(2); auto column = insn.word(3); - dbg->setPosition(state, path, line, column); + dbg->setLocation(state, path, line, column); } return EmitResult::Continue; }