Import Tint changes from Dawn

Changes:
  - 2eae44a628063255ab08f92ba5dbe2afd1908862 [ir] Dump before validating, when dumping by James Price <jrprice@google.com>
  - 5b3ae14cca5b2d0573c47f64b3c37c24ce61135f msl-writer: support subgroupBroadcast by David Neto <dneto@google.com>
  - 7d8ee4a956fb4acf14b7b8a233cf2808a72834d6 [tint] Move ZeroValue() to constant::Manager by James Price <jrprice@google.com>
  - cd6422ffc51fb8e02fc85c6972d9c3d4046fc6cd [tint] Add missing include for type::Manager usage by James Price <jrprice@google.com>
  - 4dcbddaee8328d6cc50b65d25871a4baf5d7bafb [tint] Simplify custom hash-code implementations by Ben Clayton <bclayton@google.com>
  - 02b56ad75053428c9ce0ada4786e1756feb096a2 [spirv-reader] use sem::Load to translate atomics by James Price <jrprice@google.com>
  - 8fade133d35e900f1e20e4a75d2d0cf7543b2332 [ir] Validate store instructions by James Price <jrprice@google.com>
  - 4650ca1404368950e106b23bb79d5446f03df23b [tint][ir] Rename UserCall::Func() -> Target() by Ben Clayton <bclayton@google.com>
  - 47fe0f58edf58a86a7b4a943454305aa0bcf88b2 [tint][ir] Make Builder insertion point logic more flexib... by Ben Clayton <bclayton@google.com>
  - 7b4ec6e836a5bca7182fd2e144690283846413f1 [ir] Move `image_query_size` and `image_query_size_lod` o... by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: 2eae44a628063255ab08f92ba5dbe2afd1908862
Change-Id: I14787d54ca46eaac5b31840bfa267c3713bb5be3
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/152640
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/core/constant/eval.cc b/src/tint/lang/core/constant/eval.cc
index 4c58f59..74cc427 100644
--- a/src/tint/lang/core/constant/eval.cc
+++ b/src/tint/lang/core/constant/eval.cc
@@ -30,7 +30,6 @@
 #include "src/tint/lang/core/number.h"
 #include "src/tint/lang/core/type/abstract_float.h"
 #include "src/tint/lang/core/type/abstract_int.h"
-#include "src/tint/lang/core/type/array.h"
 #include "src/tint/lang/core/type/bool.h"
 #include "src/tint/lang/core/type/f16.h"
 #include "src/tint/lang/core/type/f32.h"
@@ -638,7 +637,7 @@
         if (!std::isfinite(v.value)) {
             AddError(OverflowErrorMessage(v, t->FriendlyName()), source);
             if (use_runtime_semantics_) {
-                return ZeroValue(t);
+                return mgr.Zero(t);
             } else {
                 return tint::Failure;
             }
@@ -647,52 +646,6 @@
     return mgr.Get<Scalar<T>>(t, v);
 }
 
-const Value* Eval::ZeroValue(const core::type::Type* type) {
-    return Switch(
-        type,  //
-        [&](const core::type::Vector* v) -> const Value* {
-            auto* zero_el = ZeroValue(v->type());
-            return mgr.Splat(type, zero_el, v->Width());
-        },
-        [&](const core::type::Matrix* m) -> const Value* {
-            auto* zero_el = ZeroValue(m->ColumnType());
-            return mgr.Splat(type, zero_el, m->columns());
-        },
-        [&](const core::type::Array* a) -> const Value* {
-            if (auto n = a->ConstantCount()) {
-                if (auto* zero_el = ZeroValue(a->ElemType())) {
-                    return mgr.Splat(type, zero_el, n.value());
-                }
-            }
-            return nullptr;
-        },
-        [&](const core::type::Struct* s) -> const Value* {
-            Hashmap<const core::type::Type*, const Value*, 8> zero_by_type;
-            Vector<const Value*, 4> zeros;
-            zeros.Reserve(s->Members().Length());
-            for (auto* member : s->Members()) {
-                auto* zero = zero_by_type.GetOrCreate(member->Type(),
-                                                      [&] { return ZeroValue(member->Type()); });
-                if (!zero) {
-                    return nullptr;
-                }
-                zeros.Push(zero);
-            }
-            if (zero_by_type.Count() == 1) {
-                // All members were of the same type, so the zero value is the same for all members.
-                return mgr.Splat(type, zeros[0], s->Members().Length());
-            }
-            return mgr.Composite(s, std::move(zeros));
-        },
-        [&](Default) -> const Value* {
-            return ZeroTypeDispatch(type, [&](auto zero) -> const Value* {
-                auto el = CreateScalar(Source{}, type, zero);
-                TINT_ASSERT(el);
-                return el.Get();
-            });
-        });
-}
-
 template <typename NumberT>
 tint::Result<NumberT> Eval::Add(const Source& source, NumberT a, NumberT b) {
     NumberT result;
@@ -1323,7 +1276,7 @@
 
 Eval::Result Eval::ArrayOrStructCtor(const core::type::Type* ty, VectorRef<const Value*> args) {
     if (args.IsEmpty()) {
-        return ZeroValue(ty);
+        return mgr.Zero(ty);
     }
 
     if (args.Length() == 1 && args[0]->Type() == ty) {
@@ -1351,7 +1304,7 @@
 }
 
 Eval::Result Eval::Zero(const core::type::Type* ty, VectorRef<const Value*>, const Source&) {
-    return ZeroValue(ty);
+    return mgr.Zero(ty);
 }
 
 Eval::Result Eval::Identity(const core::type::Type*, VectorRef<const Value*> args, const Source&) {
@@ -1436,7 +1389,7 @@
         }
         AddError("index " + std::to_string(idx) + " out of bounds" + range, idx_source);
         if (use_runtime_semantics_) {
-            return ZeroValue(el.type);
+            return mgr.Zero(el.type);
         } else {
             return tint::Failure;
         }
@@ -2178,7 +2131,7 @@
                 AddError("acos must be called with a value in the range [-1 .. 1] (inclusive)",
                          source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2199,7 +2152,7 @@
             if (i < NumberT(1.0)) {
                 AddError("acosh must be called with a value >= 1.0", source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2234,7 +2187,7 @@
                 AddError("asin must be called with a value in the range [-1 .. 1] (inclusive)",
                          source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2281,7 +2234,7 @@
                 AddError("atanh must be called with a value in the range (-1 .. 1) (exclusive)",
                          source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2551,7 +2504,7 @@
             if (!std::isfinite(val.value)) {
                 AddError(OverflowExpErrorMessage("e", e0), source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2573,7 +2526,7 @@
             if (!std::isfinite(val.value)) {
                 AddError(OverflowExpErrorMessage("2", e0), source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2922,7 +2875,7 @@
             if (e <= NumberT(0)) {
                 AddError("inverseSqrt must be called with a value > 0", source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -2979,7 +2932,7 @@
             if (e2 > bias + 1) {
                 AddError("e2 must be less than or equal to " + std::to_string(bias + 1), source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c1->Type());
+                    return mgr.Zero(c1->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -3015,7 +2968,7 @@
             if (v <= NumberT(0)) {
                 AddError("log must be called with a value > 0", source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -3036,7 +2989,7 @@
             if (v <= NumberT(0)) {
                 AddError("log2 must be called with a value > 0", source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -3161,7 +3114,7 @@
     if (v->AllZero()) {
         AddError("zero length vector can not be normalized", source);
         if (use_runtime_semantics_) {
-            return ZeroValue(ty);
+            return mgr.Zero(ty);
         } else {
             return tint::Failure;
         }
@@ -3282,7 +3235,7 @@
             if (!r) {
                 AddError(OverflowErrorMessage(e1, "^", e2), source);
                 if (use_runtime_semantics_) {
-                    return ZeroValue(c0->Type());
+                    return mgr.Zero(c0->Type());
                 } else {
                     return tint::Failure;
                 }
@@ -3436,7 +3389,7 @@
 
         // If k < 0.0, returns the refraction vector 0.0
         if (k.Get()->ValueAs<AFloat>() < 0) {
-            return ZeroValue(ty);
+            return mgr.Zero(ty);
         }
 
         // Otherwise return the refraction vector e3 * e1 - (e3 * dot(e2, e1) + sqrt(k)) * e2
@@ -3862,7 +3815,7 @@
         if (!conv) {
             AddError(OverflowErrorMessage(value, "f16"), source);
             if (use_runtime_semantics_) {
-                return ZeroValue(c->Type());
+                return mgr.Zero(c->Type());
             } else {
                 return tint::Failure;
             }
diff --git a/src/tint/lang/core/constant/eval.h b/src/tint/lang/core/constant/eval.h
index 035f353..17f298e 100644
--- a/src/tint/lang/core/constant/eval.h
+++ b/src/tint/lang/core/constant/eval.h
@@ -953,9 +953,6 @@
     template <typename T>
     Eval::Result CreateScalar(const Source& source, const core::type::Type* t, T v);
 
-    /// ZeroValue returns a Constant for the zero-value of the type `type`.
-    const Value* ZeroValue(const core::type::Type* type);
-
     /// Adds two Number<T>s
     /// @param source the source location
     /// @param a the lhs number
diff --git a/src/tint/lang/core/constant/manager.cc b/src/tint/lang/core/constant/manager.cc
index 0a23ab4..22ee8ee 100644
--- a/src/tint/lang/core/constant/manager.cc
+++ b/src/tint/lang/core/constant/manager.cc
@@ -19,13 +19,17 @@
 #include "src/tint/lang/core/constant/splat.h"
 #include "src/tint/lang/core/type/abstract_float.h"
 #include "src/tint/lang/core/type/abstract_int.h"
+#include "src/tint/lang/core/type/array.h"
 #include "src/tint/lang/core/type/bool.h"
 #include "src/tint/lang/core/type/f16.h"
 #include "src/tint/lang/core/type/f32.h"
 #include "src/tint/lang/core/type/i32.h"
 #include "src/tint/lang/core/type/manager.h"
+#include "src/tint/lang/core/type/matrix.h"
 #include "src/tint/lang/core/type/u32.h"
+#include "src/tint/lang/core/type/vector.h"
 #include "src/tint/utils/containers/predicates.h"
+#include "src/tint/utils/rtti/switch.h"
 
 namespace tint::core::constant {
 
@@ -102,4 +106,54 @@
     return Get<Scalar<AInt>>(types.AInt(), value);
 }
 
+const Value* Manager::Zero(const core::type::Type* type) {
+    return Switch(
+        type,  //
+        [&](const core::type::Vector* v) -> const Value* {
+            auto* zero_el = Zero(v->type());
+            return Splat(type, zero_el, v->Width());
+        },
+        [&](const core::type::Matrix* m) -> const Value* {
+            auto* zero_el = Zero(m->ColumnType());
+            return Splat(type, zero_el, m->columns());
+        },
+        [&](const core::type::Array* a) -> const Value* {
+            if (auto n = a->ConstantCount()) {
+                if (auto* zero_el = Zero(a->ElemType())) {
+                    return Splat(type, zero_el, n.value());
+                }
+            }
+            return nullptr;
+        },
+        [&](const core::type::Struct* s) -> const Value* {
+            Hashmap<const core::type::Type*, const Value*, 8> zero_by_type;
+            Vector<const Value*, 4> zeros;
+            zeros.Reserve(s->Members().Length());
+            for (auto* member : s->Members()) {
+                auto* zero =
+                    zero_by_type.GetOrCreate(member->Type(), [&] { return Zero(member->Type()); });
+                if (!zero) {
+                    return nullptr;
+                }
+                zeros.Push(zero);
+            }
+            if (zero_by_type.Count() == 1) {
+                // All members were of the same type, so the zero value is the same for all members.
+                return Splat(type, zeros[0], s->Members().Length());
+            }
+            return Composite(s, std::move(zeros));
+        },
+        [&](Default) -> const Value* {
+            return Switch(
+                type,                                                              //
+                [&](const core::type::AbstractInt*) { return Get(AInt(0)); },      //
+                [&](const core::type::AbstractFloat*) { return Get(AFloat(0)); },  //
+                [&](const core::type::I32*) { return Get(i32(0)); },               //
+                [&](const core::type::U32*) { return Get(u32(0)); },               //
+                [&](const core::type::F32*) { return Get(f32(0)); },               //
+                [&](const core::type::F16*) { return Get(f16(0)); },               //
+                [&](const core::type::Bool*) { return Get(false); });
+        });
+}
+
 }  // namespace tint::core::constant
diff --git a/src/tint/lang/core/constant/manager.h b/src/tint/lang/core/constant/manager.h
index 3cc27be..dac8115 100644
--- a/src/tint/lang/core/constant/manager.h
+++ b/src/tint/lang/core/constant/manager.h
@@ -129,6 +129,11 @@
     /// @return a Scalar holding the AInt value @p value
     const Scalar<AInt>* Get(AInt value);
 
+    /// Constructs a constant zero-value of the type @p type.
+    /// @param type the constant type
+    /// @returns a constant zero-value for the type
+    const Value* Zero(const core::type::Type* type);
+
     /// The type manager
     core::type::Manager types;
 
diff --git a/src/tint/lang/core/ir/builder.cc b/src/tint/lang/core/ir/builder.cc
index 71419f9..07ffe5a 100644
--- a/src/tint/lang/core/ir/builder.cc
+++ b/src/tint/lang/core/ir/builder.cc
@@ -25,7 +25,8 @@
 
 Builder::Builder(Module& mod) : ir(mod) {}
 
-Builder::Builder(Module& mod, ir::Block* block) : current_block_(block), ir(mod) {}
+Builder::Builder(Module& mod, ir::Block* block)
+    : insertion_point_(InsertionPoints::AppendToBlock{block}), ir(mod) {}
 
 Builder::~Builder() = default;
 
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index ffa0347..90608d2 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -104,11 +104,56 @@
     using DisableIfVectorLike = tint::traits::EnableIf<
         !tint::IsVectorLike<tint::traits::Decay<tint::traits::NthTypeOf<0, TYPES..., void>>>>;
 
-    /// If set, any created instruction will be auto-appended to the block.
-    ir::Block* current_block_ = nullptr;
+    /// A namespace for the various instruction insertion method
+    struct InsertionPoints {
+        /// Insertion point method that does no insertion
+        struct NoInsertion {
+            /// The insertion point function
+            void operator()(ir::Instruction*) {}
+        };
+        /// Insertion point method that inserts the instruction to the end of #block
+        struct AppendToBlock {
+            /// The block to insert new instructions to the end of
+            ir::Block* block = nullptr;
+            /// The insertion point function
+            /// @param i the instruction to insert
+            void operator()(ir::Instruction* i) { block->Append(i); }
+        };
+        /// Insertion point method that inserts the instruction to the front of #block
+        struct PrependToBlock {
+            /// The block to insert new instructions to the front of
+            ir::Block* block = nullptr;
+            /// The insertion point function
+            /// @param i the instruction to insert
+            void operator()(ir::Instruction* i) { block->Prepend(i); }
+        };
+        /// Insertion point method that inserts the instruction after #after
+        struct InsertAfter {
+            /// The instruction to insert new instructions after
+            ir::Instruction* after = nullptr;
+            /// The insertion point function
+            /// @param i the instruction to insert
+            void operator()(ir::Instruction* i) { i->InsertAfter(after); }
+        };
+        /// Insertion point method that inserts the instruction before #before
+        struct InsertBefore {
+            /// The instruction to insert new instructions before
+            ir::Instruction* before = nullptr;
+            /// The insertion point function
+            /// @param i the instruction to insert
+            void operator()(ir::Instruction* i) { i->InsertBefore(before); }
+        };
+    };
 
-    /// If set, any created instruction will be auto-inserted before this instruction.
-    ir::Instruction* current_insertion_point_ = nullptr;
+    /// A variant of different instruction insertion methods
+    using InsertionPoint = std::variant<InsertionPoints::NoInsertion,
+                                        InsertionPoints::AppendToBlock,
+                                        InsertionPoints::PrependToBlock,
+                                        InsertionPoints::InsertAfter,
+                                        InsertionPoints::InsertBefore>;
+
+    /// The insertion method used for new instructions.
+    InsertionPoint insertion_point_{InsertionPoints::NoInsertion{}};
 
   public:
     /// Constructor
@@ -116,7 +161,7 @@
     explicit Builder(Module& mod);
     /// Constructor
     /// @param mod the ir::Module to wrap with this builder
-    /// @param block the block to insert too
+    /// @param block the block to append to
     Builder(Module& mod, ir::Block* block);
     /// Destructor
     ~Builder();
@@ -131,8 +176,25 @@
     /// @param cb the function to call with the builder appending to block @p b
     template <typename FUNCTION>
     void Append(ir::Block* b, FUNCTION&& cb) {
-        TINT_SCOPED_ASSIGNMENT(current_block_, b);
-        TINT_SCOPED_ASSIGNMENT(current_insertion_point_, nullptr);
+        TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::AppendToBlock{b});
+        cb();
+    }
+
+    /// Calls @p cb with the builder prepending to block @p b
+    /// @param b the block to set as the block to prepend to
+    /// @param cb the function to call with the builder prepending to block @p b
+    template <typename FUNCTION>
+    void Prepend(ir::Block* b, FUNCTION&& cb) {
+        TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::PrependToBlock{b});
+        cb();
+    }
+
+    /// Calls @p cb with the builder inserting after @p ip
+    /// @param ip the insertion point for new instructions
+    /// @param cb the function to call with the builder inserting new instructions after @p ip
+    template <typename FUNCTION>
+    void InsertAfter(ir::Instruction* ip, FUNCTION&& cb) {
+        TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::InsertAfter{ip});
         cb();
     }
 
@@ -141,23 +203,18 @@
     /// @param cb the function to call with the builder inserting new instructions before @p ip
     template <typename FUNCTION>
     void InsertBefore(ir::Instruction* ip, FUNCTION&& cb) {
-        TINT_SCOPED_ASSIGNMENT(current_block_, nullptr);
-        TINT_SCOPED_ASSIGNMENT(current_insertion_point_, ip);
+        TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::InsertBefore{ip});
         cb();
     }
 
-    /// Appends and returns the instruction @p val to the current insertion point. If there is no
-    /// current insertion point set, then @p val is just returned.
-    /// @param val the instruction to append
+    /// Adds and returns the instruction @p instruction to the current insertion point. If there
+    /// is no current insertion point set, then @p instruction is just returned.
+    /// @param instruction the instruction to append
     /// @returns the instruction
     template <typename T>
-    T* Append(T* val) {
-        if (current_insertion_point_) {
-            val->InsertBefore(current_insertion_point_);
-        } else if (current_block_) {
-            current_block_->Append(val);
-        }
-        return val;
+    T* Append(T* instruction) {
+        std::visit([instruction](auto&& mode) { mode(instruction); }, insertion_point_);
+        return instruction;
     }
 
     /// @returns a new block
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembler.cc
index 66ce989..079fe43 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembler.cc
@@ -449,9 +449,9 @@
         [&](Store* s) {
             EmitInstructionName(s);
             out_ << " ";
-            EmitValue(s->To());
+            EmitOperand(s, Store::kToOperandOffset);
             out_ << ", ";
-            EmitValue(s->From());
+            EmitOperand(s, Store::kFromOperandOffset);
         },
         [&](StoreVectorElement* s) {
             EmitInstructionName(s);
@@ -462,7 +462,7 @@
             EmitValueWithType(uc);
             out_ << " = ";
             EmitInstructionName(uc);
-            out_ << " %" << IdOf(uc->Func());
+            out_ << " %" << IdOf(uc->Target());
             if (!uc->Args().IsEmpty()) {
                 out_ << ", ";
             }
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
index 4ef9c26..5526360 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
@@ -249,7 +249,8 @@
     b.RootBlock()->Append(private_var);
 
     auto* func = b.Function("foo", ty.void_());
-    func->Block()->Append(b.Store(buffer, private_var));
+    auto* load = func->Block()->Append(b.Load(private_var));
+    func->Block()->Append(b.Store(buffer, load));
     func->Block()->Append(b.Return(func));
 
     auto* expect = R"(
@@ -269,8 +270,9 @@
 
 %foo = func():void -> %b2 {
   %b2 = block {
-    %4:ptr<storage, MyStruct, read_write> = access %1, 0u
-    store %4, %2
+    %4:MyStruct = load %2
+    %5:ptr<storage, MyStruct, read_write> = access %1, 0u
+    store %5, %4
     ret
   }
 }
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper.cc b/src/tint/lang/core/ir/transform/demote_to_helper.cc
index e96acd6..0226e99 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper.cc
@@ -102,7 +102,7 @@
                 },
                 [&](UserCall* call) {
                     // Check if we are calling a function that contains a discard.
-                    discard = HasDiscard(call->Func());
+                    discard = HasDiscard(call->Target());
                 },
                 [&](ControlInstruction* ctrl) {
                     // Recurse into control instructions and check their blocks.
@@ -165,7 +165,7 @@
                 },
                 [&](UserCall* call) {
                     // Recurse into user functions.
-                    ProcessFunction(call->Func());
+                    ProcessFunction(call->Target());
                 },
                 [&](Store* store) {
                     // Conditionalize stores to host-visible address spaces.
diff --git a/src/tint/lang/core/ir/user_call.h b/src/tint/lang/core/ir/user_call.h
index 58a381f..f6155ab 100644
--- a/src/tint/lang/core/ir/user_call.h
+++ b/src/tint/lang/core/ir/user_call.h
@@ -42,8 +42,12 @@
     /// @returns the call arguments
     tint::Slice<Value*> Args() override { return operands_.Slice().Offset(kArgsOperandOffset); }
 
-    /// @returns the called function name
-    Function* Func() { return operands_[kFunctionOperandOffset]->As<ir::Function>(); }
+    /// @returns the called function
+    Function* Target() { return operands_[kFunctionOperandOffset]->As<ir::Function>(); }
+
+    /// Sets called function
+    /// @param target the new target of the call
+    void SetTarget(Function* target) { operands_[kFunctionOperandOffset] = target; }
 
     /// @returns the friendly name for the instruction
     std::string FriendlyName() override { return "call"; }
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index c2ffd81..e7cc0f2 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -246,6 +246,10 @@
     /// @param l the exit loop to validate
     void CheckExitLoop(ExitLoop* l);
 
+    /// Validates the given store
+    /// @param s the store to validate
+    void CheckStore(Store* s);
+
     /// Validates the given load vector element
     /// @param l the load vector element to validate
     void CheckLoadVectorElement(LoadVectorElement* l);
@@ -483,7 +487,7 @@
         [&](Load*) {},                                               //
         [&](LoadVectorElement* l) { CheckLoadVectorElement(l); },    //
         [&](Loop* l) { CheckLoop(l); },                              //
-        [&](Store*) {},                                              //
+        [&](Store* s) { CheckStore(s); },                            //
         [&](StoreVectorElement* s) { CheckStoreVectorElement(s); },  //
         [&](Switch* s) { CheckSwitch(s); },                          //
         [&](Swizzle*) {},                                            //
@@ -794,6 +798,19 @@
     }
 }
 
+void Validator::CheckStore(Store* s) {
+    CheckOperandsNotNull(s, Store::kToOperandOffset, Store::kFromOperandOffset);
+
+    if (auto* from = s->From()) {
+        if (auto* to = s->To()) {
+            if (from->Type() != to->Type()->UnwrapPtr()) {
+                AddError(s, Store::kFromOperandOffset,
+                         "value type does not match pointer element type");
+            }
+        }
+    }
+}
+
 void Validator::CheckLoadVectorElement(LoadVectorElement* l) {
     CheckOperandsNotNull(l,  //
                          LoadVectorElement::kFromOperandOffset,
@@ -855,6 +872,14 @@
 
 Result<SuccessType, std::string> ValidateAndDumpIfNeeded([[maybe_unused]] Module& ir,
                                                          [[maybe_unused]] const char* msg) {
+#if TINT_DUMP_IR_WHEN_VALIDATING
+    Disassembler disasm(ir);
+    std::cout << "=========================================================" << std::endl;
+    std::cout << "== IR dump before " << msg << ":" << std::endl;
+    std::cout << "=========================================================" << std::endl;
+    std::cout << disasm.Disassemble();
+#endif
+
 #ifndef NDEBUG
     auto result = Validate(ir);
     if (!result) {
@@ -865,14 +890,6 @@
     }
 #endif
 
-#if TINT_DUMP_IR_WHEN_VALIDATING
-    Disassembler disasm(ir);
-    std::cout << "=========================================================" << std::endl;
-    std::cout << "== IR dump before " << msg << ":" << std::endl;
-    std::cout << "=========================================================" << std::endl;
-    std::cout << disasm.Disassemble();
-#endif
-
     return Success;
 }
 
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 52aad79..777cd01 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -2735,6 +2735,94 @@
 )");
 }
 
+TEST_F(IR_ValidatorTest, Store_NullTo) {
+    auto* f = b.Function("my_func", ty.void_());
+
+    b.Append(f->Block(), [&] {
+        b.Append(mod.instructions.Create<ir::Store>(nullptr, b.Constant(42_i)));
+        b.Return(f);
+    });
+
+    auto res = ir::Validate(mod);
+    ASSERT_FALSE(res);
+    EXPECT_EQ(res.Failure().str(), R"(:3:11 error: store: operand is undefined
+    store undef, 42i
+          ^^^^^
+
+:2:3 note: In block
+  %b1 = block {
+  ^^^^^^^^^^^
+
+note: # Disassembly
+%my_func = func():void -> %b1 {
+  %b1 = block {
+    store undef, 42i
+    ret
+  }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Store_NullFrom) {
+    auto* f = b.Function("my_func", ty.void_());
+
+    b.Append(f->Block(), [&] {
+        auto* var = b.Var(ty.ptr<function, i32>());
+        b.Append(mod.instructions.Create<ir::Store>(var->Result(), nullptr));
+        b.Return(f);
+    });
+
+    auto res = ir::Validate(mod);
+    ASSERT_FALSE(res);
+    EXPECT_EQ(res.Failure().str(), R"(:4:15 error: store: operand is undefined
+    store %2, undef
+              ^^^^^
+
+:2:3 note: In block
+  %b1 = block {
+  ^^^^^^^^^^^
+
+note: # Disassembly
+%my_func = func():void -> %b1 {
+  %b1 = block {
+    %2:ptr<function, i32, read_write> = var
+    store %2, undef
+    ret
+  }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Store_TypeMismatch) {
+    auto* f = b.Function("my_func", ty.void_());
+
+    b.Append(f->Block(), [&] {
+        auto* var = b.Var(ty.ptr<function, i32>());
+        b.Append(mod.instructions.Create<ir::Store>(var->Result(), b.Constant(42_u)));
+        b.Return(f);
+    });
+
+    auto res = ir::Validate(mod);
+    ASSERT_FALSE(res);
+    EXPECT_EQ(res.Failure().str(), R"(:4:15 error: value type does not match pointer element type
+    store %2, 42u
+              ^^^
+
+:2:3 note: In block
+  %b1 = block {
+  ^^^^^^^^^^^
+
+note: # Disassembly
+%my_func = func():void -> %b1 {
+  %b1 = block {
+    %2:ptr<function, i32, read_write> = var
+    store %2, 42u
+    ret
+  }
+}
+)");
+}
+
 TEST_F(IR_ValidatorTest, LoadVectorElement_NullResult) {
     auto* f = b.Function("my_func", ty.void_());
 
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index 8dced2c..e2fd37e 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -762,6 +762,20 @@
             break;
         }
 
+        case core::Function::kSubgroupBroadcast: {
+            // The lane argument is ushort.
+            out << "simd_broadcast(";
+            if (!EmitExpression(out, expr->args[0])) {
+                return false;
+            }
+            out << ",ushort(";
+            if (!EmitExpression(out, expr->args[1])) {
+                return false;
+            }
+            out << "))";
+            return true;
+        }
+
         default:
             break;
     }
diff --git a/src/tint/lang/spirv/intrinsic/data/data.cc b/src/tint/lang/spirv/intrinsic/data/data.cc
index 1212faa..e7dcb6f 100644
--- a/src/tint/lang/spirv/intrinsic/data/data.cc
+++ b/src/tint/lang/spirv/intrinsic/data/data.cc
@@ -1219,23 +1219,27 @@
   /* [50] */ TypeMatcherIndex(7),
   /* [51] */ TypeMatcherIndex(9),
   /* [52] */ TypeMatcherIndex(3),
-  /* [53] */ TypeMatcherIndex(11),
-  /* [54] */ TypeMatcherIndex(7),
-  /* [55] */ TypeMatcherIndex(11),
+  /* [53] */ TypeMatcherIndex(9),
+  /* [54] */ TypeMatcherIndex(8),
+  /* [55] */ TypeMatcherIndex(10),
   /* [56] */ TypeMatcherIndex(8),
-  /* [57] */ TypeMatcherIndex(9),
-  /* [58] */ TypeMatcherIndex(0),
-  /* [59] */ TypeMatcherIndex(10),
-  /* [60] */ TypeMatcherIndex(0),
-  /* [61] */ TypeMatcherIndex(22),
+  /* [57] */ TypeMatcherIndex(11),
+  /* [58] */ TypeMatcherIndex(7),
+  /* [59] */ TypeMatcherIndex(11),
+  /* [60] */ TypeMatcherIndex(8),
+  /* [61] */ TypeMatcherIndex(9),
   /* [62] */ TypeMatcherIndex(0),
-  /* [63] */ TypeMatcherIndex(21),
-  /* [64] */ TypeMatcherIndex(4),
-  /* [65] */ TypeMatcherIndex(37),
-  /* [66] */ TypeMatcherIndex(38),
-  /* [67] */ TypeMatcherIndex(39),
-  /* [68] */ TypeMatcherIndex(40),
-  /* [69] */ TypeMatcherIndex(41),
+  /* [63] */ TypeMatcherIndex(10),
+  /* [64] */ TypeMatcherIndex(0),
+  /* [65] */ TypeMatcherIndex(22),
+  /* [66] */ TypeMatcherIndex(0),
+  /* [67] */ TypeMatcherIndex(21),
+  /* [68] */ TypeMatcherIndex(4),
+  /* [69] */ TypeMatcherIndex(37),
+  /* [70] */ TypeMatcherIndex(38),
+  /* [71] */ TypeMatcherIndex(39),
+  /* [72] */ TypeMatcherIndex(40),
+  /* [73] */ TypeMatcherIndex(41),
 };
 
 static_assert(TypeMatcherIndex::CanIndex(kTypeMatcherIndices),
@@ -1657,7 +1661,7 @@
   {
     /* [66] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(65),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(69),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
@@ -1777,7 +1781,7 @@
   {
     /* [86] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
   },
   {
@@ -1795,13 +1799,13 @@
   {
     /* [89] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(67),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(71),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
   },
   {
     /* [90] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(57),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(61),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
@@ -1813,13 +1817,13 @@
   {
     /* [92] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
   },
   {
     /* [93] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(59),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(63),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
@@ -1831,13 +1835,13 @@
   {
     /* [95] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(69),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(73),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
   },
   {
     /* [96] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(59),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(63),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
@@ -1849,7 +1853,7 @@
   {
     /* [98] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
@@ -1867,7 +1871,7 @@
   {
     /* [101] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(63),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(67),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(1),
   },
   {
@@ -1885,7 +1889,7 @@
   {
     /* [104] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(61),
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(65),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
   },
   {
@@ -1903,148 +1907,148 @@
   {
     /* [107] */
     /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(61),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
-  },
-  {
-    /* [108] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(61),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
-  },
-  {
-    /* [109] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(61),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
-  },
-  {
-    /* [110] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-  },
-  {
-    /* [111] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(61),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
-  },
-  {
-    /* [112] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(23),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(1),
-  },
-  {
-    /* [113] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
-    /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-  },
-  {
-    /* [114] */
-    /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(7),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [115] */
+    /* [108] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [116] */
+    /* [109] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [117] */
+    /* [110] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [118] */
+    /* [111] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(13),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [119] */
+    /* [112] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [120] */
+    /* [113] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(16),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [121] */
+    /* [114] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [122] */
+    /* [115] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(19),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [123] */
+    /* [116] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [124] */
+    /* [117] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(28),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [125] */
+    /* [118] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [126] */
+    /* [119] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(34),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [127] */
+    /* [120] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [128] */
+    /* [121] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(38),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [129] */
+    /* [122] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
-    /* [130] */
+    /* [123] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(40),
     /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
   },
   {
+    /* [124] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+  },
+  {
+    /* [125] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(65),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
+  },
+  {
+    /* [126] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(65),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
+  },
+  {
+    /* [127] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(65),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
+  },
+  {
+    /* [128] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+  },
+  {
+    /* [129] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(65),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(3),
+  },
+  {
+    /* [130] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* type_matcher_indices */ TypeMatcherIndicesIndex(23),
+    /* number_matcher_indices */ NumberMatcherIndicesIndex(1),
+  },
+  {
     /* [131] */
     /* usage */ core::ParameterUsage::kNone,
     /* type_matcher_indices */ TypeMatcherIndicesIndex(2),
@@ -2190,17 +2194,17 @@
   {
     /* [3] */
     /* name */ "F",
-    /* matcher_index */ NumberMatcherIndex(6),
+    /* matcher_index */ NumberMatcherIndex(/* invalid */),
   },
   {
     /* [4] */
     /* name */ "A",
-    /* matcher_index */ NumberMatcherIndex(9),
+    /* matcher_index */ NumberMatcherIndex(/* invalid */),
   },
   {
     /* [5] */
     /* name */ "F",
-    /* matcher_index */ NumberMatcherIndex(7),
+    /* matcher_index */ NumberMatcherIndex(6),
   },
   {
     /* [6] */
@@ -2210,7 +2214,7 @@
   {
     /* [7] */
     /* name */ "F",
-    /* matcher_index */ NumberMatcherIndex(8),
+    /* matcher_index */ NumberMatcherIndex(7),
   },
   {
     /* [8] */
@@ -2219,21 +2223,26 @@
   },
   {
     /* [9] */
+    /* name */ "F",
+    /* matcher_index */ NumberMatcherIndex(8),
+  },
+  {
+    /* [10] */
+    /* name */ "A",
+    /* matcher_index */ NumberMatcherIndex(9),
+  },
+  {
+    /* [11] */
     /* name */ "N",
     /* matcher_index */ NumberMatcherIndex(/* invalid */),
   },
   {
-    /* [10] */
+    /* [12] */
     /* name */ "M",
     /* matcher_index */ NumberMatcherIndex(/* invalid */),
   },
   {
-    /* [11] */
-    /* name */ "A",
-    /* matcher_index */ NumberMatcherIndex(/* invalid */),
-  },
-  {
-    /* [12] */
+    /* [13] */
     /* name */ "S",
     /* matcher_index */ NumberMatcherIndex(5),
   },
@@ -2246,6 +2255,214 @@
   {
     /* [0] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(38),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(54),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [1] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(42),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [2] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(46),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [3] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(50),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [4] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(113),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [5] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(115),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [6] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(0),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(54),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [7] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(58),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [8] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(62),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [9] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(121),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [10] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(123),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [11] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(66),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [12] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 2,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(3),
+    /* parameters */ ParameterIndex(86),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(54),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [13] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 2,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(3),
+    /* parameters */ ParameterIndex(89),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [14] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 2,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(3),
+    /* parameters */ ParameterIndex(92),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [15] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_template_types */ 0,
+    /* num_template_numbers */ 2,
+    /* template_types */ TemplateTypeIndex(/* invalid */),
+    /* template_numbers */ TemplateNumberIndex(3),
+    /* parameters */ ParameterIndex(95),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [16] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
     /* num_template_numbers */ 0,
@@ -2257,7 +2474,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [1] */
+    /* [17] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2270,7 +2487,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [2] */
+    /* [18] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 5,
     /* num_template_types */ 3,
@@ -2283,7 +2500,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [3] */
+    /* [19] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2296,7 +2513,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [4] */
+    /* [20] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 5,
     /* num_template_types */ 4,
@@ -2309,7 +2526,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [5] */
+    /* [21] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2322,7 +2539,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [6] */
+    /* [22] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2335,7 +2552,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [7] */
+    /* [23] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2348,7 +2565,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [8] */
+    /* [24] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2361,7 +2578,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [9] */
+    /* [25] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 5,
     /* num_template_types */ 3,
@@ -2374,7 +2591,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [10] */
+    /* [26] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2387,7 +2604,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [11] */
+    /* [27] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 5,
     /* num_template_types */ 3,
@@ -2400,7 +2617,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [12] */
+    /* [28] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2413,7 +2630,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [13] */
+    /* [29] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2426,20 +2643,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [14] */
-    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* num_parameters */ 3,
-    /* num_template_types */ 2,
-    /* num_template_numbers */ 2,
-    /* template_types */ TemplateTypeIndex(7),
-    /* template_numbers */ TemplateNumberIndex(3),
-    /* parameters */ ParameterIndex(86),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
-    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
-  },
-  {
-    /* [15] */
+    /* [30] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2447,12 +2651,12 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(5),
     /* parameters */ ParameterIndex(86),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [16] */
+    /* [31] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2460,25 +2664,25 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(7),
     /* parameters */ ParameterIndex(86),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(57),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [17] */
+    /* [32] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
     /* num_template_numbers */ 2,
     /* template_types */ TemplateTypeIndex(7),
-    /* template_numbers */ TemplateNumberIndex(3),
-    /* parameters */ ParameterIndex(89),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
+    /* template_numbers */ TemplateNumberIndex(9),
+    /* parameters */ ParameterIndex(86),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(59),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [18] */
+    /* [33] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2486,12 +2690,12 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(5),
     /* parameters */ ParameterIndex(89),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [19] */
+    /* [34] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2499,25 +2703,25 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(7),
     /* parameters */ ParameterIndex(89),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(57),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [20] */
+    /* [35] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
     /* num_template_numbers */ 2,
     /* template_types */ TemplateTypeIndex(7),
-    /* template_numbers */ TemplateNumberIndex(3),
-    /* parameters */ ParameterIndex(92),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
+    /* template_numbers */ TemplateNumberIndex(9),
+    /* parameters */ ParameterIndex(89),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(59),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [21] */
+    /* [36] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2525,12 +2729,12 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(5),
     /* parameters */ ParameterIndex(92),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [22] */
+    /* [37] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2538,25 +2742,25 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(7),
     /* parameters */ ParameterIndex(92),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(57),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [23] */
+    /* [38] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
     /* num_template_numbers */ 2,
     /* template_types */ TemplateTypeIndex(7),
-    /* template_numbers */ TemplateNumberIndex(3),
-    /* parameters */ ParameterIndex(95),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
+    /* template_numbers */ TemplateNumberIndex(9),
+    /* parameters */ ParameterIndex(92),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(59),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [24] */
+    /* [39] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2564,12 +2768,12 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(5),
     /* parameters */ ParameterIndex(95),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(25),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [25] */
+    /* [40] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
@@ -2577,12 +2781,155 @@
     /* template_types */ TemplateTypeIndex(7),
     /* template_numbers */ TemplateNumberIndex(7),
     /* parameters */ ParameterIndex(95),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(57),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [41] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 3,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 2,
+    /* template_types */ TemplateTypeIndex(7),
+    /* template_numbers */ TemplateNumberIndex(9),
+    /* parameters */ ParameterIndex(95),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(59),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [42] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(4),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(38),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(54),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [43] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(4),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(107),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [44] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(4),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(109),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [26] */
+    /* [45] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(4),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(111),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [46] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(4),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(113),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [47] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 2,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(4),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(115),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [48] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(5),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(117),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [49] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(5),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(119),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [50] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(5),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(121),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [51] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_template_types */ 1,
+    /* num_template_numbers */ 0,
+    /* template_types */ TemplateTypeIndex(5),
+    /* template_numbers */ TemplateNumberIndex(/* invalid */),
+    /* parameters */ ParameterIndex(123),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(55),
+    /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [52] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 2,
@@ -2595,124 +2942,124 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [27] */
+    /* [53] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 2,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(17),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(114),
+    /* parameters */ ParameterIndex(107),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [28] */
+    /* [54] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 2,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(17),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(116),
+    /* parameters */ ParameterIndex(109),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [29] */
+    /* [55] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 2,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(17),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(118),
+    /* parameters */ ParameterIndex(111),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [30] */
+    /* [56] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 2,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(17),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(120),
+    /* parameters */ ParameterIndex(113),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(15),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [31] */
+    /* [57] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 2,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(17),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(122),
+    /* parameters */ ParameterIndex(115),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(18),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [32] */
+    /* [58] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(18),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(124),
+    /* parameters */ ParameterIndex(117),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(27),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [33] */
+    /* [59] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(18),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(126),
+    /* parameters */ ParameterIndex(119),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [34] */
+    /* [60] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(18),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(128),
+    /* parameters */ ParameterIndex(121),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(37),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [35] */
+    /* [61] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 0,
     /* template_types */ TemplateTypeIndex(18),
     /* template_numbers */ TemplateNumberIndex(/* invalid */),
-    /* parameters */ ParameterIndex(130),
+    /* parameters */ ParameterIndex(123),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(39),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [36] */
+    /* [62] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 4,
@@ -2725,7 +3072,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [37] */
+    /* [63] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 4,
@@ -2738,7 +3085,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [38] */
+    /* [64] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 4,
@@ -2751,7 +3098,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [39] */
+    /* [65] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 4,
@@ -2764,7 +3111,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [40] */
+    /* [66] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 4,
@@ -2777,7 +3124,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [41] */
+    /* [67] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2790,7 +3137,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [42] */
+    /* [68] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2803,7 +3150,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [43] */
+    /* [69] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 3,
@@ -2816,7 +3163,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [44] */
+    /* [70] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2829,7 +3176,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [45] */
+    /* [71] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 5,
     /* num_template_types */ 3,
@@ -2842,7 +3189,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [46] */
+    /* [72] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2855,7 +3202,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [47] */
+    /* [73] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 5,
     /* num_template_types */ 3,
@@ -2868,7 +3215,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [48] */
+    /* [74] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2881,7 +3228,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [49] */
+    /* [75] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
@@ -2894,7 +3241,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [50] */
+    /* [76] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 1,
@@ -2907,157 +3254,157 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [51] */
+    /* [77] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 1,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(21),
-    /* template_numbers */ TemplateNumberIndex(9),
+    /* template_numbers */ TemplateNumberIndex(11),
     /* parameters */ ParameterIndex(101),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(23),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [52] */
+    /* [78] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(19),
-    /* template_numbers */ TemplateNumberIndex(11),
+    /* template_numbers */ TemplateNumberIndex(4),
     /* parameters */ ParameterIndex(105),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(56),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(54),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [53] */
+    /* [79] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(15),
-    /* template_numbers */ TemplateNumberIndex(12),
+    /* template_numbers */ TemplateNumberIndex(13),
     /* parameters */ ParameterIndex(26),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [54] */
+    /* [80] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 6,
     /* num_template_types */ 2,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(15),
-    /* template_numbers */ TemplateNumberIndex(12),
+    /* template_numbers */ TemplateNumberIndex(13),
     /* parameters */ ParameterIndex(0),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [55] */
+    /* [81] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_template_types */ 2,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(15),
-    /* template_numbers */ TemplateNumberIndex(12),
+    /* template_numbers */ TemplateNumberIndex(13),
     /* parameters */ ParameterIndex(0),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [56] */
+    /* [82] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 4,
     /* num_template_types */ 2,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(15),
-    /* template_numbers */ TemplateNumberIndex(12),
+    /* template_numbers */ TemplateNumberIndex(13),
     /* parameters */ ParameterIndex(26),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(/* invalid */),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [57] */
+    /* [83] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(20),
-    /* template_numbers */ TemplateNumberIndex(9),
+    /* template_numbers */ TemplateNumberIndex(11),
     /* parameters */ ParameterIndex(102),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [58] */
+    /* [84] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 3,
     /* template_types */ TemplateTypeIndex(20),
     /* template_numbers */ TemplateNumberIndex(0),
-    /* parameters */ ParameterIndex(107),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(61),
+    /* parameters */ ParameterIndex(125),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(65),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [59] */
+    /* [85] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 2,
     /* template_types */ TemplateTypeIndex(20),
-    /* template_numbers */ TemplateNumberIndex(9),
-    /* parameters */ ParameterIndex(109),
-    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(61),
+    /* template_numbers */ TemplateNumberIndex(11),
+    /* parameters */ ParameterIndex(127),
+    /* return_type_matcher_indices */ TypeMatcherIndicesIndex(65),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(3),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [60] */
+    /* [86] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 2,
     /* template_types */ TemplateTypeIndex(20),
-    /* template_numbers */ TemplateNumberIndex(9),
-    /* parameters */ ParameterIndex(111),
+    /* template_numbers */ TemplateNumberIndex(11),
+    /* parameters */ ParameterIndex(129),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(23),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [61] */
+    /* [87] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 2,
     /* template_types */ TemplateTypeIndex(20),
-    /* template_numbers */ TemplateNumberIndex(9),
+    /* template_numbers */ TemplateNumberIndex(11),
     /* parameters */ ParameterIndex(103),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(23),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [62] */
+    /* [88] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_template_types */ 1,
     /* num_template_numbers */ 1,
     /* template_types */ TemplateTypeIndex(20),
-    /* template_numbers */ TemplateNumberIndex(9),
-    /* parameters */ ParameterIndex(112),
+    /* template_numbers */ TemplateNumberIndex(11),
+    /* parameters */ ParameterIndex(130),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(23),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -3072,91 +3419,91 @@
     /* [0] */
     /* fn array_length<I : u32, A : access>(ptr<storage, struct_with_runtime_array, A>, I) -> u32 */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(52),
+    /* overloads */ OverloadIndex(78),
   },
   {
     /* [1] */
     /* fn atomic_and<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [2] */
     /* fn atomic_compare_exchange<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, U, T, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(54),
+    /* overloads */ OverloadIndex(80),
   },
   {
     /* [3] */
     /* fn atomic_exchange<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [4] */
     /* fn atomic_iadd<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [5] */
     /* fn atomic_isub<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [6] */
     /* fn atomic_load<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(55),
+    /* overloads */ OverloadIndex(81),
   },
   {
     /* [7] */
     /* fn atomic_or<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [8] */
     /* fn atomic_smax<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [9] */
     /* fn atomic_smin<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [10] */
     /* fn atomic_store<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(56),
+    /* overloads */ OverloadIndex(82),
   },
   {
     /* [11] */
     /* fn atomic_umax<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [12] */
     /* fn atomic_umin<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [13] */
     /* fn atomic_xor<T : iu32, U : u32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, U, U, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(53),
+    /* overloads */ OverloadIndex(79),
   },
   {
     /* [14] */
     /* fn dot<N : num, T : f32_f16>(vec<N, T>, vec<N, T>) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(57),
+    /* overloads */ OverloadIndex(83),
   },
   {
     /* [15] */
@@ -3167,7 +3514,7 @@
     /* fn image_dref_gather<A : f32, B : iu32>(sampled_image<texture_depth_cube>, vec3<f32>, A, B) -> vec4<f32> */
     /* fn image_dref_gather<A : f32, B : iu32>(sampled_image<texture_depth_cube_array>, vec4<f32>, A, B) -> vec4<f32> */
     /* num overloads */ 6,
-    /* overloads */ OverloadIndex(44),
+    /* overloads */ OverloadIndex(70),
   },
   {
     /* [16] */
@@ -3180,7 +3527,7 @@
     /* fn image_fetch<I : iu32, C : iu32, S : iu32>(texture_depth_2d_array, vec3<C>, I, S) -> vec4<f32> */
     /* fn image_fetch<I : iu32, C : iu32, S : iu32>(texture_depth_multisampled_2d, vec2<C>, I, S) -> vec4<f32> */
     /* num overloads */ 8,
-    /* overloads */ OverloadIndex(36),
+    /* overloads */ OverloadIndex(62),
   },
   {
     /* [17] */
@@ -3199,10 +3546,46 @@
     /* fn image_gather<A : iu32, B : iu32>(sampled_image<texture_depth_cube>, vec3<f32>, A, B) -> vec4<f32> */
     /* fn image_gather<A : iu32, B : iu32>(sampled_image<texture_depth_cube_array>, vec4<f32>, A, B) -> vec4<f32> */
     /* num overloads */ 14,
-    /* overloads */ OverloadIndex(0),
+    /* overloads */ OverloadIndex(16),
   },
   {
     /* [18] */
+    /* fn image_query_size<T : fiu32>(texture_1d<T>) -> u32 */
+    /* fn image_query_size<T : fiu32>(texture_2d<T>) -> vec2<u32> */
+    /* fn image_query_size<T : fiu32>(texture_2d_array<T>) -> vec3<u32> */
+    /* fn image_query_size<T : fiu32>(texture_3d<T>) -> vec3<u32> */
+    /* fn image_query_size<T : fiu32>(texture_cube<T>) -> vec2<u32> */
+    /* fn image_query_size<T : fiu32>(texture_cube_array<T>) -> vec3<u32> */
+    /* fn image_query_size<T : fiu32>(texture_multisampled_2d<T>) -> vec2<u32> */
+    /* fn image_query_size(texture_depth_2d) -> vec2<u32> */
+    /* fn image_query_size(texture_depth_2d_array) -> vec3<u32> */
+    /* fn image_query_size(texture_depth_cube) -> vec2<u32> */
+    /* fn image_query_size(texture_depth_cube_array) -> vec3<u32> */
+    /* fn image_query_size(texture_depth_multisampled_2d) -> vec2<u32> */
+    /* fn image_query_size<F : texel_format, A : access>(texture_storage_1d<F, A>) -> u32 */
+    /* fn image_query_size<F : texel_format, A : access>(texture_storage_2d<F, A>) -> vec2<u32> */
+    /* fn image_query_size<F : texel_format, A : access>(texture_storage_2d_array<F, A>) -> vec3<u32> */
+    /* fn image_query_size<F : texel_format, A : access>(texture_storage_3d<F, A>) -> vec3<u32> */
+    /* num overloads */ 16,
+    /* overloads */ OverloadIndex(0),
+  },
+  {
+    /* [19] */
+    /* fn image_query_size_lod<T : fiu32, A : iu32>(texture_1d<T>, A) -> u32 */
+    /* fn image_query_size_lod<T : fiu32, A : iu32>(texture_2d<T>, A) -> vec2<u32> */
+    /* fn image_query_size_lod<T : fiu32, A : iu32>(texture_2d_array<T>, A) -> vec3<u32> */
+    /* fn image_query_size_lod<T : fiu32, A : iu32>(texture_3d<T>, A) -> vec3<u32> */
+    /* fn image_query_size_lod<T : fiu32, A : iu32>(texture_cube<T>, A) -> vec2<u32> */
+    /* fn image_query_size_lod<T : fiu32, A : iu32>(texture_cube_array<T>, A) -> vec3<u32> */
+    /* fn image_query_size_lod<A : iu32>(texture_depth_2d, A) -> vec2<u32> */
+    /* fn image_query_size_lod<A : iu32>(texture_depth_2d_array, A) -> vec3<u32> */
+    /* fn image_query_size_lod<A : iu32>(texture_depth_cube, A) -> vec2<u32> */
+    /* fn image_query_size_lod<A : iu32>(texture_depth_cube_array, A) -> vec3<u32> */
+    /* num overloads */ 10,
+    /* overloads */ OverloadIndex(42),
+  },
+  {
+    /* [20] */
     /* fn image_read<F : f32_texel_format, A : readable, C : iu32, S : iu32>(texture_storage_1d<F, A>, C, S) -> vec4<f32> */
     /* fn image_read<F : i32_texel_format, A : readable, C : iu32, S : iu32>(texture_storage_1d<F, A>, C, S) -> vec4<i32> */
     /* fn image_read<F : u32_texel_format, A : readable, C : iu32, S : iu32>(texture_storage_1d<F, A>, C, S) -> vec4<u32> */
@@ -3216,28 +3599,28 @@
     /* fn image_read<F : i32_texel_format, A : readable, C : iu32, S : iu32>(texture_storage_3d<F, A>, vec3<C>, S) -> vec4<i32> */
     /* fn image_read<F : u32_texel_format, A : readable, C : iu32, S : iu32>(texture_storage_3d<F, A>, vec3<C>, S) -> vec4<u32> */
     /* num overloads */ 12,
-    /* overloads */ OverloadIndex(14),
-  },
-  {
-    /* [19] */
-    /* fn matrix_times_matrix<T : f32_f16, K : num, C : num, R : num>(mat<K, R, T>, mat<C, K, T>) -> mat<C, R, T> */
-    /* num overloads */ 1,
-    /* overloads */ OverloadIndex(58),
-  },
-  {
-    /* [20] */
-    /* fn matrix_times_scalar<T : f32_f16, N : num, M : num>(mat<N, M, T>, T) -> mat<N, M, T> */
-    /* num overloads */ 1,
-    /* overloads */ OverloadIndex(59),
+    /* overloads */ OverloadIndex(30),
   },
   {
     /* [21] */
-    /* fn matrix_times_vector<T : f32_f16, N : num, M : num>(mat<N, M, T>, vec<N, T>) -> vec<M, T> */
+    /* fn matrix_times_matrix<T : f32_f16, K : num, C : num, R : num>(mat<K, R, T>, mat<C, K, T>) -> mat<C, R, T> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(60),
+    /* overloads */ OverloadIndex(84),
   },
   {
     /* [22] */
+    /* fn matrix_times_scalar<T : f32_f16, N : num, M : num>(mat<N, M, T>, T) -> mat<N, M, T> */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(85),
+  },
+  {
+    /* [23] */
+    /* fn matrix_times_vector<T : f32_f16, N : num, M : num>(mat<N, M, T>, vec<N, T>) -> vec<M, T> */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(86),
+  },
+  {
+    /* [24] */
     /* fn sampled_image<T : fiu32, S : samplers>(texture_1d<T>, S) -> sampled_image<texture_1d<T>> */
     /* fn sampled_image<T : fiu32, S : samplers>(texture_2d<T>, S) -> sampled_image<texture_2d<T>> */
     /* fn sampled_image<T : fiu32, S : samplers>(texture_2d_array<T>, S) -> sampled_image<texture_2d_array<T>> */
@@ -3249,26 +3632,26 @@
     /* fn sampled_image<S : samplers>(texture_depth_cube, S) -> sampled_image<texture_depth_cube> */
     /* fn sampled_image<S : samplers>(texture_depth_cube_array, S) -> sampled_image<texture_depth_cube_array> */
     /* num overloads */ 10,
-    /* overloads */ OverloadIndex(26),
-  },
-  {
-    /* [23] */
-    /* fn select<T : scalar>(bool, T, T) -> T */
-    /* fn select<N : num, T : scalar>(vec<N, bool>, vec<N, T>, vec<N, T>) -> vec<N, T> */
-    /* num overloads */ 2,
-    /* overloads */ OverloadIndex(50),
-  },
-  {
-    /* [24] */
-    /* fn vector_times_matrix<T : f32_f16, N : num, M : num>(vec<N, T>, mat<M, N, T>) -> vec<M, T> */
-    /* num overloads */ 1,
-    /* overloads */ OverloadIndex(61),
+    /* overloads */ OverloadIndex(52),
   },
   {
     /* [25] */
+    /* fn select<T : scalar>(bool, T, T) -> T */
+    /* fn select<N : num, T : scalar>(vec<N, bool>, vec<N, T>, vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ OverloadIndex(76),
+  },
+  {
+    /* [26] */
+    /* fn vector_times_matrix<T : f32_f16, N : num, M : num>(vec<N, T>, mat<M, N, T>) -> vec<M, T> */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(87),
+  },
+  {
+    /* [27] */
     /* fn vector_times_scalar<T : f32_f16, N : num>(vec<N, T>, T) -> vec<N, T> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(62),
+    /* overloads */ OverloadIndex(88),
   },
 };
 
diff --git a/src/tint/lang/spirv/intrinsic/data/type_matchers.h b/src/tint/lang/spirv/intrinsic/data/type_matchers.h
index 56f57fd..9840ab8 100644
--- a/src/tint/lang/spirv/intrinsic/data/type_matchers.h
+++ b/src/tint/lang/spirv/intrinsic/data/type_matchers.h
@@ -17,6 +17,7 @@
 
 #include "src/tint/lang/core/intrinsic/table.h"
 #include "src/tint/lang/core/type/array.h"
+#include "src/tint/lang/core/type/manager.h"
 #include "src/tint/lang/core/type/struct.h"
 #include "src/tint/lang/spirv/type/sampled_image.h"
 
diff --git a/src/tint/lang/spirv/ir/function.cc b/src/tint/lang/spirv/ir/function.cc
index b535f1e..bb86b6c 100644
--- a/src/tint/lang/spirv/ir/function.cc
+++ b/src/tint/lang/spirv/ir/function.cc
@@ -65,6 +65,10 @@
             return "spirv.image_fetch";
         case Function::kImageGather:
             return "spirv.image_gather";
+        case Function::kImageQuerySize:
+            return "spirv.image_query_size";
+        case Function::kImageQuerySizeLod:
+            return "spirv.image_query_size_lod";
         case Function::kImageRead:
             return "spirv.image_read";
         case Function::kMatrixTimesMatrix:
diff --git a/src/tint/lang/spirv/ir/function.h b/src/tint/lang/spirv/ir/function.h
index eb63425..caeb705 100644
--- a/src/tint/lang/spirv/ir/function.h
+++ b/src/tint/lang/spirv/ir/function.h
@@ -52,6 +52,8 @@
     kImageDrefGather,
     kImageFetch,
     kImageGather,
+    kImageQuerySize,
+    kImageQuerySizeLod,
     kImageRead,
     kMatrixTimesMatrix,
     kMatrixTimesScalar,
diff --git a/src/tint/lang/spirv/ir/intrinsic.cc b/src/tint/lang/spirv/ir/intrinsic.cc
index 542ee90..3146175 100644
--- a/src/tint/lang/spirv/ir/intrinsic.cc
+++ b/src/tint/lang/spirv/ir/intrinsic.cc
@@ -29,12 +29,6 @@
 /// @param str the string to parse
 /// @returns the parsed enum, or Intrinsic::kUndefined if the string could not be parsed.
 Intrinsic ParseIntrinsic(std::string_view str) {
-    if (str == "image_query_size") {
-        return Intrinsic::kImageQuerySize;
-    }
-    if (str == "image_query_size_lod") {
-        return Intrinsic::kImageQuerySizeLod;
-    }
     if (str == "image_sample_dref_explicit_lod") {
         return Intrinsic::kImageSampleDrefExplicitLod;
     }
@@ -57,10 +51,6 @@
     switch (value) {
         case Intrinsic::kUndefined:
             return "undefined";
-        case Intrinsic::kImageQuerySize:
-            return "image_query_size";
-        case Intrinsic::kImageQuerySizeLod:
-            return "image_query_size_lod";
         case Intrinsic::kImageSampleDrefExplicitLod:
             return "image_sample_dref_explicit_lod";
         case Intrinsic::kImageSampleDrefImplicitLod:
diff --git a/src/tint/lang/spirv/ir/intrinsic.h b/src/tint/lang/spirv/ir/intrinsic.h
index a90e848..0404fba 100644
--- a/src/tint/lang/spirv/ir/intrinsic.h
+++ b/src/tint/lang/spirv/ir/intrinsic.h
@@ -34,8 +34,6 @@
 /// Intrinsic
 enum class Intrinsic : uint8_t {
     kUndefined,
-    kImageQuerySize,
-    kImageQuerySizeLod,
     kImageSampleDrefExplicitLod,
     kImageSampleDrefImplicitLod,
     kImageSampleExplicitLod,
@@ -61,8 +59,6 @@
 Intrinsic ParseIntrinsic(std::string_view str);
 
 constexpr const char* kIntrinsicStrings[] = {
-    "image_query_size",
-    "image_query_size_lod",
     "image_sample_dref_explicit_lod",
     "image_sample_dref_implicit_lod",
     "image_sample_explicit_lod",
diff --git a/src/tint/lang/spirv/reader/ast_lower/atomics.cc b/src/tint/lang/spirv/reader/ast_lower/atomics.cc
index 0d3b3fc..bd2aee4 100644
--- a/src/tint/lang/spirv/reader/ast_lower/atomics.cc
+++ b/src/tint/lang/spirv/reader/ast_lower/atomics.cc
@@ -28,6 +28,7 @@
 #include "src/tint/lang/wgsl/sem/block_statement.h"
 #include "src/tint/lang/wgsl/sem/function.h"
 #include "src/tint/lang/wgsl/sem/index_accessor_expression.h"
+#include "src/tint/lang/wgsl/sem/load.h"
 #include "src/tint/lang/wgsl/sem/member_accessor_expression.h"
 #include "src/tint/lang/wgsl/sem/statement.h"
 #include "src/tint/utils/containers/map.h"
@@ -247,48 +248,27 @@
             return false;
         };
 
-        // Look for loads and stores via assignments and decls of atomic variables we've collected
-        // so far, and replace them with atomicLoad and atomicStore.
-        for (auto* atomic_var : atomic_variables) {
-            for (auto* vu : atomic_var->Users()) {
-                Switch(
-                    vu->Stmt()->Declaration(),
-                    [&](const ast::AssignmentStatement* assign) {
-                        auto* sem_lhs = ctx.src->Sem().GetVal(assign->lhs);
-                        if (is_ref_to_atomic_var(sem_lhs)) {
-                            ctx.Replace(assign, [=] {
-                                auto* lhs = ctx.CloneWithoutTransform(assign->lhs);
-                                auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
-                                auto* call = b.Call(core::str(core::Function::kAtomicStore),
-                                                    b.AddressOf(lhs), rhs);
-                                return b.CallStmt(call);
-                            });
-                            return;
-                        }
-
-                        auto sem_rhs = ctx.src->Sem().GetVal(assign->rhs);
-                        if (is_ref_to_atomic_var(sem_rhs->UnwrapLoad())) {
-                            ctx.Replace(assign->rhs, [=] {
-                                auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
-                                return b.Call(core::str(core::Function::kAtomicLoad),
-                                              b.AddressOf(rhs));
-                            });
-                            return;
-                        }
-                    },
-                    [&](const ast::VariableDeclStatement* decl) {
-                        auto* var = decl->variable;
-                        if (auto* sem_init = ctx.src->Sem().GetVal(var->initializer)) {
-                            if (is_ref_to_atomic_var(sem_init->UnwrapLoad())) {
-                                ctx.Replace(var->initializer, [=] {
-                                    auto* rhs = ctx.CloneWithoutTransform(var->initializer);
-                                    return b.Call(core::str(core::Function::kAtomicLoad),
-                                                  b.AddressOf(rhs));
-                                });
-                                return;
-                            }
-                        }
+        // Look for loads and stores of atomic variables we've collected so far, and replace them
+        // with atomicLoad and atomicStore.
+        for (auto* node : ctx.src->ASTNodes().Objects()) {
+            if (auto* load = ctx.src->Sem().Get<sem::Load>(node)) {
+                if (is_ref_to_atomic_var(load->Reference())) {
+                    ctx.Replace(load->Reference()->Declaration(), [=] {
+                        auto* expr = ctx.CloneWithoutTransform(load->Reference()->Declaration());
+                        return b.Call(core::str(core::Function::kAtomicLoad), b.AddressOf(expr));
                     });
+                }
+            } else if (auto* assign = node->As<ast::AssignmentStatement>()) {
+                auto* sem_lhs = ctx.src->Sem().GetVal(assign->lhs);
+                if (is_ref_to_atomic_var(sem_lhs)) {
+                    ctx.Replace(assign, [=] {
+                        auto* lhs = ctx.CloneWithoutTransform(assign->lhs);
+                        auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
+                        auto* call =
+                            b.Call(core::str(core::Function::kAtomicStore), b.AddressOf(lhs), rhs);
+                        return b.CallStmt(call);
+                    });
+                }
             }
         }
     }
diff --git a/src/tint/lang/spirv/reader/ast_lower/atomics_test.cc b/src/tint/lang/spirv/reader/ast_lower/atomics_test.cc
index 9bef265..8898c52 100644
--- a/src/tint/lang/spirv/reader/ast_lower/atomics_test.cc
+++ b/src/tint/lang/spirv/reader/ast_lower/atomics_test.cc
@@ -1376,5 +1376,76 @@
 
     EXPECT_EQ(expect, str(got));
 }
+
+TEST_F(AtomicsTest, ReplaceBitcastArgument_Scaler) {
+    auto* src = R"(
+var<workgroup> wg : u32;
+
+fn f() {
+  stub_atomicAdd_u32(wg, 1u);
+
+  wg = 0u;
+  var b : f32;
+  b = bitcast<f32>(wg);
+}
+)";
+
+    auto* expect = R"(
+var<workgroup> wg : atomic<u32>;
+
+fn f() {
+  atomicAdd(&(wg), 1u);
+  atomicStore(&(wg), 0u);
+  var b : f32;
+  b = bitcast<f32>(atomicLoad(&(wg)));
+}
+)";
+
+    auto got = Run(src);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(AtomicsTest, ReplaceBitcastArgument_Struct) {
+    auto* src = R"(
+struct S {
+  a : u32,
+}
+
+var<workgroup> wg : S;
+
+fn f() {
+  stub_atomicAdd_u32(wg.a, 1u);
+
+  wg.a = 0u;
+  var b : f32;
+  b = bitcast<f32>(wg.a);
+}
+)";
+
+    auto* expect = R"(
+struct S_atomic {
+  a : atomic<u32>,
+}
+
+struct S {
+  a : u32,
+}
+
+var<workgroup> wg : S_atomic;
+
+fn f() {
+  atomicAdd(&(wg.a), 1u);
+  atomicStore(&(wg.a), 0u);
+  var b : f32;
+  b = bitcast<f32>(atomicLoad(&(wg.a)));
+}
+)";
+
+    auto got = Run(src);
+
+    EXPECT_EQ(expect, str(got));
+}
+
 }  // namespace
 }  // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/spirv.def b/src/tint/lang/spirv/spirv.def
index 5b858ae..814352c 100644
--- a/src/tint/lang/spirv/spirv.def
+++ b/src/tint/lang/spirv/spirv.def
@@ -144,8 +144,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 enum intrinsic {
-  image_query_size
-  image_query_size_lod
   image_sample_implicit_lod
   image_sample_explicit_lod
   image_sample_dref_implicit_lod
@@ -205,6 +203,34 @@
 fn image_gather<A: iu32, B: iu32>(sampled_image<texture_depth_cube>, vec3<f32>, A, B) -> vec4<f32>
 fn image_gather<A: iu32, B: iu32>(sampled_image<texture_depth_cube_array>, vec4<f32>, A, B) -> vec4<f32>
 
+fn image_query_size<T: fiu32>(texture_1d<T>) -> u32
+fn image_query_size<T: fiu32>(texture_2d<T>) -> vec2<u32>
+fn image_query_size<T: fiu32>(texture_2d_array<T>) -> vec3<u32>
+fn image_query_size<T: fiu32>(texture_3d<T>) -> vec3<u32>
+fn image_query_size<T: fiu32>(texture_cube<T>) -> vec2<u32>
+fn image_query_size<T: fiu32>(texture_cube_array<T>) -> vec3<u32>
+fn image_query_size<T: fiu32>(texture_multisampled_2d<T>) -> vec2<u32>
+fn image_query_size(texture_depth_2d) -> vec2<u32>
+fn image_query_size(texture_depth_2d_array) -> vec3<u32>
+fn image_query_size(texture_depth_cube) -> vec2<u32>
+fn image_query_size(texture_depth_cube_array) -> vec3<u32>
+fn image_query_size(texture_depth_multisampled_2d) -> vec2<u32>
+fn image_query_size<F: texel_format, A: access>(texture_storage_1d<F, A>) -> u32
+fn image_query_size<F: texel_format, A: access>(texture_storage_2d<F, A>) -> vec2<u32>
+fn image_query_size<F: texel_format, A: access>(texture_storage_2d_array<F, A>) -> vec3<u32>
+fn image_query_size<F: texel_format, A: access>(texture_storage_3d<F, A>) -> vec3<u32>
+
+fn image_query_size_lod<T: fiu32, A: iu32>(texture_1d<T>, A) -> u32
+fn image_query_size_lod<T: fiu32, A: iu32>(texture_2d<T>, A) -> vec2<u32>
+fn image_query_size_lod<T: fiu32, A: iu32>(texture_2d_array<T>, A) -> vec3<u32>
+fn image_query_size_lod<T: fiu32, A: iu32>(texture_3d<T>, A) -> vec3<u32>
+fn image_query_size_lod<T: fiu32, A: iu32>(texture_cube<T>, A) -> vec2<u32>
+fn image_query_size_lod<T: fiu32, A: iu32>(texture_cube_array<T>, A) -> vec3<u32>
+fn image_query_size_lod<A: iu32>(texture_depth_2d, A) -> vec2<u32>
+fn image_query_size_lod<A: iu32>(texture_depth_2d_array, A) -> vec3<u32>
+fn image_query_size_lod<A: iu32>(texture_depth_cube, A) -> vec2<u32>
+fn image_query_size_lod<A: iu32>(texture_depth_cube_array, A) -> vec3<u32>
+
 fn image_read<F: f32_texel_format, A: readable, C: iu32, S: iu32>(texture_storage_1d<F, A>, C, S) -> vec4<f32>
 fn image_read<F: i32_texel_format, A: readable, C: iu32, S: iu32>(texture_storage_1d<F, A>, C, S) -> vec4<i32>
 fn image_read<F: u32_texel_format, A: readable, C: iu32, S: iu32>(texture_storage_1d<F, A>, C, S) -> vec4<u32>
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index 137c705..d5b2d92 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -1090,6 +1090,14 @@
         case spirv::ir::Function::kImageGather:
             op = spv::Op::OpImageGather;
             break;
+        case spirv::ir::Function::kImageQuerySize:
+            module_.PushCapability(SpvCapabilityImageQuery);
+            op = spv::Op::OpImageQuerySize;
+            break;
+        case spirv::ir::Function::kImageQuerySizeLod:
+            module_.PushCapability(SpvCapabilityImageQuery);
+            op = spv::Op::OpImageQuerySizeLod;
+            break;
         case spirv::ir::Function::kImageRead:
             op = spv::Op::OpImageRead;
             break;
@@ -1583,14 +1591,6 @@
 
     spv::Op op = spv::Op::Max;
     switch (call->Kind()) {
-        case spirv::ir::Intrinsic::kImageQuerySize:
-            module_.PushCapability(SpvCapabilityImageQuery);
-            op = spv::Op::OpImageQuerySize;
-            break;
-        case spirv::ir::Intrinsic::kImageQuerySizeLod:
-            module_.PushCapability(SpvCapabilityImageQuery);
-            op = spv::Op::OpImageQuerySizeLod;
-            break;
         case spirv::ir::Intrinsic::kImageSampleImplicitLod:
             op = spv::Op::OpImageSampleImplicitLod;
             break;
@@ -1777,7 +1777,7 @@
 
 void Printer::EmitUserCall(core::ir::UserCall* call) {
     auto id = Value(call);
-    OperandList operands = {Type(call->Result()->Type()), id, Value(call->Func())};
+    OperandList operands = {Type(call->Result()->Type()), id, Value(call->Target())};
     for (auto* arg : call->Args()) {
         operands.push_back(Value(arg));
     }
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
index 9e60294..5b06c9d 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
@@ -751,22 +751,22 @@
         auto* texture = next_arg();
         auto* texture_ty = texture->Type()->As<core::type::Texture>();
 
-        Vector<core::ir::Value*, 8> intrinsic_args;
-        intrinsic_args.Push(texture);
+        Vector<core::ir::Value*, 8> function_args;
+        function_args.Push(texture);
 
-        // Determine which SPIR-V intrinsic to use, and add the Lod argument if needed.
-        enum spirv::ir::Intrinsic intrinsic;
+        // Determine which SPIR-V function to use, and add the Lod argument if needed.
+        enum spirv::ir::Function function;
         if (texture_ty
                 ->IsAnyOf<core::type::MultisampledTexture, core::type::DepthMultisampledTexture,
                           core::type::StorageTexture>()) {
-            intrinsic = spirv::ir::Intrinsic::kImageQuerySize;
+            function = spirv::ir::Function::kImageQuerySize;
         } else {
-            intrinsic = spirv::ir::Intrinsic::kImageQuerySizeLod;
+            function = spirv::ir::Function::kImageQuerySizeLod;
             if (auto* lod = next_arg()) {
-                intrinsic_args.Push(lod);
+                function_args.Push(lod);
             } else {
                 // Lod wasn't explicit, so assume 0.
-                intrinsic_args.Push(b.Constant(0_u));
+                function_args.Push(b.Constant(0_u));
             }
         }
 
@@ -777,9 +777,9 @@
             result_ty = ty.vec(vec->type(), vec->Width() + 1);
         }
 
-        // Call the intrinsic.
+        // Call the function.
         auto* texture_call =
-            b.Call<spirv::ir::IntrinsicCall>(result_ty, intrinsic, std::move(intrinsic_args));
+            b.Call<spirv::ir::BuiltinCall>(result_ty, function, std::move(function_args));
         texture_call->InsertBefore(builtin);
 
         auto* result = texture_call->Result();
@@ -801,23 +801,23 @@
         auto* texture = builtin->Args()[0];
         auto* texture_ty = texture->Type()->As<core::type::Texture>();
 
-        Vector<core::ir::Value*, 2> intrinsic_args;
-        intrinsic_args.Push(texture);
+        Vector<core::ir::Value*, 2> function_args;
+        function_args.Push(texture);
 
-        // Determine which SPIR-V intrinsic to use, and add the Lod argument if needed.
-        enum spirv::ir::Intrinsic intrinsic;
+        // Determine which SPIR-V function to use, and add the Lod argument if needed.
+        enum spirv::ir::Function function;
         if (texture_ty
                 ->IsAnyOf<core::type::MultisampledTexture, core::type::DepthMultisampledTexture,
                           core::type::StorageTexture>()) {
-            intrinsic = spirv::ir::Intrinsic::kImageQuerySize;
+            function = spirv::ir::Function::kImageQuerySize;
         } else {
-            intrinsic = spirv::ir::Intrinsic::kImageQuerySizeLod;
-            intrinsic_args.Push(b.Constant(0_u));
+            function = spirv::ir::Function::kImageQuerySizeLod;
+            function_args.Push(b.Constant(0_u));
         }
 
-        // Call the intrinsic.
+        // Call the function.
         auto* texture_call =
-            b.Call<spirv::ir::IntrinsicCall>(ty.vec3<u32>(), intrinsic, std::move(intrinsic_args));
+            b.Call<spirv::ir::BuiltinCall>(ty.vec3<u32>(), function, std::move(function_args));
         texture_call->InsertBefore(builtin);
 
         // Extract the third component to get the number of array layers.
diff --git a/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc b/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc
index 28db994..9cdc734 100644
--- a/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc
+++ b/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc
@@ -43,6 +43,8 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
+namespace tint::ast::transform {
+
 namespace {
 
 /// AccessRoot describes the root of an AccessShape.
@@ -56,6 +58,9 @@
     tint::sem::Variable const* variable = nullptr;
     /// The address space of the variable or pointer type.
     tint::core::AddressSpace address_space = tint::core::AddressSpace::kUndefined;
+
+    /// @return a hash code for this object
+    size_t HashCode() const { return Hash(type, variable); }
 };
 
 /// Inequality operator for AccessRoot
@@ -68,6 +73,9 @@
 struct DynamicIndex {
     /// The index of the expression in DirectVariableAccess::State::AccessChain::dynamic_indices
     size_t slot = 0;
+
+    /// @return a hash code for this object
+    size_t HashCode() const { return Hash(slot); }
 };
 
 /// Inequality operator for DynamicIndex
@@ -140,6 +148,9 @@
         }
         return count;
     }
+
+    /// @return a hash code for this object
+    size_t HashCode() const { return Hash(root, ops); }
 };
 
 /// Equality operator for AccessShape
@@ -156,46 +167,13 @@
 struct AccessChain : AccessShape {
     /// The array accessor index expressions. This vector is indexed by the `DynamicIndex`s in
     /// #indices.
-    tint::Vector<const tint::sem::ValueExpression*, 8> dynamic_indices;
+    Vector<const sem::ValueExpression*, 8> dynamic_indices;
     /// If true, then this access chain is used as an argument to call a variant.
     bool used_in_call = false;
 };
 
 }  // namespace
 
-namespace tint {
-
-/// Hasher specialization for AccessRoot
-template <>
-struct Hasher<AccessRoot> {
-    /// The hash function for the AccessRoot
-    /// @param d the AccessRoot to hash
-    /// @return the hash for the given AccessRoot
-    size_t operator()(const AccessRoot& d) const { return Hash(d.type, d.variable); }
-};
-
-/// Hasher specialization for DynamicIndex
-template <>
-struct Hasher<DynamicIndex> {
-    /// The hash function for the DynamicIndex
-    /// @param d the DynamicIndex to hash
-    /// @return the hash for the given DynamicIndex
-    size_t operator()(const DynamicIndex& d) const { return Hash(d.slot); }
-};
-
-/// Hasher specialization for AccessShape
-template <>
-struct Hasher<AccessShape> {
-    /// The hash function for the AccessShape
-    /// @param s the AccessShape to hash
-    /// @return the hash for the given AccessShape
-    size_t operator()(const AccessShape& s) const { return Hash(s.root, s.ops); }
-};
-
-}  // namespace tint
-
-namespace tint::ast::transform {
-
 /// The PIMPL state for the DirectVariableAccess transform
 struct DirectVariableAccess::State {
     /// Constructor
diff --git a/src/tint/lang/wgsl/ast/transform/remove_phonies.cc b/src/tint/lang/wgsl/ast/transform/remove_phonies.cc
index e50b3b6..4a6a392 100644
--- a/src/tint/lang/wgsl/ast/transform/remove_phonies.cc
+++ b/src/tint/lang/wgsl/ast/transform/remove_phonies.cc
@@ -49,7 +49,7 @@
 
     auto& sem = src->Sem();
 
-    Hashmap<SinkSignature, Symbol, 8, Hasher<SinkSignature>> sinks;
+    Hashmap<SinkSignature, Symbol, 8> sinks;
 
     bool made_changes = false;
     for (auto* node : src->ASTNodes().Objects()) {
diff --git a/src/tint/lang/wgsl/ast/transform/std140.cc b/src/tint/lang/wgsl/ast/transform/std140.cc
index 3d41108..fd3193c 100644
--- a/src/tint/lang/wgsl/ast/transform/std140.cc
+++ b/src/tint/lang/wgsl/ast/transform/std140.cc
@@ -38,10 +38,14 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
+namespace tint::ast::transform {
 namespace {
 
 /// UniformVariable is used by Std140::State::AccessIndex to indicate the root uniform variable
-struct UniformVariable {};
+struct UniformVariable {
+    /// @returns a hash code for this object
+    size_t HashCode() const { return 0; }
+};
 
 /// Inequality operator for UniformVariable
 bool operator!=(const UniformVariable&, const UniformVariable&) {
@@ -51,6 +55,9 @@
 /// DynamicIndex is used by Std140::State::AccessIndex to indicate a runtime-expression index
 struct DynamicIndex {
     size_t slot;  // The index of the expression in Std140::State::AccessChain::dynamic_indices
+
+    /// @returns a hash code for this object
+    size_t HashCode() const { return Hash(slot); }
 };
 
 /// Inequality operator for DynamicIndex
@@ -60,29 +67,6 @@
 
 }  // namespace
 
-namespace tint {
-
-/// Hasher specialization for UniformVariable
-template <>
-struct Hasher<UniformVariable> {
-    /// The hash function for the UniformVariable
-    /// @return the hash for the given UniformVariable
-    size_t operator()(const UniformVariable&) const { return 0; }
-};
-
-/// Hasher specialization for DynamicIndex
-template <>
-struct Hasher<DynamicIndex> {
-    /// The hash function for the DynamicIndex
-    /// @param d the DynamicIndex to hash
-    /// @return the hash for the given DynamicIndex
-    size_t operator()(const DynamicIndex& d) const { return Hash(d.slot); }
-};
-
-}  // namespace tint
-
-namespace tint::ast::transform {
-
 /// PIMPL state for the transform
 struct Std140::State {
     /// Constructor
diff --git a/src/tint/lang/wgsl/resolver/validator.h b/src/tint/lang/wgsl/resolver/validator.h
index 8e80916..38bb8f1 100644
--- a/src/tint/lang/wgsl/resolver/validator.h
+++ b/src/tint/lang/wgsl/resolver/validator.h
@@ -82,6 +82,9 @@
     bool operator==(const TypeAndAddressSpace& other) const {
         return type == other.type && address_space == other.address_space;
     }
+
+    /// @returns the hash value of this object
+    std::size_t HashCode() const { return Hash(type, address_space); }
 };
 
 /// DiagnosticFilterStack is a scoped stack of diagnostic filters.
@@ -573,19 +576,4 @@
 
 }  // namespace tint::resolver
 
-namespace std {
-
-/// Custom std::hash specialization for tint::resolver::TypeAndAddressSpace.
-template <>
-class hash<tint::resolver::TypeAndAddressSpace> {
-  public:
-    /// @param tas the TypeAndAddressSpace
-    /// @return the hash value
-    inline std::size_t operator()(const tint::resolver::TypeAndAddressSpace& tas) const {
-        return Hash(tas.type, tas.address_space);
-    }
-};
-
-}  // namespace std
-
 #endif  // SRC_TINT_LANG_WGSL_RESOLVER_VALIDATOR_H_
diff --git a/src/tint/lang/wgsl/sem/builtin.h b/src/tint/lang/wgsl/sem/builtin.h
index 1d0ce97..838288a 100644
--- a/src/tint/lang/wgsl/sem/builtin.h
+++ b/src/tint/lang/wgsl/sem/builtin.h
@@ -104,6 +104,11 @@
     /// wgsl::Extension::kNone if no extension is required.
     wgsl::Extension RequiredExtension() const;
 
+    /// @return the hash code for this object
+    std::size_t HashCode() const {
+        return Hash(Type(), SupportedStages(), ReturnType(), Parameters(), IsDeprecated());
+    }
+
   private:
     const core::Function type_;
     const PipelineStageSet supported_stages_;
@@ -118,20 +123,4 @@
 
 }  // namespace tint::sem
 
-namespace std {
-
-/// Custom std::hash specialization for tint::sem::Builtin
-template <>
-class hash<tint::sem::Builtin> {
-  public:
-    /// @param i the Builtin to create a hash for
-    /// @return the hash value
-    inline std::size_t operator()(const tint::sem::Builtin& i) const {
-        return Hash(i.Type(), i.SupportedStages(), i.ReturnType(), i.Parameters(),
-                    i.IsDeprecated());
-    }
-};
-
-}  // namespace std
-
 #endif  // SRC_TINT_LANG_WGSL_SEM_BUILTIN_H_
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 169ca8b..726eb6d 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -571,7 +571,7 @@
         tint::Switch(
             call,  //
             [&](core::ir::UserCall* c) {
-                auto* expr = b.Call(NameFor(c->Func()), std::move(args));
+                auto* expr = b.Call(NameFor(c->Target()), std::move(args));
                 if (!call->HasResults() || call->Result()->Usages().IsEmpty()) {
                     Append(b.CallStmt(expr));
                     return;
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index a479310..d4d758b 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -2386,7 +2386,7 @@
 
             b.Append(loop->Initializer(), [&] {
                 auto* load_i = b.Load(i);
-                auto* inc_i = b.Add(ty.i32(), load_i, 1_u);
+                auto* inc_i = b.Add(ty.u32(), load_i, 1_u);
                 b.Store(i, inc_i);
                 b.NextIteration(loop);
             });
diff --git a/src/tint/utils/containers/enum_set.h b/src/tint/utils/containers/enum_set.h
index 488a230..5f1c33d 100644
--- a/src/tint/utils/containers/enum_set.h
+++ b/src/tint/utils/containers/enum_set.h
@@ -134,6 +134,9 @@
     /// @return true if the set is empty
     inline bool Empty() const { return set == 0; }
 
+    /// @return the hash value of this object
+    inline size_t HashCode() const { return std::hash<uint64_t>()(Value()); }
+
     /// Equality operator
     /// @param rhs the other EnumSet to compare this to
     /// @return true if this EnumSet is equal to @p rhs
@@ -243,19 +246,4 @@
 
 }  // namespace tint
 
-namespace std {
-
-/// Custom std::hash specialization for tint::EnumSet<T>
-template <typename T>
-class hash<tint::EnumSet<T>> {
-  public:
-    /// @param e the EnumSet to create a hash for
-    /// @return the hash value
-    inline std::size_t operator()(const tint::EnumSet<T>& e) const {
-        return std::hash<uint64_t>()(e.Value());
-    }
-};
-
-}  // namespace std
-
 #endif  // SRC_TINT_UTILS_CONTAINERS_ENUM_SET_H_
diff --git a/src/tint/utils/containers/enum_set_test.cc b/src/tint/utils/containers/enum_set_test.cc
index dbeb54c..c27e499 100644
--- a/src/tint/utils/containers/enum_set_test.cc
+++ b/src/tint/utils/containers/enum_set_test.cc
@@ -202,9 +202,8 @@
     EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::C);
 }
 
-TEST(EnumSetTest, Hash) {
-    auto hash = [&](EnumSet<E> s) { return std::hash<EnumSet<E>>()(s); };
-    EXPECT_EQ(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::B)));
+TEST(EnumSetTest, HashCode) {
+    EXPECT_EQ(EnumSet<E>(E::A, E::B).HashCode(), EnumSet<E>(E::A, E::B).HashCode());
 }
 
 TEST(EnumSetTest, Value) {
diff --git a/src/tint/utils/containers/hashmap.h b/src/tint/utils/containers/hashmap.h
index d3c7b96..3fcfc01 100644
--- a/src/tint/utils/containers/hashmap.h
+++ b/src/tint/utils/containers/hashmap.h
@@ -279,7 +279,7 @@
         for (auto it : map) {
             // Use an XOR to ensure that the non-deterministic ordering of the map still produces
             // the same hash value for the same entries.
-            hash ^= Hash(it.key) * 31 + Hash(it.value);
+            hash ^= Hash(it.key, it.value);
         }
         return hash;
     }
diff --git a/src/tint/utils/containers/vector.h b/src/tint/utils/containers/vector.h
index e2e4f67..d2f2c69 100644
--- a/src/tint/utils/containers/vector.h
+++ b/src/tint/utils/containers/vector.h
@@ -441,6 +441,15 @@
     /// @returns the end for a reverse iterator
     auto rend() const { return impl_.slice.rend(); }
 
+    /// @returns a hash code for this Vector
+    size_t HashCode() const {
+        auto hash = Hash(Length());
+        for (auto& el : *this) {
+            hash = HashCombine(hash, el);
+        }
+        return hash;
+    }
+
     /// Equality operator
     /// @param other the other vector
     /// @returns true if this vector is the same length as `other`, and all elements are equal.
@@ -775,6 +784,15 @@
     /// @returns the end for a reverse iterator
     auto rend() const { return slice_.rend(); }
 
+    /// @returns a hash code of the Vector
+    size_t HashCode() const {
+        auto hash = Hash(Length());
+        for (auto& el : *this) {
+            hash = HashCombine(hash, el);
+        }
+        return hash;
+    }
+
   private:
     /// Friend class
     template <typename, size_t>
@@ -860,34 +878,6 @@
     return o;
 }
 
-/// Hasher specialization for Vector
-template <typename T, size_t N>
-struct Hasher<Vector<T, N>> {
-    /// @param vector the Vector to hash
-    /// @returns a hash of the Vector
-    size_t operator()(const Vector<T, N>& vector) const {
-        auto hash = Hash(vector.Length());
-        for (auto& el : vector) {
-            hash = HashCombine(hash, el);
-        }
-        return hash;
-    }
-};
-
-/// Hasher specialization for VectorRef
-template <typename T>
-struct Hasher<VectorRef<T>> {
-    /// @param vector the VectorRef reference to hash
-    /// @returns a hash of the Vector
-    size_t operator()(const VectorRef<T>& vector) const {
-        auto hash = Hash(vector.Length());
-        for (auto& el : vector) {
-            hash = HashCombine(hash, el);
-        }
-        return hash;
-    }
-};
-
 namespace detail {
 
 /// IsVectorLike<T>::value is true if T is a Vector or VectorRef.
diff --git a/src/tint/utils/math/hash.h b/src/tint/utils/math/hash.h
index 2fe6fee..38d9c92 100644
--- a/src/tint/utils/math/hash.h
+++ b/src/tint/utils/math/hash.h
@@ -60,6 +60,15 @@
     }
 };
 
+template <typename T, typename = void>
+struct HasHashCodeMember : std::false_type {};
+
+template <typename T>
+struct HasHashCodeMember<
+    T,
+    std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::HashCode)>>> : std::true_type {
+};
+
 }  // namespace detail
 
 /// Forward declarations (see below)
@@ -72,11 +81,20 @@
 /// A STL-compatible hasher that does a more thorough job than most implementations of std::hash.
 /// Hasher has been optimized for a better quality hash at the expense of increased computation
 /// costs.
+/// Hasher is specialized for various core Tint data types. The default implementation will use a
+/// `size_t HashCode()` method on the `T` type, and will fallback to `std::hash<T>` if
+/// `T::HashCode` is missing.
 template <typename T>
 struct Hasher {
     /// @param value the value to hash
     /// @returns a hash of the value
-    size_t operator()(const T& value) const { return std::hash<T>()(value); }
+    size_t operator()(const T& value) const {
+        if constexpr (detail::HasHashCodeMember<T>::value) {
+            return value.HashCode();
+        } else {
+            return std::hash<T>()(value);
+        }
+    }
 };
 
 /// Hasher specialization for pointers