test: Add E2E test coverage for shader IO

This provides much more complete coverage than what we have in the
unit tests. We now test:
- All builtins, for all stages, both struct and non-struct
- Multiple location attributes for vertex and fragment stages, both
  struct and non-struct
- Mixing builtins and location attributes, whilst mixing struct and
  non-struct
- A few "interesting" cases of IO structs being shared between
  different functions, stages, and with an SSBO variable

There are 7 skipped tests for MSL due to two different MSL bugs which
will be fixed in upcoming patches.

Change-Id: I8b802591762c8ff018e01bf37838551e353162b1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53120
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Auto-Submit: James Price <jrprice@google.com>
diff --git a/test/shader_io/fragment_output_mixed.wgsl.expected.spvasm b/test/shader_io/fragment_output_mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..164fdf0
--- /dev/null
+++ b/test/shader_io/fragment_output_mixed.wgsl.expected.spvasm
@@ -0,0 +1,97 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 49
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_4 %tint_symbol_5 %tint_symbol_6
+               OpExecutionMode %main OriginUpperLeft
+               OpExecutionMode %main DepthReplacing
+               OpName %tint_symbol_1 "tint_symbol_1"
+               OpName %tint_symbol_2 "tint_symbol_2"
+               OpName %tint_symbol_3 "tint_symbol_3"
+               OpName %tint_symbol_4 "tint_symbol_4"
+               OpName %tint_symbol_5 "tint_symbol_5"
+               OpName %tint_symbol_6 "tint_symbol_6"
+               OpName %FragmentOutputs "FragmentOutputs"
+               OpMemberName %FragmentOutputs 0 "loc0"
+               OpMemberName %FragmentOutputs 1 "frag_depth"
+               OpMemberName %FragmentOutputs 2 "loc1"
+               OpMemberName %FragmentOutputs 3 "loc2"
+               OpMemberName %FragmentOutputs 4 "sample_mask"
+               OpMemberName %FragmentOutputs 5 "loc3"
+               OpName %tint_symbol_7 "tint_symbol_7"
+               OpName %tint_symbol "tint_symbol"
+               OpName %main "main"
+               OpDecorate %tint_symbol_1 Location 0
+               OpDecorate %tint_symbol_2 BuiltIn FragDepth
+               OpDecorate %tint_symbol_3 Location 1
+               OpDecorate %tint_symbol_4 Location 2
+               OpDecorate %_arr_uint_uint_1 ArrayStride 4
+               OpDecorate %tint_symbol_5 BuiltIn SampleMask
+               OpDecorate %tint_symbol_6 Location 3
+               OpMemberDecorate %FragmentOutputs 0 Offset 0
+               OpMemberDecorate %FragmentOutputs 1 Offset 4
+               OpMemberDecorate %FragmentOutputs 2 Offset 8
+               OpMemberDecorate %FragmentOutputs 3 Offset 12
+               OpMemberDecorate %FragmentOutputs 4 Offset 16
+               OpMemberDecorate %FragmentOutputs 5 Offset 32
+        %int = OpTypeInt 32 1
+%_ptr_Output_int = OpTypePointer Output %int
+          %4 = OpConstantNull %int
+%tint_symbol_1 = OpVariable %_ptr_Output_int Output %4
+      %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%tint_symbol_2 = OpVariable %_ptr_Output_float Output %8
+       %uint = OpTypeInt 32 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+         %12 = OpConstantNull %uint
+%tint_symbol_3 = OpVariable %_ptr_Output_uint Output %12
+%tint_symbol_4 = OpVariable %_ptr_Output_float Output %8
+     %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Output__arr_uint_uint_1 = OpTypePointer Output %_arr_uint_uint_1
+         %18 = OpConstantNull %_arr_uint_uint_1
+%tint_symbol_5 = OpVariable %_ptr_Output__arr_uint_uint_1 Output %18
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+         %22 = OpConstantNull %v4float
+%tint_symbol_6 = OpVariable %_ptr_Output_v4float Output %22
+       %void = OpTypeVoid
+%FragmentOutputs = OpTypeStruct %int %float %uint %float %uint %v4float
+         %23 = OpTypeFunction %void %FragmentOutputs
+      %int_0 = OpConstant %int 0
+         %37 = OpTypeFunction %void
+      %int_1 = OpConstant %int 1
+    %float_2 = OpConstant %float 2
+    %float_1 = OpConstant %float 1
+     %uint_2 = OpConstant %uint 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %47 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %48 = OpConstantComposite %FragmentOutputs %int_1 %float_2 %uint_1 %float_1 %uint_2 %47
+%tint_symbol_7 = OpFunction %void None %23
+%tint_symbol = OpFunctionParameter %FragmentOutputs
+         %28 = OpLabel
+         %29 = OpCompositeExtract %int %tint_symbol 0
+               OpStore %tint_symbol_1 %29
+         %30 = OpCompositeExtract %float %tint_symbol 1
+               OpStore %tint_symbol_2 %30
+         %31 = OpCompositeExtract %uint %tint_symbol 2
+               OpStore %tint_symbol_3 %31
+         %32 = OpCompositeExtract %float %tint_symbol 3
+               OpStore %tint_symbol_4 %32
+         %34 = OpAccessChain %_ptr_Output_uint %tint_symbol_5 %int_0
+         %35 = OpCompositeExtract %uint %tint_symbol 4
+               OpStore %34 %35
+         %36 = OpCompositeExtract %v4float %tint_symbol 5
+               OpStore %tint_symbol_6 %36
+               OpReturn
+               OpFunctionEnd
+       %main = OpFunction %void None %37
+         %39 = OpLabel
+         %40 = OpFunctionCall %void %tint_symbol_7 %48
+               OpReturn
+               OpFunctionEnd