[ir] Emit `continue` statements when converting to a Program.
In `IRToProgram` the `continue` statements were never emitted. There
happened to be no tests which required continues to be emitted to be
correct. Add a test case which requires the continues and emit as
needed.
Change-Id: If67ca5c6b7fe8e5d8ccd76c1494137eb9ba13aef
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/243575
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index afe718d..a829ee7 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -73,7 +73,6 @@
result.err = ir_module.Failure().reason;
return result;
}
-
result.ir_pre_raise = core::ir::Disassembler(ir_module.Get()).Plain();
if (auto res = tint::wgsl::writer::Raise(ir_module.Get()); res != Success) {
@@ -2771,6 +2770,44 @@
)");
}
+TEST_F(IRToProgramRoundtripTest, Loop_WithRequiredContinues) {
+ RUN_TEST(R"(
+var<private> v : u32;
+
+var<private> v_1 : bool;
+
+var<private> v_2 : bool;
+
+fn f() {
+ let v_3 = v_1;
+ let v_4 = v_2;
+ loop {
+ var v_5 : u32;
+ if (v_3) {
+ break;
+ } else {
+ if (v_4) {
+ v_5 = 0u;
+ continue;
+ } else {
+ v_5 = 1u;
+ }
+ if (true) {
+ v_5 = 2u;
+ continue;
+ }
+ v_5 = 3u;
+ continue;
+ }
+
+ continuing {
+ v = v_5;
+ }
+ }
+}
+)");
+}
+
////////////////////////////////////////////////////////////////////////////////
// While
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index a0e8015..a941f19 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -367,7 +367,7 @@
[&](const core::ir::Binary* i) { Binary(i); }, //
[&](const core::ir::BreakIf* i) { BreakIf(i); }, //
[&](const core::ir::Call* i) { Call(i); }, //
- [&](const core::ir::Continue*) {}, //
+ [&](const core::ir::Continue* c) { EmitContinue(c); }, //
[&](const core::ir::ExitIf*) {}, //
[&](const core::ir::ExitLoop* i) { ExitLoop(i); }, //
[&](const core::ir::ExitSwitch* i) { ExitSwitch(i); }, //
@@ -548,6 +548,15 @@
Append(b.Break());
}
+ void EmitContinue(const core::ir::Continue* c) {
+ auto* loop = c->Loop();
+ // No need to emit the continue as the last statement in loop as it's implicit
+ if (loop->Body()->Terminator() == c) {
+ return;
+ }
+ Append(b.Continue());
+ }
+
void ExitLoop(const core::ir::ExitLoop*) { Append(b.Break()); }
void BreakIf(const core::ir::BreakIf* i) { Append(b.BreakIf(Expr(i->Condition()))); }