SpirvShaderDebugger: Make Function extend Scope Reading between the lines of the spec, Functions are also scopes. Move common scope fields into the base Scope class. Fix `scope` fields requiring a `LexicalBlock` to take the more general `Scope`. Bug: b/148401179 Change-Id: Iac7b4fd4440a701905e2dbcdf71b91146ea8ff7d Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/42248 Reviewed-by: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Pipeline/SpirvShaderDebugger.cpp b/src/Pipeline/SpirvShaderDebugger.cpp index 3ede3ac..d744859 100644 --- a/src/Pipeline/SpirvShaderDebugger.cpp +++ b/src/Pipeline/SpirvShaderDebugger.cpp
@@ -205,10 +205,12 @@ static constexpr bool kindof(Kind kind) { return kind == Kind::CompilationUnit || + kind == Kind::Function || kind == Kind::LexicalBlock; } struct Source *source = nullptr; + Scope *parent = nullptr; }; struct Type : public Object @@ -290,14 +292,12 @@ uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags }; -struct Function : ObjectImpl<Function, Object, Object::Kind::Function> +struct Function : ObjectImpl<Function, Scope, Object::Kind::Function> { std::string name; FunctionType *type = nullptr; - Source *source = nullptr; uint32_t line = 0; uint32_t column = 0; - struct LexicalBlock *parent = nullptr; std::string linkage; uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags uint32_t scopeLine = 0; @@ -308,9 +308,7 @@ { uint32_t line = 0; uint32_t column = 0; - Scope *parent = nullptr; std::string name; - Function *function = nullptr; }; struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt> @@ -322,7 +320,7 @@ struct SourceScope : ObjectImpl<SourceScope, Object, Object::Kind::SourceScope> { - LexicalBlock *scope = nullptr; + Scope *scope = nullptr; InlinedAt *inlinedAt = nullptr; }; @@ -367,6 +365,16 @@ const Scope Scope::Root = CompilationUnit{}; +// find<T>() searches the nested scopes, returning for the first scope that is +// castable to type T. If no scope can be found of type T, then nullptr is +// returned. +template<typename T> +T *find(Scope *scope) +{ + if(auto out = cast<T>(scope)) { return out; } + return scope->parent ? find<T>(scope->parent) : nullptr; +} + } // namespace debug } // anonymous namespace @@ -629,6 +637,10 @@ void SpirvShader::Impl::Debugger::State::createScope(const debug::Scope *spirvScope) { + // TODO(b/151338669): We're creating scopes per-shader invocation. + // This is all really static information, and should only be created + // once *per program*. + ASSERT(spirvScope != nullptr); // TODO: Deal with scope nesting. @@ -653,23 +665,26 @@ if(oldSrcScope == newSrcScope) { return; } srcScope = newSrcScope; - auto lock = debugger->ctx->lock(); - auto thread = lock.currentThread(); - - debug::Function *oldFunction = oldSrcScope ? oldSrcScope->scope->function : nullptr; - debug::Function *newFunction = newSrcScope ? newSrcScope->scope->function : nullptr; - - if(oldFunction != newFunction) + if(debug::cast<debug::LexicalBlock>(srcScope->scope)) { - if(oldFunction) { thread->exit(); } - if(newFunction) { thread->enter(lock, newFunction->source->dbgFile, newFunction->name); } - } + auto lock = debugger->ctx->lock(); + auto thread = lock.currentThread(); - auto dbgScope = getScopes(srcScope->scope); - thread->update([&](vk::dbg::Frame &frame) { - frame.locals = dbgScope.locals; - frame.hovers = dbgScope.hovers; - }); + debug::Function *oldFunction = oldSrcScope ? debug::find<debug::Function>(oldSrcScope->scope) : nullptr; + debug::Function *newFunction = newSrcScope ? debug::find<debug::Function>(newSrcScope->scope) : nullptr; + + if(oldFunction != newFunction) + { + if(oldFunction) { thread->exit(); } + if(newFunction) { thread->enter(lock, newFunction->source->dbgFile, newFunction->name); } + } + + auto dbgScope = getScopes(srcScope->scope); + thread->update([&](vk::dbg::Frame &frame) { + frame.locals = dbgScope.locals; + frame.hovers = dbgScope.hovers; + }); + } } const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::State::getScopes(const debug::Scope *scope) @@ -680,7 +695,9 @@ } auto dbgScopeIt = scopes.find(scope); - ASSERT_MSG(dbgScopeIt != scopes.end(), "createScope() not called for debug::Scope %p", scope); + ASSERT_MSG(dbgScopeIt != scopes.end(), + "createScope() not called for debug::Scope %s %p", + cstr(scope->kind), scope); return dbgScopeIt->second; } @@ -904,14 +921,14 @@ func->source = get(debug::Source::ID(insn.word(7))); func->line = insn.word(8); func->column = insn.word(9); - func->parent = get(debug::LexicalBlock::ID(insn.word(10))); + func->parent = get(debug::Scope::ID(insn.word(10))); func->linkage = shader->getString(insn.word(11)); func->flags = insn.word(12); func->scopeLine = insn.word(13); func->function = Function::ID(insn.word(14)); // declaration: word(13) - func->parent->function = func; + rr::Call(&State::createScope, state->routine->dbgState, func); }); break; case OpenCLDebugInfo100DebugLexicalBlock: @@ -925,15 +942,12 @@ scope->name = shader->getString(insn.word(9)); } - // TODO: We're creating scopes per-shader invocation. - // This is all really static information, and should only be created - // once *per program*. rr::Call(&State::createScope, state->routine->dbgState, scope); }); break; case OpenCLDebugInfo100DebugScope: defineOrEmit(insn, pass, [&](debug::SourceScope *ss) { - ss->scope = get(debug::LexicalBlock::ID(insn.word(5))); + ss->scope = get(debug::Scope::ID(insn.word(5))); if(insn.wordCount() > 6) { ss->inlinedAt = get(debug::InlinedAt::ID(insn.word(6))); @@ -947,7 +961,7 @@ case OpenCLDebugInfo100DebugInlinedAt: defineOrEmit(insn, pass, [&](debug::InlinedAt *ia) { ia->line = insn.word(5); - ia->scope = get(debug::LexicalBlock::ID(insn.word(6))); + ia->scope = get(debug::Scope::ID(insn.word(6))); if(insn.wordCount() > 7) { ia->inlined = get(debug::InlinedAt::ID(insn.word(7)));