Fixup continue support in while loops.
The generators were not setting `emit_continuing_` when emitting while
loops. This caused a crash when a `continue` was encountered. This CL
adds the `emit_continuing_` setup to the while emission. It also guards
the `emit_continuing_` usage with making sure the function is setup.
Bug: tint:1490
Change-Id: Ia89c49e567acda71a1f851a582103723cff71d49
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/93960
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Auto-Submit: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 03ec75c..441b0d4 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -1753,7 +1753,7 @@
}
bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
- if (!emit_continuing_()) {
+ if (!emit_continuing_ || !emit_continuing_()) {
return false;
}
line() << "continue;";
@@ -2534,6 +2534,9 @@
}
}
+ auto emit_continuing = [&]() { return true; };
+ TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
+
// If the whilehas a multi-statement conditional, then we cannot emit this
// as a regular while in GLSL. Instead we need to generate a `while(true)` loop.
bool emit_as_loop = cond_pre.lines.size() > 0;
diff --git a/src/tint/writer/glsl/generator_impl_loop_test.cc b/src/tint/writer/glsl/generator_impl_loop_test.cc
index 5f4d955..ec9219a 100644
--- a/src/tint/writer/glsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/glsl/generator_impl_loop_test.cc
@@ -400,6 +400,25 @@
)");
}
+TEST_F(GlslGeneratorImplTest_Loop, Emit_While_WithContinue) {
+ // while(true) {
+ // continue;
+ // }
+
+ auto* f = While(Expr(true), Block(Continue()));
+ WrapInFunction(f);
+
+ GeneratorImpl& gen = Build();
+
+ gen.increment_indent();
+
+ ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+ EXPECT_EQ(gen.result(), R"( while(true) {
+ continue;
+ }
+)");
+}
+
TEST_F(GlslGeneratorImplTest_Loop, Emit_WhileWithMultiStmtCond) {
// while(true && false) {
// return;
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 39adcf8..b76b9e6 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -2634,7 +2634,7 @@
}
bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
- if (!emit_continuing_()) {
+ if (!emit_continuing_ || !emit_continuing_()) {
return false;
}
line() << "continue;";
@@ -3492,6 +3492,9 @@
}
}
+ auto emit_continuing = [&]() { return true; };
+ TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
+
// If the while has a multi-statement conditional, then we cannot emit this
// as a regular while in HLSL. Instead we need to generate a `while(true)` loop.
bool emit_as_loop = cond_pre.lines.size() > 0;
diff --git a/src/tint/writer/hlsl/generator_impl_loop_test.cc b/src/tint/writer/hlsl/generator_impl_loop_test.cc
index 38ecb9b..29d1822 100644
--- a/src/tint/writer/hlsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_loop_test.cc
@@ -392,6 +392,25 @@
)");
}
+TEST_F(HlslGeneratorImplTest_Loop, Emit_While_WithContinue) {
+ // while(true) {
+ // continue;
+ // }
+
+ auto* f = While(Expr(true), Block(Continue()));
+ WrapInFunction(f);
+
+ GeneratorImpl& gen = Build();
+
+ gen.increment_indent();
+
+ ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+ EXPECT_EQ(gen.result(), R"( [loop] while(true) {
+ continue;
+ }
+)");
+}
+
TEST_F(HlslGeneratorImplTest_Loop, Emit_WhileWithMultiStmtCond) {
// while(true && false) {
// return;
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 4d4c78d..e5ba3a8 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -1521,7 +1521,7 @@
}
bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
- if (!emit_continuing_()) {
+ if (!emit_continuing_ || !emit_continuing_()) {
return false;
}
@@ -2136,6 +2136,9 @@
}
}
+ auto emit_continuing = [&]() { return true; };
+ TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
+
// If the while has a multi-statement conditional, then we cannot emit this
// as a regular while in MSL. Instead we need to generate a `while(true)` loop.
bool emit_as_loop = cond_pre.lines.size() > 0;
diff --git a/src/tint/writer/msl/generator_impl_loop_test.cc b/src/tint/writer/msl/generator_impl_loop_test.cc
index 73d88c0..85f1deb 100644
--- a/src/tint/writer/msl/generator_impl_loop_test.cc
+++ b/src/tint/writer/msl/generator_impl_loop_test.cc
@@ -363,6 +363,25 @@
)");
}
+TEST_F(MslGeneratorImplTest, Emit_While_WithContinue) {
+ // while(true) {
+ // continue;
+ // }
+
+ auto* f = While(Expr(true), Block(Continue()));
+ WrapInFunction(f);
+
+ GeneratorImpl& gen = Build();
+
+ gen.increment_indent();
+
+ ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+ EXPECT_EQ(gen.result(), R"( while(true) {
+ continue;
+ }
+)");
+}
+
TEST_F(MslGeneratorImplTest, Emit_WhileWithMultiCond) {
// while(true && false) {
// return;
diff --git a/src/tint/writer/wgsl/generator_impl_loop_test.cc b/src/tint/writer/wgsl/generator_impl_loop_test.cc
index 99fcdb0..3dbae60 100644
--- a/src/tint/writer/wgsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_loop_test.cc
@@ -217,6 +217,25 @@
)");
}
+TEST_F(WgslGeneratorImplTest, Emit_While_WithContinue) {
+ // while(true) {
+ // continue;
+ // }
+
+ auto* f = While(Expr(true), Block(Continue()));
+ WrapInFunction(f);
+
+ GeneratorImpl& gen = Build();
+
+ gen.increment_indent();
+
+ ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+ EXPECT_EQ(gen.result(), R"( while(true) {
+ continue;
+ }
+)");
+}
+
TEST_F(WgslGeneratorImplTest, Emit_WhileMultiCond) {
// while(true && false) {
// return;