test/tint: Expand modf end-to-end tests

Check that these work as a mix of constant and runtime.

Bug: tint:1581
Change-Id: I572122d9425c4bb8e60125879f9829d765580d1f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/111243
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/test/tint/builtins/modf.wgsl b/test/tint/builtins/modf/scalar/const.wgsl
similarity index 70%
copy from test/tint/builtins/modf.wgsl
copy to test/tint/builtins/modf/scalar/const.wgsl
index c96821a..691638c 100644
--- a/test/tint/builtins/modf.wgsl
+++ b/test/tint/builtins/modf/scalar/const.wgsl
@@ -1,6 +1,7 @@
 @compute @workgroup_size(1)
 fn main() {
-    let res = modf(1.23);
+    const in = 1.23;
+    let res = modf(in);
     let fract : f32 = res.fract;
     let whole : f32 = res.whole;
 }
diff --git a/test/tint/builtins/modf.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/scalar/const.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/builtins/modf.wgsl.expected.dxc.hlsl
rename to test/tint/builtins/modf/scalar/const.wgsl.expected.dxc.hlsl
diff --git a/test/tint/builtins/modf.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/scalar/const.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/builtins/modf.wgsl.expected.fxc.hlsl
rename to test/tint/builtins/modf/scalar/const.wgsl.expected.fxc.hlsl
diff --git a/test/tint/builtins/modf.wgsl.expected.glsl b/test/tint/builtins/modf/scalar/const.wgsl.expected.glsl
similarity index 88%
rename from test/tint/builtins/modf.wgsl.expected.glsl
rename to test/tint/builtins/modf/scalar/const.wgsl.expected.glsl
index e59dfb0..81e5fa2 100644
--- a/test/tint/builtins/modf.wgsl.expected.glsl
+++ b/test/tint/builtins/modf/scalar/const.wgsl.expected.glsl
@@ -8,7 +8,7 @@
 
 void tint_symbol() {
   modf_result res = modf_result(0.230000019f, 1.0f);
-  float tint_symbol_1 = res.fract;
+  float tint_symbol_2 = res.fract;
   float whole = res.whole;
 }
 
diff --git a/test/tint/builtins/modf.wgsl.expected.msl b/test/tint/builtins/modf/scalar/const.wgsl.expected.msl
similarity index 100%
rename from test/tint/builtins/modf.wgsl.expected.msl
rename to test/tint/builtins/modf/scalar/const.wgsl.expected.msl
diff --git a/test/tint/builtins/modf.wgsl.expected.spvasm b/test/tint/builtins/modf/scalar/const.wgsl.expected.spvasm
similarity index 100%
rename from test/tint/builtins/modf.wgsl.expected.spvasm
rename to test/tint/builtins/modf/scalar/const.wgsl.expected.spvasm
diff --git a/test/tint/builtins/modf.wgsl.expected.wgsl b/test/tint/builtins/modf/scalar/const.wgsl.expected.wgsl
similarity index 71%
copy from test/tint/builtins/modf.wgsl.expected.wgsl
copy to test/tint/builtins/modf/scalar/const.wgsl.expected.wgsl
index c9d61eb..e608475 100644
--- a/test/tint/builtins/modf.wgsl.expected.wgsl
+++ b/test/tint/builtins/modf/scalar/const.wgsl.expected.wgsl
@@ -1,6 +1,7 @@
 @compute @workgroup_size(1)
 fn main() {
-  let res = modf(1.23);
+  const in = 1.23;
+  let res = modf(in);
   let fract : f32 = res.fract;
   let whole : f32 = res.whole;
 }
diff --git a/test/tint/builtins/modf.wgsl b/test/tint/builtins/modf/scalar/const_members.wgsl
similarity index 69%
copy from test/tint/builtins/modf.wgsl
copy to test/tint/builtins/modf/scalar/const_members.wgsl
index c96821a..474f4e9 100644
--- a/test/tint/builtins/modf.wgsl
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl
@@ -1,6 +1,7 @@
 @compute @workgroup_size(1)
 fn main() {
-    let res = modf(1.23);
+    const in = 1.23;
+    const res = modf(in);
     let fract : f32 = res.fract;
     let whole : f32 = res.whole;
 }
diff --git a/test/tint/builtins/modf/scalar/const_members.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..eb9a64a
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.dxc.hlsl
@@ -0,0 +1,12 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const modf_result tint_symbol_1 = {0.230000019f, 1.0f};
+  const float fract = tint_symbol_1.fract;
+  const modf_result tint_symbol_2 = {0.230000019f, 1.0f};
+  const float whole = tint_symbol_2.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/const_members.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..eb9a64a
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.fxc.hlsl
@@ -0,0 +1,12 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const modf_result tint_symbol_1 = {0.230000019f, 1.0f};
+  const float fract = tint_symbol_1.fract;
+  const modf_result tint_symbol_2 = {0.230000019f, 1.0f};
+  const float whole = tint_symbol_2.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/const_members.wgsl.expected.glsl b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.glsl
new file mode 100644
index 0000000..553442e
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.glsl
@@ -0,0 +1,20 @@
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void tint_symbol() {
+  modf_result tint_symbol_3 = modf_result(0.230000019f, 1.0f);
+  float tint_symbol_2 = tint_symbol_3.fract;
+  modf_result tint_symbol_4 = modf_result(0.230000019f, 1.0f);
+  float whole = tint_symbol_4.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/const_members.wgsl.expected.msl b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.msl
new file mode 100644
index 0000000..86f70cf
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.msl
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+kernel void tint_symbol() {
+  modf_result const tint_symbol_1 = modf_result{.fract=0.230000019f, .whole=1.0f};
+  float const fract = tint_symbol_1.fract;
+  modf_result const tint_symbol_2 = modf_result{.fract=0.230000019f, .whole=1.0f};
+  float const whole = tint_symbol_2.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/scalar/const_members.wgsl.expected.spvasm b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.spvasm
new file mode 100644
index 0000000..96f8bc3
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.spvasm
@@ -0,0 +1,19 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 8
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+%float_0_230000019 = OpConstant %float 0.230000019
+    %float_1 = OpConstant %float 1
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf.wgsl.expected.wgsl b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.wgsl
similarity index 70%
copy from test/tint/builtins/modf.wgsl.expected.wgsl
copy to test/tint/builtins/modf/scalar/const_members.wgsl.expected.wgsl
index c9d61eb..dd8a7ee 100644
--- a/test/tint/builtins/modf.wgsl.expected.wgsl
+++ b/test/tint/builtins/modf/scalar/const_members.wgsl.expected.wgsl
@@ -1,6 +1,7 @@
 @compute @workgroup_size(1)
 fn main() {
-  let res = modf(1.23);
+  const in = 1.23;
+  const res = modf(in);
   let fract : f32 = res.fract;
   let whole : f32 = res.whole;
 }
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl b/test/tint/builtins/modf/scalar/mixed.wgsl
new file mode 100644
index 0000000..e005ad4
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+    const const_in = 1.23;
+    let runtime_in = 1.23;
+    var res = modf(const_in);
+    res = modf(runtime_in);
+    res = modf(const_in);
+    let fract : f32 = res.fract;
+    let whole : f32 = res.whole;
+}
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..d71fe40
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.dxc.hlsl
@@ -0,0 +1,21 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float runtime_in = 1.230000019f;
+  modf_result res = {0.230000019f, 1.0f};
+  res = tint_modf(runtime_in);
+  const modf_result c = {0.230000019f, 1.0f};
+  res = c;
+  const float fract = res.fract;
+  const float whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..d71fe40
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.fxc.hlsl
@@ -0,0 +1,21 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float runtime_in = 1.230000019f;
+  modf_result res = {0.230000019f, 1.0f};
+  res = tint_modf(runtime_in);
+  const modf_result c = {0.230000019f, 1.0f};
+  res = c;
+  const float fract = res.fract;
+  const float whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl.expected.glsl b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.glsl
new file mode 100644
index 0000000..1f993e6
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+
+void tint_symbol() {
+  float runtime_in = 1.230000019f;
+  modf_result res = modf_result(0.230000019f, 1.0f);
+  res = tint_modf(runtime_in);
+  res = modf_result(0.230000019f, 1.0f);
+  float tint_symbol_1 = res.fract;
+  float whole = res.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl.expected.msl b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.msl
new file mode 100644
index 0000000..6da4d7b
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float const runtime_in = 1.230000019f;
+  modf_result res = modf_result{.fract=0.230000019f, .whole=1.0f};
+  res = tint_modf(runtime_in);
+  res = modf_result{.fract=0.230000019f, .whole=1.0f};
+  float const fract = res.fract;
+  float const whole = res.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl.expected.spvasm b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..dd2dbe1
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.spvasm
@@ -0,0 +1,44 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+               OpCapability Shader
+         %15 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__modf_result "__modf_result"
+               OpMemberName %__modf_result 0 "fract"
+               OpMemberName %__modf_result 1 "whole"
+               OpName %res "res"
+               OpMemberDecorate %__modf_result 0 Offset 0
+               OpMemberDecorate %__modf_result 1 Offset 4
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+%float_1_23000002 = OpConstant %float 1.23000002
+%__modf_result = OpTypeStruct %float %float
+%float_0_230000019 = OpConstant %float 0.230000019
+    %float_1 = OpConstant %float 1
+         %10 = OpConstantComposite %__modf_result %float_0_230000019 %float_1
+%_ptr_Function___modf_result = OpTypePointer Function %__modf_result
+         %13 = OpConstantNull %__modf_result
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Function_float = OpTypePointer Function %float
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result Function %13
+               OpStore %res %10
+         %14 = OpExtInst %__modf_result %15 ModfStruct %float_1_23000002
+               OpStore %res %14
+               OpStore %res %10
+         %19 = OpAccessChain %_ptr_Function_float %res %uint_0
+         %20 = OpLoad %float %19
+         %22 = OpAccessChain %_ptr_Function_float %res %uint_1
+         %23 = OpLoad %float %22
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf/scalar/mixed.wgsl.expected.wgsl b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..2531d47
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/mixed.wgsl.expected.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+  const const_in = 1.23;
+  let runtime_in = 1.23;
+  var res = modf(const_in);
+  res = modf(runtime_in);
+  res = modf(const_in);
+  let fract : f32 = res.fract;
+  let whole : f32 = res.whole;
+}
diff --git a/test/tint/builtins/modf.wgsl b/test/tint/builtins/modf/scalar/runtime.wgsl
similarity index 71%
rename from test/tint/builtins/modf.wgsl
rename to test/tint/builtins/modf/scalar/runtime.wgsl
index c96821a..8012549 100644
--- a/test/tint/builtins/modf.wgsl
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl
@@ -1,6 +1,7 @@
 @compute @workgroup_size(1)
 fn main() {
-    let res = modf(1.23);
+    let in = 1.23;
+    let res = modf(in);
     let fract : f32 = res.fract;
     let whole : f32 = res.whole;
 }
diff --git a/test/tint/builtins/modf/scalar/runtime.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..d1d0c5c
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.dxc.hlsl
@@ -0,0 +1,18 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float tint_symbol = 1.230000019f;
+  const modf_result res = tint_modf(tint_symbol);
+  const float fract = res.fract;
+  const float whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/runtime.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..d1d0c5c
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.fxc.hlsl
@@ -0,0 +1,18 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float tint_symbol = 1.230000019f;
+  const modf_result res = tint_modf(tint_symbol);
+  const float fract = res.fract;
+  const float whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/runtime.wgsl.expected.glsl b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.glsl
new file mode 100644
index 0000000..a3d99cd
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.glsl
@@ -0,0 +1,26 @@
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+
+void tint_symbol() {
+  float tint_symbol_1 = 1.230000019f;
+  modf_result res = tint_modf(tint_symbol_1);
+  float tint_symbol_2 = res.fract;
+  float whole = res.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/scalar/runtime.wgsl.expected.msl b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.msl
new file mode 100644
index 0000000..3dc7887
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+modf_result tint_modf(float param_0) {
+  modf_result result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float const in = 1.230000019f;
+  modf_result const res = tint_modf(in);
+  float const fract = res.fract;
+  float const whole = res.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/scalar/runtime.wgsl.expected.spvasm b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.spvasm
new file mode 100644
index 0000000..410b6b5
--- /dev/null
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.spvasm
@@ -0,0 +1,28 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 12
+; Schema: 0
+               OpCapability Shader
+          %9 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__modf_result "__modf_result"
+               OpMemberName %__modf_result 0 "fract"
+               OpMemberName %__modf_result 1 "whole"
+               OpMemberDecorate %__modf_result 0 Offset 0
+               OpMemberDecorate %__modf_result 1 Offset 4
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+%float_1_23000002 = OpConstant %float 1.23000002
+%__modf_result = OpTypeStruct %float %float
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+          %7 = OpExtInst %__modf_result %9 ModfStruct %float_1_23000002
+         %10 = OpCompositeExtract %float %7 0
+         %11 = OpCompositeExtract %float %7 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf.wgsl.expected.wgsl b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.wgsl
similarity index 72%
rename from test/tint/builtins/modf.wgsl.expected.wgsl
rename to test/tint/builtins/modf/scalar/runtime.wgsl.expected.wgsl
index c9d61eb..74d6daa 100644
--- a/test/tint/builtins/modf.wgsl.expected.wgsl
+++ b/test/tint/builtins/modf/scalar/runtime.wgsl.expected.wgsl
@@ -1,6 +1,7 @@
 @compute @workgroup_size(1)
 fn main() {
-  let res = modf(1.23);
+  let in = 1.23;
+  let res = modf(in);
   let fract : f32 = res.fract;
   let whole : f32 = res.whole;
 }
diff --git a/test/tint/builtins/modf/vector/const.wgsl b/test/tint/builtins/modf/vector/const.wgsl
new file mode 100644
index 0000000..ea42ea7
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    const in = vec2(1.23, 3.45);
+    let res = modf(in);
+    let fract : vec2<f32> = res.fract;
+    let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/const.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/vector/const.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..42e4b1a
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl.expected.dxc.hlsl
@@ -0,0 +1,11 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const modf_result_vec2 res = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  const float2 fract = res.fract;
+  const float2 whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/const.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/vector/const.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..42e4b1a
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl.expected.fxc.hlsl
@@ -0,0 +1,11 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const modf_result_vec2 res = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  const float2 fract = res.fract;
+  const float2 whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/const.wgsl.expected.glsl b/test/tint/builtins/modf/vector/const.wgsl.expected.glsl
new file mode 100644
index 0000000..a62e59f
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl.expected.glsl
@@ -0,0 +1,19 @@
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void tint_symbol() {
+  modf_result_vec2 res = modf_result_vec2(vec2(0.230000019f, 0.450000048f), vec2(1.0f, 3.0f));
+  vec2 tint_symbol_2 = res.fract;
+  vec2 whole = res.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/const.wgsl.expected.msl b/test/tint/builtins/modf/vector/const.wgsl.expected.msl
new file mode 100644
index 0000000..9722fb4
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl.expected.msl
@@ -0,0 +1,15 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+kernel void tint_symbol() {
+  modf_result_vec2 const res = modf_result_vec2{.fract=float2(0.230000019f, 0.450000048f), .whole=float2(1.0f, 3.0f)};
+  float2 const fract = res.fract;
+  float2 const whole = res.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/vector/const.wgsl.expected.spvasm b/test/tint/builtins/modf/vector/const.wgsl.expected.spvasm
new file mode 100644
index 0000000..acbabcd
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl.expected.spvasm
@@ -0,0 +1,33 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 17
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__modf_result_vec2 "__modf_result_vec2"
+               OpMemberName %__modf_result_vec2 0 "fract"
+               OpMemberName %__modf_result_vec2 1 "whole"
+               OpMemberDecorate %__modf_result_vec2 0 Offset 0
+               OpMemberDecorate %__modf_result_vec2 1 Offset 8
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%__modf_result_vec2 = OpTypeStruct %v2float %v2float
+%float_0_230000019 = OpConstant %float 0.230000019
+%float_0_450000048 = OpConstant %float 0.450000048
+         %10 = OpConstantComposite %v2float %float_0_230000019 %float_0_450000048
+    %float_1 = OpConstant %float 1
+    %float_3 = OpConstant %float 3
+         %13 = OpConstantComposite %v2float %float_1 %float_3
+         %14 = OpConstantComposite %__modf_result_vec2 %10 %13
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+         %15 = OpCompositeExtract %v2float %14 0
+         %16 = OpCompositeExtract %v2float %14 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf/vector/const.wgsl.expected.wgsl b/test/tint/builtins/modf/vector/const.wgsl.expected.wgsl
new file mode 100644
index 0000000..d2ff4a4
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  const in = vec2(1.23, 3.45);
+  let res = modf(in);
+  let fract : vec2<f32> = res.fract;
+  let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl b/test/tint/builtins/modf/vector/const_members.wgsl
new file mode 100644
index 0000000..e976aba
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    const in = vec2(1.23, 3.45);
+    const res = modf(in);
+    let fract : vec2<f32> = res.fract;
+    let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/vector/const_members.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..c4c8e9c
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl.expected.dxc.hlsl
@@ -0,0 +1,12 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const modf_result_vec2 tint_symbol_1 = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  const float2 fract = tint_symbol_1.fract;
+  const modf_result_vec2 tint_symbol_2 = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  const float2 whole = tint_symbol_2.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/vector/const_members.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..c4c8e9c
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl.expected.fxc.hlsl
@@ -0,0 +1,12 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const modf_result_vec2 tint_symbol_1 = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  const float2 fract = tint_symbol_1.fract;
+  const modf_result_vec2 tint_symbol_2 = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  const float2 whole = tint_symbol_2.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl.expected.glsl b/test/tint/builtins/modf/vector/const_members.wgsl.expected.glsl
new file mode 100644
index 0000000..86e29eb
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl.expected.glsl
@@ -0,0 +1,20 @@
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void tint_symbol() {
+  modf_result_vec2 tint_symbol_3 = modf_result_vec2(vec2(0.230000019f, 0.450000048f), vec2(1.0f, 3.0f));
+  vec2 tint_symbol_2 = tint_symbol_3.fract;
+  modf_result_vec2 tint_symbol_4 = modf_result_vec2(vec2(0.230000019f, 0.450000048f), vec2(1.0f, 3.0f));
+  vec2 whole = tint_symbol_4.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl.expected.msl b/test/tint/builtins/modf/vector/const_members.wgsl.expected.msl
new file mode 100644
index 0000000..137dcf3
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl.expected.msl
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+kernel void tint_symbol() {
+  modf_result_vec2 const tint_symbol_1 = modf_result_vec2{.fract=float2(0.230000019f, 0.450000048f), .whole=float2(1.0f, 3.0f)};
+  float2 const fract = tint_symbol_1.fract;
+  modf_result_vec2 const tint_symbol_2 = modf_result_vec2{.fract=float2(0.230000019f, 0.450000048f), .whole=float2(1.0f, 3.0f)};
+  float2 const whole = tint_symbol_2.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl.expected.spvasm b/test/tint/builtins/modf/vector/const_members.wgsl.expected.spvasm
new file mode 100644
index 0000000..8b32d12
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl.expected.spvasm
@@ -0,0 +1,24 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 13
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%float_0_230000019 = OpConstant %float 0.230000019
+%float_0_450000048 = OpConstant %float 0.450000048
+          %9 = OpConstantComposite %v2float %float_0_230000019 %float_0_450000048
+    %float_1 = OpConstant %float 1
+    %float_3 = OpConstant %float 3
+         %12 = OpConstantComposite %v2float %float_1 %float_3
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf/vector/const_members.wgsl.expected.wgsl b/test/tint/builtins/modf/vector/const_members.wgsl.expected.wgsl
new file mode 100644
index 0000000..18f85e3
--- /dev/null
+++ b/test/tint/builtins/modf/vector/const_members.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  const in = vec2(1.23, 3.45);
+  const res = modf(in);
+  let fract : vec2<f32> = res.fract;
+  let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl b/test/tint/builtins/modf/vector/mixed.wgsl
new file mode 100644
index 0000000..cc840a2
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+    const const_in = vec2(1.23, 3.45);
+    let runtime_in = vec2(1.23, 3.45);
+    var res = modf(const_in);
+    res = modf(runtime_in);
+    res = modf(const_in);
+    let fract : vec2<f32> = res.fract;
+    let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/vector/mixed.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..4f324c8
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl.expected.dxc.hlsl
@@ -0,0 +1,21 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+modf_result_vec2 tint_modf(float2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 runtime_in = float2(1.230000019f, 3.450000048f);
+  modf_result_vec2 res = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  res = tint_modf(runtime_in);
+  const modf_result_vec2 c = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  res = c;
+  const float2 fract = res.fract;
+  const float2 whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/vector/mixed.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..4f324c8
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl.expected.fxc.hlsl
@@ -0,0 +1,21 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+modf_result_vec2 tint_modf(float2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 runtime_in = float2(1.230000019f, 3.450000048f);
+  modf_result_vec2 res = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  res = tint_modf(runtime_in);
+  const modf_result_vec2 c = {float2(0.230000019f, 0.450000048f), float2(1.0f, 3.0f)};
+  res = c;
+  const float2 fract = res.fract;
+  const float2 whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl.expected.glsl b/test/tint/builtins/modf/vector/mixed.wgsl.expected.glsl
new file mode 100644
index 0000000..61c5152
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+modf_result_vec2 tint_modf(vec2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+
+void tint_symbol() {
+  vec2 runtime_in = vec2(1.230000019f, 3.450000048f);
+  modf_result_vec2 res = modf_result_vec2(vec2(0.230000019f, 0.450000048f), vec2(1.0f, 3.0f));
+  res = tint_modf(runtime_in);
+  res = modf_result_vec2(vec2(0.230000019f, 0.450000048f), vec2(1.0f, 3.0f));
+  vec2 tint_symbol_1 = res.fract;
+  vec2 whole = res.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl.expected.msl b/test/tint/builtins/modf/vector/mixed.wgsl.expected.msl
new file mode 100644
index 0000000..da46ae1
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+modf_result_vec2 tint_modf(float2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float2 const runtime_in = float2(1.230000019f, 3.450000048f);
+  modf_result_vec2 res = modf_result_vec2{.fract=float2(0.230000019f, 0.450000048f), .whole=float2(1.0f, 3.0f)};
+  res = tint_modf(runtime_in);
+  res = modf_result_vec2{.fract=float2(0.230000019f, 0.450000048f), .whole=float2(1.0f, 3.0f)};
+  float2 const fract = res.fract;
+  float2 const whole = res.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl.expected.spvasm b/test/tint/builtins/modf/vector/mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..89f129a
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl.expected.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+               OpCapability Shader
+         %22 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__modf_result_vec2 "__modf_result_vec2"
+               OpMemberName %__modf_result_vec2 0 "fract"
+               OpMemberName %__modf_result_vec2 1 "whole"
+               OpName %res "res"
+               OpMemberDecorate %__modf_result_vec2 0 Offset 0
+               OpMemberDecorate %__modf_result_vec2 1 Offset 8
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%float_1_23000002 = OpConstant %float 1.23000002
+%float_3_45000005 = OpConstant %float 3.45000005
+          %9 = OpConstantComposite %v2float %float_1_23000002 %float_3_45000005
+%__modf_result_vec2 = OpTypeStruct %v2float %v2float
+%float_0_230000019 = OpConstant %float 0.230000019
+%float_0_450000048 = OpConstant %float 0.450000048
+         %13 = OpConstantComposite %v2float %float_0_230000019 %float_0_450000048
+    %float_1 = OpConstant %float 1
+    %float_3 = OpConstant %float 3
+         %16 = OpConstantComposite %v2float %float_1 %float_3
+         %17 = OpConstantComposite %__modf_result_vec2 %13 %16
+%_ptr_Function___modf_result_vec2 = OpTypePointer Function %__modf_result_vec2
+         %20 = OpConstantNull %__modf_result_vec2
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec2 Function %20
+               OpStore %res %17
+         %21 = OpExtInst %__modf_result_vec2 %22 ModfStruct %9
+               OpStore %res %21
+               OpStore %res %17
+         %26 = OpAccessChain %_ptr_Function_v2float %res %uint_0
+         %27 = OpLoad %v2float %26
+         %29 = OpAccessChain %_ptr_Function_v2float %res %uint_1
+         %30 = OpLoad %v2float %29
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf/vector/mixed.wgsl.expected.wgsl b/test/tint/builtins/modf/vector/mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..ae23542
--- /dev/null
+++ b/test/tint/builtins/modf/vector/mixed.wgsl.expected.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+  const const_in = vec2(1.23, 3.45);
+  let runtime_in = vec2(1.23, 3.45);
+  var res = modf(const_in);
+  res = modf(runtime_in);
+  res = modf(const_in);
+  let fract : vec2<f32> = res.fract;
+  let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl b/test/tint/builtins/modf/vector/runtime.wgsl
new file mode 100644
index 0000000..b305179
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    let in = vec2(1.23, 3.45);
+    let res = modf(in);
+    let fract : vec2<f32> = res.fract;
+    let whole : vec2<f32> = res.whole;
+}
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl.expected.dxc.hlsl b/test/tint/builtins/modf/vector/runtime.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..4511adc
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl.expected.dxc.hlsl
@@ -0,0 +1,18 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+modf_result_vec2 tint_modf(float2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 tint_symbol = float2(1.230000019f, 3.450000048f);
+  const modf_result_vec2 res = tint_modf(tint_symbol);
+  const float2 fract = res.fract;
+  const float2 whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl.expected.fxc.hlsl b/test/tint/builtins/modf/vector/runtime.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..4511adc
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl.expected.fxc.hlsl
@@ -0,0 +1,18 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+modf_result_vec2 tint_modf(float2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 tint_symbol = float2(1.230000019f, 3.450000048f);
+  const modf_result_vec2 res = tint_modf(tint_symbol);
+  const float2 fract = res.fract;
+  const float2 whole = res.whole;
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl.expected.glsl b/test/tint/builtins/modf/vector/runtime.wgsl.expected.glsl
new file mode 100644
index 0000000..682b55d
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl.expected.glsl
@@ -0,0 +1,26 @@
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+modf_result_vec2 tint_modf(vec2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+
+void tint_symbol() {
+  vec2 tint_symbol_1 = vec2(1.230000019f, 3.450000048f);
+  modf_result_vec2 res = tint_modf(tint_symbol_1);
+  vec2 tint_symbol_2 = res.fract;
+  vec2 whole = res.whole;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol();
+  return;
+}
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl.expected.msl b/test/tint/builtins/modf/vector/runtime.wgsl.expected.msl
new file mode 100644
index 0000000..d284359
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+modf_result_vec2 tint_modf(float2 param_0) {
+  modf_result_vec2 result;
+  result.fract = modf(param_0, result.whole);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float2 const in = float2(1.230000019f, 3.450000048f);
+  modf_result_vec2 const res = tint_modf(in);
+  float2 const fract = res.fract;
+  float2 const whole = res.whole;
+  return;
+}
+
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl.expected.spvasm b/test/tint/builtins/modf/vector/runtime.wgsl.expected.spvasm
new file mode 100644
index 0000000..5d76432
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl.expected.spvasm
@@ -0,0 +1,31 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+         %12 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__modf_result_vec2 "__modf_result_vec2"
+               OpMemberName %__modf_result_vec2 0 "fract"
+               OpMemberName %__modf_result_vec2 1 "whole"
+               OpMemberDecorate %__modf_result_vec2 0 Offset 0
+               OpMemberDecorate %__modf_result_vec2 1 Offset 8
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%float_1_23000002 = OpConstant %float 1.23000002
+%float_3_45000005 = OpConstant %float 3.45000005
+          %9 = OpConstantComposite %v2float %float_1_23000002 %float_3_45000005
+%__modf_result_vec2 = OpTypeStruct %v2float %v2float
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+         %10 = OpExtInst %__modf_result_vec2 %12 ModfStruct %9
+         %13 = OpCompositeExtract %v2float %10 0
+         %14 = OpCompositeExtract %v2float %10 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/modf/vector/runtime.wgsl.expected.wgsl b/test/tint/builtins/modf/vector/runtime.wgsl.expected.wgsl
new file mode 100644
index 0000000..2bb76f6
--- /dev/null
+++ b/test/tint/builtins/modf/vector/runtime.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  let in = vec2(1.23, 3.45);
+  let res = modf(in);
+  let fract : vec2<f32> = res.fract;
+  let whole : vec2<f32> = res.whole;
+}