diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc index c96bda2b8c..7b9e25a986 100644 --- a/src/tint/lang/core/ir/validator.cc +++ b/src/tint/lang/core/ir/validator.cc @@ -1250,6 +1250,10 @@ class Validator { /// @param inst the instruction /// @returns the function const ir::Function* ContainingFunction(const ir::Instruction* inst) { + if (inst->Block() == mod_.root_block) { + return nullptr; + } + return block_to_function_.GetOrAdd(inst->Block(), [&] { // return ContainingFunction(inst->Block()->Parent()); }); @@ -1259,6 +1263,10 @@ class Validator { /// @param f the function /// @returns all end points that call the function Hashset ContainingEndPoints(const ir::Function* f) { + if (!f) { + return {}; + } + Hashset result{}; Hashset visited{f}; @@ -1266,6 +1274,10 @@ class Validator { while (!call_sites.IsEmpty()) { auto call_site = call_sites.Pop(); auto calling_function = ContainingFunction(call_site); + if (!calling_function) { + continue; + } + if (visited.Contains(calling_function)) { continue; } @@ -1336,8 +1348,13 @@ Disassembler& Validator::Disassemble() { Result Validator::Run() { RunStructuralSoundnessChecks(); - CheckForOrphanedInstructions(); - CheckForNonFragmentDiscards(); + if (!diagnostics_.ContainsErrors()) { + CheckForOrphanedInstructions(); + } + + if (!diagnostics_.ContainsErrors()) { + CheckForNonFragmentDiscards(); + } if (diagnostics_.ContainsErrors()) { diagnostics_.AddNote(Source{}) << "# Disassembly\n" << Disassemble().Text(); @@ -1861,6 +1878,9 @@ void Validator::CheckRootBlock(const Block* blk) { AddError(inst) << "root block: invalid instruction: " << inst->TypeInfo().name; } }, + [&](const core::ir::Discard* d) { + AddError(d) << "root block: invalid instruction: " << d->TypeInfo().name; + }, [&](Default) { // Note, this validation is looser then it could be. There are only certain // expressions and builtins which can be used in an override. We can tighten this up diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc index 5e4dc7b8f2..1381505392 100644 --- a/src/tint/lang/core/ir/validator_test.cc +++ b/src/tint/lang/core/ir/validator_test.cc @@ -3849,6 +3849,29 @@ note: # Disassembly )"); } +TEST_F(IR_ValidatorTest, Discard_OutsideFunction) { + auto* d = b.Discard(); + mod.root_block->Append(d); + + auto res = ir::Validate(mod); + ASSERT_NE(res, Success); + EXPECT_EQ(res.Failure().reason.Str(), + R"(:2:3 error: discard: root block: invalid instruction: tint::core::ir::Discard + discard + ^^^^^^^ + +:1:1 note: in block +$B1: { # root +^^^ + +note: # Disassembly +$B1: { # root + discard +} + +)"); +} + TEST_F(IR_ValidatorTest, Terminator_HasResult) { auto* ret_func = b.Function("ret_func", ty.void_()); b.Append(ret_func->Block(), [&] {