From 70d48ee2ec9e1f75507bf5821ed7132c50fbd071 Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Sat, 2 Nov 2024 01:35:44 +0000 Subject: [PATCH] [ir] Add source information to the IR. This CL adds a value to source map to the IR module and populates it during the program to IR translation. Change-Id: If0a9a32c4ff52580cf539b7c9b3da2314d8cb374 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/213174 Commit-Queue: dan sinclair Reviewed-by: James Price --- src/tint/lang/core/ir/module.cc | 20 +++++++++++++++++ src/tint/lang/core/ir/module.h | 22 +++++++++++++++++++ src/tint/lang/core/ir/value.h | 1 + .../reader/program_to_ir/program_to_ir.cc | 14 ++++++------ .../program_to_ir/program_to_ir_test.cc | 12 +++++----- 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/tint/lang/core/ir/module.cc b/src/tint/lang/core/ir/module.cc index 31e7363ce3c..58bece32323 100644 --- a/src/tint/lang/core/ir/module.cc +++ b/src/tint/lang/core/ir/module.cc @@ -150,6 +150,26 @@ void Module::ClearName(Value* value) { value_to_name_.Remove(value); } +void Module::SetSource(Instruction* inst, Source src) { + TINT_ASSERT(inst->Results().Length() == 1); + SetSource(inst->Result(0), src); +} + +void Module::SetSource(Value* value, Source src) { + value_to_source_.Replace(value, src); +} + +Source Module::SourceOf(const Instruction* inst) const { + if (inst->Results().Length() != 1) { + return Source{}; + } + return SourceOf(inst->Result(0)); +} + +Source Module::SourceOf(const Value* value) const { + return value_to_source_.GetOr(value, Source{}); +} + Vector Module::DependencyOrderedFunctions() { return FunctionSorter::SortFunctions(*this); } diff --git a/src/tint/lang/core/ir/module.h b/src/tint/lang/core/ir/module.h index c77cc365646..5ef2b7f0be2 100644 --- a/src/tint/lang/core/ir/module.h +++ b/src/tint/lang/core/ir/module.h @@ -58,6 +58,9 @@ class Module { /// Map of value to name Hashmap value_to_name_; + // The source information for a value + Hashmap value_to_source_; + /// A predicate function that returns true if the instruction or value is alive. struct IsAlive { bool operator()(const Instruction* instruction) const { return instruction->Alive(); } @@ -123,6 +126,25 @@ class Module { /// @param value the value to remove the name from void ClearName(Value* value); + /// @param inst the instruction to set the source of + /// @param src the source + /// @note requires the instruction be a single result instruction. + void SetSource(Instruction* inst, Source src); + + /// @param value the value to set the source + /// @param src the source + void SetSource(Value* value, Source src); + + /// @param inst the instruction + /// @return the source of the given instruction, or an empty source if the instruction does not + /// have a source or does not have a single return value. + Source SourceOf(const Instruction* inst) const; + + /// @param value the value + /// @return the source of the given value, or an empty source if the value does not have a + /// source. + Source SourceOf(const Value* value) const; + /// @return the type manager for the module core::type::Manager& Types() { return constant_values.types; } diff --git a/src/tint/lang/core/ir/value.h b/src/tint/lang/core/ir/value.h index f1b3f50787b..c2475b6aee6 100644 --- a/src/tint/lang/core/ir/value.h +++ b/src/tint/lang/core/ir/value.h @@ -158,6 +158,7 @@ class Value : public Castable { /// Bitset of value flags tint::EnumSet flags_; }; + } // namespace tint::core::ir #endif // SRC_TINT_LANG_CORE_IR_VALUE_H_ diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc index 673889e696b..66ae2d49481 100644 --- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc +++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc @@ -267,7 +267,6 @@ class Impl { auto* ir_func = builder_.Function(ast_func->name->symbol.NameView(), sem->ReturnType()->Clone(clone_ctx_.type_ctx)); current_function_ = ir_func; - scopes_.Set(ast_func->name->symbol, ir_func); if (ast_func->IsEntryPoint()) { @@ -718,10 +717,7 @@ class Impl { // the code has to continue as before it just predicates writes. If WGSL grows some kind of // terminating discard that would probably make sense as a Block but would then require // figuring out the multi-level exit that is triggered. - void EmitDiscard(const ast::DiscardStatement*) { - auto* inst = builder_.Discard(); - current_block_->Append(inst); - } + void EmitDiscard(const ast::DiscardStatement*) { current_block_->Append(builder_.Discard()); } void EmitBreakIf(const ast::BreakIfStatement* stmt) { auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch); @@ -1162,6 +1158,7 @@ class Impl { core::ir::Value* EmitValueExpression(const ast::Expression* root) { auto res = EmitExpression(root); if (auto** val = std::get_if(&res)) { + builder_.ir.SetSource(*val, root->source); return *val; } TINT_ICE() << "expression did not resolve to a value"; @@ -1204,8 +1201,9 @@ class Impl { // Store the declaration so we can get the instruction to store too scopes_.Set(v->name->symbol, val->Result(0)); - // Record the original name of the var + // Record the original name and source of the var builder_.ir.SetName(val, v->name->symbol.Name()); + builder_.ir.SetSource(val, v->source); }, [&](const ast::Let* l) { auto init = EmitValueExpression(l->initializer); @@ -1217,6 +1215,7 @@ class Impl { // Store the results of the initialization scopes_.Set(l->name->symbol, let->Result(0)); + builder_.ir.SetSource(let, l->source); }, [&](const ast::Override* o) { auto* o_sem = program_.Sem().Get(o); @@ -1238,8 +1237,9 @@ class Impl { // Store the declaration so we can get the instruction to store too scopes_.Set(o->name->symbol, override->Result(0)); - // Record the original name of the var + // Record the original name and source of the var builder_.ir.SetName(override, o->name->symbol.Name()); + builder_.ir.SetSource(override, o->source); }, [&](const ast::Const*) { // Skip. This should be handled by const-eval already, so the const will be a diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc index 57457f5008b..60722d799f5 100644 --- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc +++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc @@ -78,7 +78,6 @@ TEST_F(IR_FromProgramTest, Func) { core::ir::Function* f = m->functions[0]; ASSERT_NE(f->Block(), nullptr); - EXPECT_EQ(m->functions[0]->Stage(), core::ir::Function::PipelineStage::kUndefined); EXPECT_EQ(core::ir::Disassembler(m.Get()).Plain(), R"(%f = func():void { @@ -1181,16 +1180,19 @@ TEST_F(IR_FromProgramTest, BugChromium324466107) { } TEST_F(IR_FromProgramTest, OverrideNoInitializer) { - Override("a", ty.i32()); + Override(Source{{1, 2}}, "a", ty.i32()); auto res = Build(); ASSERT_EQ(res, Success); auto m = res.Move(); - auto* overide = FindSingleInstruction(m); + auto* override = FindSingleInstruction(m); + + ASSERT_NE(override, nullptr); + ASSERT_EQ(override->Initializer(), nullptr); - ASSERT_NE(overide, nullptr); - ASSERT_EQ(overide->Initializer(), nullptr); + Source::Location loc{1u, 2u}; + EXPECT_EQ(m.SourceOf(override).range.begin, loc); EXPECT_EQ(core::ir::Disassembler(m).Plain(), R"($B1: { # root %a:i32 = override @id(0)