[ir][msl] Emit loops
Add support for the ir loops.
Bug: tint:1967
Change-Id: I8e16293a2948b80d373fd05a94d3f20f941fcc47
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162263
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index d5b3908..4bf5b2f 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -37,16 +37,20 @@
#include "src/tint/lang/core/ir/access.h"
#include "src/tint/lang/core/ir/binary.h"
#include "src/tint/lang/core/ir/bitcast.h"
+#include "src/tint/lang/core/ir/break_if.h"
#include "src/tint/lang/core/ir/constant.h"
#include "src/tint/lang/core/ir/construct.h"
+#include "src/tint/lang/core/ir/continue.h"
#include "src/tint/lang/core/ir/discard.h"
#include "src/tint/lang/core/ir/exit_if.h"
+#include "src/tint/lang/core/ir/exit_loop.h"
#include "src/tint/lang/core/ir/ice.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/let.h"
#include "src/tint/lang/core/ir/load.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
+#include "src/tint/lang/core/ir/next_iteration.h"
#include "src/tint/lang/core/ir/return.h"
#include "src/tint/lang/core/ir/store.h"
#include "src/tint/lang/core/ir/unreachable.h"
@@ -171,6 +175,9 @@
/// Values that can be inlined.
Hashset<core::ir::Value*, 64> can_inline_;
+ /// Block to emit for a continuing
+ std::function<void()> emit_continuing_;
+
/// @returns the name of the templated `tint_array` helper type, generating it if needed
const std::string& ArrayTemplateName() {
if (!array_template_name_.empty()) {
@@ -265,11 +272,16 @@
inst, //
[&](core::ir::ExitIf* e) { EmitExitIf(e); }, //
[&](core::ir::If* if_) { EmitIf(if_); }, //
+ [&](core::ir::Loop* l) { EmitLoop(l); }, //
[&](core::ir::Return* r) { EmitReturn(r); }, //
[&](core::ir::Unreachable*) { EmitUnreachable(); }, //
[&](core::ir::Var* v) { EmitVar(v); }, //
[&](core::ir::Discard*) { EmitDiscard(); }, //
[&](core::ir::Store* s) { EmitStore(s); }, //
+ [&](core::ir::Continue*) { EmitContinue(); }, //
+ [&](core::ir::NextIteration*) { /* do nothing */ }, //
+ [&](core::ir::BreakIf* b) { EmitBreakIf(b); }, //
+ [&](core::ir::ExitLoop*) { EmitExitLoop(); }, //
[&](core::ir::Bitcast*) { MaybeEmitInstruction(inst); }, //
[&](core::ir::Unary*) { MaybeEmitInstruction(inst); }, //
@@ -463,6 +475,51 @@
out << ";";
}
+ void EmitExitLoop() { Line() << "break;"; }
+
+ void EmitBreakIf(core::ir::BreakIf* b) {
+ auto out = Line();
+ out << "if ";
+ EmitValue(out, b->Condition());
+ out << " { break; }";
+ }
+
+ void EmitContinue() {
+ if (emit_continuing_) {
+ emit_continuing_();
+ }
+ Line() << "continue;";
+ }
+
+ void EmitLoop(core::ir::Loop* l) {
+ // Note, we can't just emit the continuing inside a conditional at the top of the loop
+ // because any variable declared in the block must be visible to the continuing.
+ //
+ // loop {
+ // var a = 3;
+ // continue {
+ // let y = a;
+ // }
+ // }
+
+ auto emit_continuing = [&] { EmitBlock(l->Continuing()); };
+ TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
+
+ Line() << "{";
+ {
+ ScopedIndent init(current_buffer_);
+ EmitBlock(l->Initializer());
+
+ Line() << "while(true) {";
+ {
+ ScopedIndent si(current_buffer_);
+ EmitBlock(l->Body());
+ }
+ Line() << "}";
+ }
+ Line() << "}";
+ }
+
/// Emit an if instruction
/// @param if_ the if instruction
void EmitIf(core::ir::If* if_) {
diff --git a/test/tint/loops/loop.wgsl.expected.ir.msl b/test/tint/loops/loop.wgsl.expected.ir.msl
index cdbf128..e696a11 100644
--- a/test/tint/loops/loop.wgsl.expected.ir.msl
+++ b/test/tint/loops/loop.wgsl.expected.ir.msl
@@ -1,9 +1,16 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ {
+ while(true) {
+ i = (i + 1);
+ if ((i > 4)) {
+ return i;
+ }
+ continue;
+ }
+ }
+ /* unreachable */
+}
diff --git a/test/tint/loops/loop_with_break_if.wgsl.expected.ir.msl b/test/tint/loops/loop_with_break_if.wgsl.expected.ir.msl
index cdbf128..118d545 100644
--- a/test/tint/loops/loop_with_break_if.wgsl.expected.ir.msl
+++ b/test/tint/loops/loop_with_break_if.wgsl.expected.ir.msl
@@ -1,9 +1,17 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ {
+ while(true) {
+ if ((i > 4)) {
+ return i;
+ }
+ i = (i + 1);
+ if (i == 4) { break; }
+ continue;
+ }
+ }
+ return i;
+}
diff --git a/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl b/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl
index cdbf128..327c76a 100644
--- a/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl
+++ b/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl
@@ -1,9 +1,16 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ {
+ while(true) {
+ if ((i > 4)) {
+ return i;
+ }
+ i = (i + 1);
+ continue;
+ }
+ }
+ /* unreachable */
+}
diff --git a/test/tint/loops/nested_loops.wgsl.expected.ir.msl b/test/tint/loops/nested_loops.wgsl.expected.ir.msl
index cdbf128..4721280 100644
--- a/test/tint/loops/nested_loops.wgsl.expected.ir.msl
+++ b/test/tint/loops/nested_loops.wgsl.expected.ir.msl
@@ -1,9 +1,26 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ int j = 0;
+ {
+ while(true) {
+ i = (i + 1);
+ if ((i > 4)) {
+ return 1;
+ }
+ {
+ while(true) {
+ j = (j + 1);
+ if ((j > 4)) {
+ return 2;
+ }
+ continue;
+ }
+ }
+ continue;
+ }
+ }
+ /* unreachable */
+}
diff --git a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl
index cdbf128..7fcf68c 100644
--- a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl
+++ b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl
@@ -1,9 +1,26 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ int j = 0;
+ {
+ while(true) {
+ if ((i > 4)) {
+ return 1;
+ }
+ {
+ while(true) {
+ if ((j > 4)) {
+ return 2;
+ }
+ j = (j + 1);
+ continue;
+ }
+ }
+ i = (i + 1);
+ continue;
+ }
+ }
+ /* unreachable */
+}
diff --git a/test/tint/loops/while.wgsl.expected.ir.msl b/test/tint/loops/while.wgsl.expected.ir.msl
index cdbf128..9686db1 100644
--- a/test/tint/loops/while.wgsl.expected.ir.msl
+++ b/test/tint/loops/while.wgsl.expected.ir.msl
@@ -1,9 +1,17 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ {
+ while(true) {
+ if ((i < 4)) {
+ } else {
+ break;
+ }
+ i = (i + 1);
+ continue;
+ }
+ }
+ return i;
+}
diff --git a/test/tint/loops/while_with_continue.wgsl.expected.ir.msl b/test/tint/loops/while_with_continue.wgsl.expected.ir.msl
index cdbf128..9686db1 100644
--- a/test/tint/loops/while_with_continue.wgsl.expected.ir.msl
+++ b/test/tint/loops/while_with_continue.wgsl.expected.ir.msl
@@ -1,9 +1,17 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Loop
-********************************************************************
-* The tint shader compiler has encountered an unexpected error. *
-* *
-* Please help us fix this issue by submitting a bug report at *
-* crbug.com/tint with the source program that triggered the bug. *
-********************************************************************
+int f() {
+ int i = 0;
+ {
+ while(true) {
+ if ((i < 4)) {
+ } else {
+ break;
+ }
+ i = (i + 1);
+ continue;
+ }
+ }
+ return i;
+}