Commit b2d7dfff by Ben Clayton

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/+/42248Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 2fecfc5b
...@@ -205,10 +205,12 @@ struct Scope : public Object ...@@ -205,10 +205,12 @@ struct Scope : public Object
static constexpr bool kindof(Kind kind) static constexpr bool kindof(Kind kind)
{ {
return kind == Kind::CompilationUnit || return kind == Kind::CompilationUnit ||
kind == Kind::Function ||
kind == Kind::LexicalBlock; kind == Kind::LexicalBlock;
} }
struct Source *source = nullptr; struct Source *source = nullptr;
Scope *parent = nullptr;
}; };
struct Type : public Object struct Type : public Object
...@@ -290,14 +292,12 @@ struct Member : ObjectImpl<Member, Object, Object::Kind::Member> ...@@ -290,14 +292,12 @@ struct Member : ObjectImpl<Member, Object, Object::Kind::Member>
uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags 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; std::string name;
FunctionType *type = nullptr; FunctionType *type = nullptr;
Source *source = nullptr;
uint32_t line = 0; uint32_t line = 0;
uint32_t column = 0; uint32_t column = 0;
struct LexicalBlock *parent = nullptr;
std::string linkage; std::string linkage;
uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
uint32_t scopeLine = 0; uint32_t scopeLine = 0;
...@@ -308,9 +308,7 @@ struct LexicalBlock : ObjectImpl<LexicalBlock, Scope, Object::Kind::LexicalBlock ...@@ -308,9 +308,7 @@ struct LexicalBlock : ObjectImpl<LexicalBlock, Scope, Object::Kind::LexicalBlock
{ {
uint32_t line = 0; uint32_t line = 0;
uint32_t column = 0; uint32_t column = 0;
Scope *parent = nullptr;
std::string name; std::string name;
Function *function = nullptr;
}; };
struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt> struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt>
...@@ -322,7 +320,7 @@ struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt> ...@@ -322,7 +320,7 @@ struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt>
struct SourceScope : ObjectImpl<SourceScope, Object, Object::Kind::SourceScope> struct SourceScope : ObjectImpl<SourceScope, Object, Object::Kind::SourceScope>
{ {
LexicalBlock *scope = nullptr; Scope *scope = nullptr;
InlinedAt *inlinedAt = nullptr; InlinedAt *inlinedAt = nullptr;
}; };
...@@ -367,6 +365,16 @@ struct Value : ObjectImpl<Value, Object, Object::Kind::Value> ...@@ -367,6 +365,16 @@ struct Value : ObjectImpl<Value, Object, Object::Kind::Value>
const Scope Scope::Root = CompilationUnit{}; 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 } // namespace debug
} // anonymous namespace } // anonymous namespace
...@@ -629,6 +637,10 @@ void SpirvShader::Impl::Debugger::State::putRef(vk::dbg::VariableContainer *vc, ...@@ -629,6 +637,10 @@ void SpirvShader::Impl::Debugger::State::putRef(vk::dbg::VariableContainer *vc,
void SpirvShader::Impl::Debugger::State::createScope(const debug::Scope *spirvScope) 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); ASSERT(spirvScope != nullptr);
// TODO: Deal with scope nesting. // TODO: Deal with scope nesting.
...@@ -653,23 +665,26 @@ void SpirvShader::Impl::Debugger::State::setScope(debug::SourceScope *newSrcScop ...@@ -653,23 +665,26 @@ void SpirvShader::Impl::Debugger::State::setScope(debug::SourceScope *newSrcScop
if(oldSrcScope == newSrcScope) { return; } if(oldSrcScope == newSrcScope) { return; }
srcScope = newSrcScope; srcScope = newSrcScope;
auto lock = debugger->ctx->lock(); if(debug::cast<debug::LexicalBlock>(srcScope->scope))
auto thread = lock.currentThread(); {
auto lock = debugger->ctx->lock();
auto thread = lock.currentThread();
debug::Function *oldFunction = oldSrcScope ? oldSrcScope->scope->function : nullptr; debug::Function *oldFunction = oldSrcScope ? debug::find<debug::Function>(oldSrcScope->scope) : nullptr;
debug::Function *newFunction = newSrcScope ? newSrcScope->scope->function : nullptr; debug::Function *newFunction = newSrcScope ? debug::find<debug::Function>(newSrcScope->scope) : nullptr;
if(oldFunction != newFunction) if(oldFunction != newFunction)
{ {
if(oldFunction) { thread->exit(); } if(oldFunction) { thread->exit(); }
if(newFunction) { thread->enter(lock, newFunction->source->dbgFile, newFunction->name); } if(newFunction) { thread->enter(lock, newFunction->source->dbgFile, newFunction->name); }
} }
auto dbgScope = getScopes(srcScope->scope); auto dbgScope = getScopes(srcScope->scope);
thread->update([&](vk::dbg::Frame &frame) { thread->update([&](vk::dbg::Frame &frame) {
frame.locals = dbgScope.locals; frame.locals = dbgScope.locals;
frame.hovers = dbgScope.hovers; frame.hovers = dbgScope.hovers;
}); });
}
} }
const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::State::getScopes(const debug::Scope *scope) const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::State::getScopes(const debug::Scope *scope)
...@@ -680,7 +695,9 @@ const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::S ...@@ -680,7 +695,9 @@ const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::S
} }
auto dbgScopeIt = scopes.find(scope); 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; return dbgScopeIt->second;
} }
...@@ -904,14 +921,14 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI ...@@ -904,14 +921,14 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI
func->source = get(debug::Source::ID(insn.word(7))); func->source = get(debug::Source::ID(insn.word(7)));
func->line = insn.word(8); func->line = insn.word(8);
func->column = insn.word(9); 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->linkage = shader->getString(insn.word(11));
func->flags = insn.word(12); func->flags = insn.word(12);
func->scopeLine = insn.word(13); func->scopeLine = insn.word(13);
func->function = Function::ID(insn.word(14)); func->function = Function::ID(insn.word(14));
// declaration: word(13) // declaration: word(13)
func->parent->function = func; rr::Call(&State::createScope, state->routine->dbgState, func);
}); });
break; break;
case OpenCLDebugInfo100DebugLexicalBlock: case OpenCLDebugInfo100DebugLexicalBlock:
...@@ -925,15 +942,12 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI ...@@ -925,15 +942,12 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI
scope->name = shader->getString(insn.word(9)); 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); rr::Call(&State::createScope, state->routine->dbgState, scope);
}); });
break; break;
case OpenCLDebugInfo100DebugScope: case OpenCLDebugInfo100DebugScope:
defineOrEmit(insn, pass, [&](debug::SourceScope *ss) { 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) if(insn.wordCount() > 6)
{ {
ss->inlinedAt = get(debug::InlinedAt::ID(insn.word(6))); ss->inlinedAt = get(debug::InlinedAt::ID(insn.word(6)));
...@@ -947,7 +961,7 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI ...@@ -947,7 +961,7 @@ void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnI
case OpenCLDebugInfo100DebugInlinedAt: case OpenCLDebugInfo100DebugInlinedAt:
defineOrEmit(insn, pass, [&](debug::InlinedAt *ia) { defineOrEmit(insn, pass, [&](debug::InlinedAt *ia) {
ia->line = insn.word(5); 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) if(insn.wordCount() > 7)
{ {
ia->inlined = get(debug::InlinedAt::ID(insn.word(7))); ia->inlined = get(debug::InlinedAt::ID(insn.word(7)));
......
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