[ir][validation] Add control instruction note to errors

For the exit errors where the args or results don't match this CL adds
the control instruction as a note on the diagnostic.

Bug: tint:1952
Change-Id: I4011d455feccc409ad7e76681e935608c2460253
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/141000
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/ir/validate.cc b/src/tint/ir/validate.cc
index 9dd044a..91a4a55 100644
--- a/src/tint/ir/validate.cc
+++ b/src/tint/ir/validate.cc
@@ -480,17 +480,18 @@
             return;
         }
 
+        if (control_stack_.IsEmpty()) {
+            AddError(e, "exit: found outside all control instructions");
+            return;
+        }
+
         auto results = e->ControlInstruction()->Results();
         auto args = e->Args();
         if (results.Length() != args.Length()) {
             AddError(e, std::string("exit: args count (") + std::to_string(args.Length()) +
                             ") does not match control instruction result count (" +
                             std::to_string(results.Length()) + ")");
-            return;
-        }
-
-        if (control_stack_.IsEmpty()) {
-            AddError(e, "exit: found outside all control instructions");
+            AddNote(e->ControlInstruction(), "control instruction");
             return;
         }
 
@@ -500,6 +501,7 @@
                          std::string("exit: argument type (") + results[i]->Type()->FriendlyName() +
                              ") does not match control instruction type (" +
                              args[i]->Type()->FriendlyName() + ")");
+                AddNote(e->ControlInstruction(), "control instruction");
             }
         }
 
diff --git a/src/tint/ir/validate_test.cc b/src/tint/ir/validate_test.cc
index acdc714..211bad8 100644
--- a/src/tint/ir/validate_test.cc
+++ b/src/tint/ir/validate_test.cc
@@ -1313,6 +1313,10 @@
       %b2 = block {  # true
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = if true [t: %b2] {  # if_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -1353,6 +1357,10 @@
       %b2 = block {  # true
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = if true [t: %b2] {  # if_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -1410,6 +1418,10 @@
       %b2 = block {  # true
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = if true [t: %b2] {  # if_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -1694,6 +1706,10 @@
       %b2 = block {  # case
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = switch true [c: (default, %b2)] {  # switch_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -1734,6 +1750,10 @@
       %b2 = block {  # case
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = switch true [c: (default, %b2)] {  # switch_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -1792,6 +1812,10 @@
       %b2 = block {  # case
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = switch true [c: (default, %b2)] {  # switch_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -2065,6 +2089,10 @@
       %b2 = block {  # body
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = loop [b: %b2, c: %b3] {  # loop_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -2108,6 +2136,10 @@
       %b2 = block {  # body
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = loop [b: %b2, c: %b3] {  # loop_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
@@ -2169,6 +2201,10 @@
       %b2 = block {  # body
       ^^^^^^^^^^^
 
+:3:5 note: control instruction
+    %2:i32, %3:f32 = loop [b: %b2, c: %b3] {  # loop_1
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {