Add while statement parsing.
This CL adds parsing for the WGSL `while` statement.
Bug: tint:1425
Change-Id: Ibce5e28568935ca4f51b5ac33e7a60af7a916b4a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/93540
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index a9e290c..39adcf8 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -3481,6 +3481,53 @@
return true;
}
+bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
+ TextBuffer cond_pre;
+ std::stringstream cond_buf;
+ {
+ auto* cond = stmt->condition;
+ TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
+ if (!EmitExpression(cond_buf, cond)) {
+ return false;
+ }
+ }
+
+ // 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;
+ if (emit_as_loop) {
+ line() << LoopAttribute() << "while (true) {";
+ increment_indent();
+ TINT_DEFER({
+ decrement_indent();
+ line() << "}";
+ });
+
+ current_buffer_->Append(cond_pre);
+ line() << "if (!(" << cond_buf.str() << ")) { break; }";
+ if (!EmitStatements(stmt->body->statements)) {
+ return false;
+ }
+ } else {
+ // While can be generated.
+ {
+ auto out = line();
+ out << LoopAttribute() << "while";
+ {
+ ScopedParen sp(out);
+ out << cond_buf.str();
+ }
+ out << " {";
+ }
+ if (!EmitStatementsWithIndent(stmt->body->statements)) {
+ return false;
+ }
+ line() << "}";
+ }
+
+ return true;
+}
+
bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
const ast::MemberAccessorExpression* expr) {
if (!EmitExpression(out, expr->structure)) {
@@ -3551,6 +3598,9 @@
[&](const ast::ForLoopStatement* l) { //
return EmitForLoop(l);
},
+ [&](const ast::WhileStatement* l) { //
+ return EmitWhile(l);
+ },
[&](const ast::ReturnStatement* r) { //
return EmitReturn(r);
},