Import Tint changes from Dawn

Changes:
  - 451eee0fed2aba9892adddf692f61dfb00956856 tint: Stub intrinsic @const evaluation by Ben Clayton <bclayton@google.com>
  - e0cd855aa26fc8409597025e938c3d955622a400 tint/writer/spirv: Tweak builtin tests to use 'var's by Ben Clayton <bclayton@google.com>
  - e3e91c0d751efae1582e272e1f1f85a8a7454d4a tools: intrinsic-gen - [[decoration]] -> @attribute by Ben Clayton <bclayton@google.com>
  - 0d757d2fad1bdc682f794455b90828c2b3fe7193 tint/resolver: Enable abstract-numerics by Ben Clayton <bclayton@google.com>
  - e593585e2114d3937b7e4d21992dbd79cce5db9b tint/transform: Remove FoldConstants by Ben Clayton <bclayton@google.com>
  - a20ef0c0f137c18872d9266b6082fc734f9fa035 tint/sem: Fix Constant constructor with initializer_list by Ben Clayton <bclayton@google.com>
  - 8e3485248e5d345c168208770279a33d5f09731a tint/writer/spirv: Inline constant expressions by Ben Clayton <bclayton@google.com>
  - 609ce6de8d005fc554a314e2a8251a764b893ad9 tint/sem: Consider sign bit for Constant helpers. by Ben Clayton <bclayton@google.com>
  - e9f8b09063742796695b400a667d44e7260ade6d tint/writer/hlsl: Inline constant expressions by Ben Clayton <bclayton@google.com>
  - 84b48cf30cf42e8a74903d3dd28f0a28380ae076 Tint: num_workgroups use free binding group if not specif... by Zhaoming Jiang <zhaoming.jiang@intel.com>
  - cb6ddd2aa69f1327e0a7b18b7937d65c2a07b0d1 tint/writer/msl: Inline constant expressions by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 451eee0fed2aba9892adddf692f61dfb00956856
Change-Id: If30f613eb61c9c00f90b31aeed3d5a53e94e0641
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/92362
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 0805d5d..e7171a9 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -370,6 +370,8 @@
     "program_id.h",
     "reader/reader.cc",
     "reader/reader.h",
+    "resolver/const_eval.cc",
+    "resolver/const_eval.h",
     "resolver/ctor_conv_intrinsic.cc",
     "resolver/ctor_conv_intrinsic.h",
     "resolver/dependency_graph.cc",
@@ -471,8 +473,6 @@
     "transform/expand_compound_assignment.h",
     "transform/first_index_offset.cc",
     "transform/first_index_offset.h",
-    "transform/fold_constants.cc",
-    "transform/fold_constants.h",
     "transform/fold_trivial_single_use_lets.cc",
     "transform/fold_trivial_single_use_lets.h",
     "transform/for_loop_to_loop.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 2fd7d0d..6ffc36a 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -249,6 +249,8 @@
   program.h
   reader/reader.cc
   reader/reader.h
+  resolver/const_eval.cc
+  resolver/const_eval.h
   resolver/ctor_conv_intrinsic.cc
   resolver/ctor_conv_intrinsic.h
   resolver/dependency_graph.cc
@@ -398,8 +400,6 @@
   transform/expand_compound_assignment.h
   transform/first_index_offset.cc
   transform/first_index_offset.h
-  transform/fold_constants.cc
-  transform/fold_constants.h
   transform/fold_trivial_single_use_lets.cc
   transform/fold_trivial_single_use_lets.h
   transform/for_loop_to_loop.cc
@@ -1079,7 +1079,6 @@
       transform/disable_uniformity_analysis_test.cc
       transform/expand_compound_assignment_test.cc
       transform/first_index_offset_test.cc
-      transform/fold_constants_test.cc
       transform/fold_trivial_single_use_lets_test.cc
       transform/for_loop_to_loop_test.cc
       transform/expand_compound_assignment.cc
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index b9c6d04..c067c39 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -15,7 +15,9 @@
 #include <cstdio>
 #include <fstream>
 #include <iostream>
+#include <limits>
 #include <memory>
+#include <optional>  // NOLINT(build/include_order)
 #include <sstream>
 #include <string>
 #include <vector>
@@ -86,6 +88,7 @@
     std::string dxc_path;
     std::string xcrun_path;
     std::vector<std::string> overrides;
+    std::optional<tint::sem::BindingPoint> hlsl_root_constant_binding_point;
 };
 
 const char kUsage[] = R"(Usage: tint [options] <input-file>
@@ -112,6 +115,11 @@
                                Affects AST dumping, and text-based output languages.
   --dump-inspector-bindings -- Dump reflection data about bindins to stdout.
   -h                        -- This help text
+  --hlsl-root-constant-binding-point <group>,<binding>  -- Binding point for root constant.
+                               Specify the binding point for generated uniform buffer
+                               used for num_workgroups in HLSL. If not specified, then
+                               default to binding 0 of the largest used group plus 1,
+                               or group 0 if no resource bound.
   --validate                -- Validates the generated shader
   --fxc                     -- Ask to validate HLSL output using FXC instead of DXC.
                                When specified, automatically enables --validate
@@ -220,6 +228,27 @@
     return res;
 }
 
+std::optional<uint64_t> parse_unsigned_number(std::string number) {
+    for (char c : number) {
+        if (!std::isdigit(c)) {
+            // Found a non-digital char, return nullopt
+            return std::nullopt;
+        }
+    }
+
+    errno = 0;
+    char* p_end;
+    uint64_t result;
+    // std::strtoull will not throw exception.
+    result = std::strtoull(number.c_str(), &p_end, 10);
+    if ((errno != 0) || (static_cast<size_t>(p_end - number.c_str()) != number.length())) {
+        // Unexpected conversion result
+        return std::nullopt;
+    }
+
+    return result;
+}
+
 std::string TextureDimensionToString(tint::inspector::ResourceBinding::TextureDimension dim) {
     switch (dim) {
         case tint::inspector::ResourceBinding::TextureDimension::kNone:
@@ -402,6 +431,31 @@
                 return false;
             }
             opts->overrides = split_on_comma(args[i]);
+        } else if (arg == "--hlsl-root-constant-binding-point") {
+            ++i;
+            if (i >= args.size()) {
+                std::cerr << "Missing value for " << arg << std::endl;
+                return false;
+            }
+            auto binding_points = split_on_comma(args[i]);
+            if (binding_points.size() != 2) {
+                std::cerr << "Invalid binding point for " << arg << ": " << args[i] << std::endl;
+                return false;
+            }
+            auto group = parse_unsigned_number(binding_points[0]);
+            if ((!group.has_value()) || (group.value() > std::numeric_limits<uint32_t>::max())) {
+                std::cerr << "Invalid group for " << arg << ": " << binding_points[0] << std::endl;
+                return false;
+            }
+            auto binding = parse_unsigned_number(binding_points[1]);
+            if ((!binding.has_value()) ||
+                (binding.value() > std::numeric_limits<uint32_t>::max())) {
+                std::cerr << "Invalid binding for " << arg << ": " << binding_points[1]
+                          << std::endl;
+                return false;
+            }
+            opts->hlsl_root_constant_binding_point = tint::sem::BindingPoint{
+                static_cast<uint32_t>(group.value()), static_cast<uint32_t>(binding.value())};
         } else if (!arg.empty()) {
             if (arg[0] == '-') {
                 std::cerr << "Unrecognized option: " << arg << std::endl;
@@ -723,6 +777,7 @@
     tint::writer::hlsl::Options gen_options;
     gen_options.disable_workgroup_init = options.disable_workgroup_init;
     gen_options.generate_external_texture_bindings = true;
+    gen_options.root_constant_binding_point = options.hlsl_root_constant_binding_point;
     auto result = tint::writer::hlsl::Generate(program, gen_options);
     if (!result.success) {
         PrintWGSL(std::cerr, *program);
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 28be2d9..0c7cfb4 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -30,7 +30,7 @@
   workgroup
   uniform
   storage
-  [[internal]] handle
+  @internal handle
 }
 
 // https://gpuweb.github.io/gpuweb/wgsl/#memory-access-mode
@@ -62,7 +62,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // WGSL primitive types                                                       //
-// Types may be decorated with [[precedence(N)]] to prioritize which type     //
+// Types may be decorated with @precedence(N) to prioritize which type        //
 // will be picked when multiple types of a matcher match.                     //
 // This is used to ensure that abstract numerical types materialize to the    //
 // concrete type with the lowest conversion rank.                             //
@@ -71,11 +71,11 @@
 
 // https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
 type bool
-[[precedence(4), display("abstract-float")]] type af
-[[precedence(3), display("abstract-int")]]   type ai
-[[precedence(2)]] type i32
-[[precedence(1)]] type u32
-[[precedence(0)]] type f32
+@precedence(4) @display("abstract-float") type af
+@precedence(3) @display("abstract-int")   type ai
+@precedence(2) type i32
+@precedence(1) type u32
+@precedence(0) type f32
 type vec2<T>
 type vec3<T>
 type vec4<T>
@@ -88,8 +88,8 @@
 type mat4x2<T>
 type mat4x3<T>
 type mat4x4<T>
-[[display("vec{N}<{T}>")]]     type vec<N: num, T>
-[[display("mat{N}x{M}<{T}>")]] type mat<N: num, M: num, T>
+@display("vec{N}<{T}>")     type vec<N: num, T>
+@display("mat{N}x{M}<{T}>") type mat<N: num, M: num, T>
 type ptr<S: storage_class, T, A: access>
 type atomic<T>
 type array<T>
@@ -114,9 +114,9 @@
 type texture_external
 
 type __modf_result
-[[display("__modf_result_vec{N}")]] type __modf_result_vec<N: num>
+@display("__modf_result_vec{N}") type __modf_result_vec<N: num>
 type __frexp_result
-[[display("__frexp_result_vec{N}")]] type __frexp_result_vec<N: num>
+@display("__frexp_result_vec{N}") type __frexp_result_vec<N: num>
 
 type __atomic_compare_exchange_result<T>
 
@@ -363,18 +363,18 @@
 fn dot<N: num, T: fiu32>(vec<N, T>, vec<N, T>) -> T
 fn dot4I8Packed(u32, u32) -> i32
 fn dot4U8Packed(u32, u32) -> u32
-[[stage("fragment")]] fn dpdx(f32) -> f32
-[[stage("fragment")]] fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn dpdxCoarse(f32) -> f32
-[[stage("fragment")]] fn dpdxCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn dpdxFine(f32) -> f32
-[[stage("fragment")]] fn dpdxFine<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn dpdy(f32) -> f32
-[[stage("fragment")]] fn dpdy<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn dpdyCoarse(f32) -> f32
-[[stage("fragment")]] fn dpdyCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn dpdyFine(f32) -> f32
-[[stage("fragment")]] fn dpdyFine<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn dpdx(f32) -> f32
+@stage("fragment") fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn dpdxCoarse(f32) -> f32
+@stage("fragment") fn dpdxCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn dpdxFine(f32) -> f32
+@stage("fragment") fn dpdxFine<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn dpdy(f32) -> f32
+@stage("fragment") fn dpdy<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn dpdyCoarse(f32) -> f32
+@stage("fragment") fn dpdyCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn dpdyFine(f32) -> f32
+@stage("fragment") fn dpdyFine<N: num>(vec<N, f32>) -> vec<N, f32>
 fn exp(f32) -> f32
 fn exp<N: num>(vec<N, f32>) -> vec<N, f32>
 fn exp2(f32) -> f32
@@ -394,12 +394,12 @@
 fn fract<N: num>(vec<N, f32>) -> vec<N, f32>
 fn frexp(f32) -> __frexp_result
 fn frexp<N: num>(vec<N, f32>) -> __frexp_result_vec<N>
-[[stage("fragment")]] fn fwidth(f32) -> f32
-[[stage("fragment")]] fn fwidth<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn fwidthCoarse(f32) -> f32
-[[stage("fragment")]] fn fwidthCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
-[[stage("fragment")]] fn fwidthFine(f32) -> f32
-[[stage("fragment")]] fn fwidthFine<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn fwidth(f32) -> f32
+@stage("fragment") fn fwidth<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn fwidthCoarse(f32) -> f32
+@stage("fragment") fn fwidthCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
+@stage("fragment") fn fwidthFine(f32) -> f32
+@stage("fragment") fn fwidthFine<N: num>(vec<N, f32>) -> vec<N, f32>
 fn insertBits<T: iu32>(T, T, u32, u32) -> T
 fn insertBits<N: num, T: iu32>(vec<N, T>, vec<N, T>, u32, u32) -> vec<N, T>
 fn inverseSqrt(f32) -> f32
@@ -448,13 +448,13 @@
 fn sinh<N: num>(vec<N, f32>) -> vec<N, f32>
 fn smoothstep(f32, f32, f32) -> f32
 fn smoothstep<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32>
-[[deprecated]] fn smoothStep(f32, f32, f32) -> f32
-[[deprecated]] fn smoothStep<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32>
+@deprecated fn smoothStep(f32, f32, f32) -> f32
+@deprecated fn smoothStep<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32>
 fn sqrt(f32) -> f32
 fn sqrt<N: num>(vec<N, f32>) -> vec<N, f32>
 fn step(f32, f32) -> f32
 fn step<N: num>(vec<N, f32>, vec<N, f32>) -> vec<N, f32>
-[[stage("compute")]] fn storageBarrier()
+@stage("compute") fn storageBarrier()
 fn tan(f32) -> f32
 fn tan<N: num>(vec<N, f32>) -> vec<N, f32>
 fn tanh(f32) -> f32
@@ -467,7 +467,7 @@
 fn unpack2x16unorm(u32) -> vec2<f32>
 fn unpack4x8snorm(u32) -> vec4<f32>
 fn unpack4x8unorm(u32) -> vec4<f32>
-[[stage("compute")]] fn workgroupBarrier()
+@stage("compute") fn workgroupBarrier()
 
 fn textureDimensions<T: fiu32>(texture: texture_1d<T>) -> i32
 fn textureDimensions<T: fiu32>(texture: texture_1d<T>, level: i32) -> i32
@@ -531,35 +531,35 @@
 fn textureNumLevels(texture: texture_depth_cube_array) -> i32
 fn textureNumSamples<T: fiu32>(texture: texture_multisampled_2d<T>) -> i32
 fn textureNumSamples(texture: texture_depth_multisampled_2d) -> i32
-[[stage("fragment")]] fn textureSample(texture: texture_1d<f32>, sampler: sampler, coords: f32) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, offset: vec2<i32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, offset: vec3<i32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32) -> vec4<f32>
-[[stage("fragment")]] fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>) -> f32
-[[stage("fragment")]] fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>, offset: vec2<i32>) -> f32
-[[stage("fragment")]] fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32) -> f32
-[[stage("fragment")]] fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32, offset: vec2<i32>) -> f32
-[[stage("fragment")]] fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3<f32>) -> f32
-[[stage("fragment")]] fn textureSample(texture: texture_depth_cube_array, sampler: sampler, coords: vec3<f32>, array_index: i32) -> f32
-[[stage("fragment")]] fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32, offset: vec2<i32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, bias: f32) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, bias: f32, offset: vec2<i32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, bias: f32, offset: vec3<i32>) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleBias(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32, bias: f32) -> vec4<f32>
-[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32
-[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32
-[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32) -> f32
-[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32, offset: vec2<i32>) -> f32
-[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32
-[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3<f32>, array_index: i32, depth_ref: f32) -> f32
+@stage("fragment") fn textureSample(texture: texture_1d<f32>, sampler: sampler, coords: f32) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, offset: vec2<i32>) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, offset: vec3<i32>) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32) -> vec4<f32>
+@stage("fragment") fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>) -> f32
+@stage("fragment") fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>, offset: vec2<i32>) -> f32
+@stage("fragment") fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32) -> f32
+@stage("fragment") fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32, offset: vec2<i32>) -> f32
+@stage("fragment") fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3<f32>) -> f32
+@stage("fragment") fn textureSample(texture: texture_depth_cube_array, sampler: sampler, coords: vec3<f32>, array_index: i32) -> f32
+@stage("fragment") fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32, offset: vec2<i32>) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, bias: f32) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, bias: f32, offset: vec2<i32>) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, bias: f32, offset: vec3<i32>) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32>
+@stage("fragment") fn textureSampleBias(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32, bias: f32) -> vec4<f32>
+@stage("fragment") fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32
+@stage("fragment") fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32
+@stage("fragment") fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32) -> f32
+@stage("fragment") fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32, offset: vec2<i32>) -> f32
+@stage("fragment") fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32
+@stage("fragment") fn textureSampleCompare(texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3<f32>, array_index: i32, depth_ref: f32) -> f32
 fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32
 fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32
 fn textureSampleCompareLevel(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32) -> f32
@@ -611,17 +611,17 @@
 fn textureLoad(texture: texture_depth_multisampled_2d, coords: vec2<i32>, sample_index: i32) -> f32
 fn textureLoad(texture: texture_external, coords: vec2<i32>) -> vec4<f32>
 
-[[stage("fragment", "compute")]] fn atomicLoad<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>) -> T
-[[stage("fragment", "compute")]] fn atomicStore<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T)
-[[stage("fragment", "compute")]] fn atomicAdd<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicSub<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicMax<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicMin<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicAnd<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicOr<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicXor<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicExchange<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
-[[stage("fragment", "compute")]] fn atomicCompareExchangeWeak<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T, T) -> __atomic_compare_exchange_result<T>
+@stage("fragment", "compute") fn atomicLoad<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>) -> T
+@stage("fragment", "compute") fn atomicStore<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T)
+@stage("fragment", "compute") fn atomicAdd<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicSub<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicMax<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicMin<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicAnd<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicOr<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicXor<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicExchange<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
+@stage("fragment", "compute") fn atomicCompareExchangeWeak<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T, T) -> __atomic_compare_exchange_result<T>
 
 ////////////////////////////////////////////////////////////////////////////////
 // Type constructors                                                          //
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
new file mode 100644
index 0000000..fac2c7d
--- /dev/null
+++ b/src/tint/resolver/const_eval.cc
@@ -0,0 +1,19 @@
+// 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.
+
+#include "src/tint/resolver/const_eval.h"
+
+#include "src/tint/sem/constant.h"
+
+namespace tint::resolver::const_eval {}  // namespace tint::resolver::const_eval
diff --git a/src/tint/resolver/const_eval.h b/src/tint/resolver/const_eval.h
new file mode 100644
index 0000000..89bb3da
--- /dev/null
+++ b/src/tint/resolver/const_eval.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef SRC_TINT_RESOLVER_CONST_EVAL_H_
+#define SRC_TINT_RESOLVER_CONST_EVAL_H_
+
+#include <stddef.h>
+
+// Forward declarations
+namespace tint {
+class ProgramBuilder;
+}  // namespace tint
+
+// Forward declarations
+namespace tint::sem {
+class Constant;
+}  // namespace tint::sem
+
+namespace tint::resolver::const_eval {
+
+/// Typedef for a constant evaluation function
+using Function = sem::Constant(ProgramBuilder& builder, const sem::Constant* args, size_t num_args);
+
+}  // namespace tint::resolver::const_eval
+
+#endif  // SRC_TINT_RESOLVER_CONST_EVAL_H_
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index 4d9ab77..eb8f30e 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -844,6 +844,8 @@
     MatcherIndex const* const return_matcher_indices;
     /// The flags for the overload
     OverloadFlags flags;
+    /// The function used to evaluate the overload at shader-creation time.
+    const_eval::Function* const const_eval_fn;
 };
 
 /// IntrinsicInfo describes a builtin function or operator overload
@@ -905,9 +907,9 @@
   public:
     explicit Impl(ProgramBuilder& builder);
 
-    const sem::Builtin* Lookup(sem::BuiltinType builtin_type,
-                               const std::vector<const sem::Type*>& args,
-                               const Source& source) override;
+    Builtin Lookup(sem::BuiltinType builtin_type,
+                   const std::vector<const sem::Type*>& args,
+                   const Source& source) override;
 
     UnaryOperator Lookup(ast::UnaryOp op, const sem::Type* arg, const Source& source) override;
 
@@ -1064,9 +1066,9 @@
 
 Impl::Impl(ProgramBuilder& b) : builder(b) {}
 
-const sem::Builtin* Impl::Lookup(sem::BuiltinType builtin_type,
-                                 const std::vector<const sem::Type*>& args,
-                                 const Source& source) {
+Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
+                           const std::vector<const sem::Type*>& args,
+                           const Source& source) {
     const char* intrinsic_name = sem::str(builtin_type);
 
     // Generates an error when no overloads match the provided arguments
@@ -1090,7 +1092,7 @@
     }
 
     // De-duplicate builtins that are identical.
-    return utils::GetOrCreate(builtins, match, [&] {
+    auto* sem = utils::GetOrCreate(builtins, match, [&] {
         std::vector<sem::Parameter*> params;
         params.reserve(match.parameters.size());
         for (auto& p : match.parameters) {
@@ -1112,6 +1114,7 @@
             builtin_type, match.return_type, std::move(params), supported_stages,
             match.overload->flags.Contains(OverloadFlag::kIsDeprecated));
     });
+    return Builtin{sem, match.overload->const_eval_fn};
 }
 
 IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
diff --git a/src/tint/resolver/intrinsic_table.h b/src/tint/resolver/intrinsic_table.h
index 312f952..058b253 100644
--- a/src/tint/resolver/intrinsic_table.h
+++ b/src/tint/resolver/intrinsic_table.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <vector>
 
+#include "src/tint/resolver/const_eval.h"
 #include "src/tint/resolver/ctor_conv_intrinsic.h"
 #include "src/tint/sem/builtin.h"
 
@@ -39,22 +40,30 @@
     /// Destructor
     virtual ~IntrinsicTable();
 
+    /// Builtin describes a resolved builtin function
+    struct Builtin {
+        /// The semantic info for the builtin
+        const sem::Builtin* sem = nullptr;
+        /// The constant evaluation function
+        const_eval::Function* const_eval_fn = nullptr;
+    };
+
     /// UnaryOperator describes a resolved unary operator
     struct UnaryOperator {
         /// The result type of the unary operator
-        const sem::Type* result;
+        const sem::Type* result = nullptr;
         /// The type of the parameter of the unary operator
-        const sem::Type* parameter;
+        const sem::Type* parameter = nullptr;
     };
 
     /// BinaryOperator describes a resolved binary operator
     struct BinaryOperator {
         /// The result type of the binary operator
-        const sem::Type* result;
+        const sem::Type* result = nullptr;
         /// The type of LHS parameter of the binary operator
-        const sem::Type* lhs;
+        const sem::Type* lhs = nullptr;
         /// The type of RHS parameter of the binary operator
-        const sem::Type* rhs;
+        const sem::Type* rhs = nullptr;
     };
 
     /// Lookup looks for the builtin overload with the given signature, raising an error diagnostic
@@ -63,9 +72,9 @@
     /// @param args the argument types passed to the builtin function
     /// @param source the source of the builtin call
     /// @return the semantic builtin if found, otherwise nullptr
-    virtual const sem::Builtin* Lookup(sem::BuiltinType type,
-                                       const std::vector<const sem::Type*>& args,
-                                       const Source& source) = 0;
+    virtual Builtin Lookup(sem::BuiltinType type,
+                           const std::vector<const sem::Type*>& args,
+                           const Source& source) = 0;
 
     /// Lookup looks for the unary op overload with the given signature, raising an error
     /// diagnostic if the operator was not found.
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index 7a422fb..fab7783 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -52,7 +52,7 @@
 }
 
 /// TypeMatcher for 'type af'
-/// @see src/tint/intrinsics.def:74:51
+/// @see src/tint/intrinsics.def:74:48
 class Af : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -81,7 +81,7 @@
 }
 
 /// TypeMatcher for 'type ai'
-/// @see src/tint/intrinsics.def:75:51
+/// @see src/tint/intrinsics.def:75:48
 class Ai : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -110,7 +110,7 @@
 }
 
 /// TypeMatcher for 'type i32'
-/// @see src/tint/intrinsics.def:76:24
+/// @see src/tint/intrinsics.def:76:21
 class I32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -137,7 +137,7 @@
 }
 
 /// TypeMatcher for 'type u32'
-/// @see src/tint/intrinsics.def:77:24
+/// @see src/tint/intrinsics.def:77:21
 class U32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -164,7 +164,7 @@
 }
 
 /// TypeMatcher for 'type f32'
-/// @see src/tint/intrinsics.def:78:24
+/// @see src/tint/intrinsics.def:78:21
 class F32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -587,7 +587,7 @@
 }
 
 /// TypeMatcher for 'type vec'
-/// @see src/tint/intrinsics.def:91:37
+/// @see src/tint/intrinsics.def:91:34
 class Vec : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -628,7 +628,7 @@
 }
 
 /// TypeMatcher for 'type mat'
-/// @see src/tint/intrinsics.def:92:37
+/// @see src/tint/intrinsics.def:92:34
 class Mat : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -1416,7 +1416,7 @@
 }
 
 /// TypeMatcher for 'type __modf_result_vec'
-/// @see src/tint/intrinsics.def:117:42
+/// @see src/tint/intrinsics.def:117:39
 class ModfResultVec : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -1478,7 +1478,7 @@
 }
 
 /// TypeMatcher for 'type __frexp_result_vec'
-/// @see src/tint/intrinsics.def:119:43
+/// @see src/tint/intrinsics.def:119:40
 class FrexpResultVec : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
@@ -7681,6 +7681,7 @@
     /* parameters */ &kParameters[899],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [1] */
@@ -7692,6 +7693,7 @@
     /* parameters */ &kParameters[611],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [2] */
@@ -7703,6 +7705,7 @@
     /* parameters */ &kParameters[898],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [3] */
@@ -7714,6 +7717,7 @@
     /* parameters */ &kParameters[615],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [4] */
@@ -7725,6 +7729,7 @@
     /* parameters */ &kParameters[897],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [5] */
@@ -7736,6 +7741,7 @@
     /* parameters */ &kParameters[619],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [6] */
@@ -7747,6 +7753,7 @@
     /* parameters */ &kParameters[896],
     /* return matcher indices */ &kMatcherIndices[123],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [7] */
@@ -7758,6 +7765,7 @@
     /* parameters */ &kParameters[623],
     /* return matcher indices */ &kMatcherIndices[123],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [8] */
@@ -7769,6 +7777,7 @@
     /* parameters */ &kParameters[895],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [9] */
@@ -7780,6 +7789,7 @@
     /* parameters */ &kParameters[627],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [10] */
@@ -7791,6 +7801,7 @@
     /* parameters */ &kParameters[894],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [11] */
@@ -7802,6 +7813,7 @@
     /* parameters */ &kParameters[631],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [12] */
@@ -7813,6 +7825,7 @@
     /* parameters */ &kParameters[893],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [13] */
@@ -7824,6 +7837,7 @@
     /* parameters */ &kParameters[892],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [14] */
@@ -7835,6 +7849,7 @@
     /* parameters */ &kParameters[637],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [15] */
@@ -7846,6 +7861,7 @@
     /* parameters */ &kParameters[891],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [16] */
@@ -7857,6 +7873,7 @@
     /* parameters */ &kParameters[641],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [17] */
@@ -7868,6 +7885,7 @@
     /* parameters */ &kParameters[890],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [18] */
@@ -7879,6 +7897,7 @@
     /* parameters */ &kParameters[645],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [19] */
@@ -7890,6 +7909,7 @@
     /* parameters */ &kParameters[889],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [20] */
@@ -7901,6 +7921,7 @@
     /* parameters */ &kParameters[649],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [21] */
@@ -7912,6 +7933,7 @@
     /* parameters */ &kParameters[888],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [22] */
@@ -7923,6 +7945,7 @@
     /* parameters */ &kParameters[887],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [23] */
@@ -7934,6 +7957,7 @@
     /* parameters */ &kParameters[886],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [24] */
@@ -7945,6 +7969,7 @@
     /* parameters */ &kParameters[840],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [25] */
@@ -7956,6 +7981,7 @@
     /* parameters */ &kParameters[884],
     /* return matcher indices */ &kMatcherIndices[123],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [26] */
@@ -7967,6 +7993,7 @@
     /* parameters */ &kParameters[883],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [27] */
@@ -7978,6 +8005,7 @@
     /* parameters */ &kParameters[585],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [28] */
@@ -7989,6 +8017,7 @@
     /* parameters */ &kParameters[582],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [29] */
@@ -8000,6 +8029,7 @@
     /* parameters */ &kParameters[367],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [30] */
@@ -8011,6 +8041,7 @@
     /* parameters */ &kParameters[363],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [31] */
@@ -8022,6 +8053,7 @@
     /* parameters */ &kParameters[215],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [32] */
@@ -8033,6 +8065,7 @@
     /* parameters */ &kParameters[570],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [33] */
@@ -8044,6 +8077,7 @@
     /* parameters */ &kParameters[355],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [34] */
@@ -8055,6 +8089,7 @@
     /* parameters */ &kParameters[564],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [35] */
@@ -8066,6 +8101,7 @@
     /* parameters */ &kParameters[351],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [36] */
@@ -8077,6 +8113,7 @@
     /* parameters */ &kParameters[546],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [37] */
@@ -8088,6 +8125,7 @@
     /* parameters */ &kParameters[347],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [38] */
@@ -8099,6 +8137,7 @@
     /* parameters */ &kParameters[343],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [39] */
@@ -8110,6 +8149,7 @@
     /* parameters */ &kParameters[200],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [40] */
@@ -8121,6 +8161,7 @@
     /* parameters */ &kParameters[534],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [41] */
@@ -8132,6 +8173,7 @@
     /* parameters */ &kParameters[335],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [42] */
@@ -8143,6 +8185,7 @@
     /* parameters */ &kParameters[319],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [43] */
@@ -8154,6 +8197,7 @@
     /* parameters */ &kParameters[195],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [44] */
@@ -8165,6 +8209,7 @@
     /* parameters */ &kParameters[190],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [45] */
@@ -8176,6 +8221,7 @@
     /* parameters */ &kParameters[126],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [46] */
@@ -8187,6 +8233,7 @@
     /* parameters */ &kParameters[327],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [47] */
@@ -8198,6 +8245,7 @@
     /* parameters */ &kParameters[175],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [48] */
@@ -8209,6 +8257,7 @@
     /* parameters */ &kParameters[339],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [49] */
@@ -8220,6 +8269,7 @@
     /* parameters */ &kParameters[165],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [50] */
@@ -8231,6 +8281,7 @@
     /* parameters */ &kParameters[371],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [51] */
@@ -8242,6 +8293,7 @@
     /* parameters */ &kParameters[155],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [52] */
@@ -8253,6 +8305,7 @@
     /* parameters */ &kParameters[150],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [53] */
@@ -8264,6 +8317,7 @@
     /* parameters */ &kParameters[72],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [54] */
@@ -8275,6 +8329,7 @@
     /* parameters */ &kParameters[379],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [55] */
@@ -8286,6 +8341,7 @@
     /* parameters */ &kParameters[170],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [56] */
@@ -8297,6 +8353,7 @@
     /* parameters */ &kParameters[456],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [57] */
@@ -8308,6 +8365,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [58] */
@@ -8319,6 +8377,7 @@
     /* parameters */ &kParameters[950],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [59] */
@@ -8330,6 +8389,7 @@
     /* parameters */ &kParameters[951],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [60] */
@@ -8341,6 +8401,7 @@
     /* parameters */ &kParameters[419],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [61] */
@@ -8352,6 +8413,7 @@
     /* parameters */ &kParameters[513],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [62] */
@@ -8363,6 +8425,7 @@
     /* parameters */ &kParameters[510],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [63] */
@@ -8374,6 +8437,7 @@
     /* parameters */ &kParameters[501],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [64] */
@@ -8385,6 +8449,7 @@
     /* parameters */ &kParameters[769],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [65] */
@@ -8396,6 +8461,7 @@
     /* parameters */ &kParameters[775],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [66] */
@@ -8407,6 +8473,7 @@
     /* parameters */ &kParameters[777],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [67] */
@@ -8418,6 +8485,7 @@
     /* parameters */ &kParameters[959],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [68] */
@@ -8429,6 +8497,7 @@
     /* parameters */ &kParameters[960],
     /* return matcher indices */ &kMatcherIndices[57],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [69] */
@@ -8440,6 +8509,7 @@
     /* parameters */ &kParameters[961],
     /* return matcher indices */ &kMatcherIndices[61],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [70] */
@@ -8451,6 +8521,7 @@
     /* parameters */ &kParameters[962],
     /* return matcher indices */ &kMatcherIndices[65],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [71] */
@@ -8462,6 +8533,7 @@
     /* parameters */ &kParameters[359],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [72] */
@@ -8473,6 +8545,7 @@
     /* parameters */ &kParameters[255],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [73] */
@@ -8484,6 +8557,7 @@
     /* parameters */ &kParameters[235],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [74] */
@@ -8495,6 +8569,7 @@
     /* parameters */ &kParameters[96],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [75] */
@@ -8506,6 +8581,7 @@
     /* parameters */ &kParameters[423],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [76] */
@@ -8517,6 +8593,7 @@
     /* parameters */ &kParameters[230],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [77] */
@@ -8528,6 +8605,7 @@
     /* parameters */ &kParameters[447],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [78] */
@@ -8539,6 +8617,7 @@
     /* parameters */ &kParameters[415],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [79] */
@@ -8550,6 +8629,7 @@
     /* parameters */ &kParameters[411],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [80] */
@@ -8561,6 +8641,7 @@
     /* parameters */ &kParameters[225],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [81] */
@@ -8572,6 +8653,7 @@
     /* parameters */ &kParameters[594],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [82] */
@@ -8583,6 +8665,7 @@
     /* parameters */ &kParameters[395],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [83] */
@@ -8594,6 +8677,7 @@
     /* parameters */ &kParameters[477],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [84] */
@@ -8605,6 +8689,7 @@
     /* parameters */ &kParameters[480],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [85] */
@@ -8616,6 +8701,7 @@
     /* parameters */ &kParameters[383],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [86] */
@@ -8627,6 +8713,7 @@
     /* parameters */ &kParameters[483],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [87] */
@@ -8638,6 +8725,7 @@
     /* parameters */ &kParameters[486],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [88] */
@@ -8649,6 +8737,7 @@
     /* parameters */ &kParameters[489],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [89] */
@@ -8660,6 +8749,7 @@
     /* parameters */ &kParameters[387],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [90] */
@@ -8671,6 +8761,7 @@
     /* parameters */ &kParameters[492],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [91] */
@@ -8682,6 +8773,7 @@
     /* parameters */ &kParameters[516],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [92] */
@@ -8693,6 +8785,7 @@
     /* parameters */ &kParameters[519],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [93] */
@@ -8704,6 +8797,7 @@
     /* parameters */ &kParameters[399],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [94] */
@@ -8715,6 +8809,7 @@
     /* parameters */ &kParameters[537],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [95] */
@@ -8726,6 +8821,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[115],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [96] */
@@ -8737,6 +8833,7 @@
     /* parameters */ &kParameters[940],
     /* return matcher indices */ &kMatcherIndices[115],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [97] */
@@ -8748,6 +8845,7 @@
     /* parameters */ &kParameters[941],
     /* return matcher indices */ &kMatcherIndices[115],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [98] */
@@ -8759,6 +8857,7 @@
     /* parameters */ &kParameters[531],
     /* return matcher indices */ &kMatcherIndices[115],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [99] */
@@ -8770,6 +8869,7 @@
     /* parameters */ &kParameters[763],
     /* return matcher indices */ &kMatcherIndices[115],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [100] */
@@ -8781,6 +8881,7 @@
     /* parameters */ &kParameters[765],
     /* return matcher indices */ &kMatcherIndices[115],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [101] */
@@ -8792,6 +8893,7 @@
     /* parameters */ &kParameters[945],
     /* return matcher indices */ &kMatcherIndices[121],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [102] */
@@ -8803,6 +8905,7 @@
     /* parameters */ &kParameters[946],
     /* return matcher indices */ &kMatcherIndices[123],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [103] */
@@ -8814,6 +8917,7 @@
     /* parameters */ &kParameters[947],
     /* return matcher indices */ &kMatcherIndices[125],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [104] */
@@ -8825,6 +8929,7 @@
     /* parameters */ &kParameters[948],
     /* return matcher indices */ &kMatcherIndices[127],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [105] */
@@ -8836,6 +8941,7 @@
     /* parameters */ &kParameters[856],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [106] */
@@ -8847,6 +8953,7 @@
     /* parameters */ &kParameters[855],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [107] */
@@ -8858,6 +8965,7 @@
     /* parameters */ &kParameters[854],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [108] */
@@ -8869,6 +8977,7 @@
     /* parameters */ &kParameters[853],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [109] */
@@ -8880,6 +8989,7 @@
     /* parameters */ &kParameters[852],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [110] */
@@ -8891,6 +9001,7 @@
     /* parameters */ &kParameters[851],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [111] */
@@ -8902,6 +9013,7 @@
     /* parameters */ &kParameters[850],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [112] */
@@ -8913,6 +9025,7 @@
     /* parameters */ &kParameters[849],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [113] */
@@ -8924,6 +9037,7 @@
     /* parameters */ &kParameters[848],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [114] */
@@ -8935,6 +9049,7 @@
     /* parameters */ &kParameters[846],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [115] */
@@ -8946,6 +9061,7 @@
     /* parameters */ &kParameters[540],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [116] */
@@ -8957,6 +9073,7 @@
     /* parameters */ &kParameters[543],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [117] */
@@ -8968,6 +9085,7 @@
     /* parameters */ &kParameters[323],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [118] */
@@ -8979,6 +9097,7 @@
     /* parameters */ &kParameters[573],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [119] */
@@ -8990,6 +9109,7 @@
     /* parameters */ &kParameters[576],
     /* return matcher indices */ &kMatcherIndices[49],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [120] */
@@ -9001,6 +9121,7 @@
     /* parameters */ &kParameters[579],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [121] */
@@ -9012,6 +9133,7 @@
     /* parameters */ &kParameters[407],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [122] */
@@ -9023,6 +9145,7 @@
     /* parameters */ &kParameters[588],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [123] */
@@ -9034,6 +9157,7 @@
     /* parameters */ &kParameters[727],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [124] */
@@ -9045,6 +9169,7 @@
     /* parameters */ &kParameters[685],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [125] */
@@ -9056,6 +9181,7 @@
     /* parameters */ &kParameters[681],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [126] */
@@ -9067,6 +9193,7 @@
     /* parameters */ &kParameters[679],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [127] */
@@ -9078,6 +9205,7 @@
     /* parameters */ &kParameters[673],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [128] */
@@ -9089,6 +9217,7 @@
     /* parameters */ &kParameters[671],
     /* return matcher indices */ &kMatcherIndices[11],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [129] */
@@ -9100,6 +9229,7 @@
     /* parameters */ &kParameters[669],
     /* return matcher indices */ &kMatcherIndices[11],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [130] */
@@ -9111,6 +9241,7 @@
     /* parameters */ &kParameters[667],
     /* return matcher indices */ &kMatcherIndices[76],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [131] */
@@ -9122,6 +9253,7 @@
     /* parameters */ &kParameters[665],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [132] */
@@ -9133,6 +9265,7 @@
     /* parameters */ &kParameters[663],
     /* return matcher indices */ &kMatcherIndices[27],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [133] */
@@ -9144,6 +9277,7 @@
     /* parameters */ &kParameters[331],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [134] */
@@ -9155,6 +9289,7 @@
     /* parameters */ &kParameters[180],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [135] */
@@ -9166,6 +9301,7 @@
     /* parameters */ &kParameters[290],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [136] */
@@ -9177,6 +9313,7 @@
     /* parameters */ &kParameters[132],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [137] */
@@ -9188,6 +9325,7 @@
     /* parameters */ &kParameters[315],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [138] */
@@ -9199,6 +9337,7 @@
     /* parameters */ &kParameters[250],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [139] */
@@ -9210,6 +9349,7 @@
     /* parameters */ &kParameters[307],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [140] */
@@ -9221,6 +9361,7 @@
     /* parameters */ &kParameters[270],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [141] */
@@ -9232,6 +9373,7 @@
     /* parameters */ &kParameters[240],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [142] */
@@ -9243,6 +9385,7 @@
     /* parameters */ &kParameters[84],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [143] */
@@ -9254,6 +9397,7 @@
     /* parameters */ &kParameters[102],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [144] */
@@ -9265,6 +9409,7 @@
     /* parameters */ &kParameters[65],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [145] */
@@ -9276,6 +9421,7 @@
     /* parameters */ &kParameters[220],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [146] */
@@ -9287,6 +9433,7 @@
     /* parameters */ &kParameters[114],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [147] */
@@ -9298,6 +9445,7 @@
     /* parameters */ &kParameters[210],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [148] */
@@ -9309,6 +9457,7 @@
     /* parameters */ &kParameters[120],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [149] */
@@ -9320,6 +9469,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[105],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [150] */
@@ -9331,6 +9481,7 @@
     /* parameters */ &kParameters[932],
     /* return matcher indices */ &kMatcherIndices[105],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [151] */
@@ -9342,6 +9493,7 @@
     /* parameters */ &kParameters[933],
     /* return matcher indices */ &kMatcherIndices[105],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [152] */
@@ -9353,6 +9505,7 @@
     /* parameters */ &kParameters[759],
     /* return matcher indices */ &kMatcherIndices[105],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [153] */
@@ -9364,6 +9517,7 @@
     /* parameters */ &kParameters[935],
     /* return matcher indices */ &kMatcherIndices[103],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [154] */
@@ -9375,6 +9529,7 @@
     /* parameters */ &kParameters[936],
     /* return matcher indices */ &kMatcherIndices[109],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [155] */
@@ -9386,6 +9541,7 @@
     /* parameters */ &kParameters[937],
     /* return matcher indices */ &kMatcherIndices[111],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [156] */
@@ -9397,6 +9553,7 @@
     /* parameters */ &kParameters[938],
     /* return matcher indices */ &kMatcherIndices[113],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [157] */
@@ -9408,6 +9565,7 @@
     /* parameters */ &kParameters[391],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [158] */
@@ -9419,6 +9577,7 @@
     /* parameters */ &kParameters[205],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [159] */
@@ -9430,6 +9589,7 @@
     /* parameters */ &kParameters[185],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [160] */
@@ -9441,6 +9601,7 @@
     /* parameters */ &kParameters[138],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [161] */
@@ -9452,6 +9613,7 @@
     /* parameters */ &kParameters[375],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [162] */
@@ -9463,6 +9625,7 @@
     /* parameters */ &kParameters[160],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [163] */
@@ -9474,6 +9637,7 @@
     /* parameters */ &kParameters[303],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [164] */
@@ -9485,6 +9649,7 @@
     /* parameters */ &kParameters[265],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [165] */
@@ -9496,6 +9661,7 @@
     /* parameters */ &kParameters[260],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [166] */
@@ -9507,6 +9673,7 @@
     /* parameters */ &kParameters[144],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [167] */
@@ -9518,6 +9685,7 @@
     /* parameters */ &kParameters[311],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [168] */
@@ -9529,6 +9697,7 @@
     /* parameters */ &kParameters[245],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [169] */
@@ -9540,6 +9709,7 @@
     /* parameters */ &kParameters[299],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [170] */
@@ -9551,6 +9721,7 @@
     /* parameters */ &kParameters[280],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [171] */
@@ -9562,6 +9733,7 @@
     /* parameters */ &kParameters[285],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [172] */
@@ -9573,6 +9745,7 @@
     /* parameters */ &kParameters[108],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [173] */
@@ -9584,6 +9757,7 @@
     /* parameters */ &kParameters[295],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [174] */
@@ -9595,6 +9769,7 @@
     /* parameters */ &kParameters[275],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [175] */
@@ -9606,6 +9781,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[149],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [176] */
@@ -9617,6 +9793,7 @@
     /* parameters */ &kParameters[969],
     /* return matcher indices */ &kMatcherIndices[149],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [177] */
@@ -9628,6 +9805,7 @@
     /* parameters */ &kParameters[970],
     /* return matcher indices */ &kMatcherIndices[151],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [178] */
@@ -9639,6 +9817,7 @@
     /* parameters */ &kParameters[90],
     /* return matcher indices */ &kMatcherIndices[151],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [179] */
@@ -9650,6 +9829,7 @@
     /* parameters */ &kParameters[781],
     /* return matcher indices */ &kMatcherIndices[151],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [180] */
@@ -9661,6 +9841,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[165],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [181] */
@@ -9672,6 +9853,7 @@
     /* parameters */ &kParameters[988],
     /* return matcher indices */ &kMatcherIndices[165],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [182] */
@@ -9683,6 +9865,7 @@
     /* parameters */ &kParameters[983],
     /* return matcher indices */ &kMatcherIndices[167],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [183] */
@@ -9694,6 +9877,7 @@
     /* parameters */ &kParameters[16],
     /* return matcher indices */ &kMatcherIndices[167],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [184] */
@@ -9705,6 +9889,7 @@
     /* parameters */ &kParameters[468],
     /* return matcher indices */ &kMatcherIndices[167],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [185] */
@@ -9716,6 +9901,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[169],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [186] */
@@ -9727,6 +9913,7 @@
     /* parameters */ &kParameters[968],
     /* return matcher indices */ &kMatcherIndices[169],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [187] */
@@ -9738,6 +9925,7 @@
     /* parameters */ &kParameters[957],
     /* return matcher indices */ &kMatcherIndices[171],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [188] */
@@ -9749,6 +9937,7 @@
     /* parameters */ &kParameters[57],
     /* return matcher indices */ &kMatcherIndices[171],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [189] */
@@ -9760,6 +9949,7 @@
     /* parameters */ &kParameters[431],
     /* return matcher indices */ &kMatcherIndices[171],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [190] */
@@ -9771,6 +9961,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[4],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [191] */
@@ -9782,6 +9973,7 @@
     /* parameters */ &kParameters[964],
     /* return matcher indices */ &kMatcherIndices[4],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [192] */
@@ -9793,6 +9985,7 @@
     /* parameters */ &kParameters[965],
     /* return matcher indices */ &kMatcherIndices[147],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [193] */
@@ -9804,6 +9997,7 @@
     /* parameters */ &kParameters[427],
     /* return matcher indices */ &kMatcherIndices[147],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [194] */
@@ -9815,6 +10009,7 @@
     /* parameters */ &kParameters[779],
     /* return matcher indices */ &kMatcherIndices[147],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [195] */
@@ -9826,6 +10021,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[157],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [196] */
@@ -9837,6 +10033,7 @@
     /* parameters */ &kParameters[979],
     /* return matcher indices */ &kMatcherIndices[157],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [197] */
@@ -9848,6 +10045,7 @@
     /* parameters */ &kParameters[980],
     /* return matcher indices */ &kMatcherIndices[159],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [198] */
@@ -9859,6 +10057,7 @@
     /* parameters */ &kParameters[78],
     /* return matcher indices */ &kMatcherIndices[159],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [199] */
@@ -9870,6 +10069,7 @@
     /* parameters */ &kParameters[474],
     /* return matcher indices */ &kMatcherIndices[159],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [200] */
@@ -9881,6 +10081,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[153],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [201] */
@@ -9892,6 +10093,7 @@
     /* parameters */ &kParameters[974],
     /* return matcher indices */ &kMatcherIndices[153],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [202] */
@@ -9903,6 +10105,7 @@
     /* parameters */ &kParameters[975],
     /* return matcher indices */ &kMatcherIndices[155],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [203] */
@@ -9914,6 +10117,7 @@
     /* parameters */ &kParameters[49],
     /* return matcher indices */ &kMatcherIndices[155],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [204] */
@@ -9925,6 +10129,7 @@
     /* parameters */ &kParameters[783],
     /* return matcher indices */ &kMatcherIndices[155],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [205] */
@@ -9936,6 +10141,7 @@
     /* parameters */ &kParameters[867],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [206] */
@@ -9947,6 +10153,7 @@
     /* parameters */ &kParameters[866],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [207] */
@@ -9958,6 +10165,7 @@
     /* parameters */ &kParameters[865],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [208] */
@@ -9969,6 +10177,7 @@
     /* parameters */ &kParameters[864],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [209] */
@@ -9980,6 +10189,7 @@
     /* parameters */ &kParameters[857],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [210] */
@@ -9991,6 +10201,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[175],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [211] */
@@ -10002,6 +10213,7 @@
     /* parameters */ &kParameters[931],
     /* return matcher indices */ &kMatcherIndices[175],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [212] */
@@ -10013,6 +10225,7 @@
     /* parameters */ &kParameters[928],
     /* return matcher indices */ &kMatcherIndices[177],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [213] */
@@ -10024,6 +10237,7 @@
     /* parameters */ &kParameters[28],
     /* return matcher indices */ &kMatcherIndices[177],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [214] */
@@ -10035,6 +10249,7 @@
     /* parameters */ &kParameters[435],
     /* return matcher indices */ &kMatcherIndices[177],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [215] */
@@ -10046,6 +10261,7 @@
     /* parameters */ &kParameters[695],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [216] */
@@ -10057,6 +10273,7 @@
     /* parameters */ &kParameters[693],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [217] */
@@ -10068,6 +10285,7 @@
     /* parameters */ &kParameters[691],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [218] */
@@ -10079,6 +10297,7 @@
     /* parameters */ &kParameters[689],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [219] */
@@ -10090,6 +10309,7 @@
     /* parameters */ &kParameters[687],
     /* return matcher indices */ &kMatcherIndices[11],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [220] */
@@ -10101,6 +10321,7 @@
     /* parameters */ &kParameters[705],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [221] */
@@ -10112,6 +10333,7 @@
     /* parameters */ &kParameters[703],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [222] */
@@ -10123,6 +10345,7 @@
     /* parameters */ &kParameters[701],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [223] */
@@ -10134,6 +10357,7 @@
     /* parameters */ &kParameters[699],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [224] */
@@ -10145,6 +10369,7 @@
     /* parameters */ &kParameters[697],
     /* return matcher indices */ &kMatcherIndices[11],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [225] */
@@ -10156,6 +10381,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[185],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [226] */
@@ -10167,6 +10393,7 @@
     /* parameters */ &kParameters[919],
     /* return matcher indices */ &kMatcherIndices[185],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [227] */
@@ -10178,6 +10405,7 @@
     /* parameters */ &kParameters[912],
     /* return matcher indices */ &kMatcherIndices[137],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [228] */
@@ -10189,6 +10417,7 @@
     /* parameters */ &kParameters[0],
     /* return matcher indices */ &kMatcherIndices[137],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [229] */
@@ -10200,6 +10429,7 @@
     /* parameters */ &kParameters[443],
     /* return matcher indices */ &kMatcherIndices[137],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [230] */
@@ -10211,6 +10441,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[161],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [231] */
@@ -10222,6 +10453,7 @@
     /* parameters */ &kParameters[984],
     /* return matcher indices */ &kMatcherIndices[161],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [232] */
@@ -10233,6 +10465,7 @@
     /* parameters */ &kParameters[985],
     /* return matcher indices */ &kMatcherIndices[163],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [233] */
@@ -10244,6 +10477,7 @@
     /* parameters */ &kParameters[40],
     /* return matcher indices */ &kMatcherIndices[163],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [234] */
@@ -10255,6 +10489,7 @@
     /* parameters */ &kParameters[471],
     /* return matcher indices */ &kMatcherIndices[163],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [235] */
@@ -10266,6 +10501,7 @@
     /* parameters */ &kParameters[633],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [236] */
@@ -10277,6 +10513,7 @@
     /* parameters */ &kParameters[629],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [237] */
@@ -10288,6 +10525,7 @@
     /* parameters */ &kParameters[625],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [238] */
@@ -10299,6 +10537,7 @@
     /* parameters */ &kParameters[621],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [239] */
@@ -10310,6 +10549,7 @@
     /* parameters */ &kParameters[653],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [240] */
@@ -10321,6 +10561,7 @@
     /* parameters */ &kParameters[651],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [241] */
@@ -10332,6 +10573,7 @@
     /* parameters */ &kParameters[647],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [242] */
@@ -10343,6 +10585,7 @@
     /* parameters */ &kParameters[643],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [243] */
@@ -10354,6 +10597,7 @@
     /* parameters */ &kParameters[661],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [244] */
@@ -10365,6 +10609,7 @@
     /* parameters */ &kParameters[659],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [245] */
@@ -10376,6 +10621,7 @@
     /* parameters */ &kParameters[657],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [246] */
@@ -10387,6 +10633,7 @@
     /* parameters */ &kParameters[655],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [247] */
@@ -10398,6 +10645,7 @@
     /* parameters */ &kParameters[617],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [248] */
@@ -10409,6 +10657,7 @@
     /* parameters */ &kParameters[613],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [249] */
@@ -10420,6 +10669,7 @@
     /* parameters */ &kParameters[609],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [250] */
@@ -10431,6 +10681,7 @@
     /* parameters */ &kParameters[607],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [251] */
@@ -10442,6 +10693,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [252] */
@@ -10453,6 +10705,7 @@
     /* parameters */ &kParameters[920],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [253] */
@@ -10464,6 +10717,7 @@
     /* parameters */ &kParameters[921],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [254] */
@@ -10475,6 +10729,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [255] */
@@ -10486,6 +10741,7 @@
     /* parameters */ &kParameters[929],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [256] */
@@ -10497,6 +10753,7 @@
     /* parameters */ &kParameters[930],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [257] */
@@ -10508,6 +10765,7 @@
     /* parameters */ &kParameters[522],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [258] */
@@ -10519,6 +10777,7 @@
     /* parameters */ &kParameters[525],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [259] */
@@ -10530,6 +10789,7 @@
     /* parameters */ &kParameters[528],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [260] */
@@ -10541,6 +10801,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [261] */
@@ -10552,6 +10813,7 @@
     /* parameters */ &kParameters[923],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [262] */
@@ -10563,6 +10825,7 @@
     /* parameters */ &kParameters[924],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [263] */
@@ -10574,6 +10837,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [264] */
@@ -10585,6 +10849,7 @@
     /* parameters */ &kParameters[926],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [265] */
@@ -10596,6 +10861,7 @@
     /* parameters */ &kParameters[927],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [266] */
@@ -10607,6 +10873,7 @@
     /* parameters */ &kParameters[459],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [267] */
@@ -10618,6 +10885,7 @@
     /* parameters */ &kParameters[462],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [268] */
@@ -10629,6 +10897,7 @@
     /* parameters */ &kParameters[465],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [269] */
@@ -10640,6 +10909,7 @@
     /* parameters */ &kParameters[858],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [270] */
@@ -10651,6 +10921,7 @@
     /* parameters */ &kParameters[859],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [271] */
@@ -10662,6 +10933,7 @@
     /* parameters */ &kParameters[871],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [272] */
@@ -10673,6 +10945,7 @@
     /* parameters */ &kParameters[872],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [273] */
@@ -10684,6 +10957,7 @@
     /* parameters */ &kParameters[869],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [274] */
@@ -10695,6 +10969,7 @@
     /* parameters */ &kParameters[870],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [275] */
@@ -10706,6 +10981,7 @@
     /* parameters */ &kParameters[439],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [276] */
@@ -10717,6 +10993,7 @@
     /* parameters */ &kParameters[403],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [277] */
@@ -10728,6 +11005,7 @@
     /* parameters */ &kParameters[875],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [278] */
@@ -10739,6 +11017,7 @@
     /* parameters */ &kParameters[876],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [279] */
@@ -10750,6 +11029,7 @@
     /* parameters */ &kParameters[677],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [280] */
@@ -10761,6 +11041,7 @@
     /* parameters */ &kParameters[801],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [281] */
@@ -10772,6 +11053,7 @@
     /* parameters */ &kParameters[878],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [282] */
@@ -10783,6 +11065,7 @@
     /* parameters */ &kParameters[879],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [283] */
@@ -10794,6 +11077,7 @@
     /* parameters */ &kParameters[880],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [284] */
@@ -10805,6 +11089,7 @@
     /* parameters */ &kParameters[881],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [285] */
@@ -10816,6 +11101,7 @@
     /* parameters */ &kParameters[882],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [286] */
@@ -10827,6 +11113,7 @@
     /* parameters */ &kParameters[885],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [287] */
@@ -10838,6 +11125,7 @@
     /* parameters */ &kParameters[737],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [288] */
@@ -10849,6 +11137,7 @@
     /* parameters */ &kParameters[789],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [289] */
@@ -10860,6 +11149,7 @@
     /* parameters */ &kParameters[787],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [290] */
@@ -10871,6 +11161,7 @@
     /* parameters */ &kParameters[785],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [291] */
@@ -10882,6 +11173,7 @@
     /* parameters */ &kParameters[843],
     /* return matcher indices */ &kMatcherIndices[202],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [292] */
@@ -10893,6 +11185,7 @@
     /* parameters */ &kParameters[868],
     /* return matcher indices */ &kMatcherIndices[135],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [293] */
@@ -10904,6 +11197,7 @@
     /* parameters */ &kParameters[973],
     /* return matcher indices */ &kMatcherIndices[201],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [294] */
@@ -10915,6 +11209,7 @@
     /* parameters */ &kParameters[905],
     /* return matcher indices */ &kMatcherIndices[117],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [295] */
@@ -10926,6 +11221,7 @@
     /* parameters */ &kParameters[841],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [296] */
@@ -10937,6 +11233,7 @@
     /* parameters */ &kParameters[842],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [297] */
@@ -10948,6 +11245,7 @@
     /* parameters */ &kParameters[561],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [298] */
@@ -10959,6 +11257,7 @@
     /* parameters */ &kParameters[567],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [299] */
@@ -10970,6 +11269,7 @@
     /* parameters */ &kParameters[873],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [300] */
@@ -10981,6 +11281,7 @@
     /* parameters */ &kParameters[874],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [301] */
@@ -10992,6 +11293,7 @@
     /* parameters */ &kParameters[838],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [302] */
@@ -11003,6 +11305,7 @@
     /* parameters */ &kParameters[839],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [303] */
@@ -11014,6 +11317,7 @@
     /* parameters */ &kParameters[836],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [304] */
@@ -11025,6 +11329,7 @@
     /* parameters */ &kParameters[837],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [305] */
@@ -11036,6 +11341,7 @@
     /* parameters */ &kParameters[834],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [306] */
@@ -11047,6 +11353,7 @@
     /* parameters */ &kParameters[835],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [307] */
@@ -11058,6 +11365,7 @@
     /* parameters */ &kParameters[773],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [308] */
@@ -11069,6 +11377,7 @@
     /* parameters */ &kParameters[771],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [309] */
@@ -11080,6 +11389,7 @@
     /* parameters */ &kParameters[956],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [310] */
@@ -11091,6 +11401,7 @@
     /* parameters */ &kParameters[955],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [311] */
@@ -11102,6 +11413,7 @@
     /* parameters */ &kParameters[495],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [312] */
@@ -11113,6 +11425,7 @@
     /* parameters */ &kParameters[498],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [313] */
@@ -11124,6 +11437,7 @@
     /* parameters */ &kParameters[831],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [314] */
@@ -11135,6 +11449,7 @@
     /* parameters */ &kParameters[833],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [315] */
@@ -11146,6 +11461,7 @@
     /* parameters */ &kParameters[954],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [316] */
@@ -11157,6 +11473,7 @@
     /* parameters */ &kParameters[953],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [317] */
@@ -11168,6 +11485,7 @@
     /* parameters */ &kParameters[944],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [318] */
@@ -11179,6 +11497,7 @@
     /* parameters */ &kParameters[943],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [319] */
@@ -11190,6 +11509,7 @@
     /* parameters */ &kParameters[829],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [320] */
@@ -11201,6 +11521,7 @@
     /* parameters */ &kParameters[830],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [321] */
@@ -11212,6 +11533,7 @@
     /* parameters */ &kParameters[942],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [322] */
@@ -11223,6 +11545,7 @@
     /* parameters */ &kParameters[934],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [323] */
@@ -11234,6 +11557,7 @@
     /* parameters */ &kParameters[918],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [324] */
@@ -11245,6 +11569,7 @@
     /* parameters */ &kParameters[917],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [325] */
@@ -11256,6 +11581,7 @@
     /* parameters */ &kParameters[916],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [326] */
@@ -11267,6 +11593,7 @@
     /* parameters */ &kParameters[915],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [327] */
@@ -11278,6 +11605,7 @@
     /* parameters */ &kParameters[549],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [328] */
@@ -11289,6 +11617,7 @@
     /* parameters */ &kParameters[552],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [329] */
@@ -11300,6 +11629,7 @@
     /* parameters */ &kParameters[555],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kIsDeprecated),
+    /* const eval */ nullptr,
   },
   {
     /* [330] */
@@ -11311,6 +11641,7 @@
     /* parameters */ &kParameters[558],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kIsDeprecated),
+    /* const eval */ nullptr,
   },
   {
     /* [331] */
@@ -11322,6 +11653,7 @@
     /* parameters */ &kParameters[914],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [332] */
@@ -11333,6 +11665,7 @@
     /* parameters */ &kParameters[913],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [333] */
@@ -11344,6 +11677,7 @@
     /* parameters */ &kParameters[745],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [334] */
@@ -11355,6 +11689,7 @@
     /* parameters */ &kParameters[743],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [335] */
@@ -11366,6 +11701,7 @@
     /* parameters */ &kParameters[826],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [336] */
@@ -11377,6 +11713,7 @@
     /* parameters */ &kParameters[827],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [337] */
@@ -11388,6 +11725,7 @@
     /* parameters */ &kParameters[911],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [338] */
@@ -11399,6 +11737,7 @@
     /* parameters */ &kParameters[877],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [339] */
@@ -11410,6 +11749,7 @@
     /* parameters */ &kParameters[910],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [340] */
@@ -11421,6 +11761,7 @@
     /* parameters */ &kParameters[909],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [341] */
@@ -11432,6 +11773,7 @@
     /* parameters */ &kParameters[755],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [342] */
@@ -11443,6 +11785,7 @@
     /* parameters */ &kParameters[757],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [343] */
@@ -11454,6 +11797,7 @@
     /* parameters */ &kParameters[907],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [344] */
@@ -11465,6 +11809,7 @@
     /* parameters */ &kParameters[906],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [345] */
@@ -11476,6 +11821,7 @@
     /* parameters */ &kParameters[751],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [346] */
@@ -11487,6 +11833,7 @@
     /* parameters */ &kParameters[753],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [347] */
@@ -11498,6 +11845,7 @@
     /* parameters */ &kParameters[824],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [348] */
@@ -11509,6 +11857,7 @@
     /* parameters */ &kParameters[825],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [349] */
@@ -11520,6 +11869,7 @@
     /* parameters */ &kParameters[739],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [350] */
@@ -11531,6 +11881,7 @@
     /* parameters */ &kParameters[741],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [351] */
@@ -11542,6 +11893,7 @@
     /* parameters */ &kParameters[733],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [352] */
@@ -11553,6 +11905,7 @@
     /* parameters */ &kParameters[735],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [353] */
@@ -11564,6 +11917,7 @@
     /* parameters */ &kParameters[707],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [354] */
@@ -11575,6 +11929,7 @@
     /* parameters */ &kParameters[729],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [355] */
@@ -11586,6 +11941,7 @@
     /* parameters */ &kParameters[675],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [356] */
@@ -11597,6 +11953,7 @@
     /* parameters */ &kParameters[683],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [357] */
@@ -11608,6 +11965,7 @@
     /* parameters */ &kParameters[812],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [358] */
@@ -11619,6 +11977,7 @@
     /* parameters */ &kParameters[823],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [359] */
@@ -11630,6 +11989,7 @@
     /* parameters */ &kParameters[807],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [360] */
@@ -11641,6 +12001,7 @@
     /* parameters */ &kParameters[808],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [361] */
@@ -11652,6 +12013,7 @@
     /* parameters */ &kParameters[805],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [362] */
@@ -11663,6 +12025,7 @@
     /* parameters */ &kParameters[806],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [363] */
@@ -11674,6 +12037,7 @@
     /* parameters */ &kParameters[803],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [364] */
@@ -11685,6 +12049,7 @@
     /* parameters */ &kParameters[804],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [365] */
@@ -11696,6 +12061,7 @@
     /* parameters */ &kParameters[793],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [366] */
@@ -11707,6 +12073,7 @@
     /* parameters */ &kParameters[795],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [367] */
@@ -11718,6 +12085,7 @@
     /* parameters */ &kParameters[845],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [368] */
@@ -11729,6 +12097,7 @@
     /* parameters */ &kParameters[844],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [369] */
@@ -11740,6 +12109,7 @@
     /* parameters */ &kParameters[811],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [370] */
@@ -11751,6 +12121,7 @@
     /* parameters */ &kParameters[810],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [371] */
@@ -11762,6 +12133,7 @@
     /* parameters */ &kParameters[814],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [372] */
@@ -11773,6 +12145,7 @@
     /* parameters */ &kParameters[813],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [373] */
@@ -11784,6 +12157,7 @@
     /* parameters */ &kParameters[601],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [374] */
@@ -11795,6 +12169,7 @@
     /* parameters */ &kParameters[599],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [375] */
@@ -11806,6 +12181,7 @@
     /* parameters */ &kParameters[816],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [376] */
@@ -11817,6 +12193,7 @@
     /* parameters */ &kParameters[815],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [377] */
@@ -11828,6 +12205,7 @@
     /* parameters */ &kParameters[818],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [378] */
@@ -11839,6 +12217,7 @@
     /* parameters */ &kParameters[817],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [379] */
@@ -11850,6 +12229,7 @@
     /* parameters */ &kParameters[820],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [380] */
@@ -11861,6 +12241,7 @@
     /* parameters */ &kParameters[819],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [381] */
@@ -11872,6 +12253,7 @@
     /* parameters */ &kParameters[822],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [382] */
@@ -11883,6 +12265,7 @@
     /* parameters */ &kParameters[821],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [383] */
@@ -11894,6 +12277,7 @@
     /* parameters */ &kParameters[453],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [384] */
@@ -11905,6 +12289,7 @@
     /* parameters */ &kParameters[450],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [385] */
@@ -11916,6 +12301,7 @@
     /* parameters */ &kParameters[832],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [386] */
@@ -11927,6 +12313,7 @@
     /* parameters */ &kParameters[828],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [387] */
@@ -11938,6 +12325,7 @@
     /* parameters */ &kParameters[731],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [388] */
@@ -11949,6 +12337,7 @@
     /* parameters */ &kParameters[761],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [389] */
@@ -11960,6 +12349,7 @@
     /* parameters */ &kParameters[639],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [390] */
@@ -11971,6 +12361,7 @@
     /* parameters */ &kParameters[635],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [391] */
@@ -11982,6 +12373,7 @@
     /* parameters */ &kParameters[966],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [392] */
@@ -11993,6 +12385,7 @@
     /* parameters */ &kParameters[952],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [393] */
@@ -12004,6 +12397,7 @@
     /* parameters */ &kParameters[976],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [394] */
@@ -12015,6 +12409,7 @@
     /* parameters */ &kParameters[971],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [395] */
@@ -12026,6 +12421,7 @@
     /* parameters */ &kParameters[978],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [396] */
@@ -12037,6 +12433,7 @@
     /* parameters */ &kParameters[986],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [397] */
@@ -12048,6 +12445,7 @@
     /* parameters */ &kParameters[939],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [398] */
@@ -12059,6 +12457,7 @@
     /* parameters */ &kParameters[949],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [399] */
@@ -12070,6 +12469,7 @@
     /* parameters */ &kParameters[922],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [400] */
@@ -12081,6 +12481,7 @@
     /* parameters */ &kParameters[925],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [401] */
@@ -12092,6 +12493,7 @@
     /* parameters */ &kParameters[862],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [402] */
@@ -12103,6 +12505,7 @@
     /* parameters */ &kParameters[863],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [403] */
@@ -12114,6 +12517,7 @@
     /* parameters */ &kParameters[860],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [404] */
@@ -12125,6 +12529,7 @@
     /* parameters */ &kParameters[861],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [405] */
@@ -12136,6 +12541,7 @@
     /* parameters */ &kParameters[963],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [406] */
@@ -12147,6 +12553,7 @@
     /* parameters */ &kParameters[900],
     /* return matcher indices */ &kMatcherIndices[37],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [407] */
@@ -12158,6 +12565,7 @@
     /* parameters */ &kParameters[747],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [408] */
@@ -12169,6 +12577,7 @@
     /* parameters */ &kParameters[749],
     /* return matcher indices */ &kMatcherIndices[40],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [409] */
@@ -12180,6 +12589,7 @@
     /* parameters */ &kParameters[904],
     /* return matcher indices */ &kMatcherIndices[103],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [410] */
@@ -12191,6 +12601,7 @@
     /* parameters */ &kParameters[711],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [411] */
@@ -12202,6 +12613,7 @@
     /* parameters */ &kParameters[713],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [412] */
@@ -12213,6 +12625,7 @@
     /* parameters */ &kParameters[715],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [413] */
@@ -12224,6 +12637,7 @@
     /* parameters */ &kParameters[717],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [414] */
@@ -12235,6 +12649,7 @@
     /* parameters */ &kParameters[719],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [415] */
@@ -12246,6 +12661,7 @@
     /* parameters */ &kParameters[721],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [416] */
@@ -12257,6 +12673,7 @@
     /* parameters */ &kParameters[723],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [417] */
@@ -12268,6 +12685,7 @@
     /* parameters */ &kParameters[725],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [418] */
@@ -12279,6 +12697,7 @@
     /* parameters */ &kParameters[847],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [419] */
@@ -12290,6 +12709,7 @@
     /* parameters */ &kParameters[605],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [420] */
@@ -12301,6 +12721,7 @@
     /* parameters */ &kParameters[603],
     /* return matcher indices */ &kMatcherIndices[21],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [421] */
@@ -12312,6 +12733,7 @@
     /* parameters */ &kParameters[967],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [422] */
@@ -12323,6 +12745,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [423] */
@@ -12334,6 +12757,7 @@
     /* parameters */ &kParameters[901],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [424] */
@@ -12345,6 +12769,7 @@
     /* parameters */ &kParameters[902],
     /* return matcher indices */ &kMatcherIndices[45],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [425] */
@@ -12356,6 +12781,7 @@
     /* parameters */ &kParameters[903],
     /* return matcher indices */ &kMatcherIndices[103],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [426] */
@@ -12367,6 +12793,7 @@
     /* parameters */ &kParameters[709],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [427] */
@@ -12378,6 +12805,7 @@
     /* parameters */ &kParameters[987],
     /* return matcher indices */ &kMatcherIndices[103],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [428] */
@@ -12389,6 +12817,7 @@
     /* parameters */ &kParameters[908],
     /* return matcher indices */ &kMatcherIndices[23],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [429] */
@@ -12400,6 +12829,7 @@
     /* parameters */ &kParameters[990],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [430] */
@@ -12411,6 +12841,7 @@
     /* parameters */ &kParameters[507],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [431] */
@@ -12422,6 +12853,7 @@
     /* parameters */ &kParameters[767],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [432] */
@@ -12433,6 +12865,7 @@
     /* parameters */ &kParameters[989],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [433] */
@@ -12444,6 +12877,7 @@
     /* parameters */ &kParameters[958],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [434] */
@@ -12455,6 +12889,7 @@
     /* parameters */ &kParameters[972],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [435] */
@@ -12466,6 +12901,7 @@
     /* parameters */ &kParameters[977],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [436] */
@@ -12477,6 +12913,7 @@
     /* parameters */ &kParameters[982],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [437] */
@@ -12488,6 +12925,7 @@
     /* parameters */ &kParameters[504],
     /* return matcher indices */ &kMatcherIndices[31],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [438] */
@@ -12499,6 +12937,7 @@
     /* parameters */ &kParameters[597],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [439] */
@@ -12510,6 +12949,7 @@
     /* parameters */ &kParameters[799],
     /* return matcher indices */ &kMatcherIndices[44],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [440] */
@@ -12521,6 +12961,7 @@
     /* parameters */ &kParameters[797],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [441] */
@@ -12532,6 +12973,7 @@
     /* parameters */ &kParameters[809],
     /* return matcher indices */ &kMatcherIndices[5],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [442] */
@@ -12543,6 +12985,7 @@
     /* parameters */ &kParameters[791],
     /* return matcher indices */ &kMatcherIndices[121],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [443] */
@@ -12554,6 +12997,7 @@
     /* parameters */ &kParameters[981],
     /* return matcher indices */ &kMatcherIndices[62],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
   {
     /* [444] */
@@ -12565,6 +13009,7 @@
     /* parameters */ &kParameters[591],
     /* return matcher indices */ &kMatcherIndices[173],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* const eval */ nullptr,
   },
 };
 
diff --git a/src/tint/resolver/intrinsic_table.inl.tmpl b/src/tint/resolver/intrinsic_table.inl.tmpl
index f5e3575..663013e 100644
--- a/src/tint/resolver/intrinsic_table.inl.tmpl
+++ b/src/tint/resolver/intrinsic_table.inl.tmpl
@@ -86,11 +86,11 @@
     /* num template numbers */ {{$o.NumTemplateNumbers}},
     /* template types */
 {{-   if $o.TemplateTypesOffset }} &kTemplateTypes[{{$o.TemplateTypesOffset}}],
-{{-   else                  }} nullptr,
+{{-   else                      }} nullptr,
 {{-   end }}
     /* template numbers */
 {{-   if $o.TemplateNumbersOffset }} &kTemplateNumbers[{{$o.TemplateNumbersOffset}}]
-{{-   else                    }} nullptr
+{{-   else                        }} nullptr
 {{-   end }},
     /* parameters */ &kParameters[{{$o.ParametersOffset}}],
     /* return matcher indices */
@@ -102,6 +102,10 @@
         , OverloadFlag::kSupports{{Title $u}}Pipeline
 {{-   end }}
 {{-   if $o.IsDeprecated}}, OverloadFlag::kIsDeprecated{{end }}),
+    /* const eval */
+{{-   if $o.ConstEvalFunction }} const_eval::{{$o.ConstEvalFunction}},
+{{-   else                    }} nullptr,
+{{-   end }}
   },
 {{- end }}
 };
diff --git a/src/tint/resolver/intrinsic_table_test.cc b/src/tint/resolver/intrinsic_table_test.cc
index 9c5de1e..e2c651e 100644
--- a/src/tint/resolver/intrinsic_table_test.cc
+++ b/src/tint/resolver/intrinsic_table_test.cc
@@ -53,19 +53,19 @@
 
 TEST_F(IntrinsicTableTest, MatchF32) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kCos, {f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kCos, {f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kCos);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), f32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchF32) {
     auto* i32 = create<sem::I32>();
-    auto* result = table->Lookup(BuiltinType::kCos, {i32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kCos, {i32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -73,19 +73,19 @@
     auto* f32 = create<sem::F32>();
     auto* u32 = create<sem::U32>();
     auto* vec2_f32 = create<sem::Vector>(f32, 2u);
-    auto* result = table->Lookup(BuiltinType::kUnpack2x16float, {u32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kUnpack2x16float, {u32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kUnpack2x16float);
-    EXPECT_EQ(result->ReturnType(), vec2_f32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), u32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kUnpack2x16float);
+    EXPECT_EQ(result.sem->ReturnType(), vec2_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchU32) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kUnpack2x16float, {f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kUnpack2x16float, {f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -94,121 +94,121 @@
     auto* i32 = create<sem::I32>();
     auto* vec4_f32 = create<sem::Vector>(f32, 4u);
     auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, i32, i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, i32, i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
-    EXPECT_EQ(result->ReturnType(), vec4_f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
-    EXPECT_EQ(result->Parameters()[2]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+    EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kLevel);
 }
 
 TEST_F(IntrinsicTableTest, MismatchI32) {
     auto* f32 = create<sem::F32>();
     auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchIU32AsI32) {
     auto* i32 = create<sem::I32>();
-    auto* result = table->Lookup(BuiltinType::kCountOneBits, {i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kCountOneBits, {i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kCountOneBits);
-    EXPECT_EQ(result->ReturnType(), i32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), i32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
+    EXPECT_EQ(result.sem->ReturnType(), i32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), i32);
 }
 
 TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
     auto* u32 = create<sem::U32>();
-    auto* result = table->Lookup(BuiltinType::kCountOneBits, {u32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kCountOneBits, {u32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kCountOneBits);
-    EXPECT_EQ(result->ReturnType(), u32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), u32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
+    EXPECT_EQ(result.sem->ReturnType(), u32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchIU32) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kCountOneBits, {f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kCountOneBits, {f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
     auto* i32 = create<sem::I32>();
-    auto* result = table->Lookup(BuiltinType::kClamp, {i32, i32, i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kClamp, {i32, i32, i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kClamp);
-    EXPECT_EQ(result->ReturnType(), i32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[1]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[2]->Type(), i32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+    EXPECT_EQ(result.sem->ReturnType(), i32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
 }
 
 TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
     auto* u32 = create<sem::U32>();
-    auto* result = table->Lookup(BuiltinType::kClamp, {u32, u32, u32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kClamp, {u32, u32, u32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kClamp);
-    EXPECT_EQ(result->ReturnType(), u32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), u32);
-    EXPECT_EQ(result->Parameters()[1]->Type(), u32);
-    EXPECT_EQ(result->Parameters()[2]->Type(), u32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+    EXPECT_EQ(result.sem->ReturnType(), u32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), u32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), u32);
 }
 
 TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kClamp);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), f32);
-    EXPECT_EQ(result->Parameters()[1]->Type(), f32);
-    EXPECT_EQ(result->Parameters()[2]->Type(), f32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), f32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), f32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchFIU32) {
     auto* bool_ = create<sem::Bool>();
-    auto* result = table->Lookup(BuiltinType::kClamp, {bool_, bool_, bool_}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kClamp, {bool_, bool_, bool_}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchBool) {
     auto* f32 = create<sem::F32>();
     auto* bool_ = create<sem::Bool>();
-    auto* result = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kSelect);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), f32);
-    EXPECT_EQ(result->Parameters()[1]->Type(), f32);
-    EXPECT_EQ(result->Parameters()[2]->Type(), bool_);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), f32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), bool_);
 }
 
 TEST_F(IntrinsicTableTest, MismatchBool) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kSelect, {f32, f32, f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kSelect, {f32, f32, f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -217,41 +217,41 @@
     auto* atomicI32 = create<sem::Atomic>(i32);
     auto* ptr =
         create<sem::Pointer>(atomicI32, ast::StorageClass::kWorkgroup, ast::Access::kReadWrite);
-    auto* result = table->Lookup(BuiltinType::kAtomicLoad, {ptr}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kAtomicLoad, {ptr}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kAtomicLoad);
-    EXPECT_EQ(result->ReturnType(), i32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), ptr);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kAtomicLoad);
+    EXPECT_EQ(result.sem->ReturnType(), i32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), ptr);
 }
 
 TEST_F(IntrinsicTableTest, MismatchPointer) {
     auto* i32 = create<sem::I32>();
     auto* atomicI32 = create<sem::Atomic>(i32);
-    auto* result = table->Lookup(BuiltinType::kAtomicLoad, {atomicI32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kAtomicLoad, {atomicI32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchArray) {
     auto* arr = create<sem::Array>(create<sem::U32>(), 0u, 4u, 4u, 4u, 4u);
     auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage, ast::Access::kReadWrite);
-    auto* result = table->Lookup(BuiltinType::kArrayLength, {arr_ptr}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kArrayLength, {arr_ptr}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kArrayLength);
-    EXPECT_TRUE(result->ReturnType()->Is<sem::U32>());
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    auto* param_type = result->Parameters()[0]->Type();
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kArrayLength);
+    EXPECT_TRUE(result.sem->ReturnType()->Is<sem::U32>());
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    auto* param_type = result.sem->Parameters()[0]->Type();
     ASSERT_TRUE(param_type->Is<sem::Pointer>());
     EXPECT_TRUE(param_type->As<sem::Pointer>()->StoreType()->Is<sem::Array>());
 }
 
 TEST_F(IntrinsicTableTest, MismatchArray) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kArrayLength, {f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kArrayLength, {f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -261,26 +261,26 @@
     auto* vec4_f32 = create<sem::Vector>(f32, 4u);
     auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
     auto* sampler = create<sem::Sampler>(ast::SamplerKind::kSampler);
-    auto* result = table->Lookup(BuiltinType::kTextureSample, {tex, sampler, vec2_f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureSample, {tex, sampler, vec2_f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureSample);
-    EXPECT_EQ(result->ReturnType(), vec4_f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), sampler);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kSampler);
-    EXPECT_EQ(result->Parameters()[2]->Type(), vec2_f32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureSample);
+    EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), sampler);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kSampler);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), vec2_f32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kCoords);
 }
 
 TEST_F(IntrinsicTableTest, MismatchSampler) {
     auto* f32 = create<sem::F32>();
     auto* vec2_f32 = create<sem::Vector>(f32, 2u);
     auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
-    auto* result = table->Lookup(BuiltinType::kTextureSample, {tex, f32, vec2_f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kTextureSample, {tex, f32, vec2_f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -290,18 +290,18 @@
     auto* vec2_i32 = create<sem::Vector>(i32, 2u);
     auto* vec4_f32 = create<sem::Vector>(f32, 4u);
     auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
-    EXPECT_EQ(result->ReturnType(), vec4_f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
-    EXPECT_EQ(result->Parameters()[2]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+    EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kLevel);
 }
 
 TEST_F(IntrinsicTableTest, MatchMultisampledTexture) {
@@ -310,18 +310,18 @@
     auto* vec2_i32 = create<sem::Vector>(i32, 2u);
     auto* vec4_f32 = create<sem::Vector>(f32, 4u);
     auto* tex = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
-    EXPECT_EQ(result->ReturnType(), vec4_f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
-    EXPECT_EQ(result->Parameters()[2]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+    EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
 }
 
 TEST_F(IntrinsicTableTest, MatchDepthTexture) {
@@ -329,18 +329,18 @@
     auto* i32 = create<sem::I32>();
     auto* vec2_i32 = create<sem::Vector>(i32, 2u);
     auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
-    EXPECT_EQ(result->Parameters()[2]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kLevel);
 }
 
 TEST_F(IntrinsicTableTest, MatchDepthMultisampledTexture) {
@@ -348,18 +348,18 @@
     auto* i32 = create<sem::I32>();
     auto* vec2_i32 = create<sem::Vector>(i32, 2u);
     auto* tex = create<sem::DepthMultisampledTexture>(ast::TextureDimension::k2d);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
-    EXPECT_EQ(result->Parameters()[2]->Type(), i32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
 }
 
 TEST_F(IntrinsicTableTest, MatchExternalTexture) {
@@ -368,16 +368,16 @@
     auto* vec2_i32 = create<sem::Vector>(i32, 2u);
     auto* vec4_f32 = create<sem::Vector>(f32, 4u);
     auto* tex = create<sem::ExternalTexture>();
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
-    EXPECT_EQ(result->ReturnType(), vec4_f32);
-    ASSERT_EQ(result->Parameters().size(), 2u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+    EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 2u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
 }
 
 TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
@@ -389,83 +389,83 @@
     auto* tex = create<sem::StorageTexture>(ast::TextureDimension::k2d, ast::TexelFormat::kR32Float,
                                             ast::Access::kWrite, subtype);
 
-    auto* result = table->Lookup(BuiltinType::kTextureStore, {tex, vec2_i32, vec4_f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kTextureStore, {tex, vec2_i32, vec4_f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kTextureStore);
-    EXPECT_TRUE(result->ReturnType()->Is<sem::Void>());
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), tex);
-    EXPECT_EQ(result->Parameters()[0]->Usage(), ParameterUsage::kTexture);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_i32);
-    EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
-    EXPECT_EQ(result->Parameters()[2]->Type(), vec4_f32);
-    EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kValue);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureStore);
+    EXPECT_TRUE(result.sem->ReturnType()->Is<sem::Void>());
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
+    EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Usage(), ParameterUsage::kCoords);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), vec4_f32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Usage(), ParameterUsage::kValue);
 }
 
 TEST_F(IntrinsicTableTest, MismatchTexture) {
     auto* f32 = create<sem::F32>();
     auto* i32 = create<sem::I32>();
     auto* vec2_i32 = create<sem::Vector>(i32, 2u);
-    auto* result = table->Lookup(BuiltinType::kTextureLoad, {f32, vec2_i32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kTextureLoad, {f32, vec2_i32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(
+    auto result = table->Lookup(
         BuiltinType::kCos,
         {create<sem::Reference>(f32, ast::StorageClass::kFunction, ast::Access::kReadWrite)},
         Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kCos);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), f32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
 }
 
 TEST_F(IntrinsicTableTest, MatchTemplateType) {
     auto* f32 = create<sem::F32>();
-    auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kClamp);
-    EXPECT_EQ(result->ReturnType(), f32);
-    EXPECT_EQ(result->Parameters()[0]->Type(), f32);
-    EXPECT_EQ(result->Parameters()[1]->Type(), f32);
-    EXPECT_EQ(result->Parameters()[2]->Type(), f32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), f32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), f32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchTemplateType) {
     auto* f32 = create<sem::F32>();
     auto* u32 = create<sem::U32>();
-    auto* result = table->Lookup(BuiltinType::kClamp, {f32, u32, f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kClamp, {f32, u32, f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
     auto* f32 = create<sem::F32>();
     auto* vec2_f32 = create<sem::Vector>(f32, 2u);
-    auto* result = table->Lookup(BuiltinType::kClamp, {vec2_f32, vec2_f32, vec2_f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kClamp, {vec2_f32, vec2_f32, vec2_f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kClamp);
-    EXPECT_EQ(result->ReturnType(), vec2_f32);
-    ASSERT_EQ(result->Parameters().size(), 3u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), vec2_f32);
-    EXPECT_EQ(result->Parameters()[1]->Type(), vec2_f32);
-    EXPECT_EQ(result->Parameters()[2]->Type(), vec2_f32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+    EXPECT_EQ(result.sem->ReturnType(), vec2_f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 3u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), vec2_f32);
+    EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_f32);
+    EXPECT_EQ(result.sem->Parameters()[2]->Type(), vec2_f32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchOpenSizeVector) {
     auto* f32 = create<sem::F32>();
     auto* u32 = create<sem::U32>();
     auto* vec2_f32 = create<sem::Vector>(f32, 2u);
-    auto* result = table->Lookup(BuiltinType::kClamp, {vec2_f32, u32, vec2_f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kClamp, {vec2_f32, u32, vec2_f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -473,21 +473,21 @@
     auto* f32 = create<sem::F32>();
     auto* vec3_f32 = create<sem::Vector>(f32, 3u);
     auto* mat3_f32 = create<sem::Matrix>(vec3_f32, 3u);
-    auto* result = table->Lookup(BuiltinType::kDeterminant, {mat3_f32}, Source{});
-    ASSERT_NE(result, nullptr) << Diagnostics().str();
+    auto result = table->Lookup(BuiltinType::kDeterminant, {mat3_f32}, Source{});
+    ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
-    EXPECT_EQ(result->Type(), BuiltinType::kDeterminant);
-    EXPECT_EQ(result->ReturnType(), f32);
-    ASSERT_EQ(result->Parameters().size(), 1u);
-    EXPECT_EQ(result->Parameters()[0]->Type(), mat3_f32);
+    EXPECT_EQ(result.sem->Type(), BuiltinType::kDeterminant);
+    EXPECT_EQ(result.sem->ReturnType(), f32);
+    ASSERT_EQ(result.sem->Parameters().size(), 1u);
+    EXPECT_EQ(result.sem->Parameters()[0]->Type(), mat3_f32);
 }
 
 TEST_F(IntrinsicTableTest, MismatchOpenSizeMatrix) {
     auto* f32 = create<sem::F32>();
     auto* vec2_f32 = create<sem::Vector>(f32, 2u);
     auto* mat3x2_f32 = create<sem::Matrix>(vec2_f32, 3u);
-    auto* result = table->Lookup(BuiltinType::kDeterminant, {mat3x2_f32}, Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kDeterminant, {mat3x2_f32}, Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -572,20 +572,20 @@
     auto* f32 = create<sem::F32>();
     auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2u);
     auto* bool_ = create<sem::Bool>();
-    auto* a = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
-    ASSERT_NE(a, nullptr) << Diagnostics().str();
+    auto a = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
+    ASSERT_NE(a.sem, nullptr) << Diagnostics().str();
 
-    auto* b = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
-    ASSERT_NE(b, nullptr) << Diagnostics().str();
+    auto b = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
+    ASSERT_NE(b.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
 
-    auto* c = table->Lookup(BuiltinType::kSelect, {vec2_f32, vec2_f32, bool_}, Source{});
-    ASSERT_NE(c, nullptr) << Diagnostics().str();
+    auto c = table->Lookup(BuiltinType::kSelect, {vec2_f32, vec2_f32, bool_}, Source{});
+    ASSERT_NE(c.sem, nullptr) << Diagnostics().str();
     ASSERT_EQ(Diagnostics().str(), "");
 
-    EXPECT_EQ(a, b);
-    EXPECT_NE(a, c);
-    EXPECT_NE(b, c);
+    EXPECT_EQ(a.sem, b.sem);
+    EXPECT_NE(a.sem, c.sem);
+    EXPECT_NE(b.sem, c.sem);
 }
 
 TEST_F(IntrinsicTableTest, MatchUnaryOp) {
@@ -788,8 +788,8 @@
 TEST_F(IntrinsicTableTest, Err257Arguments) {  // crbug.com/1323605
     auto* f32 = create<sem::F32>();
     std::vector<const sem::Type*> arg_tys(257, f32);
-    auto* result = table->Lookup(BuiltinType::kAbs, std::move(arg_tys), Source{});
-    ASSERT_EQ(result, nullptr);
+    auto result = table->Lookup(BuiltinType::kAbs, std::move(arg_tys), Source{});
+    ASSERT_EQ(result.sem, nullptr);
     ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
@@ -1025,26 +1025,25 @@
     auto* arg_a = GetParam().arg_a(*this);
     auto* arg_b = GetParam().arg_b(*this);
     auto* arg_c = GetParam().arg_c(*this);
-    auto* builtin =
-        table->Lookup(sem::BuiltinType::kClamp, {arg_a, arg_b, arg_c}, Source{{12, 34}});
+    auto builtin = table->Lookup(sem::BuiltinType::kClamp, {arg_a, arg_b, arg_c}, Source{{12, 34}});
 
-    bool matched = builtin != nullptr;
+    bool matched = builtin.sem != nullptr;
     bool expected_match = GetParam().expected_match;
     EXPECT_EQ(matched, expected_match) << Diagnostics().str();
 
-    auto* result = builtin ? builtin->ReturnType() : nullptr;
+    auto* result = builtin.sem ? builtin.sem->ReturnType() : nullptr;
     auto* expected_result = GetParam().expected_result(*this);
     EXPECT_TYPE(result, expected_result);
 
-    auto* param_a = builtin ? builtin->Parameters()[0]->Type() : nullptr;
+    auto* param_a = builtin.sem ? builtin.sem->Parameters()[0]->Type() : nullptr;
     auto* expected_param_a = GetParam().expected_param_a(*this);
     EXPECT_TYPE(param_a, expected_param_a);
 
-    auto* param_b = builtin ? builtin->Parameters()[1]->Type() : nullptr;
+    auto* param_b = builtin.sem ? builtin.sem->Parameters()[1]->Type() : nullptr;
     auto* expected_param_b = GetParam().expected_param_b(*this);
     EXPECT_TYPE(param_b, expected_param_b);
 
-    auto* param_c = builtin ? builtin->Parameters()[2]->Type() : nullptr;
+    auto* param_c = builtin.sem ? builtin.sem->Parameters()[2]->Type() : nullptr;
     auto* expected_param_c = GetParam().expected_param_c(*this);
     EXPECT_TYPE(param_c, expected_param_c);
 }
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index aa09cfa..294b3fb 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -85,13 +85,12 @@
 
 namespace tint::resolver {
 
-Resolver::Resolver(ProgramBuilder* builder, bool enable_abstract_numerics)
+Resolver::Resolver(ProgramBuilder* builder)
     : builder_(builder),
       diagnostics_(builder->Diagnostics()),
       intrinsic_table_(IntrinsicTable::Create(*builder)),
       sem_(builder, dependencies_),
-      validator_(builder, sem_),
-      enable_abstract_numerics_(enable_abstract_numerics) {}
+      validator_(builder, sem_) {}
 
 Resolver::~Resolver() = default;
 
@@ -1493,30 +1492,48 @@
 sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
                                  sem::BuiltinType builtin_type,
                                  std::vector<const sem::Expression*> args) {
-    const sem::Builtin* builtin = nullptr;
+    IntrinsicTable::Builtin builtin;
     {
         auto arg_tys = utils::Transform(args, [](auto* arg) { return arg->Type(); });
         builtin = intrinsic_table_->Lookup(builtin_type, arg_tys, expr->source);
-        if (!builtin) {
+        if (!builtin.sem) {
             return nullptr;
         }
     }
 
-    if (!MaterializeArguments(args, builtin)) {
+    if (!MaterializeArguments(args, builtin.sem)) {
         return nullptr;
     }
 
-    if (builtin->IsDeprecated()) {
+    if (builtin.sem->IsDeprecated()) {
         AddWarning("use of deprecated builtin", expr->source);
     }
 
-    bool has_side_effects =
-        builtin->HasSideEffects() ||
-        std::any_of(args.begin(), args.end(), [](auto* e) { return e->HasSideEffects(); });
-    auto* call = builder_->create<sem::Call>(expr, builtin, std::move(args), current_statement_,
-                                             sem::Constant{}, has_side_effects);
+    // If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
+    sem::Constant constant;
+    if (builtin.const_eval_fn) {
+        std::vector<sem::Constant> values(args.size());
+        bool is_const = true;  // all arguments have constant values
+        for (size_t i = 0; i < values.size(); i++) {
+            if (auto v = args[i]->ConstantValue()) {
+                values[i] = std::move(v);
+            } else {
+                is_const = false;
+                break;
+            }
+        }
+        if (is_const) {
+            constant = builtin.const_eval_fn(*builder_, values.data(), args.size());
+        }
+    }
 
-    current_function_->AddDirectlyCalledBuiltin(builtin);
+    bool has_side_effects =
+        builtin.sem->HasSideEffects() ||
+        std::any_of(args.begin(), args.end(), [](auto* e) { return e->HasSideEffects(); });
+    auto* call = builder_->create<sem::Call>(expr, builtin.sem, std::move(args), current_statement_,
+                                             constant, has_side_effects);
+
+    current_function_->AddDirectlyCalledBuiltin(builtin.sem);
 
     if (!validator_.RequiredExtensionForBuiltinFunction(call, enabled_extensions_)) {
         return nullptr;
@@ -1526,7 +1543,7 @@
         if (!validator_.TextureBuiltinFunction(call)) {
             return nullptr;
         }
-        CollectTextureSamplerPairs(builtin, call->Arguments());
+        CollectTextureSamplerPairs(builtin.sem, call->Arguments());
     }
 
     if (!validator_.BuiltinCall(call)) {
@@ -1632,10 +1649,7 @@
         [&](const ast::IntLiteralExpression* i) -> sem::Type* {
             switch (i->suffix) {
                 case ast::IntLiteralExpression::Suffix::kNone:
-                    if (enable_abstract_numerics_) {
-                        return builder_->create<sem::AbstractInt>();
-                    }
-                    return builder_->create<sem::I32>();
+                    return builder_->create<sem::AbstractInt>();
                 case ast::IntLiteralExpression::Suffix::kI:
                     return builder_->create<sem::I32>();
                 case ast::IntLiteralExpression::Suffix::kU:
@@ -1644,8 +1658,7 @@
             return nullptr;
         },
         [&](const ast::FloatLiteralExpression* f) -> sem::Type* {
-            if (f->suffix == ast::FloatLiteralExpression::Suffix::kNone &&
-                enable_abstract_numerics_) {
+            if (f->suffix == ast::FloatLiteralExpression::Suffix::kNone) {
                 return builder_->create<sem::AbstractFloat>();
             }
             return builder_->create<sem::F32>();
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 9072ef3..9999651 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -76,10 +76,7 @@
   public:
     /// Constructor
     /// @param builder the program builder
-    /// @param enable_abstract_numerics if true, then treat unsuffixed integers as abstract integers
-    /// and unsuffixed floats as abstract floats. This is a temporary flag while abstract numerics
-    /// are being developed. Once complete, this will be permanently enabled.
-    explicit Resolver(ProgramBuilder* builder, bool enable_abstract_numerics = false);
+    explicit Resolver(ProgramBuilder* builder);
 
     /// Destructor
     ~Resolver();
@@ -399,8 +396,6 @@
     sem::Statement* current_statement_ = nullptr;
     sem::CompoundStatement* current_compound_statement_ = nullptr;
     sem::BlockStatement* current_block_ = nullptr;
-
-    bool enable_abstract_numerics_ = false;
 };
 
 }  // namespace tint::resolver
diff --git a/src/tint/resolver/resolver_test_helper.cc b/src/tint/resolver/resolver_test_helper.cc
index 75a6698..dd590d9 100644
--- a/src/tint/resolver/resolver_test_helper.cc
+++ b/src/tint/resolver/resolver_test_helper.cc
@@ -18,8 +18,7 @@
 
 namespace tint::resolver {
 
-TestHelper::TestHelper()
-    : resolver_(std::make_unique<Resolver>(this, /* enable_abstract_numerics */ true)) {}
+TestHelper::TestHelper() : resolver_(std::make_unique<Resolver>(this)) {}
 
 TestHelper::~TestHelper() = default;
 
diff --git a/src/tint/sem/constant.cc b/src/tint/sem/constant.cc
index a2cfe8f..8086992 100644
--- a/src/tint/sem/constant.cc
+++ b/src/tint/sem/constant.cc
@@ -14,6 +14,7 @@
 
 #include "src/tint/sem/constant.h"
 
+#include <cmath>
 #include <utility>
 
 #include "src/tint/debug.h"
@@ -26,6 +27,17 @@
 size_t CountElements(const Constant::Elements& elements) {
     return std::visit([](auto&& vec) { return vec.size(); }, elements);
 }
+
+template <typename T>
+bool IsNegativeFloat(T value) {
+    (void)value;
+    if constexpr (IsFloatingPoint<T>) {
+        return std::signbit(value);
+    } else {
+        return false;
+    }
+}
+
 }  // namespace
 
 Constant::Constant() {}
@@ -47,7 +59,7 @@
     return WithElements([&](auto&& vec) {
         using T = typename std::decay_t<decltype(vec)>::value_type;
         for (auto el : vec) {
-            if (el == T(0)) {
+            if (el == T(0) && !IsNegativeFloat(el.value)) {
                 return true;
             }
         }
@@ -59,7 +71,7 @@
     return WithElements([&](auto&& vec) {
         using T = typename std::decay_t<decltype(vec)>::value_type;
         for (auto el : vec) {
-            if (el != T(0)) {
+            if (el != T(0) || IsNegativeFloat(el.value)) {
                 return false;
             }
         }
@@ -71,8 +83,9 @@
     return WithElements([&](auto&& vec) {
         if (!vec.empty()) {
             auto value = vec[start];
+            bool float_sign = IsNegativeFloat(vec[start].value);
             for (size_t i = start + 1; i < end; i++) {
-                if (vec[i] != value) {
+                if (vec[i] != value || float_sign != IsNegativeFloat(vec[i].value)) {
                     return false;
                 }
             }
diff --git a/src/tint/sem/constant.h b/src/tint/sem/constant.h
index c99b979..c0ba9e6 100644
--- a/src/tint/sem/constant.h
+++ b/src/tint/sem/constant.h
@@ -48,6 +48,10 @@
     /// Elements is either a vector of AInts or AFloats
     using Elements = std::variant<AInts, AFloats>;
 
+    /// Helper that resolves to either AInt or AFloat based on the element type T.
+    template <typename T>
+    using ElementFor = std::conditional_t<IsFloatingPoint<UnwrapNumber<T>>, AFloat, AInt>;
+
     /// Helper that resolves to either AInts or AFloats based on the element type T.
     template <typename T>
     using ElementVectorFor = std::conditional_t<IsFloatingPoint<UnwrapNumber<T>>, AFloats, AInts>;
@@ -129,13 +133,13 @@
     /// @returns the elements as a vector of AFloat
     inline const AFloats& FElements() const { return std::get<AFloats>(elems_); }
 
-    /// @returns true if any element is zero
+    /// @returns true if any element is positive zero
     bool AnyZero() const;
 
-    /// @returns true if all elements are zero
+    /// @returns true if all elements are positive zero
     bool AllZero() const;
 
-    /// @returns true if all elements are the same value
+    /// @returns true if all elements are the same value, with the same sign-bit.
     bool AllEqual() const { return AllEqual(0, ElementCount()); }
 
     /// @param start the first element index
@@ -164,7 +168,7 @@
     ElementVectorFor<T> elements;
     elements.reserve(els.size());
     for (auto el : els) {
-        elements.emplace_back(AFloat(el));
+        elements.emplace_back(ElementFor<T>(el));
     }
     elems_ = Elements{std::move(elements)};
 }
diff --git a/src/tint/sem/constant_test.cc b/src/tint/sem/constant_test.cc
index 6ad3cd6..ed9fef8 100644
--- a/src/tint/sem/constant_test.cc
+++ b/src/tint/sem/constant_test.cc
@@ -29,16 +29,19 @@
 
 TEST_F(ConstantTest, ConstructorInitializerList) {
     {
-        Constant c(create<AbstractInt>(), {1_a});
-        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1_a)); });
+        auto i = AInt(AInt::kHighest);
+        Constant c(create<AbstractInt>(), {i});
+        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(i)); });
     }
     {
-        Constant c(create<I32>(), {1_i});
-        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1_a)); });
+        auto i = i32(i32::kHighest);
+        Constant c(create<I32>(), {i});
+        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(i)); });
     }
     {
-        Constant c(create<U32>(), {1_u});
-        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1_a)); });
+        auto i = u32(u32::kHighest);
+        Constant c(create<U32>(), {i});
+        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(i)); });
     }
     {
         Constant c(create<Bool>(), {false});
@@ -49,16 +52,19 @@
         c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1_a)); });
     }
     {
-        Constant c(create<AbstractFloat>(), {1.0_a});
-        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1.0_a)); });
+        auto f = AFloat(AFloat::kHighest);
+        Constant c(create<AbstractFloat>(), {f});
+        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(f)); });
     }
     {
-        Constant c(create<F32>(), {1.0_f});
-        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1.0_a)); });
+        auto f = f32(f32::kHighest);
+        Constant c(create<F32>(), {f});
+        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(f)); });
     }
     {
-        Constant c(create<F16>(), {1.0_h});
-        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(1.0_a)); });
+        auto f = f16(f16::kHighest);
+        Constant c(create<F16>(), {f});
+        c.WithElements([&](auto&& vec) { EXPECT_THAT(vec, testing::ElementsAre(f)); });
     }
 }
 
@@ -202,6 +208,20 @@
     EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 3_a}).AnyZero(), true);
     EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_a}).AnyZero(), true);
     EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AnyZero(), true);
+
+    auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AnyZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 3._a}).AnyZero(), true);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 3._a}).AnyZero(), true);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 0._a}).AnyZero(), true);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AnyZero(), true);
+
+    EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 3._a}).AnyZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -2._a, 3._a}).AnyZero(), true);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 3._a}).AnyZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 0._a}).AnyZero(), true);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AnyZero(), true);
+    EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, -0._a}).AnyZero(), false);
 }
 
 TEST_F(ConstantTest, AllZero) {
@@ -211,6 +231,20 @@
     EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 3_a}).AllZero(), false);
     EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_a}).AllZero(), false);
     EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AllZero(), true);
+
+    auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 3._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 3._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 0._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AllZero(), true);
+
+    EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 3._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -2._a, 3._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 3._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 0._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllZero(), false);
+    EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, -0._a}).AllZero(), false);
 }
 
 TEST_F(ConstantTest, AllEqual) {
@@ -221,6 +255,17 @@
     EXPECT_EQ(Constant(vec3_ai, {1_a, 1_a, 1_a}).AllEqual(), true);
     EXPECT_EQ(Constant(vec3_ai, {2_a, 2_a, 2_a}).AllEqual(), true);
     EXPECT_EQ(Constant(vec3_ai, {3_a, 3_a, 3_a}).AllEqual(), true);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AllEqual(), true);
+
+    auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllEqual(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 3._a}).AllEqual(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 3._a, 3._a}).AllEqual(), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 1._a}).AllEqual(), true);
+    EXPECT_EQ(Constant(vec3_af, {2._a, 2._a, 2._a}).AllEqual(), true);
+    EXPECT_EQ(Constant(vec3_af, {3._a, 3._a, 3._a}).AllEqual(), true);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AllEqual(), true);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllEqual(), false);
 }
 
 TEST_F(ConstantTest, AllEqualRange) {
@@ -231,6 +276,28 @@
     EXPECT_EQ(Constant(vec3_ai, {1_a, 1_a, 1_a}).AllEqual(1, 3), true);
     EXPECT_EQ(Constant(vec3_ai, {2_a, 2_a, 2_a}).AllEqual(1, 3), true);
     EXPECT_EQ(Constant(vec3_ai, {2_a, 2_a, 3_a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 0_a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 1_a, 0_a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 1_a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AllEqual(1, 3), true);
+
+    auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 3._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 3._a, 3._a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 1._a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {2._a, 2._a, 2._a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {2._a, 2._a, 3._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 0._a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 1._a, 0._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 1._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 0._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -1._a, 0._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 1._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllEqual(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, -0._a}).AllEqual(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, -0._a}).AllEqual(1, 3), true);
 }
 
 }  // namespace
diff --git a/src/tint/transform/fold_constants.cc b/src/tint/transform/fold_constants.cc
deleted file mode 100644
index f268800..0000000
--- a/src/tint/transform/fold_constants.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2021 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.
-
-#include "src/tint/transform/fold_constants.h"
-
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "src/tint/program_builder.h"
-#include "src/tint/sem/call.h"
-#include "src/tint/sem/expression.h"
-#include "src/tint/sem/type_constructor.h"
-#include "src/tint/sem/type_conversion.h"
-#include "src/tint/utils/transform.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::transform::FoldConstants);
-
-namespace tint::transform {
-
-FoldConstants::FoldConstants() = default;
-
-FoldConstants::~FoldConstants() = default;
-
-void FoldConstants::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
-    ctx.ReplaceAll([&](const ast::Expression* expr) -> const ast::Expression* {
-        auto* call = ctx.src->Sem().Get<sem::Call>(expr);
-        if (!call) {
-            return nullptr;
-        }
-
-        auto value = call->ConstantValue();
-        if (!value.IsValid()) {
-            return nullptr;
-        }
-
-        auto* ty = call->Type();
-
-        if (!call->Target()->IsAnyOf<sem::TypeConversion, sem::TypeConstructor>()) {
-            return nullptr;
-        }
-
-        // If original ctor expression had no init values, don't replace the expression
-        if (call->Arguments().empty()) {
-            return nullptr;
-        }
-
-        auto build_elements = [&](size_t limit) {
-            return Switch(
-                value.ElementType(),  //
-                [&](const sem::Bool*) {
-                    return utils::TransformN(value.IElements(), limit, [&](AInt i) {
-                        return static_cast<const ast::Expression*>(
-                            ctx.dst->Expr(static_cast<bool>(i.value)));
-                    });
-                },
-                [&](const sem::I32*) {
-                    return utils::TransformN(value.IElements(), limit, [&](AInt i) {
-                        return static_cast<const ast::Expression*>(ctx.dst->Expr(i32(i.value)));
-                    });
-                },
-                [&](const sem::U32*) {
-                    return utils::TransformN(value.IElements(), limit, [&](AInt i) {
-                        return static_cast<const ast::Expression*>(ctx.dst->Expr(u32(i.value)));
-                    });
-                },
-                [&](const sem::F32*) {
-                    return utils::TransformN(value.FElements(), limit, [&](AFloat f) {
-                        return static_cast<const ast::Expression*>(ctx.dst->Expr(f32(f.value)));
-                    });
-                },
-                [&](Default) {
-                    TINT_ICE(Transform, ctx.dst->Diagnostics())
-                        << "unhandled Constant::Scalar type: "
-                        << value.ElementType()->FriendlyName(ctx.src->Symbols());
-                    return ast::ExpressionList{};
-                });
-        };
-
-        if (auto* vec = ty->As<sem::Vector>()) {
-            uint32_t vec_size = static_cast<uint32_t>(vec->Width());
-
-            // We'd like to construct the new vector with the same number of
-            // constructor args that the original node had, but after folding
-            // constants, cases like the following are problematic:
-            //
-            // vec3<f32> = vec3<f32>(vec2<f32>(), 1.0) // vec_size=3, ctor_size=2
-            //
-            // In this case, creating a vec3 with 2 args is invalid, so we should
-            // create it with 3. So what we do is construct with vec_size args,
-            // except if the original vector was single-value initialized, in
-            // which case, we only construct with one arg again.
-            ast::ExpressionList ctors;
-            if (call->Arguments().size() == 1) {
-                ctors = build_elements(1);
-            } else {
-                ctors = build_elements(value.ElementCount());
-            }
-
-            auto* el_ty = CreateASTTypeFor(ctx, vec->type());
-            return ctx.dst->vec(el_ty, vec_size, ctors);
-        }
-
-        if (ty->is_scalar()) {
-            return build_elements(1)[0];
-        }
-
-        return nullptr;
-    });
-
-    ctx.Clone();
-}
-
-}  // namespace tint::transform
diff --git a/src/tint/transform/fold_constants.h b/src/tint/transform/fold_constants.h
deleted file mode 100644
index ed3e205..0000000
--- a/src/tint/transform/fold_constants.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2021 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.
-
-#ifndef SRC_TINT_TRANSFORM_FOLD_CONSTANTS_H_
-#define SRC_TINT_TRANSFORM_FOLD_CONSTANTS_H_
-
-#include "src/tint/transform/transform.h"
-
-namespace tint::transform {
-
-/// FoldConstants transforms the AST by folding constant expressions
-class FoldConstants final : public Castable<FoldConstants, Transform> {
-  public:
-    /// Constructor
-    FoldConstants();
-
-    /// Destructor
-    ~FoldConstants() override;
-
-  protected:
-    /// Runs the transform using the CloneContext built for transforming a
-    /// program. Run() is responsible for calling Clone() on the CloneContext.
-    /// @param ctx the CloneContext primed with the input program and
-    /// ProgramBuilder
-    /// @param inputs optional extra transform-specific input data
-    /// @param outputs optional extra transform-specific output data
-    void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const override;
-};
-
-}  // namespace tint::transform
-
-#endif  // SRC_TINT_TRANSFORM_FOLD_CONSTANTS_H_
diff --git a/src/tint/transform/fold_constants_test.cc b/src/tint/transform/fold_constants_test.cc
deleted file mode 100644
index 54bb2e3..0000000
--- a/src/tint/transform/fold_constants_test.cc
+++ /dev/null
@@ -1,425 +0,0 @@
-// Copyright 2021 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.
-
-#include "src/tint/transform/fold_constants.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "src/tint/transform/test_helper.h"
-
-namespace tint::transform {
-namespace {
-
-using FoldConstantsTest = TransformTest;
-
-TEST_F(FoldConstantsTest, Module_Scalar_NoConversion) {
-    auto* src = R"(
-var<private> a : i32 = i32(123);
-var<private> b : u32 = u32(123u);
-var<private> c : f32 = f32(123.0);
-var<private> d : bool = bool(true);
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : i32 = 123i;
-
-var<private> b : u32 = 123u;
-
-var<private> c : f32 = 123.0f;
-
-var<private> d : bool = true;
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Module_Scalar_Conversion) {
-    auto* src = R"(
-var<private> a : i32 = i32(123.0);
-var<private> b : u32 = u32(123);
-var<private> c : f32 = f32(123u);
-var<private> d : bool = bool(123);
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : i32 = 123i;
-
-var<private> b : u32 = 123u;
-
-var<private> c : f32 = 123.0f;
-
-var<private> d : bool = true;
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Module_Scalar_MultipleConversions) {
-    auto* src = R"(
-var<private> a : i32 = i32(u32(f32(u32(i32(123.0)))));
-var<private> b : u32 = u32(i32(f32(i32(u32(123)))));
-var<private> c : f32 = f32(u32(i32(u32(f32(123u)))));
-var<private> d : bool = bool(i32(f32(i32(u32(123)))));
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : i32 = 123i;
-
-var<private> b : u32 = 123u;
-
-var<private> c : f32 = 123.0f;
-
-var<private> d : bool = true;
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Module_Vector_NoConversion) {
-    auto* src = R"(
-var<private> a : vec3<i32> = vec3<i32>(123);
-var<private> b : vec3<u32> = vec3<u32>(123u);
-var<private> c : vec3<f32> = vec3<f32>(123.0);
-var<private> d : vec3<bool> = vec3<bool>(true);
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : vec3<i32> = vec3<i32>(123i);
-
-var<private> b : vec3<u32> = vec3<u32>(123u);
-
-var<private> c : vec3<f32> = vec3<f32>(123.0f);
-
-var<private> d : vec3<bool> = vec3<bool>(true);
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Module_Vector_Conversion) {
-    auto* src = R"(
-var<private> a : vec3<i32> = vec3<i32>(vec3<f32>(123.0));
-var<private> b : vec3<u32> = vec3<u32>(vec3<i32>(123));
-var<private> c : vec3<f32> = vec3<f32>(vec3<u32>(123u));
-var<private> d : vec3<bool> = vec3<bool>(vec3<i32>(123));
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : vec3<i32> = vec3<i32>(123i);
-
-var<private> b : vec3<u32> = vec3<u32>(123u);
-
-var<private> c : vec3<f32> = vec3<f32>(123.0f);
-
-var<private> d : vec3<bool> = vec3<bool>(true);
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Module_Vector_MultipleConversions) {
-    auto* src = R"(
-var<private> a : vec3<i32> = vec3<i32>(vec3<u32>(vec3<f32>(vec3<u32>(u32(123.0)))));
-var<private> b : vec3<u32> = vec3<u32>(vec3<i32>(vec3<f32>(vec3<i32>(i32(123)))));
-var<private> c : vec3<f32> = vec3<f32>(vec3<u32>(vec3<i32>(vec3<u32>(u32(123u)))));
-var<private> d : vec3<bool> = vec3<bool>(vec3<i32>(vec3<f32>(vec3<i32>(i32(123)))));
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : vec3<i32> = vec3<i32>(123i);
-
-var<private> b : vec3<u32> = vec3<u32>(123u);
-
-var<private> c : vec3<f32> = vec3<f32>(123.0f);
-
-var<private> d : vec3<bool> = vec3<bool>(true);
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Module_Vector_MixedSizeConversions) {
-    auto* src = R"(
-var<private> a : vec4<i32> = vec4<i32>(vec3<i32>(vec3<u32>(1u, 2u, 3u)), 4);
-var<private> b : vec4<i32> = vec4<i32>(vec2<i32>(vec2<u32>(1u, 2u)), vec2<i32>(4, 5));
-var<private> c : vec4<i32> = vec4<i32>(1, vec2<i32>(vec2<f32>(2.0, 3.0)), 4);
-var<private> d : vec4<i32> = vec4<i32>(1, 2, vec2<i32>(vec2<f32>(3.0, 4.0)));
-var<private> e : vec4<bool> = vec4<bool>(false, bool(f32(1.0)), vec2<bool>(vec2<i32>(0, i32(4u))));
-
-fn f() {
-}
-)";
-
-    auto* expect = R"(
-var<private> a : vec4<i32> = vec4<i32>(1i, 2i, 3i, 4i);
-
-var<private> b : vec4<i32> = vec4<i32>(1i, 2i, 4i, 5i);
-
-var<private> c : vec4<i32> = vec4<i32>(1i, 2i, 3i, 4i);
-
-var<private> d : vec4<i32> = vec4<i32>(1i, 2i, 3i, 4i);
-
-var<private> e : vec4<bool> = vec4<bool>(false, true, false, true);
-
-fn f() {
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Scalar_NoConversion) {
-    auto* src = R"(
-fn f() {
-  var a : i32 = i32(123);
-  var b : u32 = u32(123u);
-  var c : f32 = f32(123.0);
-  var d : bool = bool(true);
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : i32 = 123i;
-  var b : u32 = 123u;
-  var c : f32 = 123.0f;
-  var d : bool = true;
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Scalar_Conversion) {
-    auto* src = R"(
-fn f() {
-  var a : i32 = i32(123.0);
-  var b : u32 = u32(123);
-  var c : f32 = f32(123u);
-  var d : bool = bool(123);
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : i32 = 123i;
-  var b : u32 = 123u;
-  var c : f32 = 123.0f;
-  var d : bool = true;
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Scalar_MultipleConversions) {
-    auto* src = R"(
-fn f() {
-  var a : i32 = i32(u32(f32(u32(i32(123.0)))));
-  var b : u32 = u32(i32(f32(i32(u32(123)))));
-  var c : f32 = f32(u32(i32(u32(f32(123u)))));
-  var d : bool = bool(i32(f32(i32(u32(123)))));
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : i32 = 123i;
-  var b : u32 = 123u;
-  var c : f32 = 123.0f;
-  var d : bool = true;
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Vector_NoConversion) {
-    auto* src = R"(
-fn f() {
-  var a : vec3<i32> = vec3<i32>(123i);
-  var b : vec3<u32> = vec3<u32>(123u);
-  var c : vec3<f32> = vec3<f32>(123.0f);
-  var d : vec3<bool> = vec3<bool>(true);
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : vec3<i32> = vec3<i32>(123i);
-  var b : vec3<u32> = vec3<u32>(123u);
-  var c : vec3<f32> = vec3<f32>(123.0f);
-  var d : vec3<bool> = vec3<bool>(true);
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Vector_Conversion) {
-    auto* src = R"(
-fn f() {
-  var a : vec3<i32> = vec3<i32>(vec3<f32>(123.0));
-  var b : vec3<u32> = vec3<u32>(vec3<i32>(123));
-  var c : vec3<f32> = vec3<f32>(vec3<u32>(123u));
-  var d : vec3<bool> = vec3<bool>(vec3<i32>(123));
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : vec3<i32> = vec3<i32>(123i);
-  var b : vec3<u32> = vec3<u32>(123u);
-  var c : vec3<f32> = vec3<f32>(123.0f);
-  var d : vec3<bool> = vec3<bool>(true);
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Vector_MultipleConversions) {
-    auto* src = R"(
-fn f() {
-  var a : vec3<i32> = vec3<i32>(vec3<u32>(vec3<f32>(vec3<u32>(u32(123.0)))));
-  var b : vec3<u32> = vec3<u32>(vec3<i32>(vec3<f32>(vec3<i32>(i32(123)))));
-  var c : vec3<f32> = vec3<f32>(vec3<u32>(vec3<i32>(vec3<u32>(u32(123u)))));
-  var d : vec3<bool> = vec3<bool>(vec3<i32>(vec3<f32>(vec3<i32>(i32(123)))));
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : vec3<i32> = vec3<i32>(123i);
-  var b : vec3<u32> = vec3<u32>(123u);
-  var c : vec3<f32> = vec3<f32>(123.0f);
-  var d : vec3<bool> = vec3<bool>(true);
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Vector_MixedSizeConversions) {
-    auto* src = R"(
-fn f() {
-  var a : vec4<i32> = vec4<i32>(vec3<i32>(vec3<u32>(1u, 2u, 3u)), 4);
-  var b : vec4<i32> = vec4<i32>(vec2<i32>(vec2<u32>(1u, 2u)), vec2<i32>(4, 5));
-  var c : vec4<i32> = vec4<i32>(1, vec2<i32>(vec2<f32>(2.0, 3.0)), 4);
-  var d : vec4<i32> = vec4<i32>(1, 2, vec2<i32>(vec2<f32>(3.0, 4.0)));
-  var e : vec4<bool> = vec4<bool>(false, bool(f32(1.0)), vec2<bool>(vec2<i32>(0, i32(4u))));
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : vec4<i32> = vec4<i32>(1i, 2i, 3i, 4i);
-  var b : vec4<i32> = vec4<i32>(1i, 2i, 4i, 5i);
-  var c : vec4<i32> = vec4<i32>(1i, 2i, 3i, 4i);
-  var d : vec4<i32> = vec4<i32>(1i, 2i, 3i, 4i);
-  var e : vec4<bool> = vec4<bool>(false, true, false, true);
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(FoldConstantsTest, Function_Vector_ConstantWithNonConstant) {
-    auto* src = R"(
-fn f() {
-  var a : f32 = f32();
-  var b : vec2<f32> = vec2<f32>(f32(i32(1)), a);
-}
-)";
-
-    auto* expect = R"(
-fn f() {
-  var a : f32 = f32();
-  var b : vec2<f32> = vec2<f32>(1.0f, a);
-}
-)";
-
-    auto got = Run<FoldConstants>(src);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-}  // namespace
-}  // namespace tint::transform
diff --git a/src/tint/transform/num_workgroups_from_uniform.cc b/src/tint/transform/num_workgroups_from_uniform.cc
index 17814df..0bb1518 100644
--- a/src/tint/transform/num_workgroups_from_uniform.cc
+++ b/src/tint/transform/num_workgroups_from_uniform.cc
@@ -122,10 +122,31 @@
             auto* num_workgroups_struct = ctx.dst->Structure(
                 ctx.dst->Sym(),
                 {ctx.dst->Member(kNumWorkgroupsMemberName, ctx.dst->ty.vec3(ctx.dst->ty.u32()))});
+
+            uint32_t group, binding;
+            if (cfg->ubo_binding.has_value()) {
+                // If cfg->ubo_binding holds a value, use the specified binding point.
+                group = cfg->ubo_binding->group;
+                binding = cfg->ubo_binding->binding;
+            } else {
+                // If cfg->ubo_binding holds no value, use the binding 0 of the largest used group
+                // plus 1, or group 0 if no resource bound.
+                group = 0;
+
+                for (auto* var : ctx.src->AST().GlobalVariables()) {
+                    if (auto binding_point = var->BindingPoint()) {
+                        if (binding_point.group->value >= group) {
+                            group = binding_point.group->value + 1;
+                        }
+                    }
+                }
+
+                binding = 0;
+            }
+
             num_workgroups_ubo = ctx.dst->Global(
                 ctx.dst->Sym(), ctx.dst->ty.Of(num_workgroups_struct), ast::StorageClass::kUniform,
-                ast::AttributeList{
-                    ctx.dst->GroupAndBinding(cfg->ubo_binding.group, cfg->ubo_binding.binding)});
+                ast::AttributeList{ctx.dst->GroupAndBinding(group, binding)});
         }
         return num_workgroups_ubo;
     };
@@ -151,7 +172,8 @@
     ctx.Clone();
 }
 
-NumWorkgroupsFromUniform::Config::Config(sem::BindingPoint ubo_bp) : ubo_binding(ubo_bp) {}
+NumWorkgroupsFromUniform::Config::Config(std::optional<sem::BindingPoint> ubo_bp)
+    : ubo_binding(ubo_bp) {}
 NumWorkgroupsFromUniform::Config::Config(const Config&) = default;
 NumWorkgroupsFromUniform::Config::~Config() = default;
 
diff --git a/src/tint/transform/num_workgroups_from_uniform.h b/src/tint/transform/num_workgroups_from_uniform.h
index 93c4f15..9f0b6c1 100644
--- a/src/tint/transform/num_workgroups_from_uniform.h
+++ b/src/tint/transform/num_workgroups_from_uniform.h
@@ -15,6 +15,8 @@
 #ifndef SRC_TINT_TRANSFORM_NUM_WORKGROUPS_FROM_UNIFORM_H_
 #define SRC_TINT_TRANSFORM_NUM_WORKGROUPS_FROM_UNIFORM_H_
 
+#include <optional>  // NOLINT(build/include_order)
+
 #include "src/tint/sem/binding_point.h"
 #include "src/tint/transform/transform.h"
 
@@ -52,8 +54,11 @@
     /// Configuration options for the NumWorkgroupsFromUniform transform.
     struct Config : public Castable<Data, transform::Data> {
         /// Constructor
-        /// @param ubo_bp the binding point to use for the generated uniform buffer.
-        explicit Config(sem::BindingPoint ubo_bp);
+        /// @param ubo_bp the binding point to use for the generated uniform buffer. If ubo_bp
+        /// contains no value, a free binding point will be used to ensure the generated program is
+        /// valid. Specifically, binding 0 of the largest used group plus 1 is used if at least one
+        /// resource is bound, otherwise group 0 binding 0 is used.
+        explicit Config(std::optional<sem::BindingPoint> ubo_bp);
 
         /// Copy constructor
         Config(const Config&);
@@ -61,8 +66,10 @@
         /// Destructor
         ~Config() override;
 
-        /// The binding point to use for the generated uniform buffer.
-        sem::BindingPoint ubo_binding;
+        /// The binding point to use for the generated uniform buffer. If ubo_bp contains no value,
+        /// a free binding point will be used. Specifically, binding 0 of the largest used group
+        /// plus 1 is used if at least one resource is bound, otherwise group 0 binding 0 is used.
+        std::optional<sem::BindingPoint> ubo_binding;
     };
 
     /// @param program the program to inspect
diff --git a/src/tint/transform/num_workgroups_from_uniform_test.cc b/src/tint/transform/num_workgroups_from_uniform_test.cc
index de6c665..ffc0ca8 100644
--- a/src/tint/transform/num_workgroups_from_uniform_test.cc
+++ b/src/tint/transform/num_workgroups_from_uniform_test.cc
@@ -434,5 +434,261 @@
     EXPECT_EQ(expect, str(got));
 }
 
+// Test that group 0 binding 0 is used if no bound resource in the program and binding point is not
+// specified in NumWorkgroupsFromUniform::Config.
+TEST_F(NumWorkgroupsFromUniformTest, UnspecifiedBindingPoint_NoResourceBound) {
+    auto* src = R"(
+struct Builtins1 {
+  @builtin(num_workgroups) num_wgs : vec3<u32>,
+};
+
+struct Builtins2 {
+  @builtin(global_invocation_id) gid : vec3<u32>,
+  @builtin(num_workgroups) num_wgs : vec3<u32>,
+  @builtin(workgroup_id) wgid : vec3<u32>,
+};
+
+@stage(compute) @workgroup_size(1)
+fn main1(in : Builtins1) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main2(in : Builtins2) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main3(@builtin(num_workgroups) num_wgs : vec3<u32>) {
+  let groups_x = num_wgs.x;
+  let groups_y = num_wgs.y;
+  let groups_z = num_wgs.z;
+}
+)";
+
+    auto* expect = R"(
+struct tint_symbol_6 {
+  num_workgroups : vec3<u32>,
+}
+
+@group(0) @binding(0) var<uniform> tint_symbol_7 : tint_symbol_6;
+
+struct Builtins1 {
+  num_wgs : vec3<u32>,
+}
+
+struct Builtins2 {
+  gid : vec3<u32>,
+  num_wgs : vec3<u32>,
+  wgid : vec3<u32>,
+}
+
+fn main1_inner(in : Builtins1) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main1() {
+  main1_inner(Builtins1(tint_symbol_7.num_workgroups));
+}
+
+struct tint_symbol_3 {
+  @builtin(global_invocation_id)
+  gid : vec3<u32>,
+  @builtin(workgroup_id)
+  wgid : vec3<u32>,
+}
+
+fn main2_inner(in : Builtins2) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main2(tint_symbol_2 : tint_symbol_3) {
+  main2_inner(Builtins2(tint_symbol_2.gid, tint_symbol_7.num_workgroups, tint_symbol_2.wgid));
+}
+
+fn main3_inner(num_wgs : vec3<u32>) {
+  let groups_x = num_wgs.x;
+  let groups_y = num_wgs.y;
+  let groups_z = num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main3() {
+  main3_inner(tint_symbol_7.num_workgroups);
+}
+)";
+
+    DataMap data;
+    data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
+    // Make binding point unspecified.
+    data.Add<NumWorkgroupsFromUniform::Config>(std::nullopt);
+    auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
+    EXPECT_EQ(expect, str(got));
+}
+
+// Test that binding 0 of the largest used group plus 1 is used if at least one resource is bound in
+// the program and binding point is not specified in NumWorkgroupsFromUniform::Config.
+TEST_F(NumWorkgroupsFromUniformTest, UnspecifiedBindingPoint_MultipleResourceBound) {
+    auto* src = R"(
+struct Builtins1 {
+  @builtin(num_workgroups) num_wgs : vec3<u32>,
+};
+
+struct Builtins2 {
+  @builtin(global_invocation_id) gid : vec3<u32>,
+  @builtin(num_workgroups) num_wgs : vec3<u32>,
+  @builtin(workgroup_id) wgid : vec3<u32>,
+};
+
+struct S0 {
+  @size(4)
+  m0 : u32,
+  m1 : array<u32>,
+};
+
+struct S1 {
+  @size(4)
+  m0 : u32,
+  m1 : array<u32, 6>,
+};
+
+@group(0) @binding(0) var g2 : texture_2d<f32>;
+@group(1) @binding(0) var g3 : texture_depth_2d;
+@group(1) @binding(1) var g4 : texture_storage_2d<rg32float, write>;
+@group(3) @binding(0) var g5 : texture_depth_cube_array;
+@group(4) @binding(0) var g6 : texture_external;
+
+@group(0) @binding(1) var<storage, write> g8 : S0;
+@group(1) @binding(3) var<storage, read> g9 : S0;
+@group(3) @binding(2) var<storage, read_write> g10 : S0;
+
+@stage(compute) @workgroup_size(1)
+fn main1(in : Builtins1) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+  g8.m0 = 1u;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main2(in : Builtins2) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main3(@builtin(num_workgroups) num_wgs : vec3<u32>) {
+  let groups_x = num_wgs.x;
+  let groups_y = num_wgs.y;
+  let groups_z = num_wgs.z;
+}
+)";
+
+    auto* expect = R"(
+struct tint_symbol_6 {
+  num_workgroups : vec3<u32>,
+}
+
+@group(5) @binding(0) var<uniform> tint_symbol_7 : tint_symbol_6;
+
+struct Builtins1 {
+  num_wgs : vec3<u32>,
+}
+
+struct Builtins2 {
+  gid : vec3<u32>,
+  num_wgs : vec3<u32>,
+  wgid : vec3<u32>,
+}
+
+struct S0 {
+  @size(4)
+  m0 : u32,
+  m1 : array<u32>,
+}
+
+struct S1 {
+  @size(4)
+  m0 : u32,
+  m1 : array<u32, 6>,
+}
+
+@group(0) @binding(0) var g2 : texture_2d<f32>;
+
+@group(1) @binding(0) var g3 : texture_depth_2d;
+
+@group(1) @binding(1) var g4 : texture_storage_2d<rg32float, write>;
+
+@group(3) @binding(0) var g5 : texture_depth_cube_array;
+
+@group(4) @binding(0) var g6 : texture_external;
+
+@group(0) @binding(1) var<storage, write> g8 : S0;
+
+@group(1) @binding(3) var<storage, read> g9 : S0;
+
+@group(3) @binding(2) var<storage, read_write> g10 : S0;
+
+fn main1_inner(in : Builtins1) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+  g8.m0 = 1u;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main1() {
+  main1_inner(Builtins1(tint_symbol_7.num_workgroups));
+}
+
+struct tint_symbol_3 {
+  @builtin(global_invocation_id)
+  gid : vec3<u32>,
+  @builtin(workgroup_id)
+  wgid : vec3<u32>,
+}
+
+fn main2_inner(in : Builtins2) {
+  let groups_x = in.num_wgs.x;
+  let groups_y = in.num_wgs.y;
+  let groups_z = in.num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main2(tint_symbol_2 : tint_symbol_3) {
+  main2_inner(Builtins2(tint_symbol_2.gid, tint_symbol_7.num_workgroups, tint_symbol_2.wgid));
+}
+
+fn main3_inner(num_wgs : vec3<u32>) {
+  let groups_x = num_wgs.x;
+  let groups_y = num_wgs.y;
+  let groups_z = num_wgs.z;
+}
+
+@stage(compute) @workgroup_size(1)
+fn main3() {
+  main3_inner(tint_symbol_7.num_workgroups);
+}
+)";
+
+    DataMap data;
+    data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
+    // Make binding point unspecified.
+    data.Add<NumWorkgroupsFromUniform::Config>(std::nullopt);
+    auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
+    EXPECT_EQ(expect, str(got));
+}
+
 }  // namespace
 }  // namespace tint::transform
diff --git a/src/tint/writer/hlsl/generator.h b/src/tint/writer/hlsl/generator.h
index f14da6d..a18687a 100644
--- a/src/tint/writer/hlsl/generator.h
+++ b/src/tint/writer/hlsl/generator.h
@@ -16,6 +16,7 @@
 #define SRC_TINT_WRITER_HLSL_GENERATOR_H_
 
 #include <memory>
+#include <optional>  // NOLINT(build/include_order)
 #include <string>
 #include <unordered_set>
 #include <utility>
@@ -46,7 +47,7 @@
     Options& operator=(const Options&);
 
     /// The binding point to use for information passed via root constants.
-    sem::BindingPoint root_constant_binding_point;
+    std::optional<sem::BindingPoint> root_constant_binding_point;
     /// Set to `true` to disable workgroup memory zero initialization
     bool disable_workgroup_init = false;
     /// Set to 'true' to generates binding mappings for external textures
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index a2cac0f..137c466 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -33,10 +33,10 @@
 #include "src/tint/sem/atomic.h"
 #include "src/tint/sem/block_statement.h"
 #include "src/tint/sem/call.h"
+#include "src/tint/sem/constant.h"
 #include "src/tint/sem/depth_multisampled_texture.h"
 #include "src/tint/sem/depth_texture.h"
 #include "src/tint/sem/function.h"
-#include "src/tint/sem/materialize.h"
 #include "src/tint/sem/member_accessor_expression.h"
 #include "src/tint/sem/module.h"
 #include "src/tint/sem/multisampled_texture.h"
@@ -110,6 +110,18 @@
     }
 }
 
+void PrintF32(std::ostream& out, float value) {
+    // Note: Currently inf and nan should not be constructable, but this is implemented for the day
+    // we support them.
+    if (std::isinf(value)) {
+        out << (value >= 0 ? "asfloat(0x7f800000u)" : "asfloat(0xff800000u)");
+    } else if (std::isnan(value)) {
+        out << "asfloat(0x7fc00000u)";
+    } else {
+        out << FloatToString(value) << "f";
+    }
+}
+
 // Helper for writing " : register(RX, spaceY)", where R is the register, X is
 // the binding point binding value, and Y is the binding point group value.
 struct RegisterAndSpace {
@@ -802,8 +814,7 @@
         return true;
     }
 
-    out << "(";
-    TINT_DEFER(out << ")");
+    ScopedParen sp(out);
 
     if (!EmitExpression(out, expr->lhs)) {
         return false;
@@ -924,12 +935,7 @@
 }
 
 bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr) {
-    auto* sem = builder_.Sem().Get(expr);
-    if (auto* m = sem->As<sem::Materialize>()) {
-        // TODO(crbug.com/tint/1504): Just emit the constant value.
-        sem = m->Expr();
-    }
-    auto* call = sem->As<sem::Call>();
+    auto* call = builder_.Sem().Get<sem::Call>(expr);
     auto* target = call->Target();
     return Switch(
         target, [&](const sem::Function* func) { return EmitFunctionCall(out, call, func); },
@@ -2644,6 +2650,11 @@
 }
 
 bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) {
+    if (auto* sem = builder_.Sem().Get(expr)) {
+        if (auto constant = sem->ConstantValue()) {
+            return EmitConstant(out, constant);
+        }
+    }
     return Switch(
         expr,
         [&](const ast::IndexAccessorExpression* a) {  //
@@ -3119,6 +3130,111 @@
     return true;
 }
 
+bool GeneratorImpl::EmitConstant(std::ostream& out, const sem::Constant& constant) {
+    auto emit_bool = [&](size_t element_idx) {
+        out << (constant.Element<AInt>(element_idx) ? "true" : "false");
+        return true;
+    };
+    auto emit_f32 = [&](size_t element_idx) {
+        PrintF32(out, static_cast<float>(constant.Element<AFloat>(element_idx)));
+        return true;
+    };
+    auto emit_i32 = [&](size_t element_idx) {
+        out << constant.Element<AInt>(element_idx).value;
+        return true;
+    };
+    auto emit_u32 = [&](size_t element_idx) {
+        out << constant.Element<AInt>(element_idx).value << "u";
+        return true;
+    };
+    auto emit_vector = [&](const sem::Vector* vec_ty, size_t start, size_t end) {
+        if (constant.AllEqual(start, end)) {
+            {
+                ScopedParen sp(out);
+                bool ok = Switch(
+                    vec_ty->type(),                                  //
+                    [&](const sem::Bool*) { return emit_bool(0); },  //
+                    [&](const sem::F32*) { return emit_f32(0); },    //
+                    [&](const sem::I32*) { return emit_i32(0); },    //
+                    [&](const sem::U32*) { return emit_u32(0); }     //
+                );
+                if (!ok) {
+                    return false;
+                }
+            }
+            out << ".";
+            for (size_t i = start; i < end; i++) {
+                out << "x";
+            }
+            return true;
+        }
+
+        if (!EmitType(out, vec_ty, ast::StorageClass::kNone, ast::Access::kUndefined, "")) {
+            return false;
+        }
+
+        ScopedParen sp(out);
+
+        auto emit_els = [&](auto emit_el) {
+            for (size_t i = start; i < end; i++) {
+                if (i > start) {
+                    out << ", ";
+                }
+                if (!emit_el(i)) {
+                    return false;
+                }
+            }
+            return true;
+        };
+        return Switch(
+            vec_ty->type(),                                         //
+            [&](const sem::Bool*) { return emit_els(emit_bool); },  //
+            [&](const sem::F32*) { return emit_els(emit_f32); },    //
+            [&](const sem::I32*) { return emit_els(emit_i32); },    //
+            [&](const sem::U32*) { return emit_els(emit_u32); },    //
+            [&](Default) {
+                diagnostics_.add_error(diag::System::Writer,
+                                       "unhandled constant vector element type: " +
+                                           builder_.FriendlyName(vec_ty->type()));
+                return false;
+            });
+    };
+    auto emit_matrix = [&](const sem::Matrix* m) {
+        if (!EmitType(out, constant.Type(), ast::StorageClass::kNone, ast::Access::kUndefined,
+                      "")) {
+            return false;
+        }
+
+        ScopedParen sp(out);
+
+        for (size_t column_idx = 0; column_idx < m->columns(); column_idx++) {
+            if (column_idx > 0) {
+                out << ", ";
+            }
+            size_t start = m->rows() * column_idx;
+            size_t end = m->rows() * (column_idx + 1);
+            if (!emit_vector(m->ColumnType(), start, end)) {
+                return false;
+            }
+        }
+        return true;
+    };
+    return Switch(
+        constant.Type(),                                                                   //
+        [&](const sem::Bool*) { return emit_bool(0); },                                    //
+        [&](const sem::F32*) { return emit_f32(0); },                                      //
+        [&](const sem::I32*) { return emit_i32(0); },                                      //
+        [&](const sem::U32*) { return emit_u32(0); },                                      //
+        [&](const sem::Vector* v) { return emit_vector(v, 0, constant.ElementCount()); },  //
+        [&](const sem::Matrix* m) { return emit_matrix(m); },
+        [&](Default) {
+            diagnostics_.add_error(
+                diag::System::Writer,
+                "unhandled constant type: " + builder_.FriendlyName(constant.Type()));
+            return false;
+        });
+}
+
 bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression* lit) {
     return Switch(
         lit,
@@ -3127,14 +3243,7 @@
             return true;
         },
         [&](const ast::FloatLiteralExpression* l) {
-            auto f32 = static_cast<float>(l->value);
-            if (std::isinf(f32)) {
-                out << (f32 >= 0 ? "asfloat(0x7f800000u)" : "asfloat(0xff800000u)");
-            } else if (std::isnan(f32)) {
-                out << "asfloat(0x7fc00000u)";
-            } else {
-                out << FloatToString(f32) << "f";
-            }
+            PrintF32(out, static_cast<float>(l->value));
             return true;
         },
         [&](const ast::IntLiteralExpression* i) {
diff --git a/src/tint/writer/hlsl/generator_impl.h b/src/tint/writer/hlsl/generator_impl.h
index 0e8ca4c..c58d004 100644
--- a/src/tint/writer/hlsl/generator_impl.h
+++ b/src/tint/writer/hlsl/generator_impl.h
@@ -43,6 +43,7 @@
 // Forward declarations
 namespace tint::sem {
 class Call;
+class Constant;
 class Builtin;
 class TypeConstructor;
 class TypeConversion;
@@ -334,6 +335,11 @@
     /// @param stmt the statement to emit
     /// @returns true if the statement was successfully emitted
     bool EmitIf(const ast::IfStatement* stmt);
+    /// Handles a constant value
+    /// @param out the output stream
+    /// @param constant the constant value to emit
+    /// @returns true if the constant value was successfully emitted
+    bool EmitConstant(std::ostream& out, const sem::Constant& constant);
     /// Handles a literal
     /// @param out the output stream
     /// @param lit the literal to emit
diff --git a/src/tint/writer/hlsl/generator_impl_assign_test.cc b/src/tint/writer/hlsl/generator_impl_assign_test.cc
index 5e5f031..c69cbdf 100644
--- a/src/tint/writer/hlsl/generator_impl_assign_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_assign_test.cc
@@ -58,7 +58,7 @@
   float3 lhs = float3(0.0f, 0.0f, 0.0f);
   float rhs = 0.0f;
   const uint index = 0u;
-  lhs[index] = rhs;
+  lhs[0u] = rhs;
 }
 )");
 }
@@ -106,7 +106,7 @@
   float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
   float2 rhs = float2(0.0f, 0.0f);
   const uint index = 0u;
-  lhs[index] = rhs;
+  lhs[0u] = rhs;
 }
 )");
 }
@@ -159,7 +159,7 @@
   float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
   float rhs = 0.0f;
   const uint index = 0u;
-  lhs[index][index] = rhs;
+  lhs[0u][0u] = rhs;
 }
 )");
 }
diff --git a/src/tint/writer/hlsl/generator_impl_binary_test.cc b/src/tint/writer/hlsl/generator_impl_binary_test.cc
index 446a5a8..5825536 100644
--- a/src/tint/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_binary_test.cc
@@ -152,9 +152,7 @@
 
     std::stringstream out;
     EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
-    EXPECT_EQ(out.str(),
-              "(float3(1.0f, 1.0f, 1.0f) * "
-              "1.0f)");
+    EXPECT_EQ(out.str(), "((1.0f).xxx * 1.0f)");
 }
 
 TEST_F(HlslGeneratorImplTest_Binary, Multiply_ScalarVector) {
@@ -169,9 +167,7 @@
 
     std::stringstream out;
     EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
-    EXPECT_EQ(out.str(),
-              "(1.0f * float3(1.0f, 1.0f, "
-              "1.0f))");
+    EXPECT_EQ(out.str(), "(1.0f * (1.0f).xxx)");
 }
 
 TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixScalar) {
@@ -216,7 +212,7 @@
 
     std::stringstream out;
     EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
-    EXPECT_EQ(out.str(), "mul(float3(1.0f, 1.0f, 1.0f), mat)");
+    EXPECT_EQ(out.str(), "mul((1.0f).xxx, mat)");
 }
 
 TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorMatrix) {
@@ -231,7 +227,7 @@
 
     std::stringstream out;
     EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
-    EXPECT_EQ(out.str(), "mul(mat, float3(1.0f, 1.0f, 1.0f))");
+    EXPECT_EQ(out.str(), "mul(mat, (1.0f).xxx)");
 }
 
 TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixMatrix) {
@@ -576,7 +572,7 @@
 
     ASSERT_TRUE(gen.Generate());
     EXPECT_EQ(gen.result(), R"(void fn() {
-  int4 a = int4(100, 100, 100, 100);
+  int4 a = (100).xxxx;
   const int4 r = (a )" + Token() +
                                 R"( int4(50, 1, 25, 1));
 }
@@ -594,7 +590,7 @@
 
     ASSERT_TRUE(gen.Generate());
     EXPECT_EQ(gen.result(), R"(void fn() {
-  int4 a = int4(100, 100, 100, 100);
+  int4 a = (100).xxxx;
   const int4 r = (a )" + Token() +
                                 R"( 1);
 }
@@ -755,7 +751,7 @@
 }
 
 int3 zero() {
-  return int3(0, 0, 0);
+  return (0).xxx;
 }
 
 void fn() {
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
index 40f550b..b356ccd 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
@@ -324,7 +324,7 @@
 
 [numthreads(1, 1, 1)]
 void test_function() {
-  tint_modf(float3(0.0f, 0.0f, 0.0f));
+  tint_modf((0.0f).xxx);
   return;
 }
 )");
@@ -376,7 +376,7 @@
 
 [numthreads(1, 1, 1)]
 void test_function() {
-  tint_frexp(float3(0.0f, 0.0f, 0.0f));
+  tint_frexp((0.0f).xxx);
   return;
 }
 )");
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
index 60bd303..371cc1d 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
@@ -285,7 +285,7 @@
         case ValidTextureOverload::kSampleGrad2dF32:
             return R"(tint_symbol.SampleGrad(tint_symbol_1, float2(1.0f, 2.0f), float2(3.0f, 4.0f), float2(5.0f, 6.0f));)";
         case ValidTextureOverload::kSampleGrad2dOffsetF32:
-            return R"(tint_symbol.SampleGrad(tint_symbol_1, float2(1.0f, 2.0f), float2(3.0f, 4.0f), float2(5.0f, 6.0f), int2(7, 7));)";
+            return R"(tint_symbol.SampleGrad(tint_symbol_1, float2(1.0f, 2.0f), float2(3.0f, 4.0f), float2(5.0f, 6.0f), (7).xx);)";
         case ValidTextureOverload::kSampleGrad2dArrayF32:
             return R"(tint_symbol.SampleGrad(tint_symbol_1, float3(1.0f, 2.0f, float(3)), float2(4.0f, 5.0f), float2(6.0f, 7.0f));)";
         case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
diff --git a/src/tint/writer/hlsl/generator_impl_cast_test.cc b/src/tint/writer/hlsl/generator_impl_cast_test.cc
index 458f07d..2c4690a 100644
--- a/src/tint/writer/hlsl/generator_impl_cast_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_cast_test.cc
@@ -29,7 +29,7 @@
 
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
-    EXPECT_EQ(out.str(), "float(1)");
+    EXPECT_EQ(out.str(), "1.0f");
 }
 
 TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) {
@@ -40,7 +40,7 @@
 
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
-    EXPECT_EQ(out.str(), "float3(int3(1, 2, 3))");
+    EXPECT_EQ(out.str(), "float3(1.0f, 2.0f, 3.0f)");
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_constructor_test.cc b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
index b44dc69..fbcc79b 100644
--- a/src/tint/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
@@ -67,7 +67,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("float(-0.000012f)"));
+    EXPECT_THAT(gen.result(), HasSubstr("-0.000012f"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Bool) {
@@ -76,7 +76,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("bool(true)"));
+    EXPECT_THAT(gen.result(), HasSubstr("true"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Int) {
@@ -85,7 +85,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("int(-12345)"));
+    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Uint) {
@@ -94,7 +94,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("uint(12345u)"));
+    EXPECT_THAT(gen.result(), HasSubstr("12345u"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec) {
@@ -112,7 +112,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("float3(0.0f, 0.0f, 0.0f)"));
+    EXPECT_THAT(gen.result(), HasSubstr("0.0f).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_Float_Literal) {
@@ -121,7 +121,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("float3((2.0f).xxx)"));
+    EXPECT_THAT(gen.result(), HasSubstr("2.0f).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_Float_Var) {
@@ -142,7 +142,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("bool3((true).xxx)"));
+    EXPECT_THAT(gen.result(), HasSubstr("(true).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_Bool_Var) {
@@ -163,7 +163,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("int3((2).xxx)"));
+    EXPECT_THAT(gen.result(), HasSubstr("2).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_UInt) {
@@ -172,7 +172,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("uint3((2u).xxx)"));
+    EXPECT_THAT(gen.result(), HasSubstr("2u).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat) {
@@ -193,7 +193,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
 
-    EXPECT_THAT(gen.result(), HasSubstr("float2x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)"));
+    EXPECT_THAT(gen.result(), HasSubstr("float2x3 tint_symbol = float2x3((0.0f).xxx, (0.0f).xxx)"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Array) {
diff --git a/src/tint/writer/hlsl/generator_impl_function_test.cc b/src/tint/writer/hlsl/generator_impl_function_test.cc
index 6a1c566..cbd95ec 100644
--- a/src/tint/writer/hlsl/generator_impl_function_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_function_test.cc
@@ -219,7 +219,7 @@
 };
 
 Interface vert_main_inner() {
-  const Interface tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f), 0.5f, 0.25f};
+  const Interface tint_symbol_3 = {(0.0f).xxxx, 0.5f, 0.25f};
   return tint_symbol_3;
 }
 
@@ -689,9 +689,9 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_EQ(gen.result(), R"(static const int width = int(2);
-static const int height = int(3);
-static const int depth = int(4);
+    EXPECT_EQ(gen.result(), R"(static const int width = 2;
+static const int height = 3;
+static const int depth = 4;
 
 [numthreads(2, 3, 4)]
 void main() {
@@ -715,15 +715,15 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
     EXPECT_EQ(gen.result(), R"(#ifndef WGSL_SPEC_CONSTANT_7
-#define WGSL_SPEC_CONSTANT_7 int(2)
+#define WGSL_SPEC_CONSTANT_7 2
 #endif
 static const int width = WGSL_SPEC_CONSTANT_7;
 #ifndef WGSL_SPEC_CONSTANT_8
-#define WGSL_SPEC_CONSTANT_8 int(3)
+#define WGSL_SPEC_CONSTANT_8 3
 #endif
 static const int height = WGSL_SPEC_CONSTANT_8;
 #ifndef WGSL_SPEC_CONSTANT_9
-#define WGSL_SPEC_CONSTANT_9 int(4)
+#define WGSL_SPEC_CONSTANT_9 4
 #endif
 static const int depth = WGSL_SPEC_CONSTANT_9;
 
diff --git a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
index 7f2933a..10e9f10 100644
--- a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -337,7 +337,7 @@
 }
 
 void main() {
-  tint_symbol(data, 16u, float2x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+  tint_symbol(data, 16u, float2x3((0.0f).xxx, (0.0f).xxx));
   return;
 }
 )";
diff --git a/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
index 580ad46..5ed85f3 100644
--- a/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
@@ -97,7 +97,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
-    EXPECT_EQ(gen.result(), R"(float3 a = float3(0.0f, 0.0f, 0.0f);
+    EXPECT_EQ(gen.result(), R"(float3 a = (0.0f).xxx;
 )");
 }
 
@@ -111,7 +111,7 @@
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
     EXPECT_EQ(gen.result(),
-              R"(float2x3 a = float2x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+              R"(float2x3 a = float2x3((0.0f).xxx, (0.0f).xxx);
 )");
 }
 
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 578e78d..cd984b2 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -36,12 +36,12 @@
 #include "src/tint/sem/atomic.h"
 #include "src/tint/sem/bool.h"
 #include "src/tint/sem/call.h"
+#include "src/tint/sem/constant.h"
 #include "src/tint/sem/depth_multisampled_texture.h"
 #include "src/tint/sem/depth_texture.h"
 #include "src/tint/sem/f32.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/i32.h"
-#include "src/tint/sem/materialize.h"
 #include "src/tint/sem/matrix.h"
 #include "src/tint/sem/member_accessor_expression.h"
 #include "src/tint/sem/module.h"
@@ -86,6 +86,31 @@
     return IsAnyOf<ast::BreakStatement, ast::FallthroughStatement>(stmts->Last());
 }
 
+void PrintF32(std::ostream& out, float value) {
+    // Note: Currently inf and nan should not be constructable, but this is implemented for the day
+    // we support them.
+    if (std::isinf(value)) {
+        out << (value >= 0 ? "INFINITY" : "-INFINITY");
+    } else if (std::isnan(value)) {
+        out << "NAN";
+    } else {
+        out << FloatToString(value) << "f";
+    }
+}
+
+void PrintI32(std::ostream& out, int32_t value) {
+    // MSL (and C++) parse `-2147483648` as a `long` because it parses unary minus and `2147483648`
+    // as separate tokens, and the latter doesn't fit into an (32-bit) `int`.
+    // WGSL, on the other hand, parses this as an `i32`.
+    // To avoid issues with `long` to `int` casts, emit `(-2147483647 - 1)` instead, which ensures
+    // the expression type is `int`.
+    if (auto int_min = std::numeric_limits<int32_t>::min(); value == int_min) {
+        out << "(" << int_min + 1 << " - 1)";
+    } else {
+        out << value;
+    }
+}
+
 class ScopedBitCast {
   public:
     ScopedBitCast(GeneratorImpl* generator,
@@ -551,12 +576,7 @@
 }
 
 bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr) {
-    auto* sem = program_->Sem().Get(expr);
-    if (auto* m = sem->As<sem::Materialize>()) {
-        // TODO(crbug.com/tint/1504): Just emit the constant value.
-        sem = m->Expr();
-    }
-    auto* call = sem->As<sem::Call>();
+    auto* call = program_->Sem().Get<sem::Call>(expr);
     auto* target = call->Target();
     return Switch(
         target, [&](const sem::Function* func) { return EmitFunctionCall(out, call, func); },
@@ -1522,8 +1542,7 @@
             if (!EmitType(out, mat, "")) {
                 return false;
             }
-            out << "(";
-            TINT_DEFER(out << ")");
+            ScopedParen sp(out);
             return EmitZeroValue(out, mat->type());
         },
         [&](const sem::Array* arr) {
@@ -1543,6 +1562,92 @@
         });
 }
 
+bool GeneratorImpl::EmitConstant(std::ostream& out, const sem::Constant& constant) {
+    auto emit_bool = [&](size_t element_idx) {
+        out << (constant.Element<AInt>(element_idx) ? "true" : "false");
+        return true;
+    };
+    auto emit_f32 = [&](size_t element_idx) {
+        PrintF32(out, static_cast<float>(constant.Element<AFloat>(element_idx)));
+        return true;
+    };
+    auto emit_i32 = [&](size_t element_idx) {
+        PrintI32(out, static_cast<int32_t>(constant.Element<AInt>(element_idx).value));
+        return true;
+    };
+    auto emit_u32 = [&](size_t element_idx) {
+        out << constant.Element<AInt>(element_idx).value << "u";
+        return true;
+    };
+    auto emit_vector = [&](const sem::Vector* vec_ty, size_t start, size_t end) {
+        if (!EmitType(out, vec_ty, "")) {
+            return false;
+        }
+
+        ScopedParen sp(out);
+
+        auto emit_els = [&](auto emit_el) {
+            if (constant.AllEqual(start, end)) {
+                return emit_el(start);
+            }
+            for (size_t i = start; i < end; i++) {
+                if (i > start) {
+                    out << ", ";
+                }
+                if (!emit_el(i)) {
+                    return false;
+                }
+            }
+            return true;
+        };
+        return Switch(
+            vec_ty->type(),                                         //
+            [&](const sem::Bool*) { return emit_els(emit_bool); },  //
+            [&](const sem::F32*) { return emit_els(emit_f32); },    //
+            [&](const sem::I32*) { return emit_els(emit_i32); },    //
+            [&](const sem::U32*) { return emit_els(emit_u32); },    //
+            [&](Default) {
+                diagnostics_.add_error(diag::System::Writer,
+                                       "unhandled constant vector element type: " +
+                                           builder_.FriendlyName(vec_ty->type()));
+                return false;
+            });
+    };
+    auto emit_matrix = [&](const sem::Matrix* m) {
+        if (!EmitType(out, constant.Type(), "")) {
+            return false;
+        }
+
+        ScopedParen sp(out);
+
+        for (size_t column_idx = 0; column_idx < m->columns(); column_idx++) {
+            if (column_idx > 0) {
+                out << ", ";
+            }
+            size_t start = m->rows() * column_idx;
+            size_t end = m->rows() * (column_idx + 1);
+            if (!emit_vector(m->ColumnType(), start, end)) {
+                return false;
+            }
+        }
+        return true;
+    };
+    return Switch(
+        constant.Type(),                                                                   //
+        [&](const sem::Bool*) { return emit_bool(0); },                                    //
+        [&](const sem::F32*) { return emit_f32(0); },                                      //
+        [&](const sem::I32*) { return emit_i32(0); },                                      //
+        [&](const sem::U32*) { return emit_u32(0); },                                      //
+        [&](const sem::Vector* v) { return emit_vector(v, 0, constant.ElementCount()); },  //
+        [&](const sem::Matrix* m) { return emit_matrix(m); },                              //
+        [&](Default) {
+            diagnostics_.add_error(
+                diag::System::Writer,
+                "unhandled constant type: " + builder_.FriendlyName(constant.Type()));
+            return false;
+        });
+}
+
 bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression* lit) {
     return Switch(
         lit,
@@ -1551,32 +1656,14 @@
             return true;
         },
         [&](const ast::FloatLiteralExpression* l) {
-            auto f32 = static_cast<float>(l->value);
-            if (std::isinf(f32)) {
-                out << (f32 >= 0 ? "INFINITY" : "-INFINITY");
-            } else if (std::isnan(f32)) {
-                out << "NAN";
-            } else {
-                out << FloatToString(f32) << "f";
-            }
+            PrintF32(out, static_cast<float>(l->value));
             return true;
         },
         [&](const ast::IntLiteralExpression* i) {
             switch (i->suffix) {
                 case ast::IntLiteralExpression::Suffix::kNone:
                 case ast::IntLiteralExpression::Suffix::kI: {
-                    // MSL (and C++) parse `-2147483648` as a `long` because it parses
-                    // unary minus and `2147483648` as separate tokens, and the latter
-                    // doesn't fit into an (32-bit) `int`. WGSL, OTOH, parses this as an
-                    // `i32`. To avoid issues with `long` to `int` casts, emit
-                    // `(2147483647 - 1)` instead, which ensures the expression type is
-                    // `int`.
-                    const auto int_min = std::numeric_limits<int32_t>::min();
-                    if (i->value == int_min) {
-                        out << "(" << int_min + 1 << " - 1)";
-                    } else {
-                        out << i->value;
-                    }
+                    PrintI32(out, static_cast<int32_t>(i->value));
                     return true;
                 }
                 case ast::IntLiteralExpression::Suffix::kU: {
@@ -1594,6 +1681,11 @@
 }
 
 bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) {
+    if (auto* sem = builder_.Sem().Get(expr)) {
+        if (auto constant = sem->ConstantValue()) {
+            return EmitConstant(out, constant);
+        }
+    }
     return Switch(
         expr,
         [&](const ast::IndexAccessorExpression* a) {  //
diff --git a/src/tint/writer/msl/generator_impl.h b/src/tint/writer/msl/generator_impl.h
index b7a2029..21dee28 100644
--- a/src/tint/writer/msl/generator_impl.h
+++ b/src/tint/writer/msl/generator_impl.h
@@ -45,6 +45,7 @@
 // Forward declarations
 namespace tint::sem {
 class Call;
+class Constant;
 class Builtin;
 class TypeConstructor;
 class TypeConversion;
@@ -250,6 +251,11 @@
     /// @param stmt the statement to emit
     /// @returns true if the statement was successfully emitted
     bool EmitIf(const ast::IfStatement* stmt);
+    /// Handles a constant value
+    /// @param out the output stream
+    /// @param constant the constant value to emit
+    /// @returns true if the constant value was successfully emitted
+    bool EmitConstant(std::ostream& out, const sem::Constant& constant);
     /// Handles a literal
     /// @param out the output of the expression stream
     /// @param lit the literal to emit
diff --git a/src/tint/writer/msl/generator_impl_builtin_texture_test.cc b/src/tint/writer/msl/generator_impl_builtin_texture_test.cc
index a78a255..20813fa 100644
--- a/src/tint/writer/msl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_texture_test.cc
@@ -184,7 +184,7 @@
         case ValidTextureOverload::kSampleGrad2dF32:
             return R"(texture.sample(sampler, float2(1.0f, 2.0f), gradient2d(float2(3.0f, 4.0f), float2(5.0f, 6.0f))))";
         case ValidTextureOverload::kSampleGrad2dOffsetF32:
-            return R"(texture.sample(sampler, float2(1.0f, 2.0f), gradient2d(float2(3.0f, 4.0f), float2(5.0f, 6.0f)), int2(7, 7)))";
+            return R"(texture.sample(sampler, float2(1.0f, 2.0f), gradient2d(float2(3.0f, 4.0f), float2(5.0f, 6.0f)), int2(7)))";
         case ValidTextureOverload::kSampleGrad2dArrayF32:
             return R"(texture.sample(sampler, float2(1.0f, 2.0f), 3, gradient2d(float2(4.0f, 5.0f), float2(6.0f, 7.0f))))";
         case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
diff --git a/src/tint/writer/msl/generator_impl_cast_test.cc b/src/tint/writer/msl/generator_impl_cast_test.cc
index 0eca191..4b9e3f2 100644
--- a/src/tint/writer/msl/generator_impl_cast_test.cc
+++ b/src/tint/writer/msl/generator_impl_cast_test.cc
@@ -29,7 +29,7 @@
 
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
-    EXPECT_EQ(out.str(), "float(1)");
+    EXPECT_EQ(out.str(), "1.0f");
 }
 
 TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Vector) {
@@ -40,7 +40,7 @@
 
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
-    EXPECT_EQ(out.str(), "float3(int3(1, 2, 3))");
+    EXPECT_EQ(out.str(), "float3(1.0f, 2.0f, 3.0f)");
 }
 
 TEST_F(MslGeneratorImplTest, EmitExpression_Cast_IntMin) {
@@ -51,7 +51,7 @@
 
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
-    EXPECT_EQ(out.str(), "uint((-2147483647 - 1))");
+    EXPECT_EQ(out.str(), "0u");
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_constructor_test.cc b/src/tint/writer/msl/generator_impl_constructor_test.cc
index fa2e113..2fa85f0 100644
--- a/src/tint/writer/msl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/msl/generator_impl_constructor_test.cc
@@ -67,7 +67,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("float(-0.000012f)"));
+    EXPECT_THAT(gen.result(), HasSubstr("-0.000012f"));
 }
 
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Bool) {
@@ -76,7 +76,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("bool(true)"));
+    EXPECT_THAT(gen.result(), HasSubstr("true"));
 }
 
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Int) {
@@ -85,7 +85,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("int(-12345)"));
+    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
 }
 
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Uint) {
@@ -94,7 +94,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("uint(12345u)"));
+    EXPECT_THAT(gen.result(), HasSubstr("12345u"));
 }
 
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Vec) {
@@ -112,7 +112,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("float3()"));
+    EXPECT_THAT(gen.result(), HasSubstr("float3(0.0f)"));
 }
 
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Mat) {
@@ -134,7 +134,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("float4x4()"));
+    EXPECT_THAT(gen.result(), HasSubstr("float4x4(float4(0.0f), float4(0.0f)"));
 }
 
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Array) {
diff --git a/src/tint/writer/msl/generator_impl_function_test.cc b/src/tint/writer/msl/generator_impl_function_test.cc
index 5eb4905..585e8fc 100644
--- a/src/tint/writer/msl/generator_impl_function_test.cc
+++ b/src/tint/writer/msl/generator_impl_function_test.cc
@@ -207,7 +207,7 @@
 };
 
 Interface vert_main_inner() {
-  Interface const tint_symbol_3 = {.col1=0.5f, .col2=0.25f, .pos=float4()};
+  Interface const tint_symbol_3 = {.col1=0.5f, .col2=0.25f, .pos=float4(0.0f)};
   return tint_symbol_3;
 }
 
diff --git a/src/tint/writer/msl/generator_impl_test.cc b/src/tint/writer/msl/generator_impl_test.cc
index dd90715..7cef268 100644
--- a/src/tint/writer/msl/generator_impl_test.cc
+++ b/src/tint/writer/msl/generator_impl_test.cc
@@ -157,7 +157,7 @@
 
 void comp_main_inner(uint local_invocation_index, threadgroup float2x2* const tint_symbol) {
   {
-    *(tint_symbol) = float2x2();
+    *(tint_symbol) = float2x2(float2(0.0f), float2(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
   float2x2 const x = *(tint_symbol);
@@ -199,7 +199,7 @@
 void comp_main_inner(uint local_invocation_index, threadgroup tint_array_wrapper* const tint_symbol) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
-    (*(tint_symbol)).arr[i] = float2x2();
+    (*(tint_symbol)).arr[i] = float2x2(float2(0.0f), float2(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
   tint_array_wrapper const x = *(tint_symbol);
@@ -333,9 +333,9 @@
 
 void main1_inner(uint local_invocation_index, threadgroup float2x2* const tint_symbol, threadgroup float2x3* const tint_symbol_1, threadgroup float2x4* const tint_symbol_2) {
   {
-    *(tint_symbol) = float2x2();
-    *(tint_symbol_1) = float2x3();
-    *(tint_symbol_2) = float2x4();
+    *(tint_symbol) = float2x2(float2(0.0f), float2(0.0f));
+    *(tint_symbol_1) = float2x3(float3(0.0f), float3(0.0f));
+    *(tint_symbol_2) = float2x4(float4(0.0f), float4(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
   float2x2 const a1 = *(tint_symbol);
@@ -353,9 +353,9 @@
 
 void main2_inner(uint local_invocation_index_1, threadgroup float3x2* const tint_symbol_8, threadgroup float3x3* const tint_symbol_9, threadgroup float3x4* const tint_symbol_10) {
   {
-    *(tint_symbol_8) = float3x2();
-    *(tint_symbol_9) = float3x3();
-    *(tint_symbol_10) = float3x4();
+    *(tint_symbol_8) = float3x2(float2(0.0f), float2(0.0f), float2(0.0f));
+    *(tint_symbol_9) = float3x3(float3(0.0f), float3(0.0f), float3(0.0f));
+    *(tint_symbol_10) = float3x4(float4(0.0f), float4(0.0f), float4(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
   float3x2 const a1 = *(tint_symbol_8);
@@ -373,9 +373,9 @@
 
 void main3_inner(uint local_invocation_index_2, threadgroup float4x2* const tint_symbol_16, threadgroup float4x3* const tint_symbol_17, threadgroup float4x4* const tint_symbol_18) {
   {
-    *(tint_symbol_16) = float4x2();
-    *(tint_symbol_17) = float4x3();
-    *(tint_symbol_18) = float4x4();
+    *(tint_symbol_16) = float4x2(float2(0.0f), float2(0.0f), float2(0.0f), float2(0.0f));
+    *(tint_symbol_17) = float4x3(float3(0.0f), float3(0.0f), float3(0.0f), float3(0.0f));
+    *(tint_symbol_18) = float4x4(float4(0.0f), float4(0.0f), float4(0.0f), float4(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
   float4x2 const a1 = *(tint_symbol_16);
diff --git a/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
index be55cae..e41cc3b 100644
--- a/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -48,7 +48,7 @@
     gen.increment_indent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
-    EXPECT_EQ(gen.result(), "  float const a = float();\n");
+    EXPECT_EQ(gen.result(), "  float const a = 0.0f;\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Array) {
@@ -132,7 +132,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.error();
-    EXPECT_THAT(gen.result(), HasSubstr("thread float tint_symbol_1 = initializer;\n"));
+    EXPECT_THAT(gen.result(), HasSubstr("thread float tint_symbol_1 = 0.0f;\n  float const tint_symbol = tint_symbol_1;\n  return;\n"));
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Workgroup) {
@@ -158,7 +158,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
-    EXPECT_EQ(gen.result(), R"(float3 a = float3();
+    EXPECT_EQ(gen.result(), R"(float3 a = float3(0.0f);
 )");
 }
 
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 34d550b..18f983a 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -27,6 +27,7 @@
 #include "src/tint/sem/atomic.h"
 #include "src/tint/sem/builtin.h"
 #include "src/tint/sem/call.h"
+#include "src/tint/sem/constant.h"
 #include "src/tint/sem/depth_multisampled_texture.h"
 #include "src/tint/sem/depth_texture.h"
 #include "src/tint/sem/function.h"
@@ -406,6 +407,11 @@
 
 bool Builder::GenerateAssignStatement(const ast::AssignmentStatement* assign) {
     if (assign->lhs->Is<ast::PhonyExpression>()) {
+        if (builder_.Sem().Get(assign->rhs)->ConstantValue()) {
+            // RHS of phony assignment is constant.
+            // Constants can't have side-effects, so just drop this.
+            return true;
+        }
         auto rhs_id = GenerateExpression(assign->rhs);
         if (rhs_id == 0) {
             return false;
@@ -566,8 +572,14 @@
 }
 
 uint32_t Builder::GenerateExpression(const ast::Expression* expr) {
+    if (auto* sem = builder_.Sem().Get(expr)) {
+        if (auto constant = sem->ConstantValue()) {
+            return GenerateConstantIfNeeded(constant);
+        }
+    }
     return Switch(
-        expr, [&](const ast::IndexAccessorExpression* a) { return GenerateAccessorExpression(a); },
+        expr,  //
+        [&](const ast::IndexAccessorExpression* a) { return GenerateAccessorExpression(a); },
         [&](const ast::BinaryExpression* b) { return GenerateBinaryExpression(b); },
         [&](const ast::BitcastExpression* b) { return GenerateBitcastExpression(b); },
         [&](const ast::CallExpression* c) { return GenerateCallExpression(c); },
@@ -743,7 +755,15 @@
 
     uint32_t init_id = 0;
     if (var->constructor) {
-        init_id = GenerateConstructorExpression(var, var->constructor);
+        if (!var->is_overridable) {
+            auto* ctor = builder_.Sem().Get(var->constructor);
+            if (auto constant = ctor->ConstantValue()) {
+                init_id = GenerateConstantIfNeeded(std::move(constant));
+            }
+        }
+        if (init_id == 0) {
+            init_id = GenerateConstructorExpression(var, var->constructor);
+        }
         if (init_id == 0) {
             return false;
         }
@@ -1662,6 +1682,116 @@
     return GenerateConstantIfNeeded(constant);
 }
 
+uint32_t Builder::GenerateConstantIfNeeded(const sem::Constant& constant) {
+    if (constant.AllZero()) {
+        return GenerateConstantNullIfNeeded(constant.Type());
+    }
+
+    static constexpr size_t kOpsResultIdx = 1;  // operand index of the result
+    auto& global_scope = scope_stack_[0];
+
+    auto gen_bool = [&](size_t element_idx) {
+        bool val = constant.Element<AInt>(element_idx);
+        return GenerateConstantIfNeeded(ScalarConstant::Bool(val));
+    };
+    auto gen_f32 = [&](size_t element_idx) {
+        auto val = f32(constant.Element<AFloat>(element_idx));
+        return GenerateConstantIfNeeded(ScalarConstant::F32(val.value));
+    };
+    auto gen_i32 = [&](size_t element_idx) {
+        auto val = i32(constant.Element<AInt>(element_idx));
+        return GenerateConstantIfNeeded(ScalarConstant::I32(val.value));
+    };
+    auto gen_u32 = [&](size_t element_idx) {
+        auto val = u32(constant.Element<AInt>(element_idx));
+        return GenerateConstantIfNeeded(ScalarConstant::U32(val.value));
+    };
+    auto gen_els = [&](std::vector<Operand>& ids, size_t start, size_t end, auto gen_el) {
+        for (size_t i = start; i < end; i++) {
+            auto id = gen_el(i);
+            if (!id) {
+                return false;
+            }
+            ids.emplace_back(id);
+        }
+        return true;
+    };
+    auto gen_vector = [&](const sem::Vector* ty, size_t start, size_t end) -> uint32_t {
+        auto type_id = GenerateTypeIfNeeded(ty);
+        if (!type_id) {
+            return 0;
+        }
+
+        std::vector<Operand> ops;
+        ops.reserve(end - start + 2);
+        ops.emplace_back(type_id);
+        ops.push_back(Operand(0u));  // Placeholder for the result ID
+        auto ok = Switch(
+            constant.ElementType(),                                                //
+            [&](const sem::Bool*) { return gen_els(ops, start, end, gen_bool); },  //
+            [&](const sem::F32*) { return gen_els(ops, start, end, gen_f32); },    //
+            [&](const sem::I32*) { return gen_els(ops, start, end, gen_i32); },    //
+            [&](const sem::U32*) { return gen_els(ops, start, end, gen_u32); },    //
+            [&](Default) {
+                error_ = "unhandled constant element type: " + builder_.FriendlyName(ty);
+                return false;
+            });
+        if (!ok) {
+            return 0;
+        }
+
+        return utils::GetOrCreate(global_scope.type_ctor_to_id_, OperandListKey{ops},
+                                  [&]() -> uint32_t {
+                                      auto result = result_op();
+                                      ops[kOpsResultIdx] = result;
+                                      push_type(spv::Op::OpConstantComposite, std::move(ops));
+                                      return std::get<uint32_t>(result);
+                                  });
+    };
+    auto gen_matrix = [&](const sem::Matrix* m) -> uint32_t {
+        auto mat_type_id = GenerateTypeIfNeeded(m);
+        if (!mat_type_id) {
+            return 0;
+        }
+
+        std::vector<Operand> ops;
+        ops.reserve(m->columns() + 2);
+        ops.emplace_back(mat_type_id);
+        ops.push_back(Operand(0u));  // Placeholder for the result ID
+
+        for (size_t column_idx = 0; column_idx < m->columns(); column_idx++) {
+            size_t start = m->rows() * column_idx;
+            size_t end = m->rows() * (column_idx + 1);
+            auto column_id = gen_vector(m->ColumnType(), start, end);
+            if (!column_id) {
+                return 0;
+            }
+            ops.emplace_back(column_id);
+        }
+
+        return utils::GetOrCreate(global_scope.type_ctor_to_id_, OperandListKey{ops},
+                                  [&]() -> uint32_t {
+                                      auto result = result_op();
+                                      ops[kOpsResultIdx] = result;
+                                      push_type(spv::Op::OpConstantComposite, std::move(ops));
+                                      return std::get<uint32_t>(result);
+                                  });
+    };
+
+    return Switch(
+        constant.Type(),                                                                  //
+        [&](const sem::Bool*) { return gen_bool(0); },                                    //
+        [&](const sem::F32*) { return gen_f32(0); },                                      //
+        [&](const sem::I32*) { return gen_i32(0); },                                      //
+        [&](const sem::U32*) { return gen_u32(0); },                                      //
+        [&](const sem::Vector* v) { return gen_vector(v, 0, constant.ElementCount()); },  //
+        [&](const sem::Matrix* m) { return gen_matrix(m); },                              //
+        [&](Default) {
+            error_ = "unhandled constant type: " + builder_.FriendlyName(constant.Type());
+            return false;
+        });
+}
+
 uint32_t Builder::GenerateConstantIfNeeded(const ScalarConstant& constant) {
     auto it = const_to_id_.find(constant);
     if (it != const_to_id_.end()) {
@@ -2174,12 +2304,7 @@
 }
 
 uint32_t Builder::GenerateCallExpression(const ast::CallExpression* expr) {
-    auto* sem = builder_.Sem().Get(expr);
-    if (auto* m = sem->As<sem::Materialize>()) {
-        // TODO(crbug.com/tint/1504): Just emit the constant value.
-        sem = m->Expr();
-    }
-    auto* call = sem->As<sem::Call>();
+    auto* call = builder_.Sem().Get<sem::Call>(expr);
     auto* target = call->Target();
     return Switch(
         target, [&](const sem::Function* func) { return GenerateFunctionCall(call, func); },
@@ -2936,10 +3061,9 @@
             }
             spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
 
-            ast::FloatLiteralExpression float_0(ProgramID(), Source{}, 0.0,
-                                                ast::FloatLiteralExpression::Suffix::kF);
-            image_operands.emplace_back(ImageOperand{
-                SpvImageOperandsLodMask, Operand(GenerateLiteralIfNeeded(nullptr, &float_0))});
+            image_operands.emplace_back(
+                ImageOperand{SpvImageOperandsLodMask,
+                             Operand(GenerateConstantIfNeeded(ScalarConstant::F32(0.0)))});
             break;
         }
         default:
diff --git a/src/tint/writer/spirv/builder.h b/src/tint/writer/spirv/builder.h
index fc2fa13..9866328 100644
--- a/src/tint/writer/spirv/builder.h
+++ b/src/tint/writer/spirv/builder.h
@@ -43,6 +43,7 @@
 // Forward declarations
 namespace tint::sem {
 class Call;
+class Constant;
 class Reference;
 class TypeConstructor;
 class TypeConversion;
@@ -550,6 +551,11 @@
     /// @param expr the expression
     const sem::Type* TypeOf(const ast::Expression* expr) const { return builder_.TypeOf(expr); }
 
+    /// Generates a constant value if needed
+    /// @param constant the constant to generate.
+    /// @returns the ID on success or 0 on failure
+    uint32_t GenerateConstantIfNeeded(const sem::Constant& constant);
+
     /// Generates a scalar constant if needed
     /// @param constant the constant to generate.
     /// @returns the ID on success or 0 on failure
diff --git a/src/tint/writer/spirv/builder_accessor_expression_test.cc b/src/tint/writer/spirv/builder_accessor_expression_test.cc
index 82fbfd7..2df1b65 100644
--- a/src/tint/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_accessor_expression_test.cc
@@ -326,7 +326,7 @@
 
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeStruct %2 %2
-%3 = OpConstant %2 0
+%3 = OpConstantNull %2
 %4 = OpConstantComposite %1 %3 %3
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
@@ -367,7 +367,7 @@
     EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
 %2 = OpTypeStruct %3 %3
 %1 = OpTypeStruct %2
-%4 = OpConstant %3 0
+%4 = OpConstantNull %3
 %5 = OpConstantComposite %2 %4 %4
 %6 = OpConstantComposite %1 %5
 )");
@@ -729,7 +729,7 @@
 %2 = OpTypePointer Function %3
 %13 = OpConstantNull %3
 %14 = OpTypeInt 32 1
-%15 = OpConstant %14 0
+%15 = OpConstantNull %14
 %16 = OpConstant %10 0
 %17 = OpConstant %14 2
 %18 = OpTypePointer Function %8
@@ -916,7 +916,7 @@
 %7 = OpTypeInt 32 0
 %8 = OpConstant %7 3
 %5 = OpTypeArray %6 %8
-%9 = OpConstant %6 0
+%9 = OpConstantNull %6
 %10 = OpConstant %6 0.5
 %11 = OpConstant %6 1
 %12 = OpConstantComposite %5 %9 %10 %11
@@ -954,7 +954,7 @@
 %7 = OpTypeInt 32 0
 %8 = OpConstant %7 3
 %5 = OpTypeArray %6 %8
-%9 = OpConstant %6 0
+%9 = OpConstantNull %6
 %10 = OpConstant %6 0.5
 %11 = OpConstant %6 1
 %12 = OpConstantComposite %5 %9 %10 %11
diff --git a/src/tint/writer/spirv/builder_assign_test.cc b/src/tint/writer/spirv/builder_assign_test.cc
index 11ac42f..71c958c 100644
--- a/src/tint/writer/spirv/builder_assign_test.cc
+++ b/src/tint/writer/spirv/builder_assign_test.cc
@@ -98,7 +98,7 @@
 )");
 }
 
-TEST_F(BuilderTest, Assign_Var_Complex_ConstructorWithExtract) {
+TEST_F(BuilderTest, Assign_Var_Complex_ConstructorNestedVector) {
     auto* init = vec3<f32>(vec2<f32>(1_f, 2_f), 3_f);
 
     auto* v = Global("var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
@@ -121,17 +121,13 @@
 %2 = OpTypePointer Private %3
 %5 = OpConstantNull %3
 %1 = OpVariable %2 Private %5
-%6 = OpTypeVector %4 2
-%7 = OpConstant %4 1
-%8 = OpConstant %4 2
-%9 = OpConstantComposite %6 %7 %8
-%12 = OpConstant %4 3
+%6 = OpConstant %4 1
+%7 = OpConstant %4 2
+%8 = OpConstant %4 3
+%9 = OpConstantComposite %3 %6 %7 %8
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%10 = OpCompositeExtract %4 %9 0
-%11 = OpCompositeExtract %4 %9 1
-%13 = OpCompositeConstruct %3 %10 %11 %12
-OpStore %1 %13
+              R"(OpStore %1 %9
 )");
 }
 
diff --git a/src/tint/writer/spirv/builder_binary_expression_test.cc b/src/tint/writer/spirv/builder_binary_expression_test.cc
index debe63c..abaee2e 100644
--- a/src/tint/writer/spirv/builder_binary_expression_test.cc
+++ b/src/tint/writer/spirv/builder_binary_expression_test.cc
@@ -264,7 +264,7 @@
     EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
     EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
-%3 = OpConstantFalse %1
+%3 = OpConstantNull %1
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
               "%4 = " + param.name + " %1 %2 %3\n");
@@ -724,7 +724,7 @@
 %3 = OpConstantTrue %2
 %5 = OpTypePointer Private %2
 %4 = OpVariable %5 Private %3
-%6 = OpConstantFalse %2
+%6 = OpConstantNull %2
 %7 = OpVariable %5 Private %6
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
@@ -761,7 +761,7 @@
     EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
 %3 = OpConstantTrue %2
-%8 = OpConstantFalse %2
+%8 = OpConstantNull %2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
               R"(%1 = OpLabel
@@ -801,7 +801,7 @@
     EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
 %3 = OpConstantTrue %2
-%8 = OpConstantFalse %2
+%8 = OpConstantNull %2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
               R"(%1 = OpLabel
@@ -877,7 +877,7 @@
 %3 = OpConstantTrue %2
 %5 = OpTypePointer Private %2
 %4 = OpVariable %5 Private %3
-%6 = OpConstantFalse %2
+%6 = OpConstantNull %2
 %7 = OpVariable %5 Private %6
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
diff --git a/src/tint/writer/spirv/builder_builtin_test.cc b/src/tint/writer/spirv/builder_builtin_test.cc
index 7340074..4f6dca8 100644
--- a/src/tint/writer/spirv/builder_builtin_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_test.cc
@@ -518,7 +518,9 @@
     ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%10 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect =
+        R"(%10 = OpExtInstImport "GLSL.std.450"
 OpName %1 "ident"
 OpName %7 "a_func"
 %3 = OpTypeFloat 32
@@ -533,7 +535,8 @@
 %9 = OpExtInst %3 %10 RoundEven %11
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 using Builtin_Builtin_SingleParam_Float_Test = BuiltinBuilderTestWithParam<BuiltinData>;
@@ -549,7 +552,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -557,11 +561,13 @@
 %8 = OpConstant %6 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8
+%5 = OpExtInst %6 %7 )" +
+                  param.op +
+                  R"( %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_SingleParam_Float_Test, Call_Vector) {
@@ -576,7 +582,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -586,11 +593,13 @@
 %10 = OpConstantComposite %6 %9 %9
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10
+%5 = OpExtInst %6 %8 )" +
+                  param.op +
+                  R"( %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_SingleParam_Float_Test,
@@ -630,7 +639,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -641,7 +651,8 @@
 %5 = OpExtInst %6 %7 Length %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Length_Vector) {
@@ -655,7 +666,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -668,7 +680,8 @@
 %5 = OpExtInst %6 %7 Length %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Normalize) {
@@ -682,7 +695,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -695,15 +709,18 @@
 %5 = OpExtInst %6 %8 Normalize %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 using Builtin_Builtin_DualParam_Float_Test = BuiltinBuilderTestWithParam<BuiltinData>;
 TEST_P(Builtin_Builtin_DualParam_Float_Test, Call_Scalar) {
     auto param = GetParam();
-    auto* expr = Call(param.name, 1_f, 1_f);
+    auto* scalar = Var("scalar", nullptr, Expr(1_f));
+    auto* expr = Call(param.name, scalar, scalar);
     auto* func = Func("a_func", {}, ty.void_(),
                       {
+                          Decl(scalar),
                           Assign(Phony(), expr),
                       });
 
@@ -711,26 +728,38 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
+OpName %7 "scalar"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
-%6 = OpTypeFloat 32
-%8 = OpConstant %6 1
+%5 = OpTypeFloat 32
+%6 = OpConstant %5 1
+%8 = OpTypePointer Function %5
+%9 = OpConstantNull %5
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8 %8
+%7 = OpVariable %8 Function %9
+OpStore %7 %6
+%12 = OpLoad %5 %7
+%13 = OpLoad %5 %7
+%10 = OpExtInst %5 %11 )" +
+                  param.op +
+                  R"( %12 %13
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_DualParam_Float_Test, Call_Vector) {
     auto param = GetParam();
-    auto* expr = Call(param.name, vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f));
+    auto* vec = Var("vec", nullptr, vec2<f32>(1_f, 1_f));
+    auto* expr = Call(param.name, vec, vec);
     auto* func = Func("a_func", {}, ty.void_(),
                       {
+                          Decl(vec),
                           Assign(Phony(), expr),
                       });
 
@@ -738,21 +767,31 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
+OpName %9 "vec"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
-%7 = OpTypeFloat 32
-%6 = OpTypeVector %7 2
-%9 = OpConstant %7 1
-%10 = OpConstantComposite %6 %9 %9
+%6 = OpTypeFloat 32
+%5 = OpTypeVector %6 2
+%7 = OpConstant %6 1
+%8 = OpConstantComposite %5 %7 %7
+%10 = OpTypePointer Function %5
+%11 = OpConstantNull %5
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10 %10
+%9 = OpVariable %10 Function %11
+OpStore %9 %8
+%14 = OpLoad %5 %9
+%15 = OpLoad %5 %9
+%12 = OpExtInst %5 %13 )" +
+                  param.op +
+                  R"( %14 %15
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_DualParam_Float_Test,
@@ -773,7 +812,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -786,7 +826,8 @@
 %5 = OpExtInst %6 %8 Reflect %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Distance_Scalar) {
@@ -800,7 +841,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -811,7 +853,8 @@
 %5 = OpExtInst %6 %7 Distance %8 %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Distance_Vector) {
@@ -825,7 +868,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -838,7 +882,8 @@
 %5 = OpExtInst %6 %7 Distance %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Cross) {
@@ -852,7 +897,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -865,7 +911,8 @@
 %5 = OpExtInst %6 %8 Cross %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 using Builtin_Builtin_ThreeParam_Float_Test = BuiltinBuilderTestWithParam<BuiltinData>;
@@ -881,7 +928,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -889,11 +937,13 @@
 %8 = OpConstant %6 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8 %8 %8
+%5 = OpExtInst %6 %7 )" +
+                  param.op +
+                  R"( %8 %8 %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_ThreeParam_Float_Test, Call_Vector) {
@@ -908,7 +958,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -918,11 +969,13 @@
 %10 = OpConstantComposite %6 %9 %9
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10 %10 %10
+%5 = OpExtInst %6 %8 )" +
+                  param.op +
+                  R"( %10 %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_ThreeParam_Float_Test,
@@ -943,7 +996,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -956,7 +1010,8 @@
 %5 = OpExtInst %6 %8 FaceForward %10 %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 using Builtin_Builtin_SingleParam_Sint_Test = BuiltinBuilderTestWithParam<BuiltinData>;
@@ -972,7 +1027,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -980,11 +1036,13 @@
 %8 = OpConstant %6 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8
+%5 = OpExtInst %6 %7 )" +
+                  param.op +
+                  R"( %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_SingleParam_Sint_Test, Call_Vector) {
@@ -999,7 +1057,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1009,11 +1068,13 @@
 %10 = OpConstantComposite %6 %9 %9
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10
+%5 = OpExtInst %6 %8 )" +
+                  param.op +
+                  R"( %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_SingleParam_Sint_Test,
@@ -1022,7 +1083,7 @@
 // Calling abs() on an unsigned integer scalar / vector is a no-op.
 using Builtin_Builtin_Abs_Uint_Test = BuiltinBuilderTest;
 TEST_F(Builtin_Builtin_Abs_Uint_Test, Call_Scalar) {
-    auto* expr = Call("abs", 1_u);
+    auto* expr = Call("abs", Expr(1_u));
     auto* func = Func("a_func", {}, ty.void_(),
                       {
                           Assign(Phony(), expr),
@@ -1032,7 +1093,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %6 = OpTypeInt 32 0
@@ -1041,7 +1103,8 @@
 %4 = OpLabel
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(Builtin_Builtin_Abs_Uint_Test, Call_Vector) {
@@ -1055,7 +1118,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %7 = OpTypeInt 32 0
@@ -1066,15 +1130,18 @@
 %4 = OpLabel
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 using Builtin_Builtin_DualParam_SInt_Test = BuiltinBuilderTestWithParam<BuiltinData>;
 TEST_P(Builtin_Builtin_DualParam_SInt_Test, Call_Scalar) {
     auto param = GetParam();
-    auto* expr = Call(param.name, 1_i, 1_i);
+    auto* scalar = Var("scalar", nullptr, Expr(1_i));
+    auto* expr = Call(param.name, scalar, scalar);
     auto* func = Func("a_func", {}, ty.void_(),
                       {
+                          Decl(scalar),
                           Assign(Phony(), expr),
                       });
 
@@ -1082,26 +1149,38 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
+OpName %7 "scalar"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
-%6 = OpTypeInt 32 1
-%8 = OpConstant %6 1
+%5 = OpTypeInt 32 1
+%6 = OpConstant %5 1
+%8 = OpTypePointer Function %5
+%9 = OpConstantNull %5
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8 %8
+%7 = OpVariable %8 Function %9
+OpStore %7 %6
+%12 = OpLoad %5 %7
+%13 = OpLoad %5 %7
+%10 = OpExtInst %5 %11 )" +
+                  param.op +
+                  R"( %12 %13
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_DualParam_SInt_Test, Call_Vector) {
     auto param = GetParam();
-    auto* expr = Call(param.name, vec2<i32>(1_i, 1_i), vec2<i32>(1_i, 1_i));
+    auto* vec = Var("vec", nullptr, vec2<i32>(1_i, 1_i));
+    auto* expr = Call(param.name, vec, vec);
     auto* func = Func("a_func", {}, ty.void_(),
                       {
+                          Decl(vec),
                           Assign(Phony(), expr),
                       });
 
@@ -1109,21 +1188,31 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
+OpName %9 "vec"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpTypeVector %7 2
-%9 = OpConstant %7 1
-%10 = OpConstantComposite %6 %9 %9
+%6 = OpTypeInt 32 1
+%5 = OpTypeVector %6 2
+%7 = OpConstant %6 1
+%8 = OpConstantComposite %5 %7 %7
+%10 = OpTypePointer Function %5
+%11 = OpConstantNull %5
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10 %10
+%9 = OpVariable %10 Function %11
+OpStore %9 %8
+%14 = OpLoad %5 %9
+%15 = OpLoad %5 %9
+%12 = OpExtInst %5 %13 )" +
+                  param.op +
+                  R"( %14 %15
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_DualParam_SInt_Test,
@@ -1132,9 +1221,11 @@
 using Builtin_Builtin_DualParam_UInt_Test = BuiltinBuilderTestWithParam<BuiltinData>;
 TEST_P(Builtin_Builtin_DualParam_UInt_Test, Call_Scalar) {
     auto param = GetParam();
-    auto* expr = Call(param.name, 1_u, 1_u);
+    auto* scalar = Var("scalar", nullptr, Expr(1_u));
+    auto* expr = Call(param.name, scalar, scalar);
     auto* func = Func("a_func", {}, ty.void_(),
                       {
+                          Decl(scalar),
                           Assign(Phony(), expr),
                       });
 
@@ -1142,26 +1233,38 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
+OpName %7 "scalar"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
-%6 = OpTypeInt 32 0
-%8 = OpConstant %6 1
+%5 = OpTypeInt 32 0
+%6 = OpConstant %5 1
+%8 = OpTypePointer Function %5
+%9 = OpConstantNull %5
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8 %8
+%7 = OpVariable %8 Function %9
+OpStore %7 %6
+%12 = OpLoad %5 %7
+%13 = OpLoad %5 %7
+%10 = OpExtInst %5 %11 )" +
+                  param.op +
+                  R"( %12 %13
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_DualParam_UInt_Test, Call_Vector) {
     auto param = GetParam();
-    auto* expr = Call(param.name, vec2<u32>(1_u, 1_u), vec2<u32>(1_u, 1_u));
+    auto* vec = Var("vec", nullptr, vec2<u32>(1_u, 1_u));
+    auto* expr = Call(param.name, vec, vec);
     auto* func = Func("a_func", {}, ty.void_(),
                       {
+                          Decl(vec),
                           Assign(Phony(), expr),
                       });
 
@@ -1169,21 +1272,31 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
+OpName %9 "vec"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
-%7 = OpTypeInt 32 0
-%6 = OpTypeVector %7 2
-%9 = OpConstant %7 1
-%10 = OpConstantComposite %6 %9 %9
+%6 = OpTypeInt 32 0
+%5 = OpTypeVector %6 2
+%7 = OpConstant %6 1
+%8 = OpConstantComposite %5 %7 %7
+%10 = OpTypePointer Function %5
+%11 = OpConstantNull %5
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10 %10
+%9 = OpVariable %10 Function %11
+OpStore %9 %8
+%14 = OpLoad %5 %9
+%15 = OpLoad %5 %9
+%12 = OpExtInst %5 %13 )" +
+                  param.op +
+                  R"( %14 %15
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_DualParam_UInt_Test,
@@ -1202,7 +1315,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1210,11 +1324,13 @@
 %8 = OpConstant %6 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8 %8 %8
+%5 = OpExtInst %6 %7 )" +
+                  param.op +
+                  R"( %8 %8 %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_ThreeParam_Sint_Test, Call_Vector) {
@@ -1229,7 +1345,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1239,11 +1356,13 @@
 %10 = OpConstantComposite %6 %9 %9
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10 %10 %10
+%5 = OpExtInst %6 %8 )" +
+                  param.op +
+                  R"( %10 %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_ThreeParam_Sint_Test,
@@ -1262,7 +1381,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1270,11 +1390,13 @@
 %8 = OpConstant %6 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                  R"( %8 %8 %8
+%5 = OpExtInst %6 %7 )" +
+                  param.op +
+                  R"( %8 %8 %8
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_P(Builtin_Builtin_ThreeParam_Uint_Test, Call_Vector) {
@@ -1289,7 +1411,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1299,11 +1422,13 @@
 %10 = OpConstantComposite %6 %9 %9
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                  R"( %10 %10 %10
+%5 = OpExtInst %6 %8 )" +
+                  param.op +
+                  R"( %10 %10 %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
                          Builtin_Builtin_ThreeParam_Uint_Test,
@@ -1400,7 +1525,8 @@
     ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(%12 = OpExtInstImport "GLSL.std.450"
+    auto got = DumpBuilder(b);
+    auto expect = R"(%12 = OpExtInstImport "GLSL.std.450"
 OpName %1 "var"
 OpName %9 "a_func"
 %5 = OpTypeFloat 32
@@ -1417,7 +1543,8 @@
 %11 = OpExtInst %5 %12 Determinant %13
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Transpose) {
@@ -1433,7 +1560,8 @@
     ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "var"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpName %1 "var"
 OpName %9 "a_func"
 %5 = OpTypeFloat 32
 %4 = OpTypeVector %5 3
@@ -1451,7 +1579,8 @@
 %11 = OpTranspose %12 %14
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_ArrayLength) {
@@ -2107,7 +2236,8 @@
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
     if (pack4) {
-        EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+        auto got = DumpBuilder(b);
+        auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -2118,13 +2248,16 @@
 %11 = OpConstantComposite %8 %10 %10 %10 %10
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                      R"( %11
+%5 = OpExtInst %6 %7 )" +
+                      param.op +
+                      R"( %11
 OpReturn
 OpFunctionEnd
-)");
+)";
+        EXPECT_EQ(got, expect);
     } else {
-        EXPECT_EQ(DumpBuilder(b), R"(%7 = OpExtInstImport "GLSL.std.450"
+        auto got = DumpBuilder(b);
+        auto expect = R"(%7 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -2135,11 +2268,13 @@
 %11 = OpConstantComposite %8 %10 %10
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %7 )" + param.op +
-                                      R"( %11
+%5 = OpExtInst %6 %7 )" +
+                      param.op +
+                      R"( %11
 OpReturn
 OpFunctionEnd
-)");
+)";
+        EXPECT_EQ(got, expect);
     }
 }
 
@@ -2163,7 +2298,8 @@
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
     if (pack4) {
-        EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+        auto got = DumpBuilder(b);
+        auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -2173,13 +2309,16 @@
 %10 = OpConstant %9 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                      R"( %10
+%5 = OpExtInst %6 %8 )" +
+                      param.op +
+                      R"( %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+        EXPECT_EQ(got, expect);
     } else {
-        EXPECT_EQ(DumpBuilder(b), R"(%8 = OpExtInstImport "GLSL.std.450"
+        auto got = DumpBuilder(b);
+        auto expect = R"(%8 = OpExtInstImport "GLSL.std.450"
 OpName %3 "a_func"
 %2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -2189,11 +2328,13 @@
 %10 = OpConstant %9 1
 %3 = OpFunction %2 None %1
 %4 = OpLabel
-%5 = OpExtInst %6 %8 )" + param.op +
-                                      R"( %10
+%5 = OpExtInst %6 %8 )" +
+                      param.op +
+                      R"( %10
 OpReturn
 OpFunctionEnd
-)");
+)";
+        EXPECT_EQ(got, expect);
     }
 }
 
@@ -2284,7 +2425,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2309,7 +2451,8 @@
 %14 = OpBitFieldSExtract %7 %15 %16 %17
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_ExtractBits_u32) {
@@ -2323,7 +2466,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2345,7 +2489,8 @@
 %11 = OpBitFieldUExtract %7 %12 %13 %14
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_ExtractBits_vec3_i32) {
@@ -2359,7 +2504,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2385,7 +2531,8 @@
 %15 = OpBitFieldSExtract %7 %16 %17 %18
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_ExtractBits_vec3_u32) {
@@ -2399,7 +2546,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2424,7 +2572,8 @@
 %14 = OpBitFieldUExtract %7 %15 %16 %17
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_InsertBits_i32) {
@@ -2439,7 +2588,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2467,7 +2617,8 @@
 %15 = OpBitFieldInsert %7 %16 %17 %18 %19
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_InsertBits_u32) {
@@ -2482,7 +2633,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2507,7 +2659,8 @@
 %12 = OpBitFieldInsert %7 %13 %14 %15 %16
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_InsertBits_vec3_i32) {
@@ -2522,7 +2675,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2551,7 +2705,8 @@
 %16 = OpBitFieldInsert %7 %17 %18 %19 %20
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_InsertBits_vec3_u32) {
@@ -2566,7 +2721,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "v"
@@ -2594,7 +2750,8 @@
 %15 = OpBitFieldInsert %7 %16 %17 %18 %19
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Dot4I8Packed) {
@@ -2612,7 +2769,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "val1"
@@ -2632,7 +2790,8 @@
 %10 = OpSDot %11 %12 %13 PackedVectorFormat4x8Bit
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 TEST_F(BuiltinBuilderTest, Call_Dot4U8Packed) {
@@ -2650,7 +2809,8 @@
 
     ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
 
-    EXPECT_EQ(DumpBuilder(b), R"(OpEntryPoint GLCompute %3 "test_function"
+    auto got = DumpBuilder(b);
+    auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
 OpExecutionMode %3 LocalSize 1 1 1
 OpName %3 "test_function"
 OpName %5 "val1"
@@ -2669,7 +2829,8 @@
 %10 = OpUDot %7 %11 %12 PackedVectorFormat4x8Bit
 OpReturn
 OpFunctionEnd
-)");
+)";
+    EXPECT_EQ(got, expect);
 }
 
 }  // namespace
diff --git a/src/tint/writer/spirv/builder_builtin_texture_test.cc b/src/tint/writer/spirv/builder_builtin_texture_test.cc
index e76e478..b4abfcf 100644
--- a/src/tint/writer/spirv/builder_builtin_texture_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_texture_test.cc
@@ -589,7 +589,7 @@
 %16 = OpConstant %4 2
 %17 = OpConstantComposite %14 %15 %16
 %18 = OpTypeInt 32 1
-%19 = OpConstant %18 0
+%19 = OpConstantNull %18
 )",
                     R"(
 %10 = OpLoad %7 %5
@@ -615,7 +615,7 @@
 %16 = OpConstant %4 2
 %17 = OpConstantComposite %14 %15 %16
 %18 = OpTypeInt 32 1
-%19 = OpConstant %18 0
+%19 = OpConstantNull %18
 %20 = OpTypeVector %18 2
 %21 = OpConstant %18 3
 %22 = OpConstant %18 4
@@ -645,7 +645,7 @@
 %16 = OpConstant %4 2
 %18 = OpTypeInt 32 1
 %19 = OpConstant %18 3
-%21 = OpConstant %18 0
+%21 = OpConstantNull %18
 )",
                     R"(
 %10 = OpLoad %7 %5
@@ -673,7 +673,7 @@
 %16 = OpConstant %4 2
 %18 = OpTypeInt 32 1
 %19 = OpConstant %18 3
-%21 = OpConstant %18 0
+%21 = OpConstantNull %18
 %22 = OpTypeVector %18 2
 %23 = OpConstant %18 4
 %24 = OpConstant %18 5
@@ -706,7 +706,7 @@
 %17 = OpConstant %4 3
 %18 = OpConstantComposite %14 %15 %16 %17
 %19 = OpTypeInt 32 1
-%20 = OpConstant %19 0
+%20 = OpConstantNull %19
 )",
                     R"(
 %10 = OpLoad %7 %5
@@ -732,7 +732,7 @@
 %16 = OpConstant %4 3
 %18 = OpTypeInt 32 1
 %19 = OpConstant %18 4
-%21 = OpConstant %18 0
+%21 = OpConstantNull %18
 )",
                     R"(
 %10 = OpLoad %7 %5
diff --git a/src/tint/writer/spirv/builder_constructor_expression_test.cc b/src/tint/writer/spirv/builder_constructor_expression_test.cc
index ec69cfb..d1fba8f 100644
--- a/src/tint/writer/spirv/builder_constructor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_constructor_expression_test.cc
@@ -36,19 +36,6 @@
 )");
 }
 
-TEST_F(SpvBuilderConstructorTest, Type_WithCasts_OutsideFunction_IsError) {
-    auto* t = Construct<f32>(Construct<u32>(1_i));
-    WrapInFunction(t);
-
-    spirv::Builder& b = Build();
-
-    EXPECT_EQ(b.GenerateExpression(t), 0u);
-    EXPECT_TRUE(b.has_error()) << b.error();
-    EXPECT_EQ(b.error(),
-              "Internal error: trying to add SPIR-V instruction 124 outside a "
-              "function");
-}
-
 TEST_F(SpvBuilderConstructorTest, Type) {
     auto* t = vec3<f32>(1_f, 1_f, 3_f);
     WrapInFunction(t);
@@ -74,19 +61,15 @@
 
     b.push_function(Function{});
 
-    EXPECT_EQ(b.GenerateExpression(t), 7u);
+    EXPECT_EQ(b.GenerateExpression(t), 4u);
     ASSERT_FALSE(b.has_error()) << b.error();
 
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 2
-%4 = OpTypeInt 32 1
-%5 = OpConstant %4 1
+%3 = OpConstant %2 1
+%4 = OpConstantComposite %1 %3 %3
 )");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%3 = OpConvertSToF %2 %5
-%6 = OpConvertSToF %2 %5
-%7 = OpCompositeConstruct %1 %3 %6
-)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_WithAlias) {
@@ -100,15 +83,12 @@
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_EQ(b.GenerateExpression(cast), 2u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
-%3 = OpTypeFloat 32
-%4 = OpConstant %3 2.29999995
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 2
 )");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpConvertFToS %2 %4
-)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_IdentifierExpression_Param) {
@@ -142,26 +122,31 @@
 }
 
 TEST_F(SpvBuilderConstructorTest, Vector_Bitcast_Params) {
-    auto* t = vec2<u32>(Construct<u32>(1_i), Construct<u32>(1_i));
-    WrapInFunction(t);
+    auto* var = Var("v", nullptr, vec3<f32>(1_f, 2_f, 3_f));
+    auto* cast = Bitcast(ty.vec3<u32>(), var);
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_EQ(b.GenerateExpression(cast), 10u) << b.error();
 
-    EXPECT_EQ(b.GenerateExpression(t), 7u);
-    ASSERT_FALSE(b.has_error()) << b.error();
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
-%1 = OpTypeVector %2 2
-%4 = OpTypeInt 32 1
-%5 = OpConstant %4 1
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
+%8 = OpTypePointer Function %1
+%9 = OpConstantNull %1
+%12 = OpTypeInt 32 0
+%11 = OpTypeVector %12 3
 )");
-
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%3 = OpBitcast %2 %5
-%6 = OpBitcast %2 %5
-%7 = OpCompositeConstruct %1 %3 %6
+              R"(OpStore %7 %6
+%13 = OpLoad %1 %7
+%10 = OpBitcast %11 %13
 )");
 }
 
@@ -173,11 +158,11 @@
 
     b.push_function(Function{});
 
-    EXPECT_EQ(b.GenerateExpression(cast), 3u);
+    EXPECT_EQ(b.GenerateExpression(cast), 2u);
     ASSERT_FALSE(b.has_error()) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
-%3 = OpConstantTrue %2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpConstantTrue %1
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
@@ -189,10 +174,10 @@
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 3u);
+    EXPECT_EQ(b.GenerateExpression(cast), 2u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
-%3 = OpConstant %2 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
@@ -204,10 +189,10 @@
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 3u);
+    EXPECT_EQ(b.GenerateExpression(cast), 2u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
-%3 = OpConstant %2 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 0
+%2 = OpConstant %1 2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
@@ -219,10 +204,10 @@
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 3u);
+    EXPECT_EQ(b.GenerateExpression(cast), 2u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%3 = OpConstant %2 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
@@ -285,16 +270,16 @@
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
-TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_Var) {
-    auto* var = Var("v", nullptr, Expr(2_f));
-    auto* cast = vec2<f32>(var);
+TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32) {
+    auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
+    auto* cast = vec2<f32>("x", "x");
     WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-    ASSERT_EQ(b.GenerateExpression(cast), 8u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 9u);
 
     EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 2
@@ -302,31 +287,16 @@
 %5 = OpConstantNull %1
 %6 = OpTypeVector %1 2
 )");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %3 %2
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %3 %2
 %7 = OpLoad %1 %3
-%8 = OpCompositeConstruct %6 %7 %7
+%8 = OpLoad %1 %3
+%9 = OpCompositeConstruct %6 %7 %8
 )");
 }
 
-TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32) {
-    auto* cast = vec2<f32>(2_f, 2_f);
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 4u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 2
-%3 = OpConstant %2 2
-%4 = OpConstantComposite %1 %3 %3
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_Vec2) {
-    auto* value = vec2<f32>(2_f, 2_f);
-    auto* cast = vec2<f32>(value);
+TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32_Const) {
+    auto* cast = vec2<f32>(1_f, 2_f);
     WrapInFunction(cast);
 
     spirv::Builder& b = Build();
@@ -334,109 +304,131 @@
     b.push_function(Function{});
     EXPECT_EQ(b.GenerateExpression(cast), 5u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
-%2 = OpTypeVector %3 2
-%4 = OpConstant %3 2
-%5 = OpConstantComposite %2 %4 %4
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_Vec2) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
+    auto* cast = vec2<f32>("x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 10u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%10 = OpLoad %1 %6
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_Vec2_Const) {
+    auto* cast = vec2<f32>(vec2<f32>(1_f, 2_f));
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 5u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32) {
-    auto* cast = vec3<f32>(2_f);
+    auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
+    auto* cast = vec3<f32>("x", "x", "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 10u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%6 = OpTypeVector %1 3
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %3 %2
+%7 = OpLoad %1 %3
+%8 = OpLoad %1 %3
+%9 = OpLoad %1 %3
+%10 = OpCompositeConstruct %6 %7 %8 %9
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Const) {
+    auto* cast = vec3<f32>(1_f, 2_f, 3_f);
     WrapInFunction(cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 4u);
+    EXPECT_EQ(b.GenerateExpression(cast), 6u);
 
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
-%3 = OpConstant %2 2
-%4 = OpConstantComposite %1 %3 %3 %3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
 )");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Bool) {
-    auto* cast = vec3<bool>(true);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.bool_(), Expr(true)));
+    auto* cast = vec3<bool>("x", "x", "x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 4u);
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 10u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
-%1 = OpTypeVector %2 3
-%3 = OpConstantTrue %2
-%4 = OpConstantComposite %1 %3 %3 %3
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_F32_F32) {
-    auto* cast = vec3<f32>(2_f, 2_f, 2_f);
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 4u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 3
-%3 = OpConstant %2 2
-%4 = OpConstantComposite %1 %3 %3 %3
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Vec2) {
-    auto* cast = vec3<f32>(2_f, vec2<f32>(2_f, 2_f));
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 8u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 3
-%3 = OpConstant %2 2
-%4 = OpTypeVector %2 2
-%5 = OpConstantComposite %4 %3 %3
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpConstantTrue %1
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%6 = OpTypeVector %1 3
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeConstruct %1 %3 %6 %7
+              R"(OpStore %3 %2
+%7 = OpLoad %1 %3
+%8 = OpLoad %1 %3
+%9 = OpLoad %1 %3
+%10 = OpCompositeConstruct %6 %7 %8 %9
 )");
 }
 
-TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F32) {
-    auto* cast = vec3<f32>(vec2<f32>(2_f, 2_f), 2_f);
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 8u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 3
-%3 = OpTypeVector %2 2
-%4 = OpConstant %2 2
-%5 = OpConstantComposite %3 %4 %4
-)");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeConstruct %1 %6 %7 %4
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec3) {
-    auto* value = vec3<f32>(2_f, 2_f, 2_f);
-    auto* cast = vec3<f32>(value);
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Bool_Const) {
+    auto* cast = vec3<bool>(true, false, true);
     WrapInFunction(cast);
 
     spirv::Builder& b = Build();
@@ -444,15 +436,228 @@
     b.push_function(Function{});
     EXPECT_EQ(b.GenerateExpression(cast), 5u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
-%2 = OpTypeVector %3 3
-%4 = OpConstant %3 2
-%5 = OpConstantComposite %2 %4 %4 %4
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
+%1 = OpTypeVector %2 3
+%3 = OpConstantTrue %2
+%4 = OpConstantFalse %2
+%5 = OpConstantComposite %1 %3 %4 %3
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_F32_F32) {
+    auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
+    auto* cast = vec3<f32>("x", "x", "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 10u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%6 = OpTypeVector %1 3
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %3 %2
+%7 = OpLoad %1 %3
+%8 = OpLoad %1 %3
+%9 = OpLoad %1 %3
+%10 = OpCompositeConstruct %6 %7 %8 %9
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_F32_F32_Const) {
+    auto* cast = vec3<f32>(1_f, 2_f, 3_f);
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 6u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Vec2) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(2_f, 3_f)));
+    auto* cast = vec3<f32>(1_f, "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 14u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 2
+%4 = OpConstant %2 3
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+%9 = OpTypeVector %2 3
+%10 = OpConstant %2 1
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%11 = OpLoad %1 %6
+%12 = OpCompositeExtract %2 %11 0
+%13 = OpCompositeExtract %2 %11 1
+%14 = OpCompositeConstruct %9 %10 %12 %13
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Vec2_Const) {
+    auto* cast = vec3<f32>(1_f, vec2<f32>(2_f, 3_f));
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 6u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F32) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
+    auto* cast = vec3<f32>("x", 3_f);
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 14u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+%9 = OpTypeVector %2 3
+%13 = OpConstant %2 3
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%10 = OpLoad %1 %6
+%11 = OpCompositeExtract %2 %10 0
+%12 = OpCompositeExtract %2 %10 1
+%14 = OpCompositeConstruct %9 %11 %12 %13
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F32_Const) {
+    auto* cast = vec3<f32>(vec2<f32>(1_f, 2_f), 3_f);
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 6u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec3) {
+    auto* var = Decl(Var("x", ty.vec3<f32>(), vec3<f32>(1_f, 2_f, 3_f)));
+    auto* cast = vec3<f32>("x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 11u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
+%8 = OpTypePointer Function %1
+%9 = OpConstantNull %1
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %7 %6
+%11 = OpLoad %1 %7
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec3_Const) {
+    auto* cast = vec3<f32>(vec3<f32>(1_f, 2_f, 3_f));
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 6u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Bool) {
+    auto* var = Decl(Var("x", ty.bool_(), Expr(true)));
+    auto* cast = vec4<bool>("x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 8u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpConstantTrue %1
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%6 = OpTypeVector %1 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %3 %2
+%7 = OpLoad %1 %3
+%8 = OpCompositeConstruct %6 %7 %7 %7 %7
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Bool_Const) {
     auto* cast = vec4<bool>(true);
     WrapInFunction(cast);
 
@@ -466,9 +671,34 @@
 %3 = OpConstantTrue %2
 %4 = OpConstantComposite %1 %3 %3 %3 %3
 )");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32) {
+    auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
+    auto* cast = vec4<f32>("x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 8u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%6 = OpTypeVector %1 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %3 %2
+%7 = OpLoad %1 %3
+%8 = OpCompositeConstruct %6 %7 %7 %7 %7
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Const) {
     auto* cast = vec4<f32>(2_f);
     WrapInFunction(cast);
 
@@ -482,10 +712,288 @@
 %3 = OpConstant %2 2
 %4 = OpConstantComposite %1 %3 %3 %3 %3
 )");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_F32_F32) {
-    auto* cast = vec4<f32>(2_f, 2_f, 2_f, 2_f);
+    auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
+    auto* cast = vec4<f32>("x", "x", "x", "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 11u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%6 = OpTypeVector %1 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %3 %2
+%7 = OpLoad %1 %3
+%8 = OpLoad %1 %3
+%9 = OpLoad %1 %3
+%10 = OpLoad %1 %3
+%11 = OpCompositeConstruct %6 %7 %8 %9 %10
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_F32_F32_Const) {
+    auto* cast = vec4<f32>(1_f, 2_f, 3_f, 4_f);
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 7u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 4
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstant %2 4
+%7 = OpConstantComposite %1 %3 %4 %5 %6
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_Vec2) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
+    auto* cast = vec4<f32>(1_f, 2_f, "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 13u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+%9 = OpTypeVector %2 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%10 = OpLoad %1 %6
+%11 = OpCompositeExtract %2 %10 0
+%12 = OpCompositeExtract %2 %10 1
+%13 = OpCompositeConstruct %9 %3 %4 %11 %12
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_Vec2_Const) {
+    auto* cast = vec4<f32>(1_f, 2_f, vec2<f32>(3_f, 4_f));
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 7u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 4
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstant %2 4
+%7 = OpConstantComposite %1 %3 %4 %5 %6
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec2_F32) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(2_f, 3_f)));
+    auto* cast = vec4<f32>(1_f, "x", 4_f);
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 15u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 2
+%4 = OpConstant %2 3
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+%9 = OpTypeVector %2 4
+%10 = OpConstant %2 1
+%14 = OpConstant %2 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%11 = OpLoad %1 %6
+%12 = OpCompositeExtract %2 %11 0
+%13 = OpCompositeExtract %2 %11 1
+%15 = OpCompositeConstruct %9 %10 %12 %13 %14
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec2_F32_Const) {
+    auto* cast = vec4<f32>(1_f, vec2<f32>(2_f, 3_f), 4_f);
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 7u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 4
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstant %2 4
+%7 = OpConstantComposite %1 %3 %4 %5 %6
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F32_F32) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
+    auto* cast = vec4<f32>("x", 3_f, 4_f);
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 15u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+%9 = OpTypeVector %2 4
+%13 = OpConstant %2 3
+%14 = OpConstant %2 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%10 = OpLoad %1 %6
+%11 = OpCompositeExtract %2 %10 0
+%12 = OpCompositeExtract %2 %10 1
+%15 = OpCompositeConstruct %9 %11 %12 %13 %14
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F32_F32_Const) {
+    auto* cast = vec4<f32>(vec2<f32>(1_f, 2_f), 3_f, 4_f);
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 7u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 4
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstant %2 4
+%7 = OpConstantComposite %1 %3 %4 %5 %6
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_Vec2) {
+    auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
+    auto* cast = vec4<f32>("x", "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 16u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 2
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4
+%7 = OpTypePointer Function %1
+%8 = OpConstantNull %1
+%9 = OpTypeVector %2 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %6 %5
+%10 = OpLoad %1 %6
+%11 = OpCompositeExtract %2 %10 0
+%12 = OpCompositeExtract %2 %10 1
+%13 = OpLoad %1 %6
+%14 = OpCompositeExtract %2 %13 0
+%15 = OpCompositeExtract %2 %13 1
+%16 = OpCompositeConstruct %9 %11 %12 %14 %15
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_Vec2_Const) {
+    auto* cast = vec4<f32>(vec2<f32>(1_f, 2_f), vec2<f32>(1_f, 2_f));
+    WrapInFunction(cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_EQ(b.GenerateExpression(cast), 5u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 4
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstantComposite %1 %3 %4 %3 %4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec3) {
+    auto* var = Decl(Var("x", ty.vec3<f32>(), vec3<f32>(2_f, 2_f, 2_f)));
+    auto* cast = vec4<f32>(2_f, "x");
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 13u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 2
+%4 = OpConstantComposite %1 %3 %3 %3
+%6 = OpTypePointer Function %1
+%7 = OpConstantNull %1
+%8 = OpTypeVector %2 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %5 %4
+%9 = OpLoad %1 %5
+%10 = OpCompositeExtract %2 %9 0
+%11 = OpCompositeExtract %2 %9 1
+%12 = OpCompositeExtract %2 %9 2
+%13 = OpCompositeConstruct %8 %3 %10 %11 %12
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec3_Const) {
+    auto* cast = vec4<f32>(2_f, vec3<f32>(2_f, 2_f, 2_f));
     WrapInFunction(cast);
 
     spirv::Builder& b = Build();
@@ -498,142 +1006,53 @@
 %3 = OpConstant %2 2
 %4 = OpConstantComposite %1 %3 %3 %3 %3
 )");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_Vec2) {
-    auto* cast = vec4<f32>(2_f, 2_f, vec2<f32>(2_f, 2_f));
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 8u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 4
-%3 = OpConstant %2 2
-%4 = OpTypeVector %2 2
-%5 = OpConstantComposite %4 %3 %3
-)");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeConstruct %1 %3 %3 %6 %7
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec2_F32) {
-    auto* cast = vec4<f32>(2_f, vec2<f32>(2_f, 2_f), 2_f);
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 8u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 4
-%3 = OpConstant %2 2
-%4 = OpTypeVector %2 2
-%5 = OpConstantComposite %4 %3 %3
-)");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeConstruct %1 %3 %6 %7 %3
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F32_F32) {
-    auto* cast = vec4<f32>(vec2<f32>(2_f, 2_f), 2_f, 2_f);
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 8u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 4
-%3 = OpTypeVector %2 2
-%4 = OpConstant %2 2
-%5 = OpConstantComposite %3 %4 %4
-)");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeConstruct %1 %6 %7 %4 %4
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_Vec2) {
-    auto* cast = vec4<f32>(vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f));
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 10u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 4
-%3 = OpTypeVector %2 2
-%4 = OpConstant %2 2
-%5 = OpConstantComposite %3 %4 %4
-)");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeExtract %2 %5 0
-%9 = OpCompositeExtract %2 %5 1
-%10 = OpCompositeConstruct %1 %6 %7 %8 %9
-)");
-}
-
-TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec3) {
-    auto* cast = vec4<f32>(2_f, vec3<f32>(2_f, 2_f, 2_f));
-    WrapInFunction(cast);
-
-    spirv::Builder& b = Build();
-
-    b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 9u);
-
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 4
-%3 = OpConstant %2 2
-%4 = OpTypeVector %2 3
-%5 = OpConstantComposite %4 %3 %3 %3
-)");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeExtract %2 %5 2
-%9 = OpCompositeConstruct %1 %3 %6 %7 %8
-)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F32) {
+    auto* var = Decl(Var("x", ty.vec3<f32>(), vec3<f32>(2_f, 2_f, 2_f)));
+    auto* cast = vec4<f32>("x", 2_f);
+    WrapInFunction(var, cast);
+
+    spirv::Builder& b = Build();
+
+    b.push_function(Function{});
+    EXPECT_TRUE(b.GenerateStatement(var));
+    EXPECT_EQ(b.GenerateExpression(cast), 13u);
+
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 2
+%4 = OpConstantComposite %1 %3 %3 %3
+%6 = OpTypePointer Function %1
+%7 = OpConstantNull %1
+%8 = OpTypeVector %2 4
+)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+              R"(OpStore %5 %4
+%9 = OpLoad %1 %5
+%10 = OpCompositeExtract %2 %9 0
+%11 = OpCompositeExtract %2 %9 1
+%12 = OpCompositeExtract %2 %9 2
+%13 = OpCompositeConstruct %8 %10 %11 %12 %3
+)");
+}
+
+TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F32_Const) {
     auto* cast = vec4<f32>(vec3<f32>(2_f, 2_f, 2_f), 2_f);
     WrapInFunction(cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 9u);
+    EXPECT_EQ(b.GenerateExpression(cast), 4u);
 
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 4
-%3 = OpTypeVector %2 3
-%4 = OpConstant %2 2
-%5 = OpConstantComposite %3 %4 %4 %4
+%3 = OpConstant %2 2
+%4 = OpConstantComposite %1 %3 %3 %3 %3
 )");
-    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%6 = OpCompositeExtract %2 %5 0
-%7 = OpCompositeExtract %2 %5 1
-%8 = OpCompositeExtract %2 %5 2
-%9 = OpCompositeConstruct %1 %6 %7 %8 %4
-)");
+    EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec4) {
@@ -644,12 +1063,12 @@
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 5u);
+    EXPECT_EQ(b.GenerateExpression(cast), 4u);
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
-%2 = OpTypeVector %3 4
-%4 = OpConstant %3 2
-%5 = OpConstantComposite %2 %4 %4 %4 %4
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 4
+%3 = OpConstant %2 2
+%4 = OpConstantComposite %1 %3 %3 %3 %3
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()");
 }
@@ -1427,110 +1846,146 @@
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Convert_U32_To_I32) {
-    auto* cast = Construct<i32>(2_u);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.u32(), Expr(2_u)));
+    auto* cast = Construct<i32>("x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
-%3 = OpTypeInt 32 0
-%4 = OpConstant %3 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 0
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%7 = OpTypeInt 32 1
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpBitcast %2 %4
+              R"(OpStore %3 %2
+%8 = OpLoad %1 %3
+%6 = OpBitcast %7 %8
 )");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Convert_I32_To_U32) {
-    auto* cast = Construct<u32>(2_i);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.i32(), Expr(2_i)));
+    auto* cast = Construct<u32>("x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
-%3 = OpTypeInt 32 1
-%4 = OpConstant %3 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%7 = OpTypeInt 32 0
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpBitcast %2 %4
+              R"(OpStore %3 %2
+%8 = OpLoad %1 %3
+%6 = OpBitcast %7 %8
 )");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Convert_F32_To_I32) {
-    auto* cast = Construct<i32>(2.4_f);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.f32(), Expr(2.4_f)));
+    auto* cast = Construct<i32>("x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
-%3 = OpTypeFloat 32
-%4 = OpConstant %3 2.4000001
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2.4000001
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%7 = OpTypeInt 32 1
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpConvertFToS %2 %4
+              R"(OpStore %3 %2
+%8 = OpLoad %1 %3
+%6 = OpConvertFToS %7 %8
 )");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Convert_F32_To_U32) {
-    auto* cast = Construct<u32>(2.4_f);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.f32(), Expr(2.4_f)));
+    auto* cast = Construct<u32>("x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
-%3 = OpTypeFloat 32
-%4 = OpConstant %3 2.4000001
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 2.4000001
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%7 = OpTypeInt 32 0
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpConvertFToU %2 %4
+              R"(OpStore %3 %2
+%8 = OpLoad %1 %3
+%6 = OpConvertFToU %7 %8
 )");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Convert_I32_To_F32) {
-    auto* cast = Construct<f32>(2_i);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.i32(), Expr(2_i)));
+    auto* cast = Construct<f32>("x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%3 = OpTypeInt 32 1
-%4 = OpConstant %3 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%7 = OpTypeFloat 32
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpConvertSToF %2 %4
+              R"(OpStore %3 %2
+%8 = OpLoad %1 %3
+%6 = OpConvertSToF %7 %8
 )");
 }
 
 TEST_F(SpvBuilderConstructorTest, Type_Convert_U32_To_F32) {
-    auto* cast = Construct<f32>(2_u);
-    WrapInFunction(cast);
+    auto* var = Decl(Var("x", ty.u32(), Expr(2_u)));
+    auto* cast = Construct<f32>("x");
+    WrapInFunction(var, cast);
 
     spirv::Builder& b = Build();
 
     b.push_function(Function{});
-    EXPECT_EQ(b.GenerateExpression(cast), 1u);
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
 
-    EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%3 = OpTypeInt 32 0
-%4 = OpConstant %3 2
+    EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 0
+%2 = OpConstant %1 2
+%4 = OpTypePointer Function %1
+%5 = OpConstantNull %1
+%7 = OpTypeFloat 32
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
-              R"(%1 = OpConvertUToF %2 %4
+              R"(OpStore %3 %2
+%8 = OpLoad %1 %3
+%6 = OpConvertUToF %7 %8
 )");
 }
 
diff --git a/src/tint/writer/spirv/builder_global_variable_test.cc b/src/tint/writer/spirv/builder_global_variable_test.cc
index 249c048..9b30bb1 100644
--- a/src/tint/writer/spirv/builder_global_variable_test.cc
+++ b/src/tint/writer/spirv/builder_global_variable_test.cc
@@ -100,7 +100,7 @@
 )");
 }
 
-TEST_F(BuilderTest, GlobalVar_Complex_ConstructorWithExtract) {
+TEST_F(BuilderTest, GlobalVar_Complex_ConstructorNestedVector) {
     auto* init = vec3<f32>(vec2<f32>(1_f, 2_f), 3_f);
 
     auto* v = GlobalConst("var", ty.vec3<f32>(), init);
@@ -112,17 +112,10 @@
 
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
-%3 = OpTypeVector %2 2
-%4 = OpConstant %2 1
-%5 = OpConstant %2 2
-%6 = OpConstantComposite %3 %4 %5
-%8 = OpTypeInt 32 0
-%9 = OpConstant %8 0
-%7 = OpSpecConstantOp %2 CompositeExtract %6 9
-%11 = OpConstant %8 1
-%10 = OpSpecConstantOp %2 CompositeExtract %6 11
-%12 = OpConstant %2 3
-%13 = OpSpecConstantComposite %1 %7 %10 %12
+%3 = OpConstant %2 1
+%4 = OpConstant %2 2
+%5 = OpConstant %2 3
+%6 = OpConstantComposite %1 %3 %4 %5
 )");
 }
 
diff --git a/src/tint/writer/spirv/builder_if_test.cc b/src/tint/writer/spirv/builder_if_test.cc
index a32f409..8c7c8ee 100644
--- a/src/tint/writer/spirv/builder_if_test.cc
+++ b/src/tint/writer/spirv/builder_if_test.cc
@@ -223,7 +223,7 @@
 %6 = OpConstantTrue %5
 %10 = OpConstant %3 2
 %14 = OpConstant %3 3
-%15 = OpConstantFalse %5
+%15 = OpConstantNull %5
 %19 = OpConstant %3 4
 %20 = OpConstant %3 5
 )");
@@ -472,7 +472,7 @@
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
 %1 = OpTypeFunction %2
 %5 = OpConstantTrue %2
-%8 = OpConstantFalse %2
+%8 = OpConstantNull %2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
               R"(OpSelectionMerge %6 None
@@ -542,7 +542,7 @@
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
 %1 = OpTypeFunction %2
 %5 = OpConstantTrue %2
-%8 = OpConstantFalse %2
+%8 = OpConstantNull %2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
               R"(OpSelectionMerge %6 None
@@ -600,7 +600,7 @@
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %5 = OpTypeBool
-%6 = OpConstantFalse %5
+%6 = OpConstantNull %5
 %10 = OpConstantTrue %5
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
@@ -638,7 +638,7 @@
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %9 = OpTypeBool
-%10 = OpConstantFalse %9
+%10 = OpConstantNull %9
 %14 = OpConstantTrue %9
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
diff --git a/src/tint/writer/spirv/builder_unary_op_expression_test.cc b/src/tint/writer/spirv/builder_unary_op_expression_test.cc
index fa80828..e28eb78 100644
--- a/src/tint/writer/spirv/builder_unary_op_expression_test.cc
+++ b/src/tint/writer/spirv/builder_unary_op_expression_test.cc
@@ -79,7 +79,7 @@
     b.push_function(Function{});
     EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.error();
     EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool
-%3 = OpConstantFalse %2
+%3 = OpConstantNull %2
 )");
     EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
               R"(%1 = OpLogicalNot %2 %3
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index 21216bf..b8ca89c 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -23,7 +23,6 @@
 #include "src/tint/transform/canonicalize_entry_point_io.h"
 #include "src/tint/transform/disable_uniformity_analysis.h"
 #include "src/tint/transform/expand_compound_assignment.h"
-#include "src/tint/transform/fold_constants.h"
 #include "src/tint/transform/for_loop_to_loop.h"
 #include "src/tint/transform/manager.h"
 #include "src/tint/transform/promote_side_effects_to_decl.h"
@@ -73,7 +72,6 @@
     manager.Add<transform::PromoteSideEffectsToDecl>();
     manager.Add<transform::UnwindDiscardFunctions>();
     manager.Add<transform::SimplifyPointers>();  // Required for arrayLength()
-    manager.Add<transform::FoldConstants>();
     manager.Add<transform::VectorizeScalarMatrixConstructors>();
     manager.Add<transform::ForLoopToLoop>();  // Must come after
                                               // ZeroInitWorkgroupMemory
diff --git a/test/tint/BUILD.gn b/test/tint/BUILD.gn
index 7acdea9..c75f50e 100644
--- a/test/tint/BUILD.gn
+++ b/test/tint/BUILD.gn
@@ -334,7 +334,6 @@
     "../../src/tint/transform/disable_uniformity_analysis_test.cc",
     "../../src/tint/transform/expand_compound_assignment_test.cc",
     "../../src/tint/transform/first_index_offset_test.cc",
-    "../../src/tint/transform/fold_constants_test.cc",
     "../../src/tint/transform/fold_trivial_single_use_lets_test.cc",
     "../../src/tint/transform/for_loop_to_loop_test.cc",
     "../../src/tint/transform/localize_struct_array_assignment_test.cc",