tint: Implement const-eval of frexp()

Also add abstract overloads.

Bug: tint:1581
Fixed: tint:1768
Change-Id: Icda465e0cfe960b77823c2135f0cfe8f82ed394f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/111441
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/test/tint/bug/tint/1757.wgsl.expected.dxc.hlsl b/test/tint/bug/tint/1757.wgsl.expected.dxc.hlsl
index 1e0655f..895420b 100644
--- a/test/tint/bug/tint/1757.wgsl.expected.dxc.hlsl
+++ b/test/tint/bug/tint/1757.wgsl.expected.dxc.hlsl
@@ -6,16 +6,9 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  float exp;
-  float fract = frexp(param_0, exp);
-  frexp_result result = {fract, int(exp)};
-  return result;
-}
-
 [numthreads(1, 1, 1)]
 void main() {
-  const frexp_result res = tint_frexp(1.230000019f);
+  const frexp_result res = {0.61500001f, 1};
   const int exp = res.exp;
   const float sig = res.fract;
   return;
diff --git a/test/tint/bug/tint/1757.wgsl.expected.fxc.hlsl b/test/tint/bug/tint/1757.wgsl.expected.fxc.hlsl
index 1e0655f..895420b 100644
--- a/test/tint/bug/tint/1757.wgsl.expected.fxc.hlsl
+++ b/test/tint/bug/tint/1757.wgsl.expected.fxc.hlsl
@@ -6,16 +6,9 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  float exp;
-  float fract = frexp(param_0, exp);
-  frexp_result result = {fract, int(exp)};
-  return result;
-}
-
 [numthreads(1, 1, 1)]
 void main() {
-  const frexp_result res = tint_frexp(1.230000019f);
+  const frexp_result res = {0.61500001f, 1};
   const int exp = res.exp;
   const float sig = res.fract;
   return;
diff --git a/test/tint/bug/tint/1757.wgsl.expected.glsl b/test/tint/bug/tint/1757.wgsl.expected.glsl
index e6efd68..e6ff7ca 100644
--- a/test/tint/bug/tint/1757.wgsl.expected.glsl
+++ b/test/tint/bug/tint/1757.wgsl.expected.glsl
@@ -9,15 +9,9 @@
   int exp;
 };
 
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void tint_symbol() {
-  frexp_result res = tint_frexp(1.230000019f);
+  frexp_result res = frexp_result(0.61500001f, 1);
   int tint_symbol_1 = res.exp;
   float sig = res.fract;
 }
diff --git a/test/tint/bug/tint/1757.wgsl.expected.msl b/test/tint/bug/tint/1757.wgsl.expected.msl
index 8196ef6..0d960e7 100644
--- a/test/tint/bug/tint/1757.wgsl.expected.msl
+++ b/test/tint/bug/tint/1757.wgsl.expected.msl
@@ -10,14 +10,8 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 kernel void tint_symbol() {
-  frexp_result const res = tint_frexp(1.230000019f);
+  frexp_result const res = frexp_result{.fract=0.61500001f, .exp=1};
   int const exp = res.exp;
   float const sig = res.fract;
   return;
diff --git a/test/tint/bug/tint/1757.wgsl.expected.spvasm b/test/tint/bug/tint/1757.wgsl.expected.spvasm
index 4116852..79b00c0 100644
--- a/test/tint/bug/tint/1757.wgsl.expected.spvasm
+++ b/test/tint/bug/tint/1757.wgsl.expected.spvasm
@@ -8,7 +8,6 @@
 ; Bound: 13
 ; Schema: 0
                OpCapability Shader
-          %9 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %main "main"
                OpExecutionMode %main LocalSize 1 1 1
@@ -23,11 +22,12 @@
       %float = OpTypeFloat 32
         %int = OpTypeInt 32 1
 %__frexp_result = OpTypeStruct %float %int
-%float_1_23000002 = OpConstant %float 1.23000002
+%float_0_61500001 = OpConstant %float 0.61500001
+      %int_1 = OpConstant %int 1
+         %10 = OpConstantComposite %__frexp_result %float_0_61500001 %int_1
        %main = OpFunction %void None %1
           %4 = OpLabel
-          %5 = OpExtInst %__frexp_result %9 FrexpStruct %float_1_23000002
-         %11 = OpCompositeExtract %int %5 1
-         %12 = OpCompositeExtract %float %5 0
+         %11 = OpCompositeExtract %int %10 1
+         %12 = OpCompositeExtract %float %10 0
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/frexp.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp.wgsl.expected.dxc.hlsl
index 5737415..3e21c7f 100644
--- a/test/tint/builtins/frexp.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/frexp.wgsl.expected.dxc.hlsl
@@ -2,16 +2,9 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  float exp;
-  float fract = frexp(param_0, exp);
-  frexp_result result = {fract, int(exp)};
-  return result;
-}
-
 [numthreads(1, 1, 1)]
 void main() {
-  const frexp_result res = tint_frexp(1.230000019f);
+  const frexp_result res = {0.61500001f, 1};
   const int exp = res.exp;
   const float fract = res.fract;
   return;
diff --git a/test/tint/builtins/frexp.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp.wgsl.expected.fxc.hlsl
index 5737415..3e21c7f 100644
--- a/test/tint/builtins/frexp.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/frexp.wgsl.expected.fxc.hlsl
@@ -2,16 +2,9 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  float exp;
-  float fract = frexp(param_0, exp);
-  frexp_result result = {fract, int(exp)};
-  return result;
-}
-
 [numthreads(1, 1, 1)]
 void main() {
-  const frexp_result res = tint_frexp(1.230000019f);
+  const frexp_result res = {0.61500001f, 1};
   const int exp = res.exp;
   const float fract = res.fract;
   return;
diff --git a/test/tint/builtins/frexp.wgsl.expected.glsl b/test/tint/builtins/frexp.wgsl.expected.glsl
index 08ae34d..d124447 100644
--- a/test/tint/builtins/frexp.wgsl.expected.glsl
+++ b/test/tint/builtins/frexp.wgsl.expected.glsl
@@ -5,15 +5,9 @@
   int exp;
 };
 
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void tint_symbol() {
-  frexp_result res = tint_frexp(1.230000019f);
+  frexp_result res = frexp_result(0.61500001f, 1);
   int tint_symbol_1 = res.exp;
   float tint_symbol_2 = res.fract;
 }
diff --git a/test/tint/builtins/frexp.wgsl.expected.msl b/test/tint/builtins/frexp.wgsl.expected.msl
index 59dd29c..1bce450 100644
--- a/test/tint/builtins/frexp.wgsl.expected.msl
+++ b/test/tint/builtins/frexp.wgsl.expected.msl
@@ -6,14 +6,8 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 kernel void tint_symbol() {
-  frexp_result const res = tint_frexp(1.230000019f);
+  frexp_result const res = frexp_result{.fract=0.61500001f, .exp=1};
   int const exp = res.exp;
   float const fract = res.fract;
   return;
diff --git a/test/tint/builtins/frexp.wgsl.expected.spvasm b/test/tint/builtins/frexp.wgsl.expected.spvasm
index 8828159..69cdd2f 100644
--- a/test/tint/builtins/frexp.wgsl.expected.spvasm
+++ b/test/tint/builtins/frexp.wgsl.expected.spvasm
@@ -4,7 +4,6 @@
 ; Bound: 13
 ; Schema: 0
                OpCapability Shader
-          %9 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %main "main"
                OpExecutionMode %main LocalSize 1 1 1
@@ -19,11 +18,12 @@
       %float = OpTypeFloat 32
         %int = OpTypeInt 32 1
 %__frexp_result = OpTypeStruct %float %int
-%float_1_23000002 = OpConstant %float 1.23000002
+%float_0_61500001 = OpConstant %float 0.61500001
+      %int_1 = OpConstant %int 1
+         %10 = OpConstantComposite %__frexp_result %float_0_61500001 %int_1
        %main = OpFunction %void None %1
           %4 = OpLabel
-          %5 = OpExtInst %__frexp_result %9 FrexpStruct %float_1_23000002
-         %11 = OpCompositeExtract %int %5 1
-         %12 = OpCompositeExtract %float %5 0
+         %11 = OpCompositeExtract %int %10 1
+         %12 = OpCompositeExtract %float %10 0
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/frexp/scalar/const.wgsl b/test/tint/builtins/frexp/scalar/const.wgsl
new file mode 100644
index 0000000..e4ea555
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    const in = 1.25;
+    let res = frexp(in);
+    let fract : f32 = res.fract;
+    let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/const.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/scalar/const.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..f14cccd
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl.expected.dxc.hlsl
@@ -0,0 +1,11 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result res = {0.625f, 1};
+  const float fract = res.fract;
+  const int exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/const.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/scalar/const.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..f14cccd
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl.expected.fxc.hlsl
@@ -0,0 +1,11 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result res = {0.625f, 1};
+  const float fract = res.fract;
+  const int exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/const.wgsl.expected.glsl b/test/tint/builtins/frexp/scalar/const.wgsl.expected.glsl
new file mode 100644
index 0000000..ec8ca7c
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl.expected.glsl
@@ -0,0 +1,19 @@
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void tint_symbol() {
+  frexp_result res = frexp_result(0.625f, 1);
+  float tint_symbol_2 = res.fract;
+  int tint_symbol_3 = res.exp;
+}
+
+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/frexp/scalar/const.wgsl.expected.msl b/test/tint/builtins/frexp/scalar/const.wgsl.expected.msl
new file mode 100644
index 0000000..f0dcbcf
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl.expected.msl
@@ -0,0 +1,15 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+kernel void tint_symbol() {
+  frexp_result const res = frexp_result{.fract=0.625f, .exp=1};
+  float const fract = res.fract;
+  int const exp = res.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/scalar/const.wgsl.expected.spvasm b/test/tint/builtins/frexp/scalar/const.wgsl.expected.spvasm
new file mode 100644
index 0000000..541d342
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl.expected.spvasm
@@ -0,0 +1,29 @@
+; 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"
+               OpName %__frexp_result "__frexp_result"
+               OpMemberName %__frexp_result 0 "fract"
+               OpMemberName %__frexp_result 1 "exp"
+               OpMemberDecorate %__frexp_result 0 Offset 0
+               OpMemberDecorate %__frexp_result 1 Offset 4
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+        %int = OpTypeInt 32 1
+%__frexp_result = OpTypeStruct %float %int
+%float_0_625 = OpConstant %float 0.625
+      %int_1 = OpConstant %int 1
+         %10 = OpConstantComposite %__frexp_result %float_0_625 %int_1
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+         %11 = OpCompositeExtract %float %10 0
+         %12 = OpCompositeExtract %int %10 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/scalar/const.wgsl.expected.wgsl b/test/tint/builtins/frexp/scalar/const.wgsl.expected.wgsl
new file mode 100644
index 0000000..281cc00
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  const in = 1.25;
+  let res = frexp(in);
+  let fract : f32 = res.fract;
+  let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/const_members.wgsl b/test/tint/builtins/frexp/scalar/const_members.wgsl
new file mode 100644
index 0000000..1d61cac
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    const in = 1.25;
+    const res = frexp(in);
+    let fract : f32 = res.fract;
+    let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..19792b6
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.dxc.hlsl
@@ -0,0 +1,12 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result tint_symbol_1 = {0.625f, 1};
+  const float fract = tint_symbol_1.fract;
+  const frexp_result tint_symbol_2 = {0.625f, 1};
+  const int exp = tint_symbol_2.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..19792b6
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.fxc.hlsl
@@ -0,0 +1,12 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result tint_symbol_1 = {0.625f, 1};
+  const float fract = tint_symbol_1.fract;
+  const frexp_result tint_symbol_2 = {0.625f, 1};
+  const int exp = tint_symbol_2.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.glsl b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.glsl
new file mode 100644
index 0000000..6667f5f
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.glsl
@@ -0,0 +1,20 @@
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void tint_symbol() {
+  frexp_result tint_symbol_4 = frexp_result(0.625f, 1);
+  float tint_symbol_2 = tint_symbol_4.fract;
+  frexp_result tint_symbol_5 = frexp_result(0.625f, 1);
+  int tint_symbol_3 = tint_symbol_5.exp;
+}
+
+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/frexp/scalar/const_members.wgsl.expected.msl b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.msl
new file mode 100644
index 0000000..c2d6c14
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.msl
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+kernel void tint_symbol() {
+  frexp_result const tint_symbol_1 = frexp_result{.fract=0.625f, .exp=1};
+  float const fract = tint_symbol_1.fract;
+  frexp_result const tint_symbol_2 = frexp_result{.fract=0.625f, .exp=1};
+  int const exp = tint_symbol_2.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.spvasm b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.spvasm
new file mode 100644
index 0000000..a8c2cb1
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.spvasm
@@ -0,0 +1,20 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 9
+; 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_625 = OpConstant %float 0.625
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.wgsl b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.wgsl
new file mode 100644
index 0000000..94a6b90
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/const_members.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  const in = 1.25;
+  const res = frexp(in);
+  let fract : f32 = res.fract;
+  let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/mixed.wgsl b/test/tint/builtins/frexp/scalar/mixed.wgsl
new file mode 100644
index 0000000..18049a4
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+    const const_in = 1.25;
+    let runtime_in = 1.25;
+    var res = frexp(const_in);
+    res = frexp(runtime_in);
+    res = frexp(const_in);
+    let fract : f32 = res.fract;
+    let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..b1dc653
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.dxc.hlsl
@@ -0,0 +1,22 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+frexp_result tint_frexp(float param_0) {
+  float exp;
+  float fract = frexp(param_0, exp);
+  frexp_result result = {fract, int(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float runtime_in = 1.25f;
+  frexp_result res = {0.625f, 1};
+  res = tint_frexp(runtime_in);
+  const frexp_result c = {0.625f, 1};
+  res = c;
+  const float fract = res.fract;
+  const int exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..b1dc653
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.fxc.hlsl
@@ -0,0 +1,22 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+frexp_result tint_frexp(float param_0) {
+  float exp;
+  float fract = frexp(param_0, exp);
+  frexp_result result = {fract, int(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float runtime_in = 1.25f;
+  frexp_result res = {0.625f, 1};
+  res = tint_frexp(runtime_in);
+  const frexp_result c = {0.625f, 1};
+  res = c;
+  const float fract = res.fract;
+  const int exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.glsl b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.glsl
new file mode 100644
index 0000000..cd9010d
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+frexp_result tint_frexp(float param_0) {
+  frexp_result result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+
+void tint_symbol() {
+  float runtime_in = 1.25f;
+  frexp_result res = frexp_result(0.625f, 1);
+  res = tint_frexp(runtime_in);
+  res = frexp_result(0.625f, 1);
+  float tint_symbol_1 = res.fract;
+  int tint_symbol_2 = res.exp;
+}
+
+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/frexp/scalar/mixed.wgsl.expected.msl b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.msl
new file mode 100644
index 0000000..029f4e2
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+frexp_result tint_frexp(float param_0) {
+  frexp_result result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float const runtime_in = 1.25f;
+  frexp_result res = frexp_result{.fract=0.625f, .exp=1};
+  res = tint_frexp(runtime_in);
+  res = frexp_result{.fract=0.625f, .exp=1};
+  float const fract = res.fract;
+  int const exp = res.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.spvasm b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..d87b243
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.spvasm
@@ -0,0 +1,46 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+               OpCapability Shader
+         %16 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__frexp_result "__frexp_result"
+               OpMemberName %__frexp_result 0 "fract"
+               OpMemberName %__frexp_result 1 "exp"
+               OpName %res "res"
+               OpMemberDecorate %__frexp_result 0 Offset 0
+               OpMemberDecorate %__frexp_result 1 Offset 4
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+ %float_1_25 = OpConstant %float 1.25
+        %int = OpTypeInt 32 1
+%__frexp_result = OpTypeStruct %float %int
+%float_0_625 = OpConstant %float 0.625
+      %int_1 = OpConstant %int 1
+         %11 = OpConstantComposite %__frexp_result %float_0_625 %int_1
+%_ptr_Function___frexp_result = OpTypePointer Function %__frexp_result
+         %14 = OpConstantNull %__frexp_result
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Function_float = OpTypePointer Function %float
+     %uint_1 = OpConstant %uint 1
+%_ptr_Function_int = OpTypePointer Function %int
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result Function %14
+               OpStore %res %11
+         %15 = OpExtInst %__frexp_result %16 FrexpStruct %float_1_25
+               OpStore %res %15
+               OpStore %res %11
+         %20 = OpAccessChain %_ptr_Function_float %res %uint_0
+         %21 = OpLoad %float %20
+         %24 = OpAccessChain %_ptr_Function_int %res %uint_1
+         %25 = OpLoad %int %24
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.wgsl b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..c46880d
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/mixed.wgsl.expected.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+  const const_in = 1.25;
+  let runtime_in = 1.25;
+  var res = frexp(const_in);
+  res = frexp(runtime_in);
+  res = frexp(const_in);
+  let fract : f32 = res.fract;
+  let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/runtime.wgsl b/test/tint/builtins/frexp/scalar/runtime.wgsl
new file mode 100644
index 0000000..fdf9b45
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    let in = 1.25;
+    let res = frexp(in);
+    let fract : f32 = res.fract;
+    let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..3f6cc50
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.dxc.hlsl
@@ -0,0 +1,19 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+frexp_result tint_frexp(float param_0) {
+  float exp;
+  float fract = frexp(param_0, exp);
+  frexp_result result = {fract, int(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float tint_symbol = 1.25f;
+  const frexp_result res = tint_frexp(tint_symbol);
+  const float fract = res.fract;
+  const int exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..3f6cc50
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.fxc.hlsl
@@ -0,0 +1,19 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+frexp_result tint_frexp(float param_0) {
+  float exp;
+  float fract = frexp(param_0, exp);
+  frexp_result result = {fract, int(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float tint_symbol = 1.25f;
+  const frexp_result res = tint_frexp(tint_symbol);
+  const float fract = res.fract;
+  const int exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.glsl b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.glsl
new file mode 100644
index 0000000..4e3c642
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.glsl
@@ -0,0 +1,26 @@
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+frexp_result tint_frexp(float param_0) {
+  frexp_result result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+
+void tint_symbol() {
+  float tint_symbol_1 = 1.25f;
+  frexp_result res = tint_frexp(tint_symbol_1);
+  float tint_symbol_2 = res.fract;
+  int tint_symbol_3 = res.exp;
+}
+
+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/frexp/scalar/runtime.wgsl.expected.msl b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.msl
new file mode 100644
index 0000000..97eff80
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+frexp_result tint_frexp(float param_0) {
+  frexp_result result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float const in = 1.25f;
+  frexp_result const res = tint_frexp(in);
+  float const fract = res.fract;
+  int const exp = res.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.spvasm b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.spvasm
new file mode 100644
index 0000000..cf7a5ce
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.spvasm
@@ -0,0 +1,29 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 13
+; Schema: 0
+               OpCapability Shader
+         %10 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__frexp_result "__frexp_result"
+               OpMemberName %__frexp_result 0 "fract"
+               OpMemberName %__frexp_result 1 "exp"
+               OpMemberDecorate %__frexp_result 0 Offset 0
+               OpMemberDecorate %__frexp_result 1 Offset 4
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+ %float_1_25 = OpConstant %float 1.25
+        %int = OpTypeInt 32 1
+%__frexp_result = OpTypeStruct %float %int
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+          %7 = OpExtInst %__frexp_result %10 FrexpStruct %float_1_25
+         %11 = OpCompositeExtract %float %7 0
+         %12 = OpCompositeExtract %int %7 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.wgsl b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.wgsl
new file mode 100644
index 0000000..300cf78
--- /dev/null
+++ b/test/tint/builtins/frexp/scalar/runtime.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  let in = 1.25;
+  let res = frexp(in);
+  let fract : f32 = res.fract;
+  let exp : i32 = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/const.wgsl b/test/tint/builtins/frexp/vector/const.wgsl
new file mode 100644
index 0000000..eb44c96
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    const in = vec2(1.25, 3.75);
+    let res = frexp(in);
+    let fract : vec2<f32> = res.fract;
+    let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/const.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/vector/const.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..8bba86f
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl.expected.dxc.hlsl
@@ -0,0 +1,11 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result_vec2 res = {float2(0.625f, 0.9375f), int2(1, 2)};
+  const float2 fract = res.fract;
+  const int2 exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/const.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/vector/const.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..8bba86f
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl.expected.fxc.hlsl
@@ -0,0 +1,11 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result_vec2 res = {float2(0.625f, 0.9375f), int2(1, 2)};
+  const float2 fract = res.fract;
+  const int2 exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/const.wgsl.expected.glsl b/test/tint/builtins/frexp/vector/const.wgsl.expected.glsl
new file mode 100644
index 0000000..1bf02ab
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl.expected.glsl
@@ -0,0 +1,19 @@
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void tint_symbol() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.625f, 0.9375f), ivec2(1, 2));
+  vec2 tint_symbol_2 = res.fract;
+  ivec2 tint_symbol_3 = res.exp;
+}
+
+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/frexp/vector/const.wgsl.expected.msl b/test/tint/builtins/frexp/vector/const.wgsl.expected.msl
new file mode 100644
index 0000000..fb5dd60
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl.expected.msl
@@ -0,0 +1,15 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+kernel void tint_symbol() {
+  frexp_result_vec2 const res = frexp_result_vec2{.fract=float2(0.625f, 0.9375f), .exp=int2(1, 2)};
+  float2 const fract = res.fract;
+  int2 const exp = res.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/vector/const.wgsl.expected.spvasm b/test/tint/builtins/frexp/vector/const.wgsl.expected.spvasm
new file mode 100644
index 0000000..50a68f2
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl.expected.spvasm
@@ -0,0 +1,35 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 19
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__frexp_result_vec2 "__frexp_result_vec2"
+               OpMemberName %__frexp_result_vec2 0 "fract"
+               OpMemberName %__frexp_result_vec2 1 "exp"
+               OpMemberDecorate %__frexp_result_vec2 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec2 1 Offset 8
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%__frexp_result_vec2 = OpTypeStruct %v2float %v2int
+%float_0_625 = OpConstant %float 0.625
+%float_0_9375 = OpConstant %float 0.9375
+         %12 = OpConstantComposite %v2float %float_0_625 %float_0_9375
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+         %15 = OpConstantComposite %v2int %int_1 %int_2
+         %16 = OpConstantComposite %__frexp_result_vec2 %12 %15
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+         %17 = OpCompositeExtract %v2float %16 0
+         %18 = OpCompositeExtract %v2int %16 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/vector/const.wgsl.expected.wgsl b/test/tint/builtins/frexp/vector/const.wgsl.expected.wgsl
new file mode 100644
index 0000000..71a7f52
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  const in = vec2(1.25, 3.75);
+  let res = frexp(in);
+  let fract : vec2<f32> = res.fract;
+  let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/const_members.wgsl b/test/tint/builtins/frexp/vector/const_members.wgsl
new file mode 100644
index 0000000..71375c5
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    const in = vec2(1.25, 3.75);
+    const res = frexp(in);
+    let fract : vec2<f32> = res.fract;
+    let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/const_members.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..b3c80eb
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.dxc.hlsl
@@ -0,0 +1,12 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result_vec2 tint_symbol_1 = {float2(0.625f, 0.9375f), int2(1, 2)};
+  const float2 fract = tint_symbol_1.fract;
+  const frexp_result_vec2 tint_symbol_2 = {float2(0.625f, 0.9375f), int2(1, 2)};
+  const int2 exp = tint_symbol_2.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/const_members.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..b3c80eb
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.fxc.hlsl
@@ -0,0 +1,12 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+[numthreads(1, 1, 1)]
+void main() {
+  const frexp_result_vec2 tint_symbol_1 = {float2(0.625f, 0.9375f), int2(1, 2)};
+  const float2 fract = tint_symbol_1.fract;
+  const frexp_result_vec2 tint_symbol_2 = {float2(0.625f, 0.9375f), int2(1, 2)};
+  const int2 exp = tint_symbol_2.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/const_members.wgsl.expected.glsl b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.glsl
new file mode 100644
index 0000000..ae073ab
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.glsl
@@ -0,0 +1,20 @@
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void tint_symbol() {
+  frexp_result_vec2 tint_symbol_4 = frexp_result_vec2(vec2(0.625f, 0.9375f), ivec2(1, 2));
+  vec2 tint_symbol_2 = tint_symbol_4.fract;
+  frexp_result_vec2 tint_symbol_5 = frexp_result_vec2(vec2(0.625f, 0.9375f), ivec2(1, 2));
+  ivec2 tint_symbol_3 = tint_symbol_5.exp;
+}
+
+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/frexp/vector/const_members.wgsl.expected.msl b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.msl
new file mode 100644
index 0000000..bf97772
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.msl
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+kernel void tint_symbol() {
+  frexp_result_vec2 const tint_symbol_1 = frexp_result_vec2{.fract=float2(0.625f, 0.9375f), .exp=int2(1, 2)};
+  float2 const fract = tint_symbol_1.fract;
+  frexp_result_vec2 const tint_symbol_2 = frexp_result_vec2{.fract=float2(0.625f, 0.9375f), .exp=int2(1, 2)};
+  int2 const exp = tint_symbol_2.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/vector/const_members.wgsl.expected.spvasm b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.spvasm
new file mode 100644
index 0000000..4a729e8
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.spvasm
@@ -0,0 +1,26 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; 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_625 = OpConstant %float 0.625
+%float_0_9375 = OpConstant %float 0.9375
+          %9 = OpConstantComposite %v2float %float_0_625 %float_0_9375
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+         %14 = OpConstantComposite %v2int %int_1 %int_2
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/vector/const_members.wgsl.expected.wgsl b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.wgsl
new file mode 100644
index 0000000..1cb2f7f
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/const_members.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  const in = vec2(1.25, 3.75);
+  const res = frexp(in);
+  let fract : vec2<f32> = res.fract;
+  let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/mixed.wgsl b/test/tint/builtins/frexp/vector/mixed.wgsl
new file mode 100644
index 0000000..edf1927
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+    const const_in = vec2(1.25, 3.75);
+    let runtime_in = vec2(1.25, 3.75);
+    var res = frexp(const_in);
+    res = frexp(runtime_in);
+    res = frexp(const_in);
+    let fract : vec2<f32> = res.fract;
+    let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/mixed.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..7d6adb3
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.dxc.hlsl
@@ -0,0 +1,22 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+frexp_result_vec2 tint_frexp(float2 param_0) {
+  float2 exp;
+  float2 fract = frexp(param_0, exp);
+  frexp_result_vec2 result = {fract, int2(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 runtime_in = float2(1.25f, 3.75f);
+  frexp_result_vec2 res = {float2(0.625f, 0.9375f), int2(1, 2)};
+  res = tint_frexp(runtime_in);
+  const frexp_result_vec2 c = {float2(0.625f, 0.9375f), int2(1, 2)};
+  res = c;
+  const float2 fract = res.fract;
+  const int2 exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/mixed.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..7d6adb3
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.fxc.hlsl
@@ -0,0 +1,22 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+frexp_result_vec2 tint_frexp(float2 param_0) {
+  float2 exp;
+  float2 fract = frexp(param_0, exp);
+  frexp_result_vec2 result = {fract, int2(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 runtime_in = float2(1.25f, 3.75f);
+  frexp_result_vec2 res = {float2(0.625f, 0.9375f), int2(1, 2)};
+  res = tint_frexp(runtime_in);
+  const frexp_result_vec2 c = {float2(0.625f, 0.9375f), int2(1, 2)};
+  res = c;
+  const float2 fract = res.fract;
+  const int2 exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/mixed.wgsl.expected.glsl b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.glsl
new file mode 100644
index 0000000..82d9710
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+frexp_result_vec2 tint_frexp(vec2 param_0) {
+  frexp_result_vec2 result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+
+void tint_symbol() {
+  vec2 runtime_in = vec2(1.25f, 3.75f);
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.625f, 0.9375f), ivec2(1, 2));
+  res = tint_frexp(runtime_in);
+  res = frexp_result_vec2(vec2(0.625f, 0.9375f), ivec2(1, 2));
+  vec2 tint_symbol_1 = res.fract;
+  ivec2 tint_symbol_2 = res.exp;
+}
+
+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/frexp/vector/mixed.wgsl.expected.msl b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.msl
new file mode 100644
index 0000000..aba51ab
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+frexp_result_vec2 tint_frexp(float2 param_0) {
+  frexp_result_vec2 result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float2 const runtime_in = float2(1.25f, 3.75f);
+  frexp_result_vec2 res = frexp_result_vec2{.fract=float2(0.625f, 0.9375f), .exp=int2(1, 2)};
+  res = tint_frexp(runtime_in);
+  res = frexp_result_vec2{.fract=float2(0.625f, 0.9375f), .exp=int2(1, 2)};
+  float2 const fract = res.fract;
+  int2 const exp = res.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/vector/mixed.wgsl.expected.spvasm b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..2b45647
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.spvasm
@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+               OpCapability Shader
+         %24 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__frexp_result_vec2 "__frexp_result_vec2"
+               OpMemberName %__frexp_result_vec2 0 "fract"
+               OpMemberName %__frexp_result_vec2 1 "exp"
+               OpName %res "res"
+               OpMemberDecorate %__frexp_result_vec2 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec2 1 Offset 8
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+ %float_1_25 = OpConstant %float 1.25
+ %float_3_75 = OpConstant %float 3.75
+          %9 = OpConstantComposite %v2float %float_1_25 %float_3_75
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%__frexp_result_vec2 = OpTypeStruct %v2float %v2int
+%float_0_625 = OpConstant %float 0.625
+%float_0_9375 = OpConstant %float 0.9375
+         %15 = OpConstantComposite %v2float %float_0_625 %float_0_9375
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+         %18 = OpConstantComposite %v2int %int_1 %int_2
+         %19 = OpConstantComposite %__frexp_result_vec2 %15 %18
+%_ptr_Function___frexp_result_vec2 = OpTypePointer Function %__frexp_result_vec2
+         %22 = OpConstantNull %__frexp_result_vec2
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+     %uint_1 = OpConstant %uint 1
+%_ptr_Function_v2int = OpTypePointer Function %v2int
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec2 Function %22
+               OpStore %res %19
+         %23 = OpExtInst %__frexp_result_vec2 %24 FrexpStruct %9
+               OpStore %res %23
+               OpStore %res %19
+         %28 = OpAccessChain %_ptr_Function_v2float %res %uint_0
+         %29 = OpLoad %v2float %28
+         %32 = OpAccessChain %_ptr_Function_v2int %res %uint_1
+         %33 = OpLoad %v2int %32
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/vector/mixed.wgsl.expected.wgsl b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..cf570ad
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/mixed.wgsl.expected.wgsl
@@ -0,0 +1,10 @@
+@compute @workgroup_size(1)
+fn main() {
+  const const_in = vec2(1.25, 3.75);
+  let runtime_in = vec2(1.25, 3.75);
+  var res = frexp(const_in);
+  res = frexp(runtime_in);
+  res = frexp(const_in);
+  let fract : vec2<f32> = res.fract;
+  let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/runtime.wgsl b/test/tint/builtins/frexp/vector/runtime.wgsl
new file mode 100644
index 0000000..bb595dd
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+    let in = vec2(1.25, 3.75);
+    let res = frexp(in);
+    let fract : vec2<f32> = res.fract;
+    let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/frexp/vector/runtime.wgsl.expected.dxc.hlsl b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..ea744b6
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.dxc.hlsl
@@ -0,0 +1,19 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+frexp_result_vec2 tint_frexp(float2 param_0) {
+  float2 exp;
+  float2 fract = frexp(param_0, exp);
+  frexp_result_vec2 result = {fract, int2(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 tint_symbol = float2(1.25f, 3.75f);
+  const frexp_result_vec2 res = tint_frexp(tint_symbol);
+  const float2 fract = res.fract;
+  const int2 exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/runtime.wgsl.expected.fxc.hlsl b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..ea744b6
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.fxc.hlsl
@@ -0,0 +1,19 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+frexp_result_vec2 tint_frexp(float2 param_0) {
+  float2 exp;
+  float2 fract = frexp(param_0, exp);
+  frexp_result_vec2 result = {fract, int2(exp)};
+  return result;
+}
+
+[numthreads(1, 1, 1)]
+void main() {
+  const float2 tint_symbol = float2(1.25f, 3.75f);
+  const frexp_result_vec2 res = tint_frexp(tint_symbol);
+  const float2 fract = res.fract;
+  const int2 exp = res.exp;
+  return;
+}
diff --git a/test/tint/builtins/frexp/vector/runtime.wgsl.expected.glsl b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.glsl
new file mode 100644
index 0000000..ded971f
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.glsl
@@ -0,0 +1,26 @@
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+frexp_result_vec2 tint_frexp(vec2 param_0) {
+  frexp_result_vec2 result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+
+void tint_symbol() {
+  vec2 tint_symbol_1 = vec2(1.25f, 3.75f);
+  frexp_result_vec2 res = tint_frexp(tint_symbol_1);
+  vec2 tint_symbol_2 = res.fract;
+  ivec2 tint_symbol_3 = res.exp;
+}
+
+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/frexp/vector/runtime.wgsl.expected.msl b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.msl
new file mode 100644
index 0000000..30cf6cc
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+frexp_result_vec2 tint_frexp(float2 param_0) {
+  frexp_result_vec2 result;
+  result.fract = frexp(param_0, result.exp);
+  return result;
+}
+
+kernel void tint_symbol() {
+  float2 const in = float2(1.25f, 3.75f);
+  frexp_result_vec2 const res = tint_frexp(in);
+  float2 const fract = res.fract;
+  int2 const exp = res.exp;
+  return;
+}
+
diff --git a/test/tint/builtins/frexp/vector/runtime.wgsl.expected.spvasm b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.spvasm
new file mode 100644
index 0000000..8541b98
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.spvasm
@@ -0,0 +1,33 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 17
+; Schema: 0
+               OpCapability Shader
+         %14 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %__frexp_result_vec2 "__frexp_result_vec2"
+               OpMemberName %__frexp_result_vec2 0 "fract"
+               OpMemberName %__frexp_result_vec2 1 "exp"
+               OpMemberDecorate %__frexp_result_vec2 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec2 1 Offset 8
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+ %float_1_25 = OpConstant %float 1.25
+ %float_3_75 = OpConstant %float 3.75
+          %9 = OpConstantComposite %v2float %float_1_25 %float_3_75
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%__frexp_result_vec2 = OpTypeStruct %v2float %v2int
+       %main = OpFunction %void None %1
+          %4 = OpLabel
+         %10 = OpExtInst %__frexp_result_vec2 %14 FrexpStruct %9
+         %15 = OpCompositeExtract %v2float %10 0
+         %16 = OpCompositeExtract %v2int %10 1
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/frexp/vector/runtime.wgsl.expected.wgsl b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.wgsl
new file mode 100644
index 0000000..2665db3
--- /dev/null
+++ b/test/tint/builtins/frexp/vector/runtime.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+@compute @workgroup_size(1)
+fn main() {
+  let in = vec2(1.25, 3.75);
+  let res = frexp(in);
+  let fract : vec2<f32> = res.fract;
+  let exp : vec2<i32> = res.exp;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl
new file mode 100644
index 0000000..c6e393a
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl
@@ -0,0 +1,43 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(vec<4, fa>) -> __frexp_result_vec<4, fa>
+fn frexp_34bbfb() {
+  var res = frexp(vec4(1.));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_34bbfb();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_34bbfb();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_34bbfb();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..f0571de
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec4 {
+  float4 fract;
+  int4 exp;
+};
+void frexp_34bbfb() {
+  frexp_result_vec4 res = {(0.5f).xxxx, (1).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_34bbfb();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_34bbfb();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_34bbfb();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..f0571de
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec4 {
+  float4 fract;
+  int4 exp;
+};
+void frexp_34bbfb() {
+  frexp_result_vec4 res = {(0.5f).xxxx, (1).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_34bbfb();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_34bbfb();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_34bbfb();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.glsl
new file mode 100644
index 0000000..b05fb00
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result_vec4 {
+  vec4 fract;
+  ivec4 exp;
+};
+
+
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
+}
+
+vec4 vertex_main() {
+  frexp_34bbfb();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result_vec4 {
+  vec4 fract;
+  ivec4 exp;
+};
+
+
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
+}
+
+void fragment_main() {
+  frexp_34bbfb();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result_vec4 {
+  vec4 fract;
+  ivec4 exp;
+};
+
+
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
+}
+
+void compute_main() {
+  frexp_34bbfb();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.msl
new file mode 100644
index 0000000..1a5b652
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec4 {
+  float4 fract;
+  int4 exp;
+};
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4{.fract=float4(0.5f), .exp=int4(1)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_34bbfb();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_34bbfb();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_34bbfb();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.spvasm
new file mode 100644
index 0000000..146a713
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.spvasm
@@ -0,0 +1,77 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 38
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_34bbfb "frexp_34bbfb"
+               OpName %__frexp_result_vec4 "__frexp_result_vec4"
+               OpMemberName %__frexp_result_vec4 0 "fract"
+               OpMemberName %__frexp_result_vec4 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result_vec4 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec4 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %v4int = OpTypeVector %int 4
+%__frexp_result_vec4 = OpTypeStruct %v4float %v4int
+  %float_0_5 = OpConstant %float 0.5
+         %17 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %19 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
+         %20 = OpConstantComposite %__frexp_result_vec4 %17 %19
+%_ptr_Function___frexp_result_vec4 = OpTypePointer Function %__frexp_result_vec4
+         %23 = OpConstantNull %__frexp_result_vec4
+         %24 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_34bbfb = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec4 Function %23
+               OpStore %res %20
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %24
+         %26 = OpLabel
+         %27 = OpFunctionCall %void %frexp_34bbfb
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %29 = OpLabel
+         %30 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %30
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %33 = OpLabel
+         %34 = OpFunctionCall %void %frexp_34bbfb
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %36 = OpLabel
+         %37 = OpFunctionCall %void %frexp_34bbfb
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.wgsl
new file mode 100644
index 0000000..809d0bd
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/34bbfb.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn frexp_34bbfb() {
+  var res = frexp(vec4(1.0));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_34bbfb();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_34bbfb();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_34bbfb();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.dxc.hlsl
index 7c8df2f..38aad8c 100644
--- a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   vector<float16_t, 4> fract;
   int4 exp;
 };
-frexp_result_vec4_f16 tint_frexp(vector<float16_t, 4> param_0) {
-  vector<float16_t, 4> exp;
-  vector<float16_t, 4> fract = frexp(param_0, exp);
-  frexp_result_vec4_f16 result = {fract, int4(exp)};
-  return result;
-}
-
 void frexp_3dd21e() {
-  frexp_result_vec4_f16 res = tint_frexp((float16_t(1.0h)).xxxx);
+  frexp_result_vec4_f16 res = {(float16_t(0.5h)).xxxx, (1).xxxx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.glsl
index a84c5d2..273b556 100644
--- a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.glsl
@@ -6,15 +6,9 @@
   ivec4 exp;
 };
 
-frexp_result_vec4_f16 tint_frexp(f16vec4 param_0) {
-  frexp_result_vec4_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_3dd21e() {
-  frexp_result_vec4_f16 res = tint_frexp(f16vec4(1.0hf));
+  frexp_result_vec4_f16 res = frexp_result_vec4_f16(f16vec4(0.5hf), ivec4(1));
 }
 
 vec4 vertex_main() {
@@ -39,15 +33,9 @@
   ivec4 exp;
 };
 
-frexp_result_vec4_f16 tint_frexp(f16vec4 param_0) {
-  frexp_result_vec4_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_3dd21e() {
-  frexp_result_vec4_f16 res = tint_frexp(f16vec4(1.0hf));
+  frexp_result_vec4_f16 res = frexp_result_vec4_f16(f16vec4(0.5hf), ivec4(1));
 }
 
 void fragment_main() {
@@ -66,15 +54,9 @@
   ivec4 exp;
 };
 
-frexp_result_vec4_f16 tint_frexp(f16vec4 param_0) {
-  frexp_result_vec4_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_3dd21e() {
-  frexp_result_vec4_f16 res = tint_frexp(f16vec4(1.0hf));
+  frexp_result_vec4_f16 res = frexp_result_vec4_f16(f16vec4(0.5hf), ivec4(1));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.msl
index 2ea4018..c5b011c 100644
--- a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.msl
@@ -6,14 +6,8 @@
   half4 fract;
   int4 exp;
 };
-frexp_result_vec4_f16 tint_frexp(half4 param_0) {
-  frexp_result_vec4_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_3dd21e() {
-  frexp_result_vec4_f16 res = tint_frexp(half4(1.0h));
+  frexp_result_vec4_f16 res = frexp_result_vec4_f16{.fract=half4(0.5h), .exp=int4(1)};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.spvasm
index 7e70b12..1edb7a7 100644
--- a/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/3dd21e.wgsl.expected.spvasm
@@ -1,14 +1,13 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 39
+; Bound: 40
 ; Schema: 0
                OpCapability Shader
                OpCapability Float16
                OpCapability UniformAndStorageBuffer16BitAccess
                OpCapability StorageBuffer16BitAccess
                OpCapability StorageInputOutput16
-         %19 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -45,38 +44,40 @@
         %int = OpTypeInt 32 1
       %v4int = OpTypeVector %int 4
 %__frexp_result_vec4_f16 = OpTypeStruct %v4half %v4int
-%half_0x1p_0 = OpConstant %half 0x1p+0
-         %21 = OpConstantComposite %v4half %half_0x1p_0 %half_0x1p_0 %half_0x1p_0 %half_0x1p_0
+%half_0x1pn1 = OpConstant %half 0x1p-1
+         %19 = OpConstantComposite %v4half %half_0x1pn1 %half_0x1pn1 %half_0x1pn1 %half_0x1pn1
+      %int_1 = OpConstant %int 1
+         %21 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
+         %22 = OpConstantComposite %__frexp_result_vec4_f16 %19 %21
 %_ptr_Function___frexp_result_vec4_f16 = OpTypePointer Function %__frexp_result_vec4_f16
-         %24 = OpConstantNull %__frexp_result_vec4_f16
-         %25 = OpTypeFunction %v4float
+         %25 = OpConstantNull %__frexp_result_vec4_f16
+         %26 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
 %frexp_3dd21e = OpFunction %void None %9
          %12 = OpLabel
-        %res = OpVariable %_ptr_Function___frexp_result_vec4_f16 Function %24
-         %13 = OpExtInst %__frexp_result_vec4_f16 %19 FrexpStruct %21
-               OpStore %res %13
+        %res = OpVariable %_ptr_Function___frexp_result_vec4_f16 Function %25
+               OpStore %res %22
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %25
-         %27 = OpLabel
-         %28 = OpFunctionCall %void %frexp_3dd21e
+%vertex_main_inner = OpFunction %v4float None %26
+         %28 = OpLabel
+         %29 = OpFunctionCall %void %frexp_3dd21e
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %9
-         %30 = OpLabel
-         %31 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %31
+         %31 = OpLabel
+         %32 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %32
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %frexp_3dd21e
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %frexp_3dd21e
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %37 = OpLabel
-         %38 = OpFunctionCall %void %frexp_3dd21e
+         %38 = OpLabel
+         %39 = OpFunctionCall %void %frexp_3dd21e
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.dxc.hlsl
index 8737fe5..31de0eb 100644
--- a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  float exp;
-  float fract = frexp(param_0, exp);
-  frexp_result result = {fract, int(exp)};
-  return result;
-}
-
 void frexp_4b2200() {
-  frexp_result res = tint_frexp(1.0f);
+  frexp_result res = {0.5f, 1};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.fxc.hlsl
index 8737fe5..31de0eb 100644
--- a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.fxc.hlsl
@@ -2,15 +2,8 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  float exp;
-  float fract = frexp(param_0, exp);
-  frexp_result result = {fract, int(exp)};
-  return result;
-}
-
 void frexp_4b2200() {
-  frexp_result res = tint_frexp(1.0f);
+  frexp_result res = {0.5f, 1};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.glsl
index 2e58875..f5a158d 100644
--- a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.glsl
@@ -5,15 +5,9 @@
   int exp;
 };
 
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_4b2200() {
-  frexp_result res = tint_frexp(1.0f);
+  frexp_result res = frexp_result(0.5f, 1);
 }
 
 vec4 vertex_main() {
@@ -37,15 +31,9 @@
   int exp;
 };
 
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_4b2200() {
-  frexp_result res = tint_frexp(1.0f);
+  frexp_result res = frexp_result(0.5f, 1);
 }
 
 void fragment_main() {
@@ -63,15 +51,9 @@
   int exp;
 };
 
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_4b2200() {
-  frexp_result res = tint_frexp(1.0f);
+  frexp_result res = frexp_result(0.5f, 1);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.msl
index b979b5d..1fa65d3 100644
--- a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.msl
@@ -6,14 +6,8 @@
   float fract;
   int exp;
 };
-frexp_result tint_frexp(float param_0) {
-  frexp_result result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_4b2200() {
-  frexp_result res = tint_frexp(1.0f);
+  frexp_result res = frexp_result{.fract=0.5f, .exp=1};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.spvasm
index e67480b..2b4eb35 100644
--- a/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/4b2200.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 34
+; Bound: 35
 ; Schema: 0
                OpCapability Shader
-         %16 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -38,15 +37,17 @@
           %9 = OpTypeFunction %void
         %int = OpTypeInt 32 1
 %__frexp_result = OpTypeStruct %float %int
-    %float_1 = OpConstant %float 1
+  %float_0_5 = OpConstant %float 0.5
+      %int_1 = OpConstant %int 1
+         %17 = OpConstantComposite %__frexp_result %float_0_5 %int_1
 %_ptr_Function___frexp_result = OpTypePointer Function %__frexp_result
          %20 = OpConstantNull %__frexp_result
          %21 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
 %frexp_4b2200 = OpFunction %void None %9
          %12 = OpLabel
         %res = OpVariable %_ptr_Function___frexp_result Function %20
-         %13 = OpExtInst %__frexp_result %16 FrexpStruct %float_1
-               OpStore %res %13
+               OpStore %res %17
                OpReturn
                OpFunctionEnd
 %vertex_main_inner = OpFunction %v4float None %21
@@ -62,12 +63,12 @@
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %29 = OpLabel
-         %30 = OpFunctionCall %void %frexp_4b2200
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %frexp_4b2200
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %32 = OpLabel
-         %33 = OpFunctionCall %void %frexp_4b2200
+         %33 = OpLabel
+         %34 = OpFunctionCall %void %frexp_4b2200
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.dxc.hlsl
index abe82bc..09b1676 100644
--- a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   float16_t fract;
   int exp;
 };
-frexp_result_f16 tint_frexp(float16_t param_0) {
-  float16_t exp;
-  float16_t fract = frexp(param_0, exp);
-  frexp_result_f16 result = {fract, int(exp)};
-  return result;
-}
-
 void frexp_5257dd() {
-  frexp_result_f16 res = tint_frexp(float16_t(1.0h));
+  frexp_result_f16 res = {float16_t(0.5h), 1};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.glsl
index 226b7cc..eae6d64 100644
--- a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.glsl
@@ -6,15 +6,9 @@
   int exp;
 };
 
-frexp_result_f16 tint_frexp(float16_t param_0) {
-  frexp_result_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_5257dd() {
-  frexp_result_f16 res = tint_frexp(1.0hf);
+  frexp_result_f16 res = frexp_result_f16(0.5hf, 1);
 }
 
 vec4 vertex_main() {
@@ -39,15 +33,9 @@
   int exp;
 };
 
-frexp_result_f16 tint_frexp(float16_t param_0) {
-  frexp_result_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_5257dd() {
-  frexp_result_f16 res = tint_frexp(1.0hf);
+  frexp_result_f16 res = frexp_result_f16(0.5hf, 1);
 }
 
 void fragment_main() {
@@ -66,15 +54,9 @@
   int exp;
 };
 
-frexp_result_f16 tint_frexp(float16_t param_0) {
-  frexp_result_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_5257dd() {
-  frexp_result_f16 res = tint_frexp(1.0hf);
+  frexp_result_f16 res = frexp_result_f16(0.5hf, 1);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.msl
index 404e632..06dbf41 100644
--- a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.msl
@@ -6,14 +6,8 @@
   half fract;
   int exp;
 };
-frexp_result_f16 tint_frexp(half param_0) {
-  frexp_result_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_5257dd() {
-  frexp_result_f16 res = tint_frexp(1.0h);
+  frexp_result_f16 res = frexp_result_f16{.fract=0.5h, .exp=1};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.spvasm
index c750b75..3c9f0f4 100644
--- a/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/5257dd.wgsl.expected.spvasm
@@ -8,7 +8,6 @@
                OpCapability UniformAndStorageBuffer16BitAccess
                OpCapability StorageBuffer16BitAccess
                OpCapability StorageInputOutput16
-         %17 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -43,7 +42,9 @@
        %half = OpTypeFloat 16
         %int = OpTypeInt 32 1
 %__frexp_result_f16 = OpTypeStruct %half %int
-%half_0x1p_0 = OpConstant %half 0x1p+0
+%half_0x1pn1 = OpConstant %half 0x1p-1
+      %int_1 = OpConstant %int 1
+         %18 = OpConstantComposite %__frexp_result_f16 %half_0x1pn1 %int_1
 %_ptr_Function___frexp_result_f16 = OpTypePointer Function %__frexp_result_f16
          %21 = OpConstantNull %__frexp_result_f16
          %22 = OpTypeFunction %v4float
@@ -51,8 +52,7 @@
 %frexp_5257dd = OpFunction %void None %9
          %12 = OpLabel
         %res = OpVariable %_ptr_Function___frexp_result_f16 Function %21
-         %13 = OpExtInst %__frexp_result_f16 %17 FrexpStruct %half_0x1p_0
-               OpStore %res %13
+               OpStore %res %18
                OpReturn
                OpFunctionEnd
 %vertex_main_inner = OpFunction %v4float None %22
diff --git a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.dxc.hlsl
index 059e50c..3244bf1 100644
--- a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   vector<float16_t, 2> fract;
   int2 exp;
 };
-frexp_result_vec2_f16 tint_frexp(vector<float16_t, 2> param_0) {
-  vector<float16_t, 2> exp;
-  vector<float16_t, 2> fract = frexp(param_0, exp);
-  frexp_result_vec2_f16 result = {fract, int2(exp)};
-  return result;
-}
-
 void frexp_5f47bf() {
-  frexp_result_vec2_f16 res = tint_frexp((float16_t(1.0h)).xx);
+  frexp_result_vec2_f16 res = {(float16_t(0.5h)).xx, (1).xx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.glsl
index 4b44bc9..6c074b6 100644
--- a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.glsl
@@ -6,15 +6,9 @@
   ivec2 exp;
 };
 
-frexp_result_vec2_f16 tint_frexp(f16vec2 param_0) {
-  frexp_result_vec2_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_5f47bf() {
-  frexp_result_vec2_f16 res = tint_frexp(f16vec2(1.0hf));
+  frexp_result_vec2_f16 res = frexp_result_vec2_f16(f16vec2(0.5hf), ivec2(1));
 }
 
 vec4 vertex_main() {
@@ -39,15 +33,9 @@
   ivec2 exp;
 };
 
-frexp_result_vec2_f16 tint_frexp(f16vec2 param_0) {
-  frexp_result_vec2_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_5f47bf() {
-  frexp_result_vec2_f16 res = tint_frexp(f16vec2(1.0hf));
+  frexp_result_vec2_f16 res = frexp_result_vec2_f16(f16vec2(0.5hf), ivec2(1));
 }
 
 void fragment_main() {
@@ -66,15 +54,9 @@
   ivec2 exp;
 };
 
-frexp_result_vec2_f16 tint_frexp(f16vec2 param_0) {
-  frexp_result_vec2_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_5f47bf() {
-  frexp_result_vec2_f16 res = tint_frexp(f16vec2(1.0hf));
+  frexp_result_vec2_f16 res = frexp_result_vec2_f16(f16vec2(0.5hf), ivec2(1));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.msl
index 942cd07..de30665 100644
--- a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.msl
@@ -6,14 +6,8 @@
   half2 fract;
   int2 exp;
 };
-frexp_result_vec2_f16 tint_frexp(half2 param_0) {
-  frexp_result_vec2_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_5f47bf() {
-  frexp_result_vec2_f16 res = tint_frexp(half2(1.0h));
+  frexp_result_vec2_f16 res = frexp_result_vec2_f16{.fract=half2(0.5h), .exp=int2(1)};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.spvasm
index 6c21824..b6ccbe0 100644
--- a/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/5f47bf.wgsl.expected.spvasm
@@ -1,14 +1,13 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 39
+; Bound: 40
 ; Schema: 0
                OpCapability Shader
                OpCapability Float16
                OpCapability UniformAndStorageBuffer16BitAccess
                OpCapability StorageBuffer16BitAccess
                OpCapability StorageInputOutput16
-         %19 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -45,38 +44,40 @@
         %int = OpTypeInt 32 1
       %v2int = OpTypeVector %int 2
 %__frexp_result_vec2_f16 = OpTypeStruct %v2half %v2int
-%half_0x1p_0 = OpConstant %half 0x1p+0
-         %21 = OpConstantComposite %v2half %half_0x1p_0 %half_0x1p_0
+%half_0x1pn1 = OpConstant %half 0x1p-1
+         %19 = OpConstantComposite %v2half %half_0x1pn1 %half_0x1pn1
+      %int_1 = OpConstant %int 1
+         %21 = OpConstantComposite %v2int %int_1 %int_1
+         %22 = OpConstantComposite %__frexp_result_vec2_f16 %19 %21
 %_ptr_Function___frexp_result_vec2_f16 = OpTypePointer Function %__frexp_result_vec2_f16
-         %24 = OpConstantNull %__frexp_result_vec2_f16
-         %25 = OpTypeFunction %v4float
+         %25 = OpConstantNull %__frexp_result_vec2_f16
+         %26 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
 %frexp_5f47bf = OpFunction %void None %9
          %12 = OpLabel
-        %res = OpVariable %_ptr_Function___frexp_result_vec2_f16 Function %24
-         %13 = OpExtInst %__frexp_result_vec2_f16 %19 FrexpStruct %21
-               OpStore %res %13
+        %res = OpVariable %_ptr_Function___frexp_result_vec2_f16 Function %25
+               OpStore %res %22
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %25
-         %27 = OpLabel
-         %28 = OpFunctionCall %void %frexp_5f47bf
+%vertex_main_inner = OpFunction %v4float None %26
+         %28 = OpLabel
+         %29 = OpFunctionCall %void %frexp_5f47bf
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %9
-         %30 = OpLabel
-         %31 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %31
+         %31 = OpLabel
+         %32 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %32
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %frexp_5f47bf
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %frexp_5f47bf
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %37 = OpLabel
-         %38 = OpFunctionCall %void %frexp_5f47bf
+         %38 = OpLabel
+         %39 = OpFunctionCall %void %frexp_5f47bf
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl
new file mode 100644
index 0000000..5b10ae9
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl
@@ -0,0 +1,43 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(vec<2, fa>) -> __frexp_result_vec<2, fa>
+fn frexp_6fb3ad() {
+  var res = frexp(vec2(1.));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_6fb3ad();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_6fb3ad();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_6fb3ad();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..cc4ff35
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = {(0.5f).xx, (1).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_6fb3ad();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_6fb3ad();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_6fb3ad();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..cc4ff35
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = {(0.5f).xx, (1).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_6fb3ad();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_6fb3ad();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_6fb3ad();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.glsl
new file mode 100644
index 0000000..e5ecc96
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
+}
+
+vec4 vertex_main() {
+  frexp_6fb3ad();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
+}
+
+void fragment_main() {
+  frexp_6fb3ad();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
+}
+
+void compute_main() {
+  frexp_6fb3ad();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.msl
new file mode 100644
index 0000000..5356433
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2{.fract=float2(0.5f), .exp=int2(1)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_6fb3ad();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_6fb3ad();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_6fb3ad();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.spvasm
new file mode 100644
index 0000000..1d03915
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 39
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_6fb3ad "frexp_6fb3ad"
+               OpName %__frexp_result_vec2 "__frexp_result_vec2"
+               OpMemberName %__frexp_result_vec2 0 "fract"
+               OpMemberName %__frexp_result_vec2 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result_vec2 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec2 1 Offset 8
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v2float = OpTypeVector %float 2
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%__frexp_result_vec2 = OpTypeStruct %v2float %v2int
+  %float_0_5 = OpConstant %float 0.5
+         %18 = OpConstantComposite %v2float %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %20 = OpConstantComposite %v2int %int_1 %int_1
+         %21 = OpConstantComposite %__frexp_result_vec2 %18 %20
+%_ptr_Function___frexp_result_vec2 = OpTypePointer Function %__frexp_result_vec2
+         %24 = OpConstantNull %__frexp_result_vec2
+         %25 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_6fb3ad = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec2 Function %24
+               OpStore %res %21
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %25
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %frexp_6fb3ad
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %31
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %frexp_6fb3ad
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %frexp_6fb3ad
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.wgsl
new file mode 100644
index 0000000..472008b
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/6fb3ad.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn frexp_6fb3ad() {
+  var res = frexp(vec2(1.0));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_6fb3ad();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_6fb3ad();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_6fb3ad();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.dxc.hlsl
index edc72cb..9305a1e 100644
--- a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   float4 fract;
   int4 exp;
 };
-frexp_result_vec4 tint_frexp(float4 param_0) {
-  float4 exp;
-  float4 fract = frexp(param_0, exp);
-  frexp_result_vec4 result = {fract, int4(exp)};
-  return result;
-}
-
 void frexp_77af93() {
-  frexp_result_vec4 res = tint_frexp((1.0f).xxxx);
+  frexp_result_vec4 res = {(0.5f).xxxx, (1).xxxx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.fxc.hlsl
index edc72cb..9305a1e 100644
--- a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.fxc.hlsl
@@ -2,15 +2,8 @@
   float4 fract;
   int4 exp;
 };
-frexp_result_vec4 tint_frexp(float4 param_0) {
-  float4 exp;
-  float4 fract = frexp(param_0, exp);
-  frexp_result_vec4 result = {fract, int4(exp)};
-  return result;
-}
-
 void frexp_77af93() {
-  frexp_result_vec4 res = tint_frexp((1.0f).xxxx);
+  frexp_result_vec4 res = {(0.5f).xxxx, (1).xxxx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.glsl
index f346a3f..5361fab 100644
--- a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.glsl
@@ -5,15 +5,9 @@
   ivec4 exp;
 };
 
-frexp_result_vec4 tint_frexp(vec4 param_0) {
-  frexp_result_vec4 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_77af93() {
-  frexp_result_vec4 res = tint_frexp(vec4(1.0f));
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
 }
 
 vec4 vertex_main() {
@@ -37,15 +31,9 @@
   ivec4 exp;
 };
 
-frexp_result_vec4 tint_frexp(vec4 param_0) {
-  frexp_result_vec4 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_77af93() {
-  frexp_result_vec4 res = tint_frexp(vec4(1.0f));
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
 }
 
 void fragment_main() {
@@ -63,15 +51,9 @@
   ivec4 exp;
 };
 
-frexp_result_vec4 tint_frexp(vec4 param_0) {
-  frexp_result_vec4 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_77af93() {
-  frexp_result_vec4 res = tint_frexp(vec4(1.0f));
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.msl
index ebe3fb6..448b118 100644
--- a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.msl
@@ -6,14 +6,8 @@
   float4 fract;
   int4 exp;
 };
-frexp_result_vec4 tint_frexp(float4 param_0) {
-  frexp_result_vec4 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_77af93() {
-  frexp_result_vec4 res = tint_frexp(float4(1.0f));
+  frexp_result_vec4 res = frexp_result_vec4{.fract=float4(0.5f), .exp=int4(1)};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.spvasm
index 5c18e02..5ee2467 100644
--- a/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/77af93.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 36
+; Bound: 38
 ; Schema: 0
                OpCapability Shader
-         %17 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -39,37 +38,40 @@
         %int = OpTypeInt 32 1
       %v4int = OpTypeVector %int 4
 %__frexp_result_vec4 = OpTypeStruct %v4float %v4int
-    %float_1 = OpConstant %float 1
-         %19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+  %float_0_5 = OpConstant %float 0.5
+         %17 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %19 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
+         %20 = OpConstantComposite %__frexp_result_vec4 %17 %19
 %_ptr_Function___frexp_result_vec4 = OpTypePointer Function %__frexp_result_vec4
-         %22 = OpConstantNull %__frexp_result_vec4
-         %23 = OpTypeFunction %v4float
+         %23 = OpConstantNull %__frexp_result_vec4
+         %24 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
 %frexp_77af93 = OpFunction %void None %9
          %12 = OpLabel
-        %res = OpVariable %_ptr_Function___frexp_result_vec4 Function %22
-         %13 = OpExtInst %__frexp_result_vec4 %17 FrexpStruct %19
-               OpStore %res %13
+        %res = OpVariable %_ptr_Function___frexp_result_vec4 Function %23
+               OpStore %res %20
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %23
-         %25 = OpLabel
-         %26 = OpFunctionCall %void %frexp_77af93
+%vertex_main_inner = OpFunction %v4float None %24
+         %26 = OpLabel
+         %27 = OpFunctionCall %void %frexp_77af93
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %9
-         %28 = OpLabel
-         %29 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %29
+         %29 = OpLabel
+         %30 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %30
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %31 = OpLabel
-         %32 = OpFunctionCall %void %frexp_77af93
+         %33 = OpLabel
+         %34 = OpFunctionCall %void %frexp_77af93
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %frexp_77af93
+         %36 = OpLabel
+         %37 = OpFunctionCall %void %frexp_77af93
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.dxc.hlsl
index 5638db7..3952e5e 100644
--- a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   float3 fract;
   int3 exp;
 };
-frexp_result_vec3 tint_frexp(float3 param_0) {
-  float3 exp;
-  float3 fract = frexp(param_0, exp);
-  frexp_result_vec3 result = {fract, int3(exp)};
-  return result;
-}
-
 void frexp_979800() {
-  frexp_result_vec3 res = tint_frexp((1.0f).xxx);
+  frexp_result_vec3 res = {(0.5f).xxx, (1).xxx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.fxc.hlsl
index 5638db7..3952e5e 100644
--- a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.fxc.hlsl
@@ -2,15 +2,8 @@
   float3 fract;
   int3 exp;
 };
-frexp_result_vec3 tint_frexp(float3 param_0) {
-  float3 exp;
-  float3 fract = frexp(param_0, exp);
-  frexp_result_vec3 result = {fract, int3(exp)};
-  return result;
-}
-
 void frexp_979800() {
-  frexp_result_vec3 res = tint_frexp((1.0f).xxx);
+  frexp_result_vec3 res = {(0.5f).xxx, (1).xxx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.glsl
index 815df55..0e99f61 100644
--- a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.glsl
@@ -5,15 +5,9 @@
   ivec3 exp;
 };
 
-frexp_result_vec3 tint_frexp(vec3 param_0) {
-  frexp_result_vec3 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_979800() {
-  frexp_result_vec3 res = tint_frexp(vec3(1.0f));
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
 }
 
 vec4 vertex_main() {
@@ -37,15 +31,9 @@
   ivec3 exp;
 };
 
-frexp_result_vec3 tint_frexp(vec3 param_0) {
-  frexp_result_vec3 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_979800() {
-  frexp_result_vec3 res = tint_frexp(vec3(1.0f));
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
 }
 
 void fragment_main() {
@@ -63,15 +51,9 @@
   ivec3 exp;
 };
 
-frexp_result_vec3 tint_frexp(vec3 param_0) {
-  frexp_result_vec3 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_979800() {
-  frexp_result_vec3 res = tint_frexp(vec3(1.0f));
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.msl
index dfd3a1c..5dbe0f6 100644
--- a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.msl
@@ -6,14 +6,8 @@
   float3 fract;
   int3 exp;
 };
-frexp_result_vec3 tint_frexp(float3 param_0) {
-  frexp_result_vec3 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_979800() {
-  frexp_result_vec3 res = tint_frexp(float3(1.0f));
+  frexp_result_vec3 res = frexp_result_vec3{.fract=float3(0.5f), .exp=int3(1)};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.spvasm
index 78eb763..82afd21 100644
--- a/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/979800.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 37
+; Bound: 39
 ; Schema: 0
                OpCapability Shader
-         %18 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -40,37 +39,40 @@
         %int = OpTypeInt 32 1
       %v3int = OpTypeVector %int 3
 %__frexp_result_vec3 = OpTypeStruct %v3float %v3int
-    %float_1 = OpConstant %float 1
-         %20 = OpConstantComposite %v3float %float_1 %float_1 %float_1
+  %float_0_5 = OpConstant %float 0.5
+         %18 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %20 = OpConstantComposite %v3int %int_1 %int_1 %int_1
+         %21 = OpConstantComposite %__frexp_result_vec3 %18 %20
 %_ptr_Function___frexp_result_vec3 = OpTypePointer Function %__frexp_result_vec3
-         %23 = OpConstantNull %__frexp_result_vec3
-         %24 = OpTypeFunction %v4float
+         %24 = OpConstantNull %__frexp_result_vec3
+         %25 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
 %frexp_979800 = OpFunction %void None %9
          %12 = OpLabel
-        %res = OpVariable %_ptr_Function___frexp_result_vec3 Function %23
-         %13 = OpExtInst %__frexp_result_vec3 %18 FrexpStruct %20
-               OpStore %res %13
+        %res = OpVariable %_ptr_Function___frexp_result_vec3 Function %24
+               OpStore %res %21
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %24
-         %26 = OpLabel
-         %27 = OpFunctionCall %void %frexp_979800
+%vertex_main_inner = OpFunction %v4float None %25
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %frexp_979800
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %9
-         %29 = OpLabel
-         %30 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %30
+         %30 = OpLabel
+         %31 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %31
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %32 = OpLabel
-         %33 = OpFunctionCall %void %frexp_979800
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %frexp_979800
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %35 = OpLabel
-         %36 = OpFunctionCall %void %frexp_979800
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %frexp_979800
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.dxc.hlsl
index 1ae9ade..e64f0fe 100644
--- a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   vector<float16_t, 3> fract;
   int3 exp;
 };
-frexp_result_vec3_f16 tint_frexp(vector<float16_t, 3> param_0) {
-  vector<float16_t, 3> exp;
-  vector<float16_t, 3> fract = frexp(param_0, exp);
-  frexp_result_vec3_f16 result = {fract, int3(exp)};
-  return result;
-}
-
 void frexp_ae4a66() {
-  frexp_result_vec3_f16 res = tint_frexp((float16_t(1.0h)).xxx);
+  frexp_result_vec3_f16 res = {(float16_t(0.5h)).xxx, (1).xxx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.glsl
index d5d3e9b..fecb412 100644
--- a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.glsl
@@ -6,15 +6,9 @@
   ivec3 exp;
 };
 
-frexp_result_vec3_f16 tint_frexp(f16vec3 param_0) {
-  frexp_result_vec3_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_ae4a66() {
-  frexp_result_vec3_f16 res = tint_frexp(f16vec3(1.0hf));
+  frexp_result_vec3_f16 res = frexp_result_vec3_f16(f16vec3(0.5hf), ivec3(1));
 }
 
 vec4 vertex_main() {
@@ -39,15 +33,9 @@
   ivec3 exp;
 };
 
-frexp_result_vec3_f16 tint_frexp(f16vec3 param_0) {
-  frexp_result_vec3_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_ae4a66() {
-  frexp_result_vec3_f16 res = tint_frexp(f16vec3(1.0hf));
+  frexp_result_vec3_f16 res = frexp_result_vec3_f16(f16vec3(0.5hf), ivec3(1));
 }
 
 void fragment_main() {
@@ -66,15 +54,9 @@
   ivec3 exp;
 };
 
-frexp_result_vec3_f16 tint_frexp(f16vec3 param_0) {
-  frexp_result_vec3_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_ae4a66() {
-  frexp_result_vec3_f16 res = tint_frexp(f16vec3(1.0hf));
+  frexp_result_vec3_f16 res = frexp_result_vec3_f16(f16vec3(0.5hf), ivec3(1));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.msl
index 140dcd8..16c1374 100644
--- a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.msl
@@ -6,14 +6,8 @@
   half3 fract;
   int3 exp;
 };
-frexp_result_vec3_f16 tint_frexp(half3 param_0) {
-  frexp_result_vec3_f16 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_ae4a66() {
-  frexp_result_vec3_f16 res = tint_frexp(half3(1.0h));
+  frexp_result_vec3_f16 res = frexp_result_vec3_f16{.fract=half3(0.5h), .exp=int3(1)};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.spvasm
index f483930..af26946 100644
--- a/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/ae4a66.wgsl.expected.spvasm
@@ -1,14 +1,13 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 39
+; Bound: 40
 ; Schema: 0
                OpCapability Shader
                OpCapability Float16
                OpCapability UniformAndStorageBuffer16BitAccess
                OpCapability StorageBuffer16BitAccess
                OpCapability StorageInputOutput16
-         %19 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -45,38 +44,40 @@
         %int = OpTypeInt 32 1
       %v3int = OpTypeVector %int 3
 %__frexp_result_vec3_f16 = OpTypeStruct %v3half %v3int
-%half_0x1p_0 = OpConstant %half 0x1p+0
-         %21 = OpConstantComposite %v3half %half_0x1p_0 %half_0x1p_0 %half_0x1p_0
+%half_0x1pn1 = OpConstant %half 0x1p-1
+         %19 = OpConstantComposite %v3half %half_0x1pn1 %half_0x1pn1 %half_0x1pn1
+      %int_1 = OpConstant %int 1
+         %21 = OpConstantComposite %v3int %int_1 %int_1 %int_1
+         %22 = OpConstantComposite %__frexp_result_vec3_f16 %19 %21
 %_ptr_Function___frexp_result_vec3_f16 = OpTypePointer Function %__frexp_result_vec3_f16
-         %24 = OpConstantNull %__frexp_result_vec3_f16
-         %25 = OpTypeFunction %v4float
+         %25 = OpConstantNull %__frexp_result_vec3_f16
+         %26 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
 %frexp_ae4a66 = OpFunction %void None %9
          %12 = OpLabel
-        %res = OpVariable %_ptr_Function___frexp_result_vec3_f16 Function %24
-         %13 = OpExtInst %__frexp_result_vec3_f16 %19 FrexpStruct %21
-               OpStore %res %13
+        %res = OpVariable %_ptr_Function___frexp_result_vec3_f16 Function %25
+               OpStore %res %22
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %25
-         %27 = OpLabel
-         %28 = OpFunctionCall %void %frexp_ae4a66
+%vertex_main_inner = OpFunction %v4float None %26
+         %28 = OpLabel
+         %29 = OpFunctionCall %void %frexp_ae4a66
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %9
-         %30 = OpLabel
-         %31 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %31
+         %31 = OpLabel
+         %32 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %32
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %frexp_ae4a66
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %frexp_ae4a66
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %37 = OpLabel
-         %38 = OpFunctionCall %void %frexp_ae4a66
+         %38 = OpLabel
+         %39 = OpFunctionCall %void %frexp_ae4a66
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl b/test/tint/builtins/gen/literal/frexp/bee870.wgsl
new file mode 100644
index 0000000..62bdbc6
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl
@@ -0,0 +1,43 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(fa) -> __frexp_result<fa>
+fn frexp_bee870() {
+  var res = frexp(1.);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bee870();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bee870();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bee870();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..efbe069
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+void frexp_bee870() {
+  frexp_result res = {0.5f, 1};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bee870();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bee870();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bee870();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..efbe069
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+void frexp_bee870() {
+  frexp_result res = {0.5f, 1};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bee870();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bee870();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bee870();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.glsl
new file mode 100644
index 0000000..0e94ee2
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void frexp_bee870() {
+  frexp_result res = frexp_result(0.5f, 1);
+}
+
+vec4 vertex_main() {
+  frexp_bee870();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void frexp_bee870() {
+  frexp_result res = frexp_result(0.5f, 1);
+}
+
+void fragment_main() {
+  frexp_bee870();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void frexp_bee870() {
+  frexp_result res = frexp_result(0.5f, 1);
+}
+
+void compute_main() {
+  frexp_bee870();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.msl
new file mode 100644
index 0000000..8c2107d
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+void frexp_bee870() {
+  frexp_result res = frexp_result{.fract=0.5f, .exp=1};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_bee870();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_bee870();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_bee870();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.spvasm
new file mode 100644
index 0000000..b2675a6
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 35
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_bee870 "frexp_bee870"
+               OpName %__frexp_result "__frexp_result"
+               OpMemberName %__frexp_result 0 "fract"
+               OpMemberName %__frexp_result 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result 0 Offset 0
+               OpMemberDecorate %__frexp_result 1 Offset 4
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+%__frexp_result = OpTypeStruct %float %int
+  %float_0_5 = OpConstant %float 0.5
+      %int_1 = OpConstant %int 1
+         %17 = OpConstantComposite %__frexp_result %float_0_5 %int_1
+%_ptr_Function___frexp_result = OpTypePointer Function %__frexp_result
+         %20 = OpConstantNull %__frexp_result
+         %21 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_bee870 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result Function %20
+               OpStore %res %17
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %21
+         %23 = OpLabel
+         %24 = OpFunctionCall %void %frexp_bee870
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %26 = OpLabel
+         %27 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %27
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %frexp_bee870
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %33 = OpLabel
+         %34 = OpFunctionCall %void %frexp_bee870
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.wgsl
new file mode 100644
index 0000000..b3e97d4
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bee870.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn frexp_bee870() {
+  var res = frexp(1.0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bee870();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bee870();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bee870();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl
new file mode 100644
index 0000000..87876d6
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl
@@ -0,0 +1,43 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(vec<3, fa>) -> __frexp_result_vec<3, fa>
+fn frexp_bf45ae() {
+  var res = frexp(vec3(1.));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bf45ae();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bf45ae();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bf45ae();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..c896f2b
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec3 {
+  float3 fract;
+  int3 exp;
+};
+void frexp_bf45ae() {
+  frexp_result_vec3 res = {(0.5f).xxx, (1).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bf45ae();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bf45ae();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bf45ae();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..c896f2b
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec3 {
+  float3 fract;
+  int3 exp;
+};
+void frexp_bf45ae() {
+  frexp_result_vec3 res = {(0.5f).xxx, (1).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bf45ae();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bf45ae();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bf45ae();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.glsl
new file mode 100644
index 0000000..f7f382e
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result_vec3 {
+  vec3 fract;
+  ivec3 exp;
+};
+
+
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
+}
+
+vec4 vertex_main() {
+  frexp_bf45ae();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result_vec3 {
+  vec3 fract;
+  ivec3 exp;
+};
+
+
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
+}
+
+void fragment_main() {
+  frexp_bf45ae();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result_vec3 {
+  vec3 fract;
+  ivec3 exp;
+};
+
+
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
+}
+
+void compute_main() {
+  frexp_bf45ae();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.msl
new file mode 100644
index 0000000..6bbab11
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec3 {
+  float3 fract;
+  int3 exp;
+};
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3{.fract=float3(0.5f), .exp=int3(1)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_bf45ae();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_bf45ae();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_bf45ae();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.spvasm
new file mode 100644
index 0000000..28459bc
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 39
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_bf45ae "frexp_bf45ae"
+               OpName %__frexp_result_vec3 "__frexp_result_vec3"
+               OpMemberName %__frexp_result_vec3 0 "fract"
+               OpMemberName %__frexp_result_vec3 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result_vec3 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec3 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v3float = OpTypeVector %float 3
+        %int = OpTypeInt 32 1
+      %v3int = OpTypeVector %int 3
+%__frexp_result_vec3 = OpTypeStruct %v3float %v3int
+  %float_0_5 = OpConstant %float 0.5
+         %18 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %20 = OpConstantComposite %v3int %int_1 %int_1 %int_1
+         %21 = OpConstantComposite %__frexp_result_vec3 %18 %20
+%_ptr_Function___frexp_result_vec3 = OpTypePointer Function %__frexp_result_vec3
+         %24 = OpConstantNull %__frexp_result_vec3
+         %25 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_bf45ae = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec3 Function %24
+               OpStore %res %21
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %25
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %frexp_bf45ae
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %31
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %frexp_bf45ae
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %frexp_bf45ae
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.wgsl
new file mode 100644
index 0000000..9cfa8bd
--- /dev/null
+++ b/test/tint/builtins/gen/literal/frexp/bf45ae.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn frexp_bf45ae() {
+  var res = frexp(vec3(1.0));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bf45ae();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bf45ae();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bf45ae();
+}
diff --git a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.dxc.hlsl
index 3e7f473..f0e207c 100644
--- a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.dxc.hlsl
@@ -2,15 +2,8 @@
   float2 fract;
   int2 exp;
 };
-frexp_result_vec2 tint_frexp(float2 param_0) {
-  float2 exp;
-  float2 fract = frexp(param_0, exp);
-  frexp_result_vec2 result = {fract, int2(exp)};
-  return result;
-}
-
 void frexp_eb2421() {
-  frexp_result_vec2 res = tint_frexp((1.0f).xx);
+  frexp_result_vec2 res = {(0.5f).xx, (1).xx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.fxc.hlsl
index 3e7f473..f0e207c 100644
--- a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.fxc.hlsl
@@ -2,15 +2,8 @@
   float2 fract;
   int2 exp;
 };
-frexp_result_vec2 tint_frexp(float2 param_0) {
-  float2 exp;
-  float2 fract = frexp(param_0, exp);
-  frexp_result_vec2 result = {fract, int2(exp)};
-  return result;
-}
-
 void frexp_eb2421() {
-  frexp_result_vec2 res = tint_frexp((1.0f).xx);
+  frexp_result_vec2 res = {(0.5f).xx, (1).xx};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.glsl b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.glsl
index 67638a7..0495b8a 100644
--- a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.glsl
@@ -5,15 +5,9 @@
   ivec2 exp;
 };
 
-frexp_result_vec2 tint_frexp(vec2 param_0) {
-  frexp_result_vec2 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_eb2421() {
-  frexp_result_vec2 res = tint_frexp(vec2(1.0f));
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
 }
 
 vec4 vertex_main() {
@@ -37,15 +31,9 @@
   ivec2 exp;
 };
 
-frexp_result_vec2 tint_frexp(vec2 param_0) {
-  frexp_result_vec2 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_eb2421() {
-  frexp_result_vec2 res = tint_frexp(vec2(1.0f));
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
 }
 
 void fragment_main() {
@@ -63,15 +51,9 @@
   ivec2 exp;
 };
 
-frexp_result_vec2 tint_frexp(vec2 param_0) {
-  frexp_result_vec2 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 
 void frexp_eb2421() {
-  frexp_result_vec2 res = tint_frexp(vec2(1.0f));
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.msl b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.msl
index 47f9335..d920b46 100644
--- a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.msl
@@ -6,14 +6,8 @@
   float2 fract;
   int2 exp;
 };
-frexp_result_vec2 tint_frexp(float2 param_0) {
-  frexp_result_vec2 result;
-  result.fract = frexp(param_0, result.exp);
-  return result;
-}
-
 void frexp_eb2421() {
-  frexp_result_vec2 res = tint_frexp(float2(1.0f));
+  frexp_result_vec2 res = frexp_result_vec2{.fract=float2(0.5f), .exp=int2(1)};
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.spvasm
index 812b9e1..29a8679 100644
--- a/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/frexp/eb2421.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 37
+; Bound: 39
 ; Schema: 0
                OpCapability Shader
-         %18 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -40,37 +39,40 @@
         %int = OpTypeInt 32 1
       %v2int = OpTypeVector %int 2
 %__frexp_result_vec2 = OpTypeStruct %v2float %v2int
-    %float_1 = OpConstant %float 1
-         %20 = OpConstantComposite %v2float %float_1 %float_1
+  %float_0_5 = OpConstant %float 0.5
+         %18 = OpConstantComposite %v2float %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %20 = OpConstantComposite %v2int %int_1 %int_1
+         %21 = OpConstantComposite %__frexp_result_vec2 %18 %20
 %_ptr_Function___frexp_result_vec2 = OpTypePointer Function %__frexp_result_vec2
-         %23 = OpConstantNull %__frexp_result_vec2
-         %24 = OpTypeFunction %v4float
+         %24 = OpConstantNull %__frexp_result_vec2
+         %25 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
 %frexp_eb2421 = OpFunction %void None %9
          %12 = OpLabel
-        %res = OpVariable %_ptr_Function___frexp_result_vec2 Function %23
-         %13 = OpExtInst %__frexp_result_vec2 %18 FrexpStruct %20
-               OpStore %res %13
+        %res = OpVariable %_ptr_Function___frexp_result_vec2 Function %24
+               OpStore %res %21
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %24
-         %26 = OpLabel
-         %27 = OpFunctionCall %void %frexp_eb2421
+%vertex_main_inner = OpFunction %v4float None %25
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %frexp_eb2421
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %9
-         %29 = OpLabel
-         %30 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %30
+         %30 = OpLabel
+         %31 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %31
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %9
-         %32 = OpLabel
-         %33 = OpFunctionCall %void %frexp_eb2421
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %frexp_eb2421
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %9
-         %35 = OpLabel
-         %36 = OpFunctionCall %void %frexp_eb2421
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %frexp_eb2421
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..a09bda3
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec3 {
+  float3 fract;
+  float3 whole;
+};
+void modf_68d8ee() {
+  modf_result_vec3 res = {(-0.5f).xxx, (-1.0f).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_68d8ee();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_68d8ee();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_68d8ee();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..a09bda3
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec3 {
+  float3 fract;
+  float3 whole;
+};
+void modf_68d8ee() {
+  modf_result_vec3 res = {(-0.5f).xxx, (-1.0f).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_68d8ee();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_68d8ee();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_68d8ee();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.glsl b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.glsl
new file mode 100644
index 0000000..24140f3c3
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result_vec3 {
+  vec3 fract;
+  vec3 whole;
+};
+
+
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3(vec3(-0.5f), vec3(-1.0f));
+}
+
+vec4 vertex_main() {
+  modf_68d8ee();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result_vec3 {
+  vec3 fract;
+  vec3 whole;
+};
+
+
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3(vec3(-0.5f), vec3(-1.0f));
+}
+
+void fragment_main() {
+  modf_68d8ee();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result_vec3 {
+  vec3 fract;
+  vec3 whole;
+};
+
+
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3(vec3(-0.5f), vec3(-1.0f));
+}
+
+void compute_main() {
+  modf_68d8ee();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.msl b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.msl
new file mode 100644
index 0000000..d24f9fd
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec3 {
+  float3 fract;
+  float3 whole;
+};
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3{.fract=float3(-0.5f), .whole=float3(-1.0f)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_68d8ee();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_68d8ee();
+  return;
+}
+
+kernel void compute_main() {
+  modf_68d8ee();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.spvasm
new file mode 100644
index 0000000..e08886d
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_68d8ee "modf_68d8ee"
+               OpName %__modf_result_vec3 "__modf_result_vec3"
+               OpMemberName %__modf_result_vec3 0 "fract"
+               OpMemberName %__modf_result_vec3 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result_vec3 0 Offset 0
+               OpMemberDecorate %__modf_result_vec3 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v3float = OpTypeVector %float 3
+%__modf_result_vec3 = OpTypeStruct %v3float %v3float
+ %float_n0_5 = OpConstant %float -0.5
+         %16 = OpConstantComposite %v3float %float_n0_5 %float_n0_5 %float_n0_5
+   %float_n1 = OpConstant %float -1
+         %18 = OpConstantComposite %v3float %float_n1 %float_n1 %float_n1
+         %19 = OpConstantComposite %__modf_result_vec3 %16 %18
+%_ptr_Function___modf_result_vec3 = OpTypePointer Function %__modf_result_vec3
+         %22 = OpConstantNull %__modf_result_vec3
+         %23 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_68d8ee = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec3 Function %22
+               OpStore %res %19
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %23
+         %25 = OpLabel
+         %26 = OpFunctionCall %void %modf_68d8ee
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %28 = OpLabel
+         %29 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %29
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %modf_68d8ee
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %modf_68d8ee
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.wgsl
new file mode 100644
index 0000000..0c6f535
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/68d8ee.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn modf_68d8ee() {
+  var res = modf(vec3(-(1.5)));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_68d8ee();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_68d8ee();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_68d8ee();
+}
diff --git a/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..348870d
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+void modf_732aa6() {
+  modf_result_vec2 res = {(-0.5f).xx, (-1.0f).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_732aa6();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_732aa6();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_732aa6();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..348870d
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+void modf_732aa6() {
+  modf_result_vec2 res = {(-0.5f).xx, (-1.0f).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_732aa6();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_732aa6();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_732aa6();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.glsl b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.glsl
new file mode 100644
index 0000000..0695a32
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2(vec2(-0.5f), vec2(-1.0f));
+}
+
+vec4 vertex_main() {
+  modf_732aa6();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2(vec2(-0.5f), vec2(-1.0f));
+}
+
+void fragment_main() {
+  modf_732aa6();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2(vec2(-0.5f), vec2(-1.0f));
+}
+
+void compute_main() {
+  modf_732aa6();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.msl b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.msl
new file mode 100644
index 0000000..dcb1f40
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2{.fract=float2(-0.5f), .whole=float2(-1.0f)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_732aa6();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_732aa6();
+  return;
+}
+
+kernel void compute_main() {
+  modf_732aa6();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.spvasm
new file mode 100644
index 0000000..28a7da4
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_732aa6 "modf_732aa6"
+               OpName %__modf_result_vec2 "__modf_result_vec2"
+               OpMemberName %__modf_result_vec2 0 "fract"
+               OpMemberName %__modf_result_vec2 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result_vec2 0 Offset 0
+               OpMemberDecorate %__modf_result_vec2 1 Offset 8
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v2float = OpTypeVector %float 2
+%__modf_result_vec2 = OpTypeStruct %v2float %v2float
+ %float_n0_5 = OpConstant %float -0.5
+         %16 = OpConstantComposite %v2float %float_n0_5 %float_n0_5
+   %float_n1 = OpConstant %float -1
+         %18 = OpConstantComposite %v2float %float_n1 %float_n1
+         %19 = OpConstantComposite %__modf_result_vec2 %16 %18
+%_ptr_Function___modf_result_vec2 = OpTypePointer Function %__modf_result_vec2
+         %22 = OpConstantNull %__modf_result_vec2
+         %23 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_732aa6 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec2 Function %22
+               OpStore %res %19
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %23
+         %25 = OpLabel
+         %26 = OpFunctionCall %void %modf_732aa6
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %28 = OpLabel
+         %29 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %29
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %modf_732aa6
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %modf_732aa6
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.wgsl
new file mode 100644
index 0000000..a3fd30e
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/732aa6.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn modf_732aa6() {
+  var res = modf(vec2(-(1.5)));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_732aa6();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_732aa6();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_732aa6();
+}
diff --git a/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..15c5b11
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+void modf_c15f48() {
+  modf_result res = {-0.5f, -1.0f};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_c15f48();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_c15f48();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_c15f48();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..15c5b11
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+void modf_c15f48() {
+  modf_result res = {-0.5f, -1.0f};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_c15f48();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_c15f48();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_c15f48();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.glsl b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.glsl
new file mode 100644
index 0000000..3c6410f
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void modf_c15f48() {
+  modf_result res = modf_result(-0.5f, -1.0f);
+}
+
+vec4 vertex_main() {
+  modf_c15f48();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void modf_c15f48() {
+  modf_result res = modf_result(-0.5f, -1.0f);
+}
+
+void fragment_main() {
+  modf_c15f48();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void modf_c15f48() {
+  modf_result res = modf_result(-0.5f, -1.0f);
+}
+
+void compute_main() {
+  modf_c15f48();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.msl b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.msl
new file mode 100644
index 0000000..676ddc1
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+void modf_c15f48() {
+  modf_result res = modf_result{.fract=-0.5f, .whole=-1.0f};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_c15f48();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_c15f48();
+  return;
+}
+
+kernel void compute_main() {
+  modf_c15f48();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.spvasm
new file mode 100644
index 0000000..c18f9c6
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.spvasm
@@ -0,0 +1,73 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_c15f48 "modf_c15f48"
+               OpName %__modf_result "__modf_result"
+               OpMemberName %__modf_result 0 "fract"
+               OpMemberName %__modf_result 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result 0 Offset 0
+               OpMemberDecorate %__modf_result 1 Offset 4
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+%__modf_result = OpTypeStruct %float %float
+ %float_n0_5 = OpConstant %float -0.5
+   %float_n1 = OpConstant %float -1
+         %16 = OpConstantComposite %__modf_result %float_n0_5 %float_n1
+%_ptr_Function___modf_result = OpTypePointer Function %__modf_result
+         %19 = OpConstantNull %__modf_result
+         %20 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_c15f48 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result Function %19
+               OpStore %res %16
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %20
+         %22 = OpLabel
+         %23 = OpFunctionCall %void %modf_c15f48
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %25 = OpLabel
+         %26 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %26
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %29 = OpLabel
+         %30 = OpFunctionCall %void %modf_c15f48
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %modf_c15f48
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.wgsl
new file mode 100644
index 0000000..3efab9a
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/c15f48.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn modf_c15f48() {
+  var res = modf(-(1.5));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_c15f48();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_c15f48();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_c15f48();
+}
diff --git a/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..e72d03c
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec4 {
+  float4 fract;
+  float4 whole;
+};
+void modf_f3d1f9() {
+  modf_result_vec4 res = {(-0.5f).xxxx, (-1.0f).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_f3d1f9();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_f3d1f9();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_f3d1f9();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..e72d03c
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec4 {
+  float4 fract;
+  float4 whole;
+};
+void modf_f3d1f9() {
+  modf_result_vec4 res = {(-0.5f).xxxx, (-1.0f).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_f3d1f9();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_f3d1f9();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_f3d1f9();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.glsl b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.glsl
new file mode 100644
index 0000000..3f2277d
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result_vec4 {
+  vec4 fract;
+  vec4 whole;
+};
+
+
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4(vec4(-0.5f), vec4(-1.0f));
+}
+
+vec4 vertex_main() {
+  modf_f3d1f9();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result_vec4 {
+  vec4 fract;
+  vec4 whole;
+};
+
+
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4(vec4(-0.5f), vec4(-1.0f));
+}
+
+void fragment_main() {
+  modf_f3d1f9();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result_vec4 {
+  vec4 fract;
+  vec4 whole;
+};
+
+
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4(vec4(-0.5f), vec4(-1.0f));
+}
+
+void compute_main() {
+  modf_f3d1f9();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.msl b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.msl
new file mode 100644
index 0000000..087677a
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec4 {
+  float4 fract;
+  float4 whole;
+};
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4{.fract=float4(-0.5f), .whole=float4(-1.0f)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_f3d1f9();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_f3d1f9();
+  return;
+}
+
+kernel void compute_main() {
+  modf_f3d1f9();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.spvasm
new file mode 100644
index 0000000..629b8a5
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 36
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_f3d1f9 "modf_f3d1f9"
+               OpName %__modf_result_vec4 "__modf_result_vec4"
+               OpMemberName %__modf_result_vec4 0 "fract"
+               OpMemberName %__modf_result_vec4 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result_vec4 0 Offset 0
+               OpMemberDecorate %__modf_result_vec4 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+%__modf_result_vec4 = OpTypeStruct %v4float %v4float
+ %float_n0_5 = OpConstant %float -0.5
+         %15 = OpConstantComposite %v4float %float_n0_5 %float_n0_5 %float_n0_5 %float_n0_5
+   %float_n1 = OpConstant %float -1
+         %17 = OpConstantComposite %v4float %float_n1 %float_n1 %float_n1 %float_n1
+         %18 = OpConstantComposite %__modf_result_vec4 %15 %17
+%_ptr_Function___modf_result_vec4 = OpTypePointer Function %__modf_result_vec4
+         %21 = OpConstantNull %__modf_result_vec4
+         %22 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_f3d1f9 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec4 Function %21
+               OpStore %res %18
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %22
+         %24 = OpLabel
+         %25 = OpFunctionCall %void %modf_f3d1f9
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %28
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %31 = OpLabel
+         %32 = OpFunctionCall %void %modf_f3d1f9
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %modf_f3d1f9
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.wgsl
new file mode 100644
index 0000000..1bc789e
--- /dev/null
+++ b/test/tint/builtins/gen/literal/modf/f3d1f9.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+fn modf_f3d1f9() {
+  var res = modf(vec4(-(1.5)));
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_f3d1f9();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_f3d1f9();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_f3d1f9();
+}
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl
new file mode 100644
index 0000000..5a57803
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl
@@ -0,0 +1,44 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(vec<4, fa>) -> __frexp_result_vec<4, fa>
+fn frexp_34bbfb() {
+  const arg_0 = vec4(1.);
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_34bbfb();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_34bbfb();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_34bbfb();
+}
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..f0571de
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec4 {
+  float4 fract;
+  int4 exp;
+};
+void frexp_34bbfb() {
+  frexp_result_vec4 res = {(0.5f).xxxx, (1).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_34bbfb();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_34bbfb();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_34bbfb();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..f0571de
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec4 {
+  float4 fract;
+  int4 exp;
+};
+void frexp_34bbfb() {
+  frexp_result_vec4 res = {(0.5f).xxxx, (1).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_34bbfb();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_34bbfb();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_34bbfb();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.glsl b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.glsl
new file mode 100644
index 0000000..b05fb00
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result_vec4 {
+  vec4 fract;
+  ivec4 exp;
+};
+
+
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
+}
+
+vec4 vertex_main() {
+  frexp_34bbfb();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result_vec4 {
+  vec4 fract;
+  ivec4 exp;
+};
+
+
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
+}
+
+void fragment_main() {
+  frexp_34bbfb();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result_vec4 {
+  vec4 fract;
+  ivec4 exp;
+};
+
+
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4(vec4(0.5f), ivec4(1));
+}
+
+void compute_main() {
+  frexp_34bbfb();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.msl b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.msl
new file mode 100644
index 0000000..1a5b652
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec4 {
+  float4 fract;
+  int4 exp;
+};
+void frexp_34bbfb() {
+  frexp_result_vec4 res = frexp_result_vec4{.fract=float4(0.5f), .exp=int4(1)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_34bbfb();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_34bbfb();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_34bbfb();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.spvasm b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.spvasm
new file mode 100644
index 0000000..146a713
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.spvasm
@@ -0,0 +1,77 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 38
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_34bbfb "frexp_34bbfb"
+               OpName %__frexp_result_vec4 "__frexp_result_vec4"
+               OpMemberName %__frexp_result_vec4 0 "fract"
+               OpMemberName %__frexp_result_vec4 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result_vec4 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec4 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %v4int = OpTypeVector %int 4
+%__frexp_result_vec4 = OpTypeStruct %v4float %v4int
+  %float_0_5 = OpConstant %float 0.5
+         %17 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %19 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
+         %20 = OpConstantComposite %__frexp_result_vec4 %17 %19
+%_ptr_Function___frexp_result_vec4 = OpTypePointer Function %__frexp_result_vec4
+         %23 = OpConstantNull %__frexp_result_vec4
+         %24 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_34bbfb = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec4 Function %23
+               OpStore %res %20
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %24
+         %26 = OpLabel
+         %27 = OpFunctionCall %void %frexp_34bbfb
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %29 = OpLabel
+         %30 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %30
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %33 = OpLabel
+         %34 = OpFunctionCall %void %frexp_34bbfb
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %36 = OpLabel
+         %37 = OpFunctionCall %void %frexp_34bbfb
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.wgsl b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.wgsl
new file mode 100644
index 0000000..cb64b2b
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/34bbfb.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn frexp_34bbfb() {
+  const arg_0 = vec4(1.0);
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_34bbfb();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_34bbfb();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_34bbfb();
+}
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl
new file mode 100644
index 0000000..a780569
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl
@@ -0,0 +1,44 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(vec<2, fa>) -> __frexp_result_vec<2, fa>
+fn frexp_6fb3ad() {
+  const arg_0 = vec2(1.);
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_6fb3ad();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_6fb3ad();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_6fb3ad();
+}
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..cc4ff35
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = {(0.5f).xx, (1).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_6fb3ad();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_6fb3ad();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_6fb3ad();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..cc4ff35
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = {(0.5f).xx, (1).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_6fb3ad();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_6fb3ad();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_6fb3ad();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.glsl b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.glsl
new file mode 100644
index 0000000..e5ecc96
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
+}
+
+vec4 vertex_main() {
+  frexp_6fb3ad();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
+}
+
+void fragment_main() {
+  frexp_6fb3ad();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result_vec2 {
+  vec2 fract;
+  ivec2 exp;
+};
+
+
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2(vec2(0.5f), ivec2(1));
+}
+
+void compute_main() {
+  frexp_6fb3ad();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.msl b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.msl
new file mode 100644
index 0000000..5356433
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec2 {
+  float2 fract;
+  int2 exp;
+};
+void frexp_6fb3ad() {
+  frexp_result_vec2 res = frexp_result_vec2{.fract=float2(0.5f), .exp=int2(1)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_6fb3ad();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_6fb3ad();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_6fb3ad();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.spvasm b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.spvasm
new file mode 100644
index 0000000..1d03915
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 39
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_6fb3ad "frexp_6fb3ad"
+               OpName %__frexp_result_vec2 "__frexp_result_vec2"
+               OpMemberName %__frexp_result_vec2 0 "fract"
+               OpMemberName %__frexp_result_vec2 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result_vec2 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec2 1 Offset 8
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v2float = OpTypeVector %float 2
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%__frexp_result_vec2 = OpTypeStruct %v2float %v2int
+  %float_0_5 = OpConstant %float 0.5
+         %18 = OpConstantComposite %v2float %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %20 = OpConstantComposite %v2int %int_1 %int_1
+         %21 = OpConstantComposite %__frexp_result_vec2 %18 %20
+%_ptr_Function___frexp_result_vec2 = OpTypePointer Function %__frexp_result_vec2
+         %24 = OpConstantNull %__frexp_result_vec2
+         %25 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_6fb3ad = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec2 Function %24
+               OpStore %res %21
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %25
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %frexp_6fb3ad
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %31
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %frexp_6fb3ad
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %frexp_6fb3ad
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.wgsl b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.wgsl
new file mode 100644
index 0000000..208d085
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/6fb3ad.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn frexp_6fb3ad() {
+  const arg_0 = vec2(1.0);
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_6fb3ad();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_6fb3ad();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_6fb3ad();
+}
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl b/test/tint/builtins/gen/var/frexp/bee870.wgsl
new file mode 100644
index 0000000..9d01b83
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl
@@ -0,0 +1,44 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(fa) -> __frexp_result<fa>
+fn frexp_bee870() {
+  const arg_0 = 1.;
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bee870();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bee870();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bee870();
+}
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..efbe069
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+void frexp_bee870() {
+  frexp_result res = {0.5f, 1};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bee870();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bee870();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bee870();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..efbe069
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result {
+  float fract;
+  int exp;
+};
+void frexp_bee870() {
+  frexp_result res = {0.5f, 1};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bee870();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bee870();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bee870();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.glsl b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.glsl
new file mode 100644
index 0000000..0e94ee2
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void frexp_bee870() {
+  frexp_result res = frexp_result(0.5f, 1);
+}
+
+vec4 vertex_main() {
+  frexp_bee870();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void frexp_bee870() {
+  frexp_result res = frexp_result(0.5f, 1);
+}
+
+void fragment_main() {
+  frexp_bee870();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+
+
+void frexp_bee870() {
+  frexp_result res = frexp_result(0.5f, 1);
+}
+
+void compute_main() {
+  frexp_bee870();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.msl b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.msl
new file mode 100644
index 0000000..8c2107d
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result {
+  float fract;
+  int exp;
+};
+void frexp_bee870() {
+  frexp_result res = frexp_result{.fract=0.5f, .exp=1};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_bee870();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_bee870();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_bee870();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.spvasm b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.spvasm
new file mode 100644
index 0000000..b2675a6
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 35
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_bee870 "frexp_bee870"
+               OpName %__frexp_result "__frexp_result"
+               OpMemberName %__frexp_result 0 "fract"
+               OpMemberName %__frexp_result 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result 0 Offset 0
+               OpMemberDecorate %__frexp_result 1 Offset 4
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+%__frexp_result = OpTypeStruct %float %int
+  %float_0_5 = OpConstant %float 0.5
+      %int_1 = OpConstant %int 1
+         %17 = OpConstantComposite %__frexp_result %float_0_5 %int_1
+%_ptr_Function___frexp_result = OpTypePointer Function %__frexp_result
+         %20 = OpConstantNull %__frexp_result
+         %21 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_bee870 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result Function %20
+               OpStore %res %17
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %21
+         %23 = OpLabel
+         %24 = OpFunctionCall %void %frexp_bee870
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %26 = OpLabel
+         %27 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %27
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %frexp_bee870
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %33 = OpLabel
+         %34 = OpFunctionCall %void %frexp_bee870
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.wgsl b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.wgsl
new file mode 100644
index 0000000..79bda2b
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bee870.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn frexp_bee870() {
+  const arg_0 = 1.0;
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bee870();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bee870();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bee870();
+}
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl
new file mode 100644
index 0000000..c7477ac
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl
@@ -0,0 +1,44 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   test/tint/builtins/gen/gen.wgsl.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+
+// fn frexp(vec<3, fa>) -> __frexp_result_vec<3, fa>
+fn frexp_bf45ae() {
+  const arg_0 = vec3(1.);
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bf45ae();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bf45ae();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bf45ae();
+}
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..c896f2b
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec3 {
+  float3 fract;
+  int3 exp;
+};
+void frexp_bf45ae() {
+  frexp_result_vec3 res = {(0.5f).xxx, (1).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bf45ae();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bf45ae();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bf45ae();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..c896f2b
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct frexp_result_vec3 {
+  float3 fract;
+  int3 exp;
+};
+void frexp_bf45ae() {
+  frexp_result_vec3 res = {(0.5f).xxx, (1).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  frexp_bf45ae();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  frexp_bf45ae();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  frexp_bf45ae();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.glsl b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.glsl
new file mode 100644
index 0000000..f7f382e
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct frexp_result_vec3 {
+  vec3 fract;
+  ivec3 exp;
+};
+
+
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
+}
+
+vec4 vertex_main() {
+  frexp_bf45ae();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct frexp_result_vec3 {
+  vec3 fract;
+  ivec3 exp;
+};
+
+
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
+}
+
+void fragment_main() {
+  frexp_bf45ae();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct frexp_result_vec3 {
+  vec3 fract;
+  ivec3 exp;
+};
+
+
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3(vec3(0.5f), ivec3(1));
+}
+
+void compute_main() {
+  frexp_bf45ae();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.msl b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.msl
new file mode 100644
index 0000000..6bbab11
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec3 {
+  float3 fract;
+  int3 exp;
+};
+void frexp_bf45ae() {
+  frexp_result_vec3 res = frexp_result_vec3{.fract=float3(0.5f), .exp=int3(1)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  frexp_bf45ae();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  frexp_bf45ae();
+  return;
+}
+
+kernel void compute_main() {
+  frexp_bf45ae();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.spvasm b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.spvasm
new file mode 100644
index 0000000..28459bc
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 39
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %frexp_bf45ae "frexp_bf45ae"
+               OpName %__frexp_result_vec3 "__frexp_result_vec3"
+               OpMemberName %__frexp_result_vec3 0 "fract"
+               OpMemberName %__frexp_result_vec3 1 "exp"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__frexp_result_vec3 0 Offset 0
+               OpMemberDecorate %__frexp_result_vec3 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v3float = OpTypeVector %float 3
+        %int = OpTypeInt 32 1
+      %v3int = OpTypeVector %int 3
+%__frexp_result_vec3 = OpTypeStruct %v3float %v3int
+  %float_0_5 = OpConstant %float 0.5
+         %18 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
+      %int_1 = OpConstant %int 1
+         %20 = OpConstantComposite %v3int %int_1 %int_1 %int_1
+         %21 = OpConstantComposite %__frexp_result_vec3 %18 %20
+%_ptr_Function___frexp_result_vec3 = OpTypePointer Function %__frexp_result_vec3
+         %24 = OpConstantNull %__frexp_result_vec3
+         %25 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%frexp_bf45ae = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___frexp_result_vec3 Function %24
+               OpStore %res %21
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %25
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %frexp_bf45ae
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %31
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %frexp_bf45ae
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %frexp_bf45ae
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.wgsl b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.wgsl
new file mode 100644
index 0000000..0cd674d
--- /dev/null
+++ b/test/tint/builtins/gen/var/frexp/bf45ae.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn frexp_bf45ae() {
+  const arg_0 = vec3(1.0);
+  var res = frexp(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  frexp_bf45ae();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  frexp_bf45ae();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  frexp_bf45ae();
+}
diff --git a/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..a09bda3
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec3 {
+  float3 fract;
+  float3 whole;
+};
+void modf_68d8ee() {
+  modf_result_vec3 res = {(-0.5f).xxx, (-1.0f).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_68d8ee();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_68d8ee();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_68d8ee();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..a09bda3
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec3 {
+  float3 fract;
+  float3 whole;
+};
+void modf_68d8ee() {
+  modf_result_vec3 res = {(-0.5f).xxx, (-1.0f).xxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_68d8ee();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_68d8ee();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_68d8ee();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.glsl b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.glsl
new file mode 100644
index 0000000..24140f3c3
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result_vec3 {
+  vec3 fract;
+  vec3 whole;
+};
+
+
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3(vec3(-0.5f), vec3(-1.0f));
+}
+
+vec4 vertex_main() {
+  modf_68d8ee();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result_vec3 {
+  vec3 fract;
+  vec3 whole;
+};
+
+
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3(vec3(-0.5f), vec3(-1.0f));
+}
+
+void fragment_main() {
+  modf_68d8ee();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result_vec3 {
+  vec3 fract;
+  vec3 whole;
+};
+
+
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3(vec3(-0.5f), vec3(-1.0f));
+}
+
+void compute_main() {
+  modf_68d8ee();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.msl b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.msl
new file mode 100644
index 0000000..d24f9fd
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec3 {
+  float3 fract;
+  float3 whole;
+};
+void modf_68d8ee() {
+  modf_result_vec3 res = modf_result_vec3{.fract=float3(-0.5f), .whole=float3(-1.0f)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_68d8ee();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_68d8ee();
+  return;
+}
+
+kernel void compute_main() {
+  modf_68d8ee();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.spvasm b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.spvasm
new file mode 100644
index 0000000..e08886d
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_68d8ee "modf_68d8ee"
+               OpName %__modf_result_vec3 "__modf_result_vec3"
+               OpMemberName %__modf_result_vec3 0 "fract"
+               OpMemberName %__modf_result_vec3 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result_vec3 0 Offset 0
+               OpMemberDecorate %__modf_result_vec3 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v3float = OpTypeVector %float 3
+%__modf_result_vec3 = OpTypeStruct %v3float %v3float
+ %float_n0_5 = OpConstant %float -0.5
+         %16 = OpConstantComposite %v3float %float_n0_5 %float_n0_5 %float_n0_5
+   %float_n1 = OpConstant %float -1
+         %18 = OpConstantComposite %v3float %float_n1 %float_n1 %float_n1
+         %19 = OpConstantComposite %__modf_result_vec3 %16 %18
+%_ptr_Function___modf_result_vec3 = OpTypePointer Function %__modf_result_vec3
+         %22 = OpConstantNull %__modf_result_vec3
+         %23 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_68d8ee = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec3 Function %22
+               OpStore %res %19
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %23
+         %25 = OpLabel
+         %26 = OpFunctionCall %void %modf_68d8ee
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %28 = OpLabel
+         %29 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %29
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %modf_68d8ee
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %modf_68d8ee
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.wgsl b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.wgsl
new file mode 100644
index 0000000..c62b099
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/68d8ee.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn modf_68d8ee() {
+  const arg_0 = vec3(-(1.5));
+  var res = modf(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_68d8ee();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_68d8ee();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_68d8ee();
+}
diff --git a/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..348870d
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+void modf_732aa6() {
+  modf_result_vec2 res = {(-0.5f).xx, (-1.0f).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_732aa6();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_732aa6();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_732aa6();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..348870d
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+void modf_732aa6() {
+  modf_result_vec2 res = {(-0.5f).xx, (-1.0f).xx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_732aa6();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_732aa6();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_732aa6();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.glsl b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.glsl
new file mode 100644
index 0000000..0695a32
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2(vec2(-0.5f), vec2(-1.0f));
+}
+
+vec4 vertex_main() {
+  modf_732aa6();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2(vec2(-0.5f), vec2(-1.0f));
+}
+
+void fragment_main() {
+  modf_732aa6();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result_vec2 {
+  vec2 fract;
+  vec2 whole;
+};
+
+
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2(vec2(-0.5f), vec2(-1.0f));
+}
+
+void compute_main() {
+  modf_732aa6();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.msl b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.msl
new file mode 100644
index 0000000..dcb1f40
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec2 {
+  float2 fract;
+  float2 whole;
+};
+void modf_732aa6() {
+  modf_result_vec2 res = modf_result_vec2{.fract=float2(-0.5f), .whole=float2(-1.0f)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_732aa6();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_732aa6();
+  return;
+}
+
+kernel void compute_main() {
+  modf_732aa6();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.spvasm b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.spvasm
new file mode 100644
index 0000000..28a7da4
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_732aa6 "modf_732aa6"
+               OpName %__modf_result_vec2 "__modf_result_vec2"
+               OpMemberName %__modf_result_vec2 0 "fract"
+               OpMemberName %__modf_result_vec2 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result_vec2 0 Offset 0
+               OpMemberDecorate %__modf_result_vec2 1 Offset 8
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+    %v2float = OpTypeVector %float 2
+%__modf_result_vec2 = OpTypeStruct %v2float %v2float
+ %float_n0_5 = OpConstant %float -0.5
+         %16 = OpConstantComposite %v2float %float_n0_5 %float_n0_5
+   %float_n1 = OpConstant %float -1
+         %18 = OpConstantComposite %v2float %float_n1 %float_n1
+         %19 = OpConstantComposite %__modf_result_vec2 %16 %18
+%_ptr_Function___modf_result_vec2 = OpTypePointer Function %__modf_result_vec2
+         %22 = OpConstantNull %__modf_result_vec2
+         %23 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_732aa6 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec2 Function %22
+               OpStore %res %19
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %23
+         %25 = OpLabel
+         %26 = OpFunctionCall %void %modf_732aa6
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %28 = OpLabel
+         %29 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %29
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %modf_732aa6
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %modf_732aa6
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.wgsl b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.wgsl
new file mode 100644
index 0000000..e1b0b3e
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/732aa6.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn modf_732aa6() {
+  const arg_0 = vec2(-(1.5));
+  var res = modf(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_732aa6();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_732aa6();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_732aa6();
+}
diff --git a/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..15c5b11
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+void modf_c15f48() {
+  modf_result res = {-0.5f, -1.0f};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_c15f48();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_c15f48();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_c15f48();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..15c5b11
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result {
+  float fract;
+  float whole;
+};
+void modf_c15f48() {
+  modf_result res = {-0.5f, -1.0f};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_c15f48();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_c15f48();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_c15f48();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.glsl b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.glsl
new file mode 100644
index 0000000..3c6410f
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void modf_c15f48() {
+  modf_result res = modf_result(-0.5f, -1.0f);
+}
+
+vec4 vertex_main() {
+  modf_c15f48();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void modf_c15f48() {
+  modf_result res = modf_result(-0.5f, -1.0f);
+}
+
+void fragment_main() {
+  modf_c15f48();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+
+
+void modf_c15f48() {
+  modf_result res = modf_result(-0.5f, -1.0f);
+}
+
+void compute_main() {
+  modf_c15f48();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.msl b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.msl
new file mode 100644
index 0000000..676ddc1
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result {
+  float fract;
+  float whole;
+};
+void modf_c15f48() {
+  modf_result res = modf_result{.fract=-0.5f, .whole=-1.0f};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_c15f48();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_c15f48();
+  return;
+}
+
+kernel void compute_main() {
+  modf_c15f48();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.spvasm b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.spvasm
new file mode 100644
index 0000000..c18f9c6
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.spvasm
@@ -0,0 +1,73 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_c15f48 "modf_c15f48"
+               OpName %__modf_result "__modf_result"
+               OpMemberName %__modf_result 0 "fract"
+               OpMemberName %__modf_result 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result 0 Offset 0
+               OpMemberDecorate %__modf_result 1 Offset 4
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+%__modf_result = OpTypeStruct %float %float
+ %float_n0_5 = OpConstant %float -0.5
+   %float_n1 = OpConstant %float -1
+         %16 = OpConstantComposite %__modf_result %float_n0_5 %float_n1
+%_ptr_Function___modf_result = OpTypePointer Function %__modf_result
+         %19 = OpConstantNull %__modf_result
+         %20 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_c15f48 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result Function %19
+               OpStore %res %16
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %20
+         %22 = OpLabel
+         %23 = OpFunctionCall %void %modf_c15f48
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %25 = OpLabel
+         %26 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %26
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %29 = OpLabel
+         %30 = OpFunctionCall %void %modf_c15f48
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %modf_c15f48
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.wgsl b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.wgsl
new file mode 100644
index 0000000..b343662
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/c15f48.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn modf_c15f48() {
+  const arg_0 = -(1.5);
+  var res = modf(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_c15f48();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_c15f48();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_c15f48();
+}
diff --git a/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..e72d03c
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec4 {
+  float4 fract;
+  float4 whole;
+};
+void modf_f3d1f9() {
+  modf_result_vec4 res = {(-0.5f).xxxx, (-1.0f).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_f3d1f9();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_f3d1f9();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_f3d1f9();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..e72d03c
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+struct modf_result_vec4 {
+  float4 fract;
+  float4 whole;
+};
+void modf_f3d1f9() {
+  modf_result_vec4 res = {(-0.5f).xxxx, (-1.0f).xxxx};
+}
+
+struct tint_symbol {
+  float4 value : SV_Position;
+};
+
+float4 vertex_main_inner() {
+  modf_f3d1f9();
+  return (0.0f).xxxx;
+}
+
+tint_symbol vertex_main() {
+  const float4 inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+void fragment_main() {
+  modf_f3d1f9();
+  return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+  modf_f3d1f9();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.glsl b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.glsl
new file mode 100644
index 0000000..3f2277d
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.glsl
@@ -0,0 +1,67 @@
+#version 310 es
+
+struct modf_result_vec4 {
+  vec4 fract;
+  vec4 whole;
+};
+
+
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4(vec4(-0.5f), vec4(-1.0f));
+}
+
+vec4 vertex_main() {
+  modf_f3d1f9();
+  return vec4(0.0f);
+}
+
+void main() {
+  gl_PointSize = 1.0;
+  vec4 inner_result = vertex_main();
+  gl_Position = inner_result;
+  gl_Position.y = -(gl_Position.y);
+  gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+  return;
+}
+#version 310 es
+precision mediump float;
+
+struct modf_result_vec4 {
+  vec4 fract;
+  vec4 whole;
+};
+
+
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4(vec4(-0.5f), vec4(-1.0f));
+}
+
+void fragment_main() {
+  modf_f3d1f9();
+}
+
+void main() {
+  fragment_main();
+  return;
+}
+#version 310 es
+
+struct modf_result_vec4 {
+  vec4 fract;
+  vec4 whole;
+};
+
+
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4(vec4(-0.5f), vec4(-1.0f));
+}
+
+void compute_main() {
+  modf_f3d1f9();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  compute_main();
+  return;
+}
diff --git a/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.msl b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.msl
new file mode 100644
index 0000000..087677a
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct modf_result_vec4 {
+  float4 fract;
+  float4 whole;
+};
+void modf_f3d1f9() {
+  modf_result_vec4 res = modf_result_vec4{.fract=float4(-0.5f), .whole=float4(-1.0f)};
+}
+
+struct tint_symbol {
+  float4 value [[position]];
+};
+
+float4 vertex_main_inner() {
+  modf_f3d1f9();
+  return float4(0.0f);
+}
+
+vertex tint_symbol vertex_main() {
+  float4 const inner_result = vertex_main_inner();
+  tint_symbol wrapper_result = {};
+  wrapper_result.value = inner_result;
+  return wrapper_result;
+}
+
+fragment void fragment_main() {
+  modf_f3d1f9();
+  return;
+}
+
+kernel void compute_main() {
+  modf_f3d1f9();
+  return;
+}
+
diff --git a/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.spvasm b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.spvasm
new file mode 100644
index 0000000..629b8a5
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 36
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
+               OpEntryPoint Fragment %fragment_main "fragment_main"
+               OpEntryPoint GLCompute %compute_main "compute_main"
+               OpExecutionMode %fragment_main OriginUpperLeft
+               OpExecutionMode %compute_main LocalSize 1 1 1
+               OpName %value "value"
+               OpName %vertex_point_size "vertex_point_size"
+               OpName %modf_f3d1f9 "modf_f3d1f9"
+               OpName %__modf_result_vec4 "__modf_result_vec4"
+               OpMemberName %__modf_result_vec4 0 "fract"
+               OpMemberName %__modf_result_vec4 1 "whole"
+               OpName %res "res"
+               OpName %vertex_main_inner "vertex_main_inner"
+               OpName %vertex_main "vertex_main"
+               OpName %fragment_main "fragment_main"
+               OpName %compute_main "compute_main"
+               OpDecorate %value BuiltIn Position
+               OpDecorate %vertex_point_size BuiltIn PointSize
+               OpMemberDecorate %__modf_result_vec4 0 Offset 0
+               OpMemberDecorate %__modf_result_vec4 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+          %5 = OpConstantNull %v4float
+      %value = OpVariable %_ptr_Output_v4float Output %5
+%_ptr_Output_float = OpTypePointer Output %float
+          %8 = OpConstantNull %float
+%vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
+%__modf_result_vec4 = OpTypeStruct %v4float %v4float
+ %float_n0_5 = OpConstant %float -0.5
+         %15 = OpConstantComposite %v4float %float_n0_5 %float_n0_5 %float_n0_5 %float_n0_5
+   %float_n1 = OpConstant %float -1
+         %17 = OpConstantComposite %v4float %float_n1 %float_n1 %float_n1 %float_n1
+         %18 = OpConstantComposite %__modf_result_vec4 %15 %17
+%_ptr_Function___modf_result_vec4 = OpTypePointer Function %__modf_result_vec4
+         %21 = OpConstantNull %__modf_result_vec4
+         %22 = OpTypeFunction %v4float
+    %float_1 = OpConstant %float 1
+%modf_f3d1f9 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function___modf_result_vec4 Function %21
+               OpStore %res %18
+               OpReturn
+               OpFunctionEnd
+%vertex_main_inner = OpFunction %v4float None %22
+         %24 = OpLabel
+         %25 = OpFunctionCall %void %modf_f3d1f9
+               OpReturnValue %5
+               OpFunctionEnd
+%vertex_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %28
+               OpStore %vertex_point_size %float_1
+               OpReturn
+               OpFunctionEnd
+%fragment_main = OpFunction %void None %9
+         %31 = OpLabel
+         %32 = OpFunctionCall %void %modf_f3d1f9
+               OpReturn
+               OpFunctionEnd
+%compute_main = OpFunction %void None %9
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %modf_f3d1f9
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.wgsl b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.wgsl
new file mode 100644
index 0000000..a40cbe8
--- /dev/null
+++ b/test/tint/builtins/gen/var/modf/f3d1f9.wgsl.expected.wgsl
@@ -0,0 +1,20 @@
+fn modf_f3d1f9() {
+  const arg_0 = vec4(-(1.5));
+  var res = modf(arg_0);
+}
+
+@vertex
+fn vertex_main() -> @builtin(position) vec4<f32> {
+  modf_f3d1f9();
+  return vec4<f32>();
+}
+
+@fragment
+fn fragment_main() {
+  modf_f3d1f9();
+}
+
+@compute @workgroup_size(1)
+fn compute_main() {
+  modf_f3d1f9();
+}