test: Add loop test cases

Bug: tint:833
Bug: tint:914
Change-Id: Ieb34c734ad08c632c8d4e6152d856ec28f35cf85
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/55249
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/test/loops/loop.wgsl b/test/loops/loop.wgsl
new file mode 100644
index 0000000..aaf8ceb
--- /dev/null
+++ b/test/loops/loop.wgsl
@@ -0,0 +1,10 @@
+fn f() -> i32 {
+    var i : i32;
+    loop {
+        i = i + 1;
+        if (i > 4) {
+            return i;
+        }
+    }
+    return 0;
+}
diff --git a/test/loops/loop.wgsl.expected.hlsl b/test/loops/loop.wgsl.expected.hlsl
new file mode 100644
index 0000000..44b45fd
--- /dev/null
+++ b/test/loops/loop.wgsl.expected.hlsl
@@ -0,0 +1,15 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+int f() {
+  int i = 0;
+  while (true) {
+    i = (i + 1);
+    if ((i > 4)) {
+      return i;
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/loop.wgsl.expected.msl b/test/loops/loop.wgsl.expected.msl
new file mode 100644
index 0000000..9772ce4
--- /dev/null
+++ b/test/loops/loop.wgsl.expected.msl
@@ -0,0 +1,14 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int f() {
+  int i = 0;
+  while (true) {
+    i = (i + 1);
+    if ((i > 4)) {
+      return i;
+    }
+  }
+  return 0;
+}
+
diff --git a/test/loops/loop.wgsl.expected.spvasm b/test/loops/loop.wgsl.expected.spvasm
new file mode 100644
index 0000000..a0044b5
--- /dev/null
+++ b/test/loops/loop.wgsl.expected.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %i "i"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+          %5 = OpTypeFunction %int
+%_ptr_Function_int = OpTypePointer Function %int
+         %11 = OpConstantNull %int
+      %int_1 = OpConstant %int 1
+      %int_4 = OpConstant %int 4
+       %bool = OpTypeBool
+      %int_0 = OpConstant %int 0
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %int None %5
+          %8 = OpLabel
+          %i = OpVariable %_ptr_Function_int Function %11
+               OpBranch %12
+         %12 = OpLabel
+               OpLoopMerge %13 %14 None
+               OpBranch %15
+         %15 = OpLabel
+         %16 = OpLoad %int %i
+         %18 = OpIAdd %int %16 %int_1
+               OpStore %i %18
+         %19 = OpLoad %int %i
+         %21 = OpSGreaterThan %bool %19 %int_4
+               OpSelectionMerge %23 None
+               OpBranchConditional %21 %24 %23
+         %24 = OpLabel
+         %25 = OpLoad %int %i
+               OpReturnValue %25
+         %23 = OpLabel
+               OpBranch %14
+         %14 = OpLabel
+               OpBranch %12
+         %13 = OpLabel
+               OpReturnValue %int_0
+               OpFunctionEnd
diff --git a/test/loops/loop.wgsl.expected.wgsl b/test/loops/loop.wgsl.expected.wgsl
new file mode 100644
index 0000000..783314f
--- /dev/null
+++ b/test/loops/loop.wgsl.expected.wgsl
@@ -0,0 +1,10 @@
+fn f() -> i32 {
+  var i : i32;
+  loop {
+    i = (i + 1);
+    if ((i > 4)) {
+      return i;
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/loop_with_continuing.wgsl b/test/loops/loop_with_continuing.wgsl
new file mode 100644
index 0000000..a406853
--- /dev/null
+++ b/test/loops/loop_with_continuing.wgsl
@@ -0,0 +1,12 @@
+fn f() -> i32 {
+    var i : i32;
+    loop {
+        if (i > 4) {
+            return i;
+        }
+        continuing {
+            i = i + 1;
+        }
+    }
+    return 0;
+}
diff --git a/test/loops/loop_with_continuing.wgsl.expected.hlsl b/test/loops/loop_with_continuing.wgsl.expected.hlsl
new file mode 100644
index 0000000..0d57d1f
--- /dev/null
+++ b/test/loops/loop_with_continuing.wgsl.expected.hlsl
@@ -0,0 +1,17 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+int f() {
+  int i = 0;
+  while (true) {
+    if ((i > 4)) {
+      return i;
+    }
+    {
+      i = (i + 1);
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/loop_with_continuing.wgsl.expected.msl b/test/loops/loop_with_continuing.wgsl.expected.msl
new file mode 100644
index 0000000..fc31429
--- /dev/null
+++ b/test/loops/loop_with_continuing.wgsl.expected.msl
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int f() {
+  int i = 0;
+  while (true) {
+    if ((i > 4)) {
+      return i;
+    }
+    {
+      i = (i + 1);
+    }
+  }
+  return 0;
+}
+
diff --git a/test/loops/loop_with_continuing.wgsl.expected.spvasm b/test/loops/loop_with_continuing.wgsl.expected.spvasm
new file mode 100644
index 0000000..2bc00b4
--- /dev/null
+++ b/test/loops/loop_with_continuing.wgsl.expected.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %i "i"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+          %5 = OpTypeFunction %int
+%_ptr_Function_int = OpTypePointer Function %int
+         %11 = OpConstantNull %int
+      %int_4 = OpConstant %int 4
+       %bool = OpTypeBool
+      %int_1 = OpConstant %int 1
+      %int_0 = OpConstant %int 0
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %int None %5
+          %8 = OpLabel
+          %i = OpVariable %_ptr_Function_int Function %11
+               OpBranch %12
+         %12 = OpLabel
+               OpLoopMerge %13 %14 None
+               OpBranch %15
+         %15 = OpLabel
+         %16 = OpLoad %int %i
+         %18 = OpSGreaterThan %bool %16 %int_4
+               OpSelectionMerge %20 None
+               OpBranchConditional %18 %21 %20
+         %21 = OpLabel
+         %22 = OpLoad %int %i
+               OpReturnValue %22
+         %20 = OpLabel
+               OpBranch %14
+         %14 = OpLabel
+         %23 = OpLoad %int %i
+         %25 = OpIAdd %int %23 %int_1
+               OpStore %i %25
+               OpBranch %12
+         %13 = OpLabel
+               OpReturnValue %int_0
+               OpFunctionEnd
diff --git a/test/loops/loop_with_continuing.wgsl.expected.wgsl b/test/loops/loop_with_continuing.wgsl.expected.wgsl
new file mode 100644
index 0000000..eba6d8f
--- /dev/null
+++ b/test/loops/loop_with_continuing.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+fn f() -> i32 {
+  var i : i32;
+  loop {
+    if ((i > 4)) {
+      return i;
+    }
+
+    continuing {
+      i = (i + 1);
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/nested_loops.wgsl b/test/loops/nested_loops.wgsl
new file mode 100644
index 0000000..3b8f6dd
--- /dev/null
+++ b/test/loops/nested_loops.wgsl
@@ -0,0 +1,17 @@
+fn f() -> i32 {
+    var i : i32;
+    var j : i32;
+    loop {
+        i = i + 1;
+        if (i > 4) {
+            return 1;
+        }
+        loop {
+            j = j + 1;
+            if (j > 4) {
+                return 2;
+            }
+        }
+    }
+    return 0;
+}
diff --git a/test/loops/nested_loops.wgsl.expected.hlsl b/test/loops/nested_loops.wgsl.expected.hlsl
new file mode 100644
index 0000000..793339e
--- /dev/null
+++ b/test/loops/nested_loops.wgsl.expected.hlsl
@@ -0,0 +1,22 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+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;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/nested_loops.wgsl.expected.msl b/test/loops/nested_loops.wgsl.expected.msl
new file mode 100644
index 0000000..e813828
--- /dev/null
+++ b/test/loops/nested_loops.wgsl.expected.msl
@@ -0,0 +1,21 @@
+#include <metal_stdlib>
+
+using namespace metal;
+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;
+      }
+    }
+  }
+  return 0;
+}
+
diff --git a/test/loops/nested_loops.wgsl.expected.spvasm b/test/loops/nested_loops.wgsl.expected.spvasm
new file mode 100644
index 0000000..b978879
--- /dev/null
+++ b/test/loops/nested_loops.wgsl.expected.spvasm
@@ -0,0 +1,72 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 38
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %i "i"
+               OpName %j "j"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+          %5 = OpTypeFunction %int
+%_ptr_Function_int = OpTypePointer Function %int
+         %11 = OpConstantNull %int
+      %int_1 = OpConstant %int 1
+      %int_4 = OpConstant %int 4
+       %bool = OpTypeBool
+      %int_2 = OpConstant %int 2
+      %int_0 = OpConstant %int 0
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %int None %5
+          %8 = OpLabel
+          %i = OpVariable %_ptr_Function_int Function %11
+          %j = OpVariable %_ptr_Function_int Function %11
+               OpBranch %13
+         %13 = OpLabel
+               OpLoopMerge %14 %15 None
+               OpBranch %16
+         %16 = OpLabel
+         %17 = OpLoad %int %i
+         %19 = OpIAdd %int %17 %int_1
+               OpStore %i %19
+         %20 = OpLoad %int %i
+         %22 = OpSGreaterThan %bool %20 %int_4
+               OpSelectionMerge %24 None
+               OpBranchConditional %22 %25 %24
+         %25 = OpLabel
+               OpReturnValue %int_1
+         %24 = OpLabel
+               OpBranch %26
+         %26 = OpLabel
+               OpLoopMerge %27 %28 None
+               OpBranch %29
+         %29 = OpLabel
+         %30 = OpLoad %int %j
+         %31 = OpIAdd %int %30 %int_1
+               OpStore %j %31
+         %32 = OpLoad %int %j
+         %33 = OpSGreaterThan %bool %32 %int_4
+               OpSelectionMerge %34 None
+               OpBranchConditional %33 %35 %34
+         %35 = OpLabel
+               OpReturnValue %int_2
+         %34 = OpLabel
+               OpBranch %28
+         %28 = OpLabel
+               OpBranch %26
+         %27 = OpLabel
+               OpBranch %15
+         %15 = OpLabel
+               OpBranch %13
+         %14 = OpLabel
+               OpReturnValue %int_0
+               OpFunctionEnd
diff --git a/test/loops/nested_loops.wgsl.expected.wgsl b/test/loops/nested_loops.wgsl.expected.wgsl
new file mode 100644
index 0000000..048cd04
--- /dev/null
+++ b/test/loops/nested_loops.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+fn f() -> i32 {
+  var i : i32;
+  var j : i32;
+  loop {
+    i = (i + 1);
+    if ((i > 4)) {
+      return 1;
+    }
+    loop {
+      j = (j + 1);
+      if ((j > 4)) {
+        return 2;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/nested_loops_with_continuing.wgsl b/test/loops/nested_loops_with_continuing.wgsl
new file mode 100644
index 0000000..d1e3db6
--- /dev/null
+++ b/test/loops/nested_loops_with_continuing.wgsl
@@ -0,0 +1,21 @@
+fn f() -> i32 {
+    var i : i32;
+    var j : i32;
+    loop {
+        if (i > 4) {
+            return 1;
+        }
+        loop {
+            if (j > 4) {
+                return 2;
+            }
+            continuing {
+                j = j + 1;
+            }
+        }
+        continuing {
+            i = i + 1;
+        }
+    }
+    return 0;
+}
diff --git a/test/loops/nested_loops_with_continuing.wgsl.expected.hlsl b/test/loops/nested_loops_with_continuing.wgsl.expected.hlsl
new file mode 100644
index 0000000..9ccdf02
--- /dev/null
+++ b/test/loops/nested_loops_with_continuing.wgsl.expected.hlsl
@@ -0,0 +1,26 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+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);
+      }
+    }
+    {
+      i = (i + 1);
+    }
+  }
+  return 0;
+}
diff --git a/test/loops/nested_loops_with_continuing.wgsl.expected.msl b/test/loops/nested_loops_with_continuing.wgsl.expected.msl
new file mode 100644
index 0000000..8c9f8fd
--- /dev/null
+++ b/test/loops/nested_loops_with_continuing.wgsl.expected.msl
@@ -0,0 +1,25 @@
+#include <metal_stdlib>
+
+using namespace metal;
+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);
+      }
+    }
+    {
+      i = (i + 1);
+    }
+  }
+  return 0;
+}
+
diff --git a/test/loops/nested_loops_with_continuing.wgsl.expected.spvasm b/test/loops/nested_loops_with_continuing.wgsl.expected.spvasm
new file mode 100644
index 0000000..633b73c
--- /dev/null
+++ b/test/loops/nested_loops_with_continuing.wgsl.expected.spvasm
@@ -0,0 +1,72 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 38
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %i "i"
+               OpName %j "j"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+          %5 = OpTypeFunction %int
+%_ptr_Function_int = OpTypePointer Function %int
+         %11 = OpConstantNull %int
+      %int_4 = OpConstant %int 4
+       %bool = OpTypeBool
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+      %int_0 = OpConstant %int 0
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %int None %5
+          %8 = OpLabel
+          %i = OpVariable %_ptr_Function_int Function %11
+          %j = OpVariable %_ptr_Function_int Function %11
+               OpBranch %13
+         %13 = OpLabel
+               OpLoopMerge %14 %15 None
+               OpBranch %16
+         %16 = OpLabel
+         %17 = OpLoad %int %i
+         %19 = OpSGreaterThan %bool %17 %int_4
+               OpSelectionMerge %21 None
+               OpBranchConditional %19 %22 %21
+         %22 = OpLabel
+               OpReturnValue %int_1
+         %21 = OpLabel
+               OpBranch %24
+         %24 = OpLabel
+               OpLoopMerge %25 %26 None
+               OpBranch %27
+         %27 = OpLabel
+         %28 = OpLoad %int %j
+         %29 = OpSGreaterThan %bool %28 %int_4
+               OpSelectionMerge %30 None
+               OpBranchConditional %29 %31 %30
+         %31 = OpLabel
+               OpReturnValue %int_2
+         %30 = OpLabel
+               OpBranch %26
+         %26 = OpLabel
+         %33 = OpLoad %int %j
+         %34 = OpIAdd %int %33 %int_1
+               OpStore %j %34
+               OpBranch %24
+         %25 = OpLabel
+               OpBranch %15
+         %15 = OpLabel
+         %35 = OpLoad %int %i
+         %36 = OpIAdd %int %35 %int_1
+               OpStore %i %36
+               OpBranch %13
+         %14 = OpLabel
+               OpReturnValue %int_0
+               OpFunctionEnd
diff --git a/test/loops/nested_loops_with_continuing.wgsl.expected.wgsl b/test/loops/nested_loops_with_continuing.wgsl.expected.wgsl
new file mode 100644
index 0000000..469e4c1
--- /dev/null
+++ b/test/loops/nested_loops_with_continuing.wgsl.expected.wgsl
@@ -0,0 +1,23 @@
+fn f() -> i32 {
+  var i : i32;
+  var j : i32;
+  loop {
+    if ((i > 4)) {
+      return 1;
+    }
+    loop {
+      if ((j > 4)) {
+        return 2;
+      }
+
+      continuing {
+        j = (j + 1);
+      }
+    }
+
+    continuing {
+      i = (i + 1);
+    }
+  }
+  return 0;
+}