Import Tint changes from Dawn

Changes:
  - 109e648f2f452424d2d1d0b1eba1e1b9fe036645 Support const expression with dot4{I|U}8Packed by Jiawei Shao <jiawei.shao@intel.com>
  - 0f64392b2721f3fe759ad0fe1dc5d6a9fe289653 Tint/MSL: Fix translation of dot4{I|U}8Packed by Jiawei Shao <jiawei.shao@intel.com>
  - 4a66dd3f407d2ad25ef20ba7b870bd90a91bde9c [spirv-reader] Add --use-ir-reader option to exe by James Price <jrprice@google.com>
  - cbd7bc52f397f316d5251861203bdc1f6ad0bb65 [tint][ir] Serialize If instructions by Ben Clayton <bclayton@google.com>
  - 65d0b6d452fb90f0d7617f96fabf000bc10cbf5d [tint][ir] Serialize Atomics by Ben Clayton <bclayton@google.com>
  - abd95badaa3a4112f6e2964f550497fd3e4af643 [tint][ir] Serialize Convert instructions by Ben Clayton <bclayton@google.com>
  - fb728a34f167b35190041b1c21c3bba02a4c1707 [wgsl-writer] Add ProgramOptions for IR->AST by James Price <jrprice@google.com>
  - 2735fb1962246442021a3bb1e525d982daa2744a [spirv-reader] Add entry point for IR parser by James Price <jrprice@google.com>
  - cdcbe83771d83d5145ab81d471d0ae47b4637a9d [tint][ir] Serialize CoreBuiltinCall instruction by Ben Clayton <bclayton@google.com>
  - c027f09d4948116b9974f518ffc9ec4b6b176b43 [tint][ir] Serialize struct types by Ben Clayton <bclayton@google.com>
  - e6d2d2a94d619d83797472d1a1e7cad0cc86e240 [tools] Add --vebose flag to tint_remote_compile by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 109e648f2f452424d2d1d0b1eba1e1b9fe036645
Change-Id: I7e844f58113784a4dd34c12442c13bc10d548b76
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/165320
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/api/BUILD.bazel b/src/tint/api/BUILD.bazel
index 22d06eb..32a7773 100644
--- a/src/tint/api/BUILD.bazel
+++ b/src/tint/api/BUILD.bazel
@@ -59,6 +59,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/api/BUILD.cmake b/src/tint/api/BUILD.cmake
index dea891a..af664e6 100644
--- a/src/tint/api/BUILD.cmake
+++ b/src/tint/api/BUILD.cmake
@@ -61,6 +61,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/api/BUILD.gn b/src/tint/api/BUILD.gn
index 4c3586f..ff3f483 100644
--- a/src/tint/api/BUILD.gn
+++ b/src/tint/api/BUILD.gn
@@ -58,6 +58,7 @@
     "${tint_src_dir}/lang/wgsl/features",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
     "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/bench/BUILD.bazel b/src/tint/cmd/bench/BUILD.bazel
index df4a15f..48b45c3 100644
--- a/src/tint/cmd/bench/BUILD.bazel
+++ b/src/tint/cmd/bench/BUILD.bazel
@@ -56,6 +56,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/cmd/bench/BUILD.cmake b/src/tint/cmd/bench/BUILD.cmake
index 0af9aa2..9df1c7a 100644
--- a/src/tint/cmd/bench/BUILD.cmake
+++ b/src/tint/cmd/bench/BUILD.cmake
@@ -132,6 +132,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/cmd/bench/BUILD.gn b/src/tint/cmd/bench/BUILD.gn
index 5143ce9..8697f0c 100644
--- a/src/tint/cmd/bench/BUILD.gn
+++ b/src/tint/cmd/bench/BUILD.gn
@@ -61,6 +61,7 @@
       "${tint_src_dir}/lang/wgsl/features",
       "${tint_src_dir}/lang/wgsl/program",
       "${tint_src_dir}/lang/wgsl/sem",
+      "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
       "${tint_src_dir}/utils/containers",
       "${tint_src_dir}/utils/diagnostic",
       "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/common/BUILD.bazel b/src/tint/cmd/common/BUILD.bazel
index acade5c..c768f73 100644
--- a/src/tint/cmd/common/BUILD.bazel
+++ b/src/tint/cmd/common/BUILD.bazel
@@ -61,6 +61,7 @@
     "//src/tint/lang/wgsl/inspector",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/cmd/common/BUILD.cmake b/src/tint/cmd/common/BUILD.cmake
index b795733..43d472f 100644
--- a/src/tint/cmd/common/BUILD.cmake
+++ b/src/tint/cmd/common/BUILD.cmake
@@ -60,6 +60,7 @@
   tint_lang_wgsl_inspector
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/cmd/common/BUILD.gn b/src/tint/cmd/common/BUILD.gn
index 99229d6..4b1f5e3 100644
--- a/src/tint/cmd/common/BUILD.gn
+++ b/src/tint/cmd/common/BUILD.gn
@@ -64,6 +64,7 @@
     "${tint_src_dir}/lang/wgsl/inspector",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
     "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/common/helper.cc b/src/tint/cmd/common/helper.cc
index 4570f41..4e2bc38 100644
--- a/src/tint/cmd/common/helper.cc
+++ b/src/tint/cmd/common/helper.cc
@@ -37,6 +37,7 @@
 #endif
 
 #if TINT_BUILD_WGSL_WRITER
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
 #include "src/tint/lang/wgsl/writer/writer.h"
 #endif
 
@@ -109,6 +110,38 @@
     }
 }
 
+#if TINT_BUILD_SPV_READER
+tint::Program ReadSpirv(const std::vector<uint32_t>& data, const LoadProgramOptions& opts) {
+    if (opts.use_ir) {
+#if TINT_BUILD_WGSL_WRITER
+        // Parse the SPIR-V binary to a core Tint IR module.
+        auto result = tint::spirv::reader::ReadIR(data);
+        if (!result) {
+            std::cerr << "Failed to parse SPIR-V: " << result.Failure() << "\n";
+            exit(1);
+        }
+
+        // Convert the IR module to a WGSL AST program.
+        tint::wgsl::writer::ProgramOptions options;
+        options.allow_non_uniform_derivatives =
+            opts.spirv_reader_options.allow_non_uniform_derivatives;
+        options.allowed_features = opts.spirv_reader_options.allowed_features;
+        auto ast = tint::wgsl::writer::IRToProgram(result.Get(), options);
+        if (!ast.IsValid() || ast.Diagnostics().contains_errors()) {
+            std::cerr << "Failed to convert IR to AST:\n\n" << ast.Diagnostics() << "\n";
+            exit(1);
+        }
+        return ast;
+#else
+        std::cerr << "Tint not built with the WGSL writer enabled" << std::endl;
+        exit(1);
+#endif  // TINT_BUILD_WGSL_READER
+    } else {
+        return tint::spirv::reader::Read(data, opts.spirv_reader_options);
+    }
+}
+#endif  // TINT_BUILD_SPV_READER
+
 }  // namespace
 
 [[noreturn]] void TintInternalCompilerErrorReporter(const InternalCompilerError& err) {
@@ -180,7 +213,7 @@
                 }
 
                 return ProgramInfo{
-                    /* program */ tint::spirv::reader::Read(data, opts.spirv_reader_options),
+                    /* program */ ReadSpirv(data, opts),
                     /* source_file */ nullptr,
                 };
 #else
@@ -211,7 +244,7 @@
                     opts.filename, std::string(text.begin(), text.end()));
 
                 return ProgramInfo{
-                    /* program */ tint::spirv::reader::Read(data, opts.spirv_reader_options),
+                    /* program */ ReadSpirv(data, opts),
                     /* source_file */ std::move(file),
                 };
 #else
diff --git a/src/tint/cmd/common/helper.h b/src/tint/cmd/common/helper.h
index c711346..04e6961 100644
--- a/src/tint/cmd/common/helper.h
+++ b/src/tint/cmd/common/helper.h
@@ -79,6 +79,7 @@
     std::string filename;
 #if TINT_BUILD_SPV_READER
     /// Spirv-reader options
+    bool use_ir = false;
     tint::spirv::reader::Options spirv_reader_options;
 #endif
 };
diff --git a/src/tint/cmd/loopy/BUILD.bazel b/src/tint/cmd/loopy/BUILD.bazel
index 7d42293..e0b4ebe 100644
--- a/src/tint/cmd/loopy/BUILD.bazel
+++ b/src/tint/cmd/loopy/BUILD.bazel
@@ -60,6 +60,7 @@
     "//src/tint/lang/wgsl/inspector",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/cmd/loopy/BUILD.cmake b/src/tint/cmd/loopy/BUILD.cmake
index f72d122..abf2e07 100644
--- a/src/tint/cmd/loopy/BUILD.cmake
+++ b/src/tint/cmd/loopy/BUILD.cmake
@@ -61,6 +61,7 @@
   tint_lang_wgsl_inspector
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/cmd/loopy/BUILD.gn b/src/tint/cmd/loopy/BUILD.gn
index 4879c29..3241429 100644
--- a/src/tint/cmd/loopy/BUILD.gn
+++ b/src/tint/cmd/loopy/BUILD.gn
@@ -60,6 +60,7 @@
     "${tint_src_dir}/lang/wgsl/inspector",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
     "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/remote_compile/main.cc b/src/tint/cmd/remote_compile/main.cc
index 60a0464..726f986 100644
--- a/src/tint/cmd/remote_compile/main.cc
+++ b/src/tint/cmd/remote_compile/main.cc
@@ -45,12 +45,6 @@
 
 namespace {
 
-#if 0
-#define DEBUG(msg, ...) printf(msg "\n", ##__VA_ARGS__)
-#else
-#define DEBUG(...)
-#endif
-
 /// The return structure of a compile function
 struct CompileResult {
     /// True if shader compiled
@@ -280,7 +274,7 @@
             m.Serialize([&s](auto& value) { s >> value; });
         } else {
             std::stringstream ss;
-            ss << "expected message type " << static_cast<int>(m.type) << ", got "
+            ss << "Expected message type " << static_cast<int>(m.type) << ", got "
                << static_cast<int>(ty);
             s.error = ss.str();
         }
@@ -305,15 +299,17 @@
 
 }  // namespace
 
-bool RunServer(std::string port);
+bool RunServer(std::string port, bool verbose);
 bool RunClient(std::string address,
                std::string port,
                std::string file,
                int version_major,
-               int version_minor);
+               int version_minor,
+               bool verbose);
 
 int main(int argc, char* argv[]) {
     bool run_server = false;
+    bool verbose = false;
     int version_major = 0;
     int version_minor = 0;
     std::string port = "19000";
@@ -337,6 +333,10 @@
             }
             continue;
         }
+        if (arg == "-v" || arg == "--verbose") {
+            verbose = true;
+            continue;
+        }
 
         // xcrun flags are ignored so this executable can be used as a replacement for xcrun.
         if ((arg == "-x" || arg == "-sdk") && (i < argc - 1)) {
@@ -366,7 +366,7 @@
     bool success = false;
 
     if (run_server) {
-        success = RunServer(port);
+        success = RunServer(port, verbose);
     } else {
         std::string address;
         std::string file;
@@ -384,13 +384,13 @@
                 file = args[1];
                 break;
             default:
-                std::cerr << "expected 1 or 2 arguments, got " << args.size() << "\n\n";
+                std::cerr << "Expected 1 or 2 arguments, got " << args.size() << "\n\n";
                 ShowUsage();
         }
         if (address.empty() || file.empty()) {
             ShowUsage();
         }
-        success = RunClient(address, port, file, version_major, version_minor);
+        success = RunClient(address, port, file, version_major, version_minor, verbose);
     }
 
     if (!success) {
@@ -400,7 +400,7 @@
     return 0;
 }
 
-bool RunServer(std::string port) {
+bool RunServer(std::string port, bool verbose) {
     auto server_socket = tint::socket::Socket::Listen("", port.c_str());
     if (!server_socket) {
         std::cout << "Failed to listen on port " << port << "\n";
@@ -409,31 +409,43 @@
     std::cout << "Listening on port " << port.c_str() << "...\n";
     while (auto conn = server_socket->Accept()) {
         std::thread([=] {
-            DEBUG("Client connected...");
+            auto tid = std::this_thread::get_id();
+            if (verbose) {
+                std::cout << tid << " Client connected...\n";
+            }
             Stream stream{conn.get(), ""};
 
             {
                 ConnectionRequest req;
                 stream >> req;
                 if (!stream.error.empty()) {
-                    DEBUG("%s", stream.error.c_str());
+                    if (verbose) {
+                        std::cout << tid << " Error: " << stream.error << "\n";
+                    }
                     return;
                 }
                 ConnectionResponse resp;
                 if (req.protocol_version != kProtocolVersion) {
-                    DEBUG("Protocol version mismatch");
+                    if (verbose) {
+                        std::cout << tid << " Protocol version mismatch. requested: "
+                                  << req.protocol_version << "\n";
+                    }
                     resp.error = "Protocol version mismatch";
                     stream << resp;
                     return;
                 }
                 stream << resp;
             }
-            DEBUG("Connection established");
+            if (verbose) {
+                std::cout << tid << " Connection established\n";
+            }
             {
                 CompileRequest req;
                 stream >> req;
                 if (!stream.error.empty()) {
-                    DEBUG("%s\n", stream.error.c_str());
+                    if (verbose) {
+                        std::cout << tid << " Error: " << stream.error << "\n";
+                    }
                     return;
                 }
 #if TINT_BUILD_MSL_WRITER && defined(__APPLE__)
@@ -451,6 +463,11 @@
                         resp.error = result.output;
                     }
                     stream << resp;
+
+                    if (verbose) {
+                        std::cout << tid << " Shader compilation "
+                                  << (result.failed ? "failed" : "passed") << "\n";
+                    }
                     return;
                 }
 #endif
@@ -467,7 +484,8 @@
                std::string port,
                std::string file,
                int version_major,
-               int version_minor) {
+               int version_minor,
+               bool verbose) {
     // Read the file
     std::ifstream input(file, std::ios::binary);
     if (!input) {
@@ -476,8 +494,10 @@
     }
     std::string source((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
 
-    constexpr const int timeout_ms = 10000;
-    DEBUG("Connecting to %s:%s...", address.c_str(), port.c_str());
+    constexpr const int timeout_ms = 100'000;
+    if (verbose) {
+        std::cout << "Connecting to " << address << ":" << port << "\n";
+    }
     auto conn = tint::socket::Socket::Connect(address.c_str(), port.c_str(), timeout_ms);
     if (!conn) {
         std::cerr << "Connection failed\n";
@@ -486,7 +506,9 @@
 
     Stream stream{conn.get(), ""};
 
-    DEBUG("Sending connection request...");
+    if (verbose) {
+        std::cout << "Sending connection request...\n";
+    }
     auto conn_resp = Send(stream, ConnectionRequest{kProtocolVersion});
     if (!stream.error.empty()) {
         std::cerr << stream.error << "\n";
@@ -496,7 +518,9 @@
         std::cerr << conn_resp.error << "\n";
         return false;
     }
-    DEBUG("Connection established. Requesting compile...");
+    if (verbose) {
+        std::cout << "Connection established. Requesting compile...\n";
+    }
     auto comp_resp =
         Send(stream, CompileRequest{SourceLanguage::MSL, version_major, version_minor, source});
     if (!stream.error.empty()) {
@@ -507,6 +531,8 @@
         std::cerr << comp_resp.error << "\n";
         return false;
     }
-    DEBUG("Compilation successful");
+    if (verbose) {
+        std::cout << "Compilation successful\n";
+    }
     return true;
 }
diff --git a/src/tint/cmd/tint/BUILD.bazel b/src/tint/cmd/tint/BUILD.bazel
index b6fb729..934ff47 100644
--- a/src/tint/cmd/tint/BUILD.bazel
+++ b/src/tint/cmd/tint/BUILD.bazel
@@ -61,6 +61,7 @@
     "//src/tint/lang/wgsl/inspector",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/cli",
     "//src/tint/utils/command",
     "//src/tint/utils/containers",
diff --git a/src/tint/cmd/tint/BUILD.cmake b/src/tint/cmd/tint/BUILD.cmake
index 9f35d05..3924e7d 100644
--- a/src/tint/cmd/tint/BUILD.cmake
+++ b/src/tint/cmd/tint/BUILD.cmake
@@ -62,6 +62,7 @@
   tint_lang_wgsl_inspector
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_cli
   tint_utils_command
   tint_utils_containers
diff --git a/src/tint/cmd/tint/BUILD.gn b/src/tint/cmd/tint/BUILD.gn
index c5b628c..b9fca30 100644
--- a/src/tint/cmd/tint/BUILD.gn
+++ b/src/tint/cmd/tint/BUILD.gn
@@ -61,6 +61,7 @@
     "${tint_src_dir}/lang/wgsl/inspector",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/cli",
     "${tint_src_dir}/utils/command",
     "${tint_src_dir}/utils/containers",
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 07bf73b..57aaa08 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -179,6 +179,7 @@
 
     bool dump_ir = false;
     bool use_ir = false;
+    bool use_ir_reader = false;
 
 #if TINT_BUILD_SYNTAX_TREE_WRITER
     bool dump_ast = false;
@@ -292,6 +293,10 @@
         "use-ir", "Use the IR for writers and transforms when possible", Default{false});
     TINT_DEFER(opts->use_ir = *use_ir.value);
 
+    auto& use_ir_reader = options.Add<BoolOption>(
+        "use-ir-reader", "Use the IR for the SPIR-V reader", Default{false});
+    TINT_DEFER(opts->use_ir_reader = *use_ir_reader.value);
+
     auto& verbose =
         options.Add<BoolOption>("verbose", "Verbose output", ShortName{"v"}, Default{false});
     TINT_DEFER(opts->verbose = *verbose.value);
@@ -1149,6 +1154,7 @@
     tint::cmd::LoadProgramOptions opts;
     opts.filename = options.input_filename;
 #if TINT_BUILD_SPV_READER
+    opts.use_ir = options.use_ir_reader;
     opts.spirv_reader_options = options.spirv_reader_options;
 #endif
 
diff --git a/src/tint/lang/core/constant/eval.cc b/src/tint/lang/core/constant/eval.cc
index 97e62d5..cd21f0a 100644
--- a/src/tint/lang/core/constant/eval.cc
+++ b/src/tint/lang/core/constant/eval.cc
@@ -2510,6 +2510,36 @@
     return r;
 }
 
+Eval::Result Eval::dot4I8Packed(const core::type::Type* ty,
+                                VectorRef<const Value*> args,
+                                const Source& source) {
+    uint32_t packed_int8_vec4_1 = args[0]->ValueAs<u32>();
+    uint32_t packed_int8_vec4_2 = args[1]->ValueAs<u32>();
+
+    int8_t* int8_vec4_1 = reinterpret_cast<int8_t*>(&packed_int8_vec4_1);
+    int8_t* int8_vec4_2 = reinterpret_cast<int8_t*>(&packed_int8_vec4_2);
+    int32_t result = 0;
+    for (uint8_t i = 0; i < 4; ++i) {
+        result += int8_vec4_1[i] * int8_vec4_2[i];
+    }
+    return CreateScalar(source, ty, i32(result));
+}
+
+Eval::Result Eval::dot4U8Packed(const core::type::Type* ty,
+                                VectorRef<const Value*> args,
+                                const Source& source) {
+    uint32_t packed_uint8_vec4_1 = args[0]->ValueAs<u32>();
+    uint32_t packed_uint8_vec4_2 = args[1]->ValueAs<u32>();
+
+    uint8_t* uint8_vec4_1 = reinterpret_cast<uint8_t*>(&packed_uint8_vec4_1);
+    uint8_t* uint8_vec4_2 = reinterpret_cast<uint8_t*>(&packed_uint8_vec4_2);
+    uint32_t result = 0;
+    for (uint8_t i = 0; i < 4; ++i) {
+        result += uint8_vec4_1[i] * uint8_vec4_2[i];
+    }
+    return CreateScalar(source, ty, u32(result));
+}
+
 Eval::Result Eval::exp(const core::type::Type* ty,
                        VectorRef<const Value*> args,
                        const Source& source) {
diff --git a/src/tint/lang/core/constant/eval.h b/src/tint/lang/core/constant/eval.h
index 21a04e4..7d12980 100644
--- a/src/tint/lang/core/constant/eval.h
+++ b/src/tint/lang/core/constant/eval.h
@@ -550,6 +550,24 @@
     /// @return the result value, or null if the value cannot be calculated
     Result dot(const core::type::Type* ty, VectorRef<const Value*> args, const Source& source);
 
+    /// dot4I8Packed builtin
+    /// @param ty the expression type
+    /// @param args the input arguments
+    /// @param source the source location
+    /// @return the result value, or null if the value cannot be calculated
+    Result dot4I8Packed(const core::type::Type* ty,
+                        VectorRef<const Value*> args,
+                        const Source& source);
+
+    /// dot4U8Packed builtin
+    /// @param ty the expression type
+    /// @param args the input arguments
+    /// @param source the source location
+    /// @return the result value, or null if the value cannot be calculated
+    Result dot4U8Packed(const core::type::Type* ty,
+                        VectorRef<const Value*> args,
+                        const Source& source);
+
     /// exp builtin
     /// @param ty the expression type
     /// @param args the input arguments
diff --git a/src/tint/lang/core/constant/eval_builtin_test.cc b/src/tint/lang/core/constant/eval_builtin_test.cc
index 5581730..c2ae7a2 100644
--- a/src/tint/lang/core/constant/eval_builtin_test.cc
+++ b/src/tint/lang/core/constant/eval_builtin_test.cc
@@ -2934,5 +2934,45 @@
     testing::Combine(testing::Values(core::BuiltinFn::kQuantizeToF16),
                      testing::ValuesIn(QuantizeToF16Cases())));
 
+std::vector<Case> Dot4I8PackedCases() {
+    return {
+        // {-1, -2, -3, -4} . {-5, -6, -7, -8}
+        C({Val(u32(0xFFFEFDFC)), Val(u32(0xFBFAF9F8))}, Val(i32(70))),
+        // {1, 2, 3, 4} . {-1, -2, -3, -4}
+        C({Val(u32(0x01020304)), Val(u32(0xFFFEFDFC))}, Val(i32(-30))),
+        // {-9, -10, -11, -12} . {5, 6, 7, 8}
+        C({Val(u32(0xF7F6F5F4)), Val(u32(0x05060708))}, Val(i32(-278))),
+        // {0, 0, 0, 0} . {0, 0, 0, 0}
+        C({Val(u32(0)), Val(u32(0))}, Val(i32(0))),
+        // {127, 127, 127, 127} . {127, 127, 127, 127}
+        C({Val(u32(0x7F7F7F7F)), Val(u32(0x7F7F7F7F))}, Val(i32(64516))),
+        // {-128, -128, -128, -128} . {-128, -128, -128, -128}
+        C({Val(u32(0x80808080)), Val(u32(0x80808080))}, Val(i32(65536))),
+    };
+}
+INSTANTIATE_TEST_SUITE_P(  //
+    Dot4I8Packed,
+    ConstEvalBuiltinTest,
+    testing::Combine(testing::Values(core::BuiltinFn::kDot4I8Packed),
+                     testing::ValuesIn(Dot4I8PackedCases())));
+
+std::vector<Case> Dot4U8PackedCases() {
+    return {
+        // {255, 254, 253, 252} . {251, 250, 249, 248}
+        C({Val(u32(0xFFFEFDFC)), Val(u32(0xFBFAF9F8))}, Val(u32(252998))),
+        // {1, 2, 3, 4} . {255, 254, 253, 252}
+        C({Val(u32(0x01020304)), Val(u32(0xFFFEFDFC))}, Val(u32(2530))),
+        // {0, 0, 0, 0} . {0, 0, 0, 0}
+        C({Val(u32(0)), Val(u32(0))}, Val(u32(0))),
+        // {255, 255, 255, 255} . {255, 255, 255, 255}
+        C({Val(u32(0xFFFFFFFF)), Val(u32(0xFFFFFFFF))}, Val(u32(260100))),
+    };
+}
+INSTANTIATE_TEST_SUITE_P(  //
+    Dot4U8Packed,
+    ConstEvalBuiltinTest,
+    testing::Combine(testing::Values(core::BuiltinFn::kDot4U8Packed),
+                     testing::ValuesIn(Dot4U8PackedCases())));
+
 }  // namespace
 }  // namespace tint::core::constant::test
diff --git a/src/tint/lang/core/ir/binary/decode.cc b/src/tint/lang/core/ir/binary/decode.cc
index ca40071..e69373b 100644
--- a/src/tint/lang/core/ir/binary/decode.cc
+++ b/src/tint/lang/core/ir/binary/decode.cc
@@ -52,6 +52,8 @@
     Vector<ir::Value*, 32> values_{};
     Builder b{mod_out_};
 
+    Vector<ir::ExitIf*, 32> exit_ifs_{};
+
     void Decode() {
         {
             const size_t n = static_cast<size_t>(mod_in_.types().size());
@@ -100,6 +102,25 @@
         for (size_t i = 0, n = static_cast<size_t>(mod_in_.blocks().size()); i < n; i++) {
             PopulateBlock(blocks_[i], mod_in_.blocks()[static_cast<int>(i)]);
         }
+
+        for (auto* exit : exit_ifs_) {
+            InferControlInstruction(exit, &ExitIf::SetIf);
+        }
+    }
+
+    template <typename EXIT, typename CTRL_INST>
+    void InferControlInstruction(EXIT* exit, void (EXIT::*set)(CTRL_INST*)) {
+        for (auto* block = exit->Block(); block;) {
+            auto* parent = block->Parent();
+            if (!parent) {
+                break;
+            }
+            if (auto* ctrl_inst = parent->template As<CTRL_INST>()) {
+                (exit->*set)(ctrl_inst);
+                break;
+            }
+            block = parent->Block();
+        }
     }
 
     ////////////////////////////////////////////////////////////////////////////
@@ -151,11 +172,10 @@
     ////////////////////////////////////////////////////////////////////////////
     ir::Block* CreateBlock(const pb::Block&) { return b.Block(); }
 
-    ir::Block* PopulateBlock(ir::Block* block_out, const pb::Block& block_in) {
+    void PopulateBlock(ir::Block* block_out, const pb::Block& block_in) {
         for (auto& inst : block_in.instructions()) {
             block_out->Append(Instruction(inst));
         }
-        return block_out;
     }
 
     ir::Block* Block(uint32_t id) { return id > 0 ? blocks_[id - 1] : nullptr; }
@@ -172,12 +192,24 @@
             case pb::Instruction::KindCase::kBinary:
                 inst_out = CreateInstructionBinary(inst_in.binary());
                 break;
+            case pb::Instruction::KindCase::kBuiltinCall:
+                inst_out = CreateInstructionBuiltinCall(inst_in.builtin_call());
+                break;
             case pb::Instruction::KindCase::kConstruct:
                 inst_out = CreateInstructionConstruct(inst_in.construct());
                 break;
+            case pb::Instruction::KindCase::kConvert:
+                inst_out = CreateInstructionConvert(inst_in.convert());
+                break;
+            case pb::Instruction::KindCase::kExitIf:
+                inst_out = CreateInstructionExitIf(inst_in.exit_if());
+                break;
             case pb::Instruction::KindCase::kDiscard:
                 inst_out = CreateInstructionDiscard(inst_in.discard());
                 break;
+            case pb::Instruction::KindCase::kIf:
+                inst_out = CreateInstructionIf(inst_in.if_());
+                break;
             case pb::Instruction::KindCase::kLet:
                 inst_out = CreateInstructionLet(inst_in.let());
                 break;
@@ -239,14 +271,41 @@
         return binary_out;
     }
 
+    ir::CoreBuiltinCall* CreateInstructionBuiltinCall(const pb::InstructionBuiltinCall& call_in) {
+        auto* call_out = mod_out_.instructions.Create<ir::CoreBuiltinCall>();
+        call_out->SetFunc(BuiltinFn(call_in.builtin()));
+        return call_out;
+    }
+
     ir::Construct* CreateInstructionConstruct(const pb::InstructionConstruct&) {
         return mod_out_.instructions.Create<ir::Construct>();
     }
 
+    ir::Convert* CreateInstructionConvert(const pb::InstructionConvert&) {
+        return mod_out_.instructions.Create<ir::Convert>();
+    }
+
+    ir::ExitIf* CreateInstructionExitIf(const pb::InstructionExitIf&) {
+        auto* exit_out = mod_out_.instructions.Create<ir::ExitIf>();
+        exit_ifs_.Push(exit_out);
+        return exit_out;
+    }
+
     ir::Discard* CreateInstructionDiscard(const pb::InstructionDiscard&) {
         return mod_out_.instructions.Create<ir::Discard>();
     }
 
+    ir::If* CreateInstructionIf(const pb::InstructionIf& if_in) {
+        auto* if_out = mod_out_.instructions.Create<ir::If>();
+        if (if_in.has_true_()) {
+            if_out->SetTrue(Block(if_in.true_()));
+        }
+        if (if_in.has_false_()) {
+            if_out->SetFalse(Block(if_in.false_()));
+        }
+        return if_out;
+    }
+
     ir::Let* CreateInstructionLet(const pb::InstructionLet&) {
         return mod_out_.instructions.Create<ir::Let>();
     }
@@ -315,16 +374,16 @@
                 return CreateTypeMatrix(type_in.matrix());
             case pb::Type::KindCase::kPointer:
                 return CreateTypePointer(type_in.pointer());
+            case pb::Type::KindCase::kStruct:
+                return CreateTypeStruct(type_in.struct_());
+            case pb::Type::KindCase::kAtomic:
+                return CreateTypeAtomic(type_in.atomic());
             case pb::Type::KindCase::kArray:
                 return CreateTypeArray(type_in.array());
-            case pb::Type::KindCase::kAtomic:
-                TINT_UNIMPLEMENTED() << type_in.kind_case();
-                return nullptr;
-
-            case pb::Type::KindCase::KIND_NOT_SET:
+            default:
                 break;
         }
-        TINT_ICE() << "invalid TypeDecl.kind";
+        TINT_ICE() << type_in.kind_case();
         return nullptr;
     }
 
@@ -366,6 +425,59 @@
         return mod_out_.Types().ptr(address_space, store_ty, access);
     }
 
+    const type::Struct* CreateTypeStruct(const pb::TypeStruct& struct_in) {
+        Vector<const core::type::StructMember*, 8> members_out;
+        uint32_t offset = 0;
+        for (auto& member_in : struct_in.member()) {
+            auto symbol = mod_out_.symbols.Register(member_in.name());
+            auto* type = Type(member_in.type());
+            auto index = static_cast<uint32_t>(members_out.Length());
+            auto align = member_in.align();
+            auto size = member_in.size();
+            core::type::StructMemberAttributes attributes_out{};
+            if (member_in.has_attributes()) {
+                auto& attributes_in = member_in.attributes();
+                if (attributes_in.has_location()) {
+                    attributes_out.location = attributes_in.location();
+                }
+                if (attributes_in.has_index()) {
+                    attributes_out.index = attributes_in.index();
+                }
+                if (attributes_in.has_color()) {
+                    attributes_out.color = attributes_in.color();
+                }
+                if (attributes_in.has_builtin()) {
+                    attributes_out.builtin = BuiltinValue(attributes_in.builtin());
+                }
+                if (attributes_in.has_interpolation()) {
+                    auto& interpolation_in = attributes_in.interpolation();
+                    attributes_out.interpolation = core::Interpolation{
+                        InterpolationType(interpolation_in.type()),
+                        InterpolationSampling::kUndefined,
+                    };
+                    if (interpolation_in.has_sampling()) {
+                        attributes_out.interpolation->sampling =
+                            InterpolationSampling(interpolation_in.sampling());
+                    }
+                }
+                if (attributes_in.has_invariant()) {
+                    attributes_out.invariant = attributes_in.invariant();
+                }
+            }
+            offset = RoundUp(align, offset);
+            auto* member_out = mod_out_.Types().Get<core::type::StructMember>(
+                symbol, type, index, offset, align, size, std::move(attributes_out));
+            offset += size;
+            members_out.Push(member_out);
+        }
+        auto name = mod_out_.symbols.Register(struct_in.name());
+        return mod_out_.Types().Struct(name, std::move(members_out));
+    }
+
+    const type::Atomic* CreateTypeAtomic(const pb::TypeAtomic& atomic_in) {
+        return mod_out_.Types().atomic(Type(atomic_in.type()));
+    }
+
     const type::Array* CreateTypeArray(const pb::TypeArray& array_in) {
         auto* element = Type(array_in.element());
         uint32_t stride = static_cast<uint32_t>(array_in.stride());
@@ -576,6 +688,314 @@
                 return core::ir::BinaryOp::kAdd;
         }
     }
+
+    core::InterpolationType InterpolationType(pb::InterpolationType in) {
+        switch (in) {
+            case pb::InterpolationType::flat:
+                return core::InterpolationType::kFlat;
+            case pb::InterpolationType::linear:
+                return core::InterpolationType::kLinear;
+            case pb::InterpolationType::perspective:
+                return core::InterpolationType::kPerspective;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid InterpolationType: " << in;
+        return core::InterpolationType::kFlat;
+    }
+
+    core::InterpolationSampling InterpolationSampling(pb::InterpolationSampling in) {
+        switch (in) {
+            case pb::InterpolationSampling::center:
+                return core::InterpolationSampling::kCenter;
+            case pb::InterpolationSampling::centroid:
+                return core::InterpolationSampling::kCentroid;
+            case pb::InterpolationSampling::sample:
+                return core::InterpolationSampling::kSample;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid InterpolationSampling: " << in;
+        return core::InterpolationSampling::kCenter;
+    }
+
+    core::BuiltinValue BuiltinValue(pb::BuiltinValue in) {
+        switch (in) {
+            case pb::BuiltinValue::point_size:
+                return core::BuiltinValue::kPointSize;
+            case pb::BuiltinValue::frag_depth:
+                return core::BuiltinValue::kFragDepth;
+            case pb::BuiltinValue::front_facing:
+                return core::BuiltinValue::kFrontFacing;
+            case pb::BuiltinValue::global_invocation_id:
+                return core::BuiltinValue::kGlobalInvocationId;
+            case pb::BuiltinValue::instance_index:
+                return core::BuiltinValue::kInstanceIndex;
+            case pb::BuiltinValue::local_invocation_id:
+                return core::BuiltinValue::kLocalInvocationId;
+            case pb::BuiltinValue::local_invocation_index:
+                return core::BuiltinValue::kLocalInvocationIndex;
+            case pb::BuiltinValue::num_workgroups:
+                return core::BuiltinValue::kNumWorkgroups;
+            case pb::BuiltinValue::position:
+                return core::BuiltinValue::kPosition;
+            case pb::BuiltinValue::sample_index:
+                return core::BuiltinValue::kSampleIndex;
+            case pb::BuiltinValue::sample_mask:
+                return core::BuiltinValue::kSampleMask;
+            case pb::BuiltinValue::subgroup_invocation_id:
+                return core::BuiltinValue::kSubgroupInvocationId;
+            case pb::BuiltinValue::subgroup_size:
+                return core::BuiltinValue::kSubgroupSize;
+            case pb::BuiltinValue::vertex_index:
+                return core::BuiltinValue::kVertexIndex;
+            case pb::BuiltinValue::workgroup_id:
+                return core::BuiltinValue::kWorkgroupId;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid BuiltinValue: " << in;
+        return core::BuiltinValue::kPointSize;
+    }
+
+    core::BuiltinFn BuiltinFn(pb::BuiltinFn in) {
+        switch (in) {
+            case pb::BuiltinFn::abs:
+                return core::BuiltinFn::kAbs;
+            case pb::BuiltinFn::acos:
+                return core::BuiltinFn::kAcos;
+            case pb::BuiltinFn::acosh:
+                return core::BuiltinFn::kAcosh;
+            case pb::BuiltinFn::all:
+                return core::BuiltinFn::kAll;
+            case pb::BuiltinFn::any:
+                return core::BuiltinFn::kAny;
+            case pb::BuiltinFn::array_length:
+                return core::BuiltinFn::kArrayLength;
+            case pb::BuiltinFn::asin:
+                return core::BuiltinFn::kAsin;
+            case pb::BuiltinFn::asinh:
+                return core::BuiltinFn::kAsinh;
+            case pb::BuiltinFn::atan:
+                return core::BuiltinFn::kAtan;
+            case pb::BuiltinFn::atan2:
+                return core::BuiltinFn::kAtan2;
+            case pb::BuiltinFn::atanh:
+                return core::BuiltinFn::kAtanh;
+            case pb::BuiltinFn::ceil:
+                return core::BuiltinFn::kCeil;
+            case pb::BuiltinFn::clamp:
+                return core::BuiltinFn::kClamp;
+            case pb::BuiltinFn::cos:
+                return core::BuiltinFn::kCos;
+            case pb::BuiltinFn::cosh:
+                return core::BuiltinFn::kCosh;
+            case pb::BuiltinFn::count_leading_zeros:
+                return core::BuiltinFn::kCountLeadingZeros;
+            case pb::BuiltinFn::count_one_bits:
+                return core::BuiltinFn::kCountOneBits;
+            case pb::BuiltinFn::count_trailing_zeros:
+                return core::BuiltinFn::kCountTrailingZeros;
+            case pb::BuiltinFn::cross:
+                return core::BuiltinFn::kCross;
+            case pb::BuiltinFn::degrees:
+                return core::BuiltinFn::kDegrees;
+            case pb::BuiltinFn::determinant:
+                return core::BuiltinFn::kDeterminant;
+            case pb::BuiltinFn::distance:
+                return core::BuiltinFn::kDistance;
+            case pb::BuiltinFn::dot:
+                return core::BuiltinFn::kDot;
+            case pb::BuiltinFn::dot4i8_packed:
+                return core::BuiltinFn::kDot4I8Packed;
+            case pb::BuiltinFn::dot4u8_packed:
+                return core::BuiltinFn::kDot4U8Packed;
+            case pb::BuiltinFn::dpdx:
+                return core::BuiltinFn::kDpdx;
+            case pb::BuiltinFn::dpdx_coarse:
+                return core::BuiltinFn::kDpdxCoarse;
+            case pb::BuiltinFn::dpdx_fine:
+                return core::BuiltinFn::kDpdxFine;
+            case pb::BuiltinFn::dpdy:
+                return core::BuiltinFn::kDpdy;
+            case pb::BuiltinFn::dpdy_coarse:
+                return core::BuiltinFn::kDpdyCoarse;
+            case pb::BuiltinFn::dpdy_fine:
+                return core::BuiltinFn::kDpdyFine;
+            case pb::BuiltinFn::exp:
+                return core::BuiltinFn::kExp;
+            case pb::BuiltinFn::exp2:
+                return core::BuiltinFn::kExp2;
+            case pb::BuiltinFn::extract_bits:
+                return core::BuiltinFn::kExtractBits;
+            case pb::BuiltinFn::face_forward:
+                return core::BuiltinFn::kFaceForward;
+            case pb::BuiltinFn::first_leading_bit:
+                return core::BuiltinFn::kFirstLeadingBit;
+            case pb::BuiltinFn::first_trailing_bit:
+                return core::BuiltinFn::kFirstTrailingBit;
+            case pb::BuiltinFn::floor:
+                return core::BuiltinFn::kFloor;
+            case pb::BuiltinFn::fma:
+                return core::BuiltinFn::kFma;
+            case pb::BuiltinFn::fract:
+                return core::BuiltinFn::kFract;
+            case pb::BuiltinFn::frexp:
+                return core::BuiltinFn::kFrexp;
+            case pb::BuiltinFn::fwidth:
+                return core::BuiltinFn::kFwidth;
+            case pb::BuiltinFn::fwidth_coarse:
+                return core::BuiltinFn::kFwidthCoarse;
+            case pb::BuiltinFn::fwidth_fine:
+                return core::BuiltinFn::kFwidthFine;
+            case pb::BuiltinFn::insert_bits:
+                return core::BuiltinFn::kInsertBits;
+            case pb::BuiltinFn::inverse_sqrt:
+                return core::BuiltinFn::kInverseSqrt;
+            case pb::BuiltinFn::ldexp:
+                return core::BuiltinFn::kLdexp;
+            case pb::BuiltinFn::length:
+                return core::BuiltinFn::kLength;
+            case pb::BuiltinFn::log:
+                return core::BuiltinFn::kLog;
+            case pb::BuiltinFn::log2:
+                return core::BuiltinFn::kLog2;
+            case pb::BuiltinFn::max:
+                return core::BuiltinFn::kMax;
+            case pb::BuiltinFn::min:
+                return core::BuiltinFn::kMin;
+            case pb::BuiltinFn::mix:
+                return core::BuiltinFn::kMix;
+            case pb::BuiltinFn::modf:
+                return core::BuiltinFn::kModf;
+            case pb::BuiltinFn::normalize:
+                return core::BuiltinFn::kNormalize;
+            case pb::BuiltinFn::pack2x16_float:
+                return core::BuiltinFn::kPack2X16Float;
+            case pb::BuiltinFn::pack2x16_snorm:
+                return core::BuiltinFn::kPack2X16Snorm;
+            case pb::BuiltinFn::pack2x16_unorm:
+                return core::BuiltinFn::kPack2X16Unorm;
+            case pb::BuiltinFn::pack4x8_snorm:
+                return core::BuiltinFn::kPack4X8Snorm;
+            case pb::BuiltinFn::pack4x8_unorm:
+                return core::BuiltinFn::kPack4X8Unorm;
+            case pb::BuiltinFn::pow:
+                return core::BuiltinFn::kPow;
+            case pb::BuiltinFn::quantize_to_f16:
+                return core::BuiltinFn::kQuantizeToF16;
+            case pb::BuiltinFn::radians:
+                return core::BuiltinFn::kRadians;
+            case pb::BuiltinFn::reflect:
+                return core::BuiltinFn::kReflect;
+            case pb::BuiltinFn::refract:
+                return core::BuiltinFn::kRefract;
+            case pb::BuiltinFn::reverse_bits:
+                return core::BuiltinFn::kReverseBits;
+            case pb::BuiltinFn::round:
+                return core::BuiltinFn::kRound;
+            case pb::BuiltinFn::saturate:
+                return core::BuiltinFn::kSaturate;
+            case pb::BuiltinFn::select:
+                return core::BuiltinFn::kSelect;
+            case pb::BuiltinFn::sign:
+                return core::BuiltinFn::kSign;
+            case pb::BuiltinFn::sin:
+                return core::BuiltinFn::kSin;
+            case pb::BuiltinFn::sinh:
+                return core::BuiltinFn::kSinh;
+            case pb::BuiltinFn::smoothstep:
+                return core::BuiltinFn::kSmoothstep;
+            case pb::BuiltinFn::sqrt:
+                return core::BuiltinFn::kSqrt;
+            case pb::BuiltinFn::step:
+                return core::BuiltinFn::kStep;
+            case pb::BuiltinFn::storage_barrier:
+                return core::BuiltinFn::kStorageBarrier;
+            case pb::BuiltinFn::tan:
+                return core::BuiltinFn::kTan;
+            case pb::BuiltinFn::tanh:
+                return core::BuiltinFn::kTanh;
+            case pb::BuiltinFn::transpose:
+                return core::BuiltinFn::kTranspose;
+            case pb::BuiltinFn::trunc:
+                return core::BuiltinFn::kTrunc;
+            case pb::BuiltinFn::unpack2x16_float:
+                return core::BuiltinFn::kUnpack2X16Float;
+            case pb::BuiltinFn::unpack2x16_snorm:
+                return core::BuiltinFn::kUnpack2X16Snorm;
+            case pb::BuiltinFn::unpack2x16_unorm:
+                return core::BuiltinFn::kUnpack2X16Unorm;
+            case pb::BuiltinFn::unpack4x8_snorm:
+                return core::BuiltinFn::kUnpack4X8Snorm;
+            case pb::BuiltinFn::unpack4x8_unorm:
+                return core::BuiltinFn::kUnpack4X8Unorm;
+            case pb::BuiltinFn::workgroup_barrier:
+                return core::BuiltinFn::kWorkgroupBarrier;
+            case pb::BuiltinFn::texture_barrier:
+                return core::BuiltinFn::kTextureBarrier;
+            case pb::BuiltinFn::texture_dimensions:
+                return core::BuiltinFn::kTextureDimensions;
+            case pb::BuiltinFn::texture_gather:
+                return core::BuiltinFn::kTextureGather;
+            case pb::BuiltinFn::texture_gather_compare:
+                return core::BuiltinFn::kTextureGatherCompare;
+            case pb::BuiltinFn::texture_num_layers:
+                return core::BuiltinFn::kTextureNumLayers;
+            case pb::BuiltinFn::texture_num_levels:
+                return core::BuiltinFn::kTextureNumLevels;
+            case pb::BuiltinFn::texture_num_samples:
+                return core::BuiltinFn::kTextureNumSamples;
+            case pb::BuiltinFn::texture_sample:
+                return core::BuiltinFn::kTextureSample;
+            case pb::BuiltinFn::texture_sample_bias:
+                return core::BuiltinFn::kTextureSampleBias;
+            case pb::BuiltinFn::texture_sample_compare:
+                return core::BuiltinFn::kTextureSampleCompare;
+            case pb::BuiltinFn::texture_sample_compare_level:
+                return core::BuiltinFn::kTextureSampleCompareLevel;
+            case pb::BuiltinFn::texture_sample_grad:
+                return core::BuiltinFn::kTextureSampleGrad;
+            case pb::BuiltinFn::texture_sample_level:
+                return core::BuiltinFn::kTextureSampleLevel;
+            case pb::BuiltinFn::texture_sample_base_clamp_to_edge:
+                return core::BuiltinFn::kTextureSampleBaseClampToEdge;
+            case pb::BuiltinFn::texture_store:
+                return core::BuiltinFn::kTextureStore;
+            case pb::BuiltinFn::texture_load:
+                return core::BuiltinFn::kTextureLoad;
+            case pb::BuiltinFn::atomic_load:
+                return core::BuiltinFn::kAtomicLoad;
+            case pb::BuiltinFn::atomic_store:
+                return core::BuiltinFn::kAtomicStore;
+            case pb::BuiltinFn::atomic_add:
+                return core::BuiltinFn::kAtomicAdd;
+            case pb::BuiltinFn::atomic_sub:
+                return core::BuiltinFn::kAtomicSub;
+            case pb::BuiltinFn::atomic_max:
+                return core::BuiltinFn::kAtomicMax;
+            case pb::BuiltinFn::atomic_min:
+                return core::BuiltinFn::kAtomicMin;
+            case pb::BuiltinFn::atomic_and:
+                return core::BuiltinFn::kAtomicAnd;
+            case pb::BuiltinFn::atomic_or:
+                return core::BuiltinFn::kAtomicOr;
+            case pb::BuiltinFn::atomic_xor:
+                return core::BuiltinFn::kAtomicXor;
+            case pb::BuiltinFn::atomic_exchange:
+                return core::BuiltinFn::kAtomicExchange;
+            case pb::BuiltinFn::atomic_compare_exchange_weak:
+                return core::BuiltinFn::kAtomicCompareExchangeWeak;
+            case pb::BuiltinFn::subgroup_ballot:
+                return core::BuiltinFn::kSubgroupBallot;
+            case pb::BuiltinFn::subgroup_broadcast:
+                return core::BuiltinFn::kSubgroupBroadcast;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid BuiltinFn: " << in;
+        return core::BuiltinFn::kAbs;
+    }
 };
 
 }  // namespace
diff --git a/src/tint/lang/core/ir/binary/encode.cc b/src/tint/lang/core/ir/binary/encode.cc
index ab18fe9..e8910d1 100644
--- a/src/tint/lang/core/ir/binary/encode.cc
+++ b/src/tint/lang/core/ir/binary/encode.cc
@@ -29,14 +29,20 @@
 
 #include <utility>
 
+#include "src/tint/lang/core/builtin_fn.h"
+#include "src/tint/lang/core/builtin_value.h"
 #include "src/tint/lang/core/constant/composite.h"
 #include "src/tint/lang/core/constant/scalar.h"
 #include "src/tint/lang/core/constant/splat.h"
 #include "src/tint/lang/core/ir/access.h"
 #include "src/tint/lang/core/ir/binary.h"
 #include "src/tint/lang/core/ir/construct.h"
+#include "src/tint/lang/core/ir/convert.h"
+#include "src/tint/lang/core/ir/core_builtin_call.h"
 #include "src/tint/lang/core/ir/discard.h"
+#include "src/tint/lang/core/ir/exit_if.h"
 #include "src/tint/lang/core/ir/function_param.h"
+#include "src/tint/lang/core/ir/if.h"
 #include "src/tint/lang/core/ir/let.h"
 #include "src/tint/lang/core/ir/load.h"
 #include "src/tint/lang/core/ir/load_vector_element.h"
@@ -136,10 +142,11 @@
         }
         return blocks_.GetOrCreate(block_in, [&]() -> uint32_t {
             auto& block_out = *mod_out_.add_blocks();
+            auto id = static_cast<uint32_t>(blocks_.Count());
             for (auto* inst : *block_in) {
                 Instruction(*block_out.add_instructions(), inst);
             }
-            return static_cast<uint32_t>(blocks_.Count());
+            return id;
         });
     }
 
@@ -151,8 +158,14 @@
             inst_in,  //
             [&](const ir::Access* i) { InstructionAccess(*inst_out.mutable_access(), i); },
             [&](const ir::Binary* i) { InstructionBinary(*inst_out.mutable_binary(), i); },
+            [&](const ir::CoreBuiltinCall* i) {
+                InstructionBuiltinCall(*inst_out.mutable_builtin_call(), i);
+            },
             [&](const ir::Construct* i) { InstructionConstruct(*inst_out.mutable_construct(), i); },
+            [&](const ir::Convert* i) { InstructionConvert(*inst_out.mutable_convert(), i); },
             [&](const ir::Discard* i) { InstructionDiscard(*inst_out.mutable_discard(), i); },
+            [&](const ir::ExitIf* i) { InstructionExitIf(*inst_out.mutable_exit_if(), i); },
+            [&](const ir::If* i) { InstructionIf(*inst_out.mutable_if_(), i); },
             [&](const ir::Let* i) { InstructionLet(*inst_out.mutable_let(), i); },
             [&](const ir::Load* i) { InstructionLoad(*inst_out.mutable_load(), i); },
             [&](const ir::LoadVectorElement* i) {
@@ -182,10 +195,28 @@
         binary_out.set_op(BinaryOp(binary_in->Op()));
     }
 
+    void InstructionBuiltinCall(pb::InstructionBuiltinCall& call_out,
+                                const ir::CoreBuiltinCall* call_in) {
+        call_out.set_builtin(BuiltinFn(call_in->Func()));
+    }
+
     void InstructionConstruct(pb::InstructionConstruct&, const ir::Construct*) {}
 
+    void InstructionConvert(pb::InstructionConvert&, const ir::Convert*) {}
+
+    void InstructionIf(pb::InstructionIf& if_out, const ir::If* if_in) {
+        if (auto* block = if_in->True()) {
+            if_out.set_true_(Block(block));
+        }
+        if (auto* block = if_in->False()) {
+            if_out.set_false_(Block(block));
+        }
+    }
+
     void InstructionDiscard(pb::InstructionDiscard&, const ir::Discard*) {}
 
+    void InstructionExitIf(pb::InstructionExitIf&, const ir::ExitIf*) {}
+
     void InstructionLet(pb::InstructionLet&, const ir::Let*) {}
 
     void InstructionLoad(pb::InstructionLoad&, const ir::Load*) {}
@@ -240,6 +271,8 @@
                 [&](const core::type::Vector* v) { TypeVector(*type_out.mutable_vector(), v); },
                 [&](const core::type::Matrix* m) { TypeMatrix(*type_out.mutable_matrix(), m); },
                 [&](const core::type::Pointer* m) { TypePointer(*type_out.mutable_pointer(), m); },
+                [&](const core::type::Struct* s) { TypeStruct(*type_out.mutable_struct_(), s); },
+                [&](const core::type::Atomic* a) { TypeAtomic(*type_out.mutable_atomic(), a); },
                 [&](const core::type::Array* m) { TypeArray(*type_out.mutable_array(), m); },
                 TINT_ICE_ON_NO_MATCH);
 
@@ -265,6 +298,46 @@
         pointer_out.set_access(Access(pointer_in->Access()));
     }
 
+    void TypeStruct(pb::TypeStruct& struct_out, const core::type::Struct* struct_in) {
+        struct_out.set_name(struct_in->Name().Name());
+        for (auto* member_in : struct_in->Members()) {
+            auto& member_out = *struct_out.add_member();
+            member_out.set_name(member_in->Name().Name());
+            member_out.set_type(Type(member_in->Type()));
+            member_out.set_size(member_in->Size());
+            member_out.set_align(member_in->Align());
+
+            auto& attrs_in = member_in->Attributes();
+            if (attrs_in.location) {
+                member_out.mutable_attributes()->set_location(*attrs_in.location);
+            }
+            if (attrs_in.index) {
+                member_out.mutable_attributes()->set_index(*attrs_in.index);
+            }
+            if (attrs_in.color) {
+                member_out.mutable_attributes()->set_color(*attrs_in.color);
+            }
+            if (attrs_in.builtin) {
+                member_out.mutable_attributes()->set_builtin(BuiltinValue(*attrs_in.builtin));
+            }
+            if (auto& interpolation_in = attrs_in.interpolation) {
+                auto& interpolation_out = *member_out.mutable_attributes()->mutable_interpolation();
+                interpolation_out.set_type(InterpolationType(interpolation_in->type));
+                if (interpolation_in->sampling != InterpolationSampling::kUndefined) {
+                    interpolation_out.set_sampling(
+                        InterpolationSampling(interpolation_in->sampling));
+                }
+            }
+            if (attrs_in.invariant) {
+                member_out.mutable_attributes()->set_invariant(true);
+            }
+        }
+    }
+
+    void TypeAtomic(pb::TypeAtomic& atomic_out, const core::type::Atomic* atomic_in) {
+        atomic_out.set_type(Type(atomic_in->Type()));
+    }
+
     void TypeArray(pb::TypeArray& array_out, const core::type::Array* array_in) {
         array_out.set_element(Type(array_in->ElemType()));
         array_out.set_stride(array_in->Stride());
@@ -458,6 +531,314 @@
         TINT_ICE() << "invalid BinaryOp: " << in;
         return pb::BinaryOp::add_;
     }
+
+    pb::InterpolationType InterpolationType(core::InterpolationType in) {
+        switch (in) {
+            case core::InterpolationType::kFlat:
+                return pb::InterpolationType::flat;
+            case core::InterpolationType::kLinear:
+                return pb::InterpolationType::linear;
+            case core::InterpolationType::kPerspective:
+                return pb::InterpolationType::perspective;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid InterpolationType: " << in;
+        return pb::InterpolationType::flat;
+    }
+
+    pb::InterpolationSampling InterpolationSampling(core::InterpolationSampling in) {
+        switch (in) {
+            case core::InterpolationSampling::kCenter:
+                return pb::InterpolationSampling::center;
+            case core::InterpolationSampling::kCentroid:
+                return pb::InterpolationSampling::centroid;
+            case core::InterpolationSampling::kSample:
+                return pb::InterpolationSampling::sample;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid InterpolationSampling: " << in;
+        return pb::InterpolationSampling::center;
+    }
+
+    pb::BuiltinValue BuiltinValue(core::BuiltinValue in) {
+        switch (in) {
+            case core::BuiltinValue::kPointSize:
+                return pb::BuiltinValue::point_size;
+            case core::BuiltinValue::kFragDepth:
+                return pb::BuiltinValue::frag_depth;
+            case core::BuiltinValue::kFrontFacing:
+                return pb::BuiltinValue::front_facing;
+            case core::BuiltinValue::kGlobalInvocationId:
+                return pb::BuiltinValue::global_invocation_id;
+            case core::BuiltinValue::kInstanceIndex:
+                return pb::BuiltinValue::instance_index;
+            case core::BuiltinValue::kLocalInvocationId:
+                return pb::BuiltinValue::local_invocation_id;
+            case core::BuiltinValue::kLocalInvocationIndex:
+                return pb::BuiltinValue::local_invocation_index;
+            case core::BuiltinValue::kNumWorkgroups:
+                return pb::BuiltinValue::num_workgroups;
+            case core::BuiltinValue::kPosition:
+                return pb::BuiltinValue::position;
+            case core::BuiltinValue::kSampleIndex:
+                return pb::BuiltinValue::sample_index;
+            case core::BuiltinValue::kSampleMask:
+                return pb::BuiltinValue::sample_mask;
+            case core::BuiltinValue::kSubgroupInvocationId:
+                return pb::BuiltinValue::subgroup_invocation_id;
+            case core::BuiltinValue::kSubgroupSize:
+                return pb::BuiltinValue::subgroup_size;
+            case core::BuiltinValue::kVertexIndex:
+                return pb::BuiltinValue::vertex_index;
+            case core::BuiltinValue::kWorkgroupId:
+                return pb::BuiltinValue::workgroup_id;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid BuiltinValue: " << in;
+        return pb::BuiltinValue::point_size;
+    }
+
+    pb::BuiltinFn BuiltinFn(core::BuiltinFn in) {
+        switch (in) {
+            case core::BuiltinFn::kAbs:
+                return pb::BuiltinFn::abs;
+            case core::BuiltinFn::kAcos:
+                return pb::BuiltinFn::acos;
+            case core::BuiltinFn::kAcosh:
+                return pb::BuiltinFn::acosh;
+            case core::BuiltinFn::kAll:
+                return pb::BuiltinFn::all;
+            case core::BuiltinFn::kAny:
+                return pb::BuiltinFn::any;
+            case core::BuiltinFn::kArrayLength:
+                return pb::BuiltinFn::array_length;
+            case core::BuiltinFn::kAsin:
+                return pb::BuiltinFn::asin;
+            case core::BuiltinFn::kAsinh:
+                return pb::BuiltinFn::asinh;
+            case core::BuiltinFn::kAtan:
+                return pb::BuiltinFn::atan;
+            case core::BuiltinFn::kAtan2:
+                return pb::BuiltinFn::atan2;
+            case core::BuiltinFn::kAtanh:
+                return pb::BuiltinFn::atanh;
+            case core::BuiltinFn::kCeil:
+                return pb::BuiltinFn::ceil;
+            case core::BuiltinFn::kClamp:
+                return pb::BuiltinFn::clamp;
+            case core::BuiltinFn::kCos:
+                return pb::BuiltinFn::cos;
+            case core::BuiltinFn::kCosh:
+                return pb::BuiltinFn::cosh;
+            case core::BuiltinFn::kCountLeadingZeros:
+                return pb::BuiltinFn::count_leading_zeros;
+            case core::BuiltinFn::kCountOneBits:
+                return pb::BuiltinFn::count_one_bits;
+            case core::BuiltinFn::kCountTrailingZeros:
+                return pb::BuiltinFn::count_trailing_zeros;
+            case core::BuiltinFn::kCross:
+                return pb::BuiltinFn::cross;
+            case core::BuiltinFn::kDegrees:
+                return pb::BuiltinFn::degrees;
+            case core::BuiltinFn::kDeterminant:
+                return pb::BuiltinFn::determinant;
+            case core::BuiltinFn::kDistance:
+                return pb::BuiltinFn::distance;
+            case core::BuiltinFn::kDot:
+                return pb::BuiltinFn::dot;
+            case core::BuiltinFn::kDot4I8Packed:
+                return pb::BuiltinFn::dot4i8_packed;
+            case core::BuiltinFn::kDot4U8Packed:
+                return pb::BuiltinFn::dot4u8_packed;
+            case core::BuiltinFn::kDpdx:
+                return pb::BuiltinFn::dpdx;
+            case core::BuiltinFn::kDpdxCoarse:
+                return pb::BuiltinFn::dpdx_coarse;
+            case core::BuiltinFn::kDpdxFine:
+                return pb::BuiltinFn::dpdx_fine;
+            case core::BuiltinFn::kDpdy:
+                return pb::BuiltinFn::dpdy;
+            case core::BuiltinFn::kDpdyCoarse:
+                return pb::BuiltinFn::dpdy_coarse;
+            case core::BuiltinFn::kDpdyFine:
+                return pb::BuiltinFn::dpdy_fine;
+            case core::BuiltinFn::kExp:
+                return pb::BuiltinFn::exp;
+            case core::BuiltinFn::kExp2:
+                return pb::BuiltinFn::exp2;
+            case core::BuiltinFn::kExtractBits:
+                return pb::BuiltinFn::extract_bits;
+            case core::BuiltinFn::kFaceForward:
+                return pb::BuiltinFn::face_forward;
+            case core::BuiltinFn::kFirstLeadingBit:
+                return pb::BuiltinFn::first_leading_bit;
+            case core::BuiltinFn::kFirstTrailingBit:
+                return pb::BuiltinFn::first_trailing_bit;
+            case core::BuiltinFn::kFloor:
+                return pb::BuiltinFn::floor;
+            case core::BuiltinFn::kFma:
+                return pb::BuiltinFn::fma;
+            case core::BuiltinFn::kFract:
+                return pb::BuiltinFn::fract;
+            case core::BuiltinFn::kFrexp:
+                return pb::BuiltinFn::frexp;
+            case core::BuiltinFn::kFwidth:
+                return pb::BuiltinFn::fwidth;
+            case core::BuiltinFn::kFwidthCoarse:
+                return pb::BuiltinFn::fwidth_coarse;
+            case core::BuiltinFn::kFwidthFine:
+                return pb::BuiltinFn::fwidth_fine;
+            case core::BuiltinFn::kInsertBits:
+                return pb::BuiltinFn::insert_bits;
+            case core::BuiltinFn::kInverseSqrt:
+                return pb::BuiltinFn::inverse_sqrt;
+            case core::BuiltinFn::kLdexp:
+                return pb::BuiltinFn::ldexp;
+            case core::BuiltinFn::kLength:
+                return pb::BuiltinFn::length;
+            case core::BuiltinFn::kLog:
+                return pb::BuiltinFn::log;
+            case core::BuiltinFn::kLog2:
+                return pb::BuiltinFn::log2;
+            case core::BuiltinFn::kMax:
+                return pb::BuiltinFn::max;
+            case core::BuiltinFn::kMin:
+                return pb::BuiltinFn::min;
+            case core::BuiltinFn::kMix:
+                return pb::BuiltinFn::mix;
+            case core::BuiltinFn::kModf:
+                return pb::BuiltinFn::modf;
+            case core::BuiltinFn::kNormalize:
+                return pb::BuiltinFn::normalize;
+            case core::BuiltinFn::kPack2X16Float:
+                return pb::BuiltinFn::pack2x16_float;
+            case core::BuiltinFn::kPack2X16Snorm:
+                return pb::BuiltinFn::pack2x16_snorm;
+            case core::BuiltinFn::kPack2X16Unorm:
+                return pb::BuiltinFn::pack2x16_unorm;
+            case core::BuiltinFn::kPack4X8Snorm:
+                return pb::BuiltinFn::pack4x8_snorm;
+            case core::BuiltinFn::kPack4X8Unorm:
+                return pb::BuiltinFn::pack4x8_unorm;
+            case core::BuiltinFn::kPow:
+                return pb::BuiltinFn::pow;
+            case core::BuiltinFn::kQuantizeToF16:
+                return pb::BuiltinFn::quantize_to_f16;
+            case core::BuiltinFn::kRadians:
+                return pb::BuiltinFn::radians;
+            case core::BuiltinFn::kReflect:
+                return pb::BuiltinFn::reflect;
+            case core::BuiltinFn::kRefract:
+                return pb::BuiltinFn::refract;
+            case core::BuiltinFn::kReverseBits:
+                return pb::BuiltinFn::reverse_bits;
+            case core::BuiltinFn::kRound:
+                return pb::BuiltinFn::round;
+            case core::BuiltinFn::kSaturate:
+                return pb::BuiltinFn::saturate;
+            case core::BuiltinFn::kSelect:
+                return pb::BuiltinFn::select;
+            case core::BuiltinFn::kSign:
+                return pb::BuiltinFn::sign;
+            case core::BuiltinFn::kSin:
+                return pb::BuiltinFn::sin;
+            case core::BuiltinFn::kSinh:
+                return pb::BuiltinFn::sinh;
+            case core::BuiltinFn::kSmoothstep:
+                return pb::BuiltinFn::smoothstep;
+            case core::BuiltinFn::kSqrt:
+                return pb::BuiltinFn::sqrt;
+            case core::BuiltinFn::kStep:
+                return pb::BuiltinFn::step;
+            case core::BuiltinFn::kStorageBarrier:
+                return pb::BuiltinFn::storage_barrier;
+            case core::BuiltinFn::kTan:
+                return pb::BuiltinFn::tan;
+            case core::BuiltinFn::kTanh:
+                return pb::BuiltinFn::tanh;
+            case core::BuiltinFn::kTranspose:
+                return pb::BuiltinFn::transpose;
+            case core::BuiltinFn::kTrunc:
+                return pb::BuiltinFn::trunc;
+            case core::BuiltinFn::kUnpack2X16Float:
+                return pb::BuiltinFn::unpack2x16_float;
+            case core::BuiltinFn::kUnpack2X16Snorm:
+                return pb::BuiltinFn::unpack2x16_snorm;
+            case core::BuiltinFn::kUnpack2X16Unorm:
+                return pb::BuiltinFn::unpack2x16_unorm;
+            case core::BuiltinFn::kUnpack4X8Snorm:
+                return pb::BuiltinFn::unpack4x8_snorm;
+            case core::BuiltinFn::kUnpack4X8Unorm:
+                return pb::BuiltinFn::unpack4x8_unorm;
+            case core::BuiltinFn::kWorkgroupBarrier:
+                return pb::BuiltinFn::workgroup_barrier;
+            case core::BuiltinFn::kTextureBarrier:
+                return pb::BuiltinFn::texture_barrier;
+            case core::BuiltinFn::kTextureDimensions:
+                return pb::BuiltinFn::texture_dimensions;
+            case core::BuiltinFn::kTextureGather:
+                return pb::BuiltinFn::texture_gather;
+            case core::BuiltinFn::kTextureGatherCompare:
+                return pb::BuiltinFn::texture_gather_compare;
+            case core::BuiltinFn::kTextureNumLayers:
+                return pb::BuiltinFn::texture_num_layers;
+            case core::BuiltinFn::kTextureNumLevels:
+                return pb::BuiltinFn::texture_num_levels;
+            case core::BuiltinFn::kTextureNumSamples:
+                return pb::BuiltinFn::texture_num_samples;
+            case core::BuiltinFn::kTextureSample:
+                return pb::BuiltinFn::texture_sample;
+            case core::BuiltinFn::kTextureSampleBias:
+                return pb::BuiltinFn::texture_sample_bias;
+            case core::BuiltinFn::kTextureSampleCompare:
+                return pb::BuiltinFn::texture_sample_compare;
+            case core::BuiltinFn::kTextureSampleCompareLevel:
+                return pb::BuiltinFn::texture_sample_compare_level;
+            case core::BuiltinFn::kTextureSampleGrad:
+                return pb::BuiltinFn::texture_sample_grad;
+            case core::BuiltinFn::kTextureSampleLevel:
+                return pb::BuiltinFn::texture_sample_level;
+            case core::BuiltinFn::kTextureSampleBaseClampToEdge:
+                return pb::BuiltinFn::texture_sample_base_clamp_to_edge;
+            case core::BuiltinFn::kTextureStore:
+                return pb::BuiltinFn::texture_store;
+            case core::BuiltinFn::kTextureLoad:
+                return pb::BuiltinFn::texture_load;
+            case core::BuiltinFn::kAtomicLoad:
+                return pb::BuiltinFn::atomic_load;
+            case core::BuiltinFn::kAtomicStore:
+                return pb::BuiltinFn::atomic_store;
+            case core::BuiltinFn::kAtomicAdd:
+                return pb::BuiltinFn::atomic_add;
+            case core::BuiltinFn::kAtomicSub:
+                return pb::BuiltinFn::atomic_sub;
+            case core::BuiltinFn::kAtomicMax:
+                return pb::BuiltinFn::atomic_max;
+            case core::BuiltinFn::kAtomicMin:
+                return pb::BuiltinFn::atomic_min;
+            case core::BuiltinFn::kAtomicAnd:
+                return pb::BuiltinFn::atomic_and;
+            case core::BuiltinFn::kAtomicOr:
+                return pb::BuiltinFn::atomic_or;
+            case core::BuiltinFn::kAtomicXor:
+                return pb::BuiltinFn::atomic_xor;
+            case core::BuiltinFn::kAtomicExchange:
+                return pb::BuiltinFn::atomic_exchange;
+            case core::BuiltinFn::kAtomicCompareExchangeWeak:
+                return pb::BuiltinFn::atomic_compare_exchange_weak;
+            case core::BuiltinFn::kSubgroupBallot:
+                return pb::BuiltinFn::subgroup_ballot;
+            case core::BuiltinFn::kSubgroupBroadcast:
+                return pb::BuiltinFn::subgroup_broadcast;
+            default:
+                break;
+        }
+        TINT_ICE() << "invalid BuiltinFn: " << in;
+        return pb::BuiltinFn::abs;
+    }
 };
 
 }  // namespace
diff --git a/src/tint/lang/core/ir/binary/ir.proto b/src/tint/lang/core/ir/binary/ir.proto
index fff8d02..95a3d21 100644
--- a/src/tint/lang/core/ir/binary/ir.proto
+++ b/src/tint/lang/core/ir/binary/ir.proto
@@ -48,7 +48,8 @@
         TypeMatrix matrix = 3;
         TypeArray array = 4;
         TypePointer pointer = 5;
-        uint32 atomic = 6;  // Module.types
+        TypeStruct struct = 6;
+        TypeAtomic atomic = 7;
         // TODO: textures, samplers
     }
 }
@@ -86,6 +87,23 @@
     AccessControl access = 3;
 }
 
+message TypeStruct {
+    string name = 1;
+    repeated TypeStructMember member = 2;
+}
+
+message TypeStructMember {
+    string name = 1;
+    uint32 type = 2;
+    uint32 size = 3;
+    uint32 align = 4;
+    optional AttributesStructMember attributes = 5;
+}
+
+message TypeAtomic {
+    uint32 type = 1;  // Module.types
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Values
 ////////////////////////////////////////////////////////////////////////////////
@@ -183,18 +201,21 @@
         InstructionUnary unary = 4;
         InstructionBinary binary = 5;
         InstructionBuiltin builtin = 6;
-        InstructionConstructor constructor = 7;
-        InstructionDiscard discard = 8;
-        InstructionLet let = 9;
-        InstructionVar var = 10;
-        InstructionConstruct construct = 11;
+        InstructionDiscard discard = 7;
+        InstructionLet let = 8;
+        InstructionVar var = 9;
+        InstructionConstruct construct = 10;
+        InstructionConvert convert = 11;
         InstructionAccess access = 12;
         InstructionUserCall user_call = 13;
-        InstructionLoad load = 14;
-        InstructionStore store = 15;
-        InstructionLoadVectorElement load_vector_element = 16;
-        InstructionStoreVectorElement store_vector_element = 17;
-        InstructionSwizzle swizzle = 18;
+        InstructionBuiltinCall builtin_call = 14;
+        InstructionLoad load = 15;
+        InstructionStore store = 16;
+        InstructionLoadVectorElement load_vector_element = 17;
+        InstructionStoreVectorElement store_vector_element = 18;
+        InstructionSwizzle swizzle = 19;
+        InstructionIf if = 20;
+        InstructionExitIf exit_if = 21;
     }
 }
 
@@ -222,10 +243,16 @@
 
 message InstructionConstruct {}
 
+message InstructionConvert {}
+
 message InstructionAccess {}
 
 message InstructionUserCall {}
 
+message InstructionBuiltinCall {
+    BuiltinFn builtin = 1;
+}
+
 message InstructionLoad {}
 
 message InstructionStore {}
@@ -238,12 +265,36 @@
     repeated uint32 indices = 1;
 }
 
+message InstructionIf {
+    optional uint32 true = 1;   // Module.blocks
+    optional uint32 false = 2;  // Module.blocks
+}
+
+message InstructionExitIf {}
+
 message BindingPoint {
     uint32 group = 1;
     uint32 binding = 2;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// Attributes
+////////////////////////////////////////////////////////////////////////////////
+message AttributesStructMember {
+    optional uint32 location = 1;
+    optional uint32 index = 2;
+    optional uint32 color = 3;
+    optional BuiltinValue builtin = 4;
+    optional AttributesInterpolation interpolation = 5;
+    optional bool invariant = 6;
+}
+
+message AttributesInterpolation {
+    InterpolationType type = 1;
+    optional InterpolationSampling sampling = 2;
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Enums
 ////////////////////////////////////////////////////////////////////////////////
 enum AddressSpace {
@@ -286,3 +337,151 @@
     shift_left = 14;
     shift_right = 15;
 }
+
+enum InterpolationType {
+    flat = 0;
+    linear = 1;
+    perspective = 2;
+}
+
+enum InterpolationSampling {
+    center = 0;
+    centroid = 1;
+    sample = 2;
+}
+
+enum BuiltinValue {
+    point_size = 0;
+    frag_depth = 1;
+    front_facing = 2;
+    global_invocation_id = 3;
+    instance_index = 4;
+    local_invocation_id = 5;
+    local_invocation_index = 6;
+    num_workgroups = 7;
+    position = 8;
+    sample_index = 9;
+    sample_mask = 10;
+    subgroup_invocation_id = 11;
+    subgroup_size = 12;
+    vertex_index = 13;
+    workgroup_id = 14;
+}
+
+enum BuiltinFn {
+    abs = 0;
+    acos = 1;
+    acosh = 2;
+    all = 3;
+    any = 4;
+    array_length = 5;
+    asin = 6;
+    asinh = 7;
+    atan = 8;
+    atan2 = 9;
+    atanh = 10;
+    ceil = 11;
+    clamp = 12;
+    cos = 13;
+    cosh = 14;
+    count_leading_zeros = 15;
+    count_one_bits = 16;
+    count_trailing_zeros = 17;
+    cross = 18;
+    degrees = 19;
+    determinant = 20;
+    distance = 21;
+    dot = 22;
+    dot4i8_packed = 23;
+    dot4u8_packed = 24;
+    dpdx = 25;
+    dpdx_coarse = 26;
+    dpdx_fine = 27;
+    dpdy = 28;
+    dpdy_coarse = 29;
+    dpdy_fine = 30;
+    exp = 31;
+    exp2 = 32;
+    extract_bits = 33;
+    face_forward = 34;
+    first_leading_bit = 35;
+    first_trailing_bit = 36;
+    floor = 37;
+    fma = 38;
+    fract = 39;
+    frexp = 40;
+    fwidth = 41;
+    fwidth_coarse = 42;
+    fwidth_fine = 43;
+    insert_bits = 44;
+    inverse_sqrt = 45;
+    ldexp = 46;
+    length = 47;
+    log = 48;
+    log2 = 49;
+    max = 50;
+    min = 51;
+    mix = 52;
+    modf = 53;
+    normalize = 54;
+    pack2x16_float = 55;
+    pack2x16_snorm = 56;
+    pack2x16_unorm = 57;
+    pack4x8_snorm = 58;
+    pack4x8_unorm = 59;
+    pow = 60;
+    quantize_to_f16 = 61;
+    radians = 62;
+    reflect = 63;
+    refract = 64;
+    reverse_bits = 65;
+    round = 66;
+    saturate = 67;
+    select = 68;
+    sign = 69;
+    sin = 70;
+    sinh = 71;
+    smoothstep = 72;
+    sqrt = 73;
+    step = 74;
+    storage_barrier = 75;
+    tan = 76;
+    tanh = 77;
+    transpose = 78;
+    trunc = 79;
+    unpack2x16_float = 80;
+    unpack2x16_snorm = 81;
+    unpack2x16_unorm = 82;
+    unpack4x8_snorm = 83;
+    unpack4x8_unorm = 84;
+    workgroup_barrier = 85;
+    texture_barrier = 86;
+    texture_dimensions = 87;
+    texture_gather = 88;
+    texture_gather_compare = 89;
+    texture_num_layers = 90;
+    texture_num_levels = 91;
+    texture_num_samples = 92;
+    texture_sample = 93;
+    texture_sample_bias = 94;
+    texture_sample_compare = 95;
+    texture_sample_compare_level = 96;
+    texture_sample_grad = 97;
+    texture_sample_level = 98;
+    texture_sample_base_clamp_to_edge = 99;
+    texture_store = 100;
+    texture_load = 101;
+    atomic_load = 102;
+    atomic_store = 103;
+    atomic_add = 104;
+    atomic_sub = 105;
+    atomic_max = 106;
+    atomic_min = 107;
+    atomic_and = 108;
+    atomic_or = 109;
+    atomic_xor = 110;
+    atomic_exchange = 111;
+    atomic_compare_exchange_weak = 112;
+    subgroup_ballot = 113;
+    subgroup_broadcast = 114;
+}
diff --git a/src/tint/lang/core/ir/binary/roundtrip_test.cc b/src/tint/lang/core/ir/binary/roundtrip_test.cc
index 57ade4e..6fbb02a 100644
--- a/src/tint/lang/core/ir/binary/roundtrip_test.cc
+++ b/src/tint/lang/core/ir/binary/roundtrip_test.cc
@@ -87,6 +87,7 @@
     });
     RUN_TEST();
 }
+
 ////////////////////////////////////////////////////////////////////////////////
 // Functions
 ////////////////////////////////////////////////////////////////////////////////
@@ -123,6 +124,120 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// Types
+////////////////////////////////////////////////////////////////////////////////
+TEST_F(IRBinaryRoundtripTest, bool) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, bool>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, i32) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, i32>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, u32) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, u32>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, f32) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, f32>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, f16) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, f16>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, vec2_f32) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, vec2<f32>>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, vec3_i32) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, vec3<i32>>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, vec4_bool) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, vec4<bool>>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, mat4x2_f32) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, vec4<mat4x2<f32>>>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, mat2x4_f16) {
+    b.Append(b.ir.root_block, [&] { b.Var<private_, vec4<mat2x4<f16>>>(); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, ptr_function_f32_read_write) {
+    auto p = b.FunctionParam<ptr<function, f32, read_write>>("p");
+    auto* fn = b.Function("Function", ty.void_());
+    fn->SetParams({p});
+    b.Append(fn->Block(), [&] { b.Return(fn); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, ptr_workgroup_i32_read) {
+    auto p = b.FunctionParam<ptr<workgroup, i32, read>>("p");
+    auto* fn = b.Function("Function", ty.void_());
+    fn->SetParams({p});
+    b.Append(fn->Block(), [&] { b.Return(fn); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, struct) {
+    Vector members{
+        ty.Get<core::type::StructMember>(b.ir.symbols.New("a"), ty.i32(), /* index */ 0u,
+                                         /* offset */ 0u, /* align */ 4u, /* size */ 4u,
+                                         type::StructMemberAttributes{}),
+        ty.Get<core::type::StructMember>(b.ir.symbols.New("b"), ty.f32(), /* index */ 1u,
+                                         /* offset */ 4u, /* align */ 4u, /* size */ 32u,
+                                         type::StructMemberAttributes{}),
+        ty.Get<core::type::StructMember>(b.ir.symbols.New("c"), ty.u32(), /* index */ 2u,
+                                         /* offset */ 36u, /* align */ 4u, /* size */ 4u,
+                                         type::StructMemberAttributes{}),
+        ty.Get<core::type::StructMember>(b.ir.symbols.New("d"), ty.u32(), /* index */ 3u,
+                                         /* offset */ 64u, /* align */ 32u, /* size */ 4u,
+                                         type::StructMemberAttributes{}),
+    };
+    auto* S = ty.Struct(b.ir.symbols.New("S"), std::move(members));
+    b.Append(b.ir.root_block, [&] { b.Var(ty.ptr<function, read_write>(S)); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, StructMemberAttributes) {
+    type::StructMemberAttributes attrs{};
+    attrs.location = 1;
+    attrs.index = 2;
+    attrs.color = 3;
+    attrs.builtin = core::BuiltinValue::kFragDepth;
+    attrs.interpolation = core::Interpolation{
+        core::InterpolationType::kLinear,
+        core::InterpolationSampling::kCentroid,
+    };
+    attrs.invariant = true;
+    Vector members{
+        ty.Get<core::type::StructMember>(b.ir.symbols.New("a"), ty.i32(), /* index */ 0u,
+                                         /* offset */ 0u, /* align */ 4u, /* size */ 4u, attrs),
+    };
+    auto* S = ty.Struct(b.ir.symbols.New("S"), std::move(members));
+    b.Append(b.ir.root_block, [&] { b.Var(ty.ptr<function, read_write>(S)); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, atomic_i32) {
+    b.Append(b.ir.root_block, [&] { b.Var<storage, atomic<i32>>(); });
+    RUN_TEST();
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Instructions
 ////////////////////////////////////////////////////////////////////////////////
 TEST_F(IRBinaryRoundtripTest, Return) {
@@ -249,6 +364,12 @@
     RUN_TEST();
 }
 
+TEST_F(IRBinaryRoundtripTest, BuiltinCall) {
+    auto* fn = b.Function("Function", ty.f32());
+    b.Append(fn->Block(), [&] { b.Return(fn, b.Call<i32>(core::BuiltinFn::kMax, 1_i, 2_i)); });
+    RUN_TEST();
+}
+
 TEST_F(IRBinaryRoundtripTest, Load) {
     auto p = b.FunctionParam<ptr<function, f32, read_write>>("p");
     auto* fn = b.Function("Function", ty.f32());
@@ -288,7 +409,7 @@
 }
 
 TEST_F(IRBinaryRoundtripTest, UnaryOp) {
-    auto x = b.FunctionParam<bool>("x");
+    auto* x = b.FunctionParam<bool>("x");
     auto* fn = b.Function("Function", ty.bool_());
     fn->SetParams({x});
     b.Append(fn->Block(), [&] { b.Return(fn, b.Not<bool>(x)); });
@@ -296,8 +417,8 @@
 }
 
 TEST_F(IRBinaryRoundtripTest, BinaryOp) {
-    auto x = b.FunctionParam<f32>("x");
-    auto y = b.FunctionParam<f32>("y");
+    auto* x = b.FunctionParam<f32>("x");
+    auto* y = b.FunctionParam<f32>("y");
     auto* fn = b.Function("Function", ty.f32());
     fn->SetParams({x, y});
     b.Append(fn->Block(), [&] { b.Return(fn, b.Add<f32>(x, y)); });
@@ -305,7 +426,7 @@
 }
 
 TEST_F(IRBinaryRoundtripTest, Swizzle) {
-    auto x = b.FunctionParam<vec4<f32>>("x");
+    auto* x = b.FunctionParam<vec4<f32>>("x");
     auto* fn = b.Function("Function", ty.vec3<f32>());
     fn->SetParams({x});
     b.Append(fn->Block(), [&] {
@@ -314,5 +435,67 @@
     RUN_TEST();
 }
 
+TEST_F(IRBinaryRoundtripTest, Convert) {
+    auto* x = b.FunctionParam<vec4<f32>>("x");
+    auto* fn = b.Function("Function", ty.vec4<u32>());
+    fn->SetParams({x});
+    b.Append(fn->Block(), [&] { b.Return(fn, b.Convert<vec4<u32>>(x)); });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, IfTrue) {
+    auto* cond = b.FunctionParam<bool>("cond");
+    auto* x = b.FunctionParam<i32>("x");
+    auto* fn = b.Function("Function", ty.i32());
+    fn->SetParams({cond, x});
+    b.Append(fn->Block(), [&] {
+        auto* if_ = b.If(cond);
+        b.Append(if_->True(), [&] { b.Return(fn, x); });
+    });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, IfFalse) {
+    auto* cond = b.FunctionParam<bool>("cond");
+    auto* x = b.FunctionParam<i32>("x");
+    auto* fn = b.Function("Function", ty.i32());
+    fn->SetParams({cond, x});
+    b.Append(fn->Block(), [&] {
+        auto* if_ = b.If(cond);
+        b.Append(if_->False(), [&] { b.Return(fn, x); });
+    });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, IfTrueFalse) {
+    auto* cond = b.FunctionParam<bool>("cond");
+    auto* x = b.FunctionParam<i32>("x");
+    auto* y = b.FunctionParam<i32>("y");
+    auto* fn = b.Function("Function", ty.i32());
+    fn->SetParams({cond, x, y});
+    b.Append(fn->Block(), [&] {
+        auto* if_ = b.If(cond);
+        b.Append(if_->True(), [&] { b.Return(fn, x); });
+        b.Append(if_->False(), [&] { b.Return(fn, y); });
+    });
+    RUN_TEST();
+}
+
+TEST_F(IRBinaryRoundtripTest, IfResults) {
+    auto* cond = b.FunctionParam<bool>("cond");
+    auto* fn = b.Function("Function", ty.i32());
+    fn->SetParams({cond});
+    b.Append(fn->Block(), [&] {
+        auto* if_ = b.If(cond);
+        auto* res_a = b.InstructionResult<i32>();
+        auto* res_b = b.InstructionResult<f32>();
+        if_->SetResults(Vector{res_a, res_b});
+        b.Append(if_->True(), [&] { b.ExitIf(if_, 1_i, 2_f); });
+        b.Append(if_->False(), [&] { b.ExitIf(if_, 3_i, 4_f); });
+        b.Return(fn, res_a);
+    });
+    RUN_TEST();
+}
+
 }  // namespace
 }  // namespace tint::core::ir::binary
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index bdbd507..ed5ed77 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -1364,6 +1364,15 @@
         return ir.values.Create<ir::InstructionResult>(type);
     }
 
+    /// Creates a new runtime value
+    /// @tparam TYPE the return type
+    /// @returns the value
+    template <typename TYPE>
+    ir::InstructionResult* InstructionResult() {
+        auto* type = ir.Types().Get<TYPE>();
+        return InstructionResult(type);
+    }
+
     /// Create a ranged loop with a callback to build the loop body.
     /// @param ty the type manager to use for new types
     /// @param start the first loop index
diff --git a/src/tint/lang/core/ir/builtin_call.cc b/src/tint/lang/core/ir/builtin_call.cc
index f6f3173..5c38785 100644
--- a/src/tint/lang/core/ir/builtin_call.cc
+++ b/src/tint/lang/core/ir/builtin_call.cc
@@ -33,6 +33,10 @@
 
 namespace tint::core::ir {
 
+BuiltinCall::BuiltinCall() {
+    flags_.Add(Flag::kSequenced);
+}
+
 BuiltinCall::BuiltinCall(InstructionResult* result, VectorRef<Value*> arguments) {
     flags_.Add(Flag::kSequenced);
     AddOperands(BuiltinCall::kArgsOperandOffset, std::move(arguments));
diff --git a/src/tint/lang/core/ir/builtin_call.h b/src/tint/lang/core/ir/builtin_call.h
index 0351ff4..1b752ec 100644
--- a/src/tint/lang/core/ir/builtin_call.h
+++ b/src/tint/lang/core/ir/builtin_call.h
@@ -40,6 +40,9 @@
     /// The base offset in Operands() for the args
     static constexpr size_t kArgsOperandOffset = 0;
 
+    /// Constructor (no results, no operands)
+    BuiltinCall();
+
     /// Constructor
     /// @param result the result value
     /// @param args the conversion arguments
diff --git a/src/tint/lang/core/ir/convert.cc b/src/tint/lang/core/ir/convert.cc
index 4a479de..3c4ac56 100644
--- a/src/tint/lang/core/ir/convert.cc
+++ b/src/tint/lang/core/ir/convert.cc
@@ -36,6 +36,8 @@
 
 namespace tint::core::ir {
 
+Convert::Convert() = default;
+
 Convert::Convert(InstructionResult* result, Value* value) {
     AddOperand(Convert::kValueOperandOffset, value);
     AddResult(result);
diff --git a/src/tint/lang/core/ir/convert.h b/src/tint/lang/core/ir/convert.h
index 20350aa..f0aed80 100644
--- a/src/tint/lang/core/ir/convert.h
+++ b/src/tint/lang/core/ir/convert.h
@@ -42,6 +42,9 @@
     /// The offset in Operands() for the value
     static constexpr size_t kValueOperandOffset = 0;
 
+    /// Constructor (no results, no operands)
+    Convert();
+
     /// Constructor
     /// @param result the result value
     /// @param value the value to convert
diff --git a/src/tint/lang/core/ir/core_builtin_call.cc b/src/tint/lang/core/ir/core_builtin_call.cc
index 33e38b5..bb876cf 100644
--- a/src/tint/lang/core/ir/core_builtin_call.cc
+++ b/src/tint/lang/core/ir/core_builtin_call.cc
@@ -37,6 +37,8 @@
 
 namespace tint::core::ir {
 
+CoreBuiltinCall::CoreBuiltinCall() = default;
+
 CoreBuiltinCall::CoreBuiltinCall(InstructionResult* result,
                                  core::BuiltinFn func,
                                  VectorRef<Value*> arguments)
diff --git a/src/tint/lang/core/ir/core_builtin_call.h b/src/tint/lang/core/ir/core_builtin_call.h
index 9e7e9f0..f153c7c 100644
--- a/src/tint/lang/core/ir/core_builtin_call.h
+++ b/src/tint/lang/core/ir/core_builtin_call.h
@@ -41,6 +41,9 @@
 /// A core builtin call instruction in the IR.
 class CoreBuiltinCall final : public Castable<CoreBuiltinCall, BuiltinCall> {
   public:
+    /// Constructor (no results, no operands)
+    CoreBuiltinCall();
+
     /// Constructor
     /// @param result the result value
     /// @param func the builtin function
@@ -56,6 +59,9 @@
     /// @returns the builtin function
     core::BuiltinFn Func() const { return func_; }
 
+    /// @param func the new builtin function
+    void SetFunc(core::BuiltinFn func) { func_ = func; }
+
     /// @returns the identifier for the function
     size_t FuncId() const override { return static_cast<size_t>(func_); }
 
diff --git a/src/tint/lang/core/ir/exit_if.cc b/src/tint/lang/core/ir/exit_if.cc
index 74cd394..5130495 100644
--- a/src/tint/lang/core/ir/exit_if.cc
+++ b/src/tint/lang/core/ir/exit_if.cc
@@ -38,6 +38,8 @@
 
 namespace tint::core::ir {
 
+ExitIf::ExitIf() = default;
+
 ExitIf::ExitIf(ir::If* i, VectorRef<Value*> args) {
     SetIf(i);
     AddOperands(ExitIf::kArgsOperandOffset, std::move(args));
diff --git a/src/tint/lang/core/ir/exit_if.h b/src/tint/lang/core/ir/exit_if.h
index 3b6f568..b561466 100644
--- a/src/tint/lang/core/ir/exit_if.h
+++ b/src/tint/lang/core/ir/exit_if.h
@@ -46,6 +46,9 @@
     /// The base offset in Operands() for the args
     static constexpr size_t kArgsOperandOffset = 0;
 
+    /// Constructor (no operands, no if)
+    ExitIf();
+
     /// Constructor
     /// @param i the if being exited
     /// @param args the target MultiInBlock arguments
diff --git a/src/tint/lang/core/ir/if.cc b/src/tint/lang/core/ir/if.cc
index 90637a3..f50abf0 100644
--- a/src/tint/lang/core/ir/if.cc
+++ b/src/tint/lang/core/ir/if.cc
@@ -36,6 +36,8 @@
 
 namespace tint::core::ir {
 
+If::If() = default;
+
 If::If(Value* cond, ir::Block* t, ir::Block* f) : true_(t), false_(f) {
     TINT_ASSERT(true_);
     TINT_ASSERT(false_);
@@ -77,4 +79,24 @@
     return new_if;
 }
 
+void If::SetTrue(ir::Block* block) {
+    if (true_ && true_->Parent() == this) {
+        true_->SetParent(nullptr);
+    }
+    true_ = block;
+    if (block) {
+        block->SetParent(this);
+    }
+}
+
+void If::SetFalse(ir::Block* block) {
+    if (false_ && false_->Parent() == this) {
+        false_->SetParent(nullptr);
+    }
+    false_ = block;
+    if (block) {
+        block->SetParent(this);
+    }
+}
+
 }  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/if.h b/src/tint/lang/core/ir/if.h
index cc03e63..7dfe6d2 100644
--- a/src/tint/lang/core/ir/if.h
+++ b/src/tint/lang/core/ir/if.h
@@ -61,6 +61,9 @@
     /// The index of the condition operand
     static constexpr size_t kConditionOperandOffset = 0;
 
+    /// Constructor (no results, no operands, no blocks)
+    If();
+
     /// Constructor
     /// @param cond the if condition
     /// @param t the true block
@@ -86,12 +89,18 @@
     /// @returns the true block
     const ir::Block* True() const { return true_; }
 
+    /// @param block the new true block
+    void SetTrue(ir::Block* block);
+
     /// @returns the false block
     ir::Block* False() { return false_; }
 
     /// @returns the false block
     const ir::Block* False() const { return false_; }
 
+    /// @param block the new false block
+    void SetFalse(ir::Block* block);
+
     /// @returns the friendly name for the instruction
     std::string FriendlyName() const override { return "if"; }
 
diff --git a/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc b/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
index 7b8a407..e1d77c1 100644
--- a/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
+++ b/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
@@ -77,7 +77,10 @@
             return "DirectVariableAccess failed:\n" + res.Failure().reason.str();
         }
 
-        auto transformed = wgsl::writer::IRToProgram(module.Get());
+        wgsl::writer::ProgramOptions program_options;
+        program_options.allowed_features.extensions.insert(
+            wgsl::Extension::kChromiumExperimentalFullPtrParameters);
+        auto transformed = wgsl::writer::IRToProgram(module.Get(), program_options);
         if (!transformed.IsValid()) {
             return "wgsl::writer::IRToProgram() failed: \n" + transformed.Diagnostics().str() +
                    "\n\nIR:\n" + ir::Disassemble(module.Get()) +  //
diff --git a/src/tint/lang/core/type/manager.cc b/src/tint/lang/core/type/manager.cc
index a3473ca..50c1a39 100644
--- a/src/tint/lang/core/type/manager.cc
+++ b/src/tint/lang/core/type/manager.cc
@@ -192,8 +192,18 @@
     return Get<core::type::Pointer>(address_space, subtype, access);
 }
 
+core::type::Struct* Manager::Struct(Symbol name, VectorRef<const StructMember*> members) {
+    uint32_t max_align = 0u;
+    for (const auto& m : members) {
+        max_align = std::max(max_align, m->Align());
+    }
+    uint32_t size = members.Back()->Offset() + members.Back()->Size();
+    return Get<core::type::Struct>(name, std::move(members), max_align,
+                                   tint::RoundUp(max_align, size), size);
+}
+
 core::type::Struct* Manager::Struct(Symbol name, VectorRef<StructMemberDesc> md) {
-    tint::Vector<const core::type::StructMember*, 4> members;
+    tint::Vector<const StructMember*, 4> members;
     uint32_t current_size = 0u;
     uint32_t max_align = 0u;
     for (const auto& m : md) {
@@ -205,8 +215,8 @@
         current_size = offset + m.type->Size();
         max_align = std::max(max_align, align);
     }
-    return Get<core::type::Struct>(name, members, max_align, tint::RoundUp(max_align, current_size),
-                                   current_size);
+    return Get<core::type::Struct>(name, std::move(members), max_align,
+                                   tint::RoundUp(max_align, current_size), current_size);
 }
 
 }  // namespace tint::core::type
diff --git a/src/tint/lang/core/type/manager.h b/src/tint/lang/core/type/manager.h
index 8f361da..d88e084 100644
--- a/src/tint/lang/core/type/manager.h
+++ b/src/tint/lang/core/type/manager.h
@@ -451,6 +451,12 @@
 
     /// Create a new structure declaration.
     /// @param name the name of the structure
+    /// @param members the list of structure members
+    /// @returns the structure type
+    core::type::Struct* Struct(Symbol name, VectorRef<const StructMember*> members);
+
+    /// Create a new structure declaration.
+    /// @param name the name of the structure
     /// @param members the list of structure member descriptors
     /// @returns the structure type
     core::type::Struct* Struct(Symbol name, VectorRef<StructMemberDesc> members);
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
index 8e05047..540f314 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
@@ -104,6 +104,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
index 8fd03ab..0ca869d 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
@@ -108,6 +108,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
index 38e3359..23c0067 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
@@ -108,6 +108,7 @@
         "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
index 1af1d58..dea6056 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
@@ -111,6 +111,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
index ad2de08..71a814c 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
@@ -115,6 +115,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn b/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
index c009305..8ac7972 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
@@ -115,6 +115,7 @@
         "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
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 a662d59..75c793b 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -1383,8 +1383,8 @@
                                       const sem::BuiltinFn* builtin) {
     return CallBuiltinHelper(
         out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
-            Line(b) << "packed_char4 vec1 = as_type<packed_char4>(" << params[0] << ");";
-            Line(b) << "packed_char4 vec2 = as_type<packed_char4>(" << params[1] << ");";
+            Line(b) << "char4 vec1 = as_type<char4>(" << params[0] << ");";
+            Line(b) << "char4 vec2 = as_type<char4>(" << params[1] << ");";
             Line(b) << "return vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2] + vec1[3] "
                        "* vec2[3];";
             return true;
@@ -1396,8 +1396,8 @@
                                       const sem::BuiltinFn* builtin) {
     return CallBuiltinHelper(
         out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
-            Line(b) << "packed_uchar4 vec1 = as_type<packed_uchar4>(" << params[0] << ");";
-            Line(b) << "packed_uchar4 vec2 = as_type<packed_uchar4>(" << params[1] << ");";
+            Line(b) << "uchar4 vec1 = as_type<uchar4>(" << params[0] << ");";
+            Line(b) << "uchar4 vec2 = as_type<uchar4>(" << params[1] << ");";
             Line(b) << "return vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2] + vec1[3] "
                        "* vec2[3];";
             return true;
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
index 8b2b905..3764a2a 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
@@ -103,6 +103,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
index 93fb394..4366d7c 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
@@ -107,6 +107,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.gn b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
index f5d025c..c3f0123 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
@@ -107,6 +107,7 @@
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/resolver",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/spirv/reader/BUILD.bazel b/src/tint/lang/spirv/reader/BUILD.bazel
index 599d625..8be26f4 100644
--- a/src/tint/lang/spirv/reader/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/BUILD.bazel
@@ -45,8 +45,10 @@
     "reader.h",
   ],
   deps = [
+    "//src/tint/api/common",
     "//src/tint/lang/core",
     "//src/tint/lang/core/constant",
+    "//src/tint/lang/core/ir",
     "//src/tint/lang/core/type",
     "//src/tint/lang/spirv/reader/common",
     "//src/tint/lang/wgsl",
diff --git a/src/tint/lang/spirv/reader/BUILD.cmake b/src/tint/lang/spirv/reader/BUILD.cmake
index 46c4639..bda6ba0 100644
--- a/src/tint/lang/spirv/reader/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/BUILD.cmake
@@ -50,8 +50,10 @@
 )
 
 tint_target_add_dependencies(tint_lang_spirv_reader lib
+  tint_api_common
   tint_lang_core
   tint_lang_core_constant
+  tint_lang_core_ir
   tint_lang_core_type
   tint_lang_spirv_reader_common
   tint_lang_wgsl
diff --git a/src/tint/lang/spirv/reader/BUILD.gn b/src/tint/lang/spirv/reader/BUILD.gn
index e6eb783..5075295 100644
--- a/src/tint/lang/spirv/reader/BUILD.gn
+++ b/src/tint/lang/spirv/reader/BUILD.gn
@@ -44,8 +44,10 @@
       "reader.h",
     ]
     deps = [
+      "${tint_src_dir}/api/common",
       "${tint_src_dir}/lang/core",
       "${tint_src_dir}/lang/core/constant",
+      "${tint_src_dir}/lang/core/ir",
       "${tint_src_dir}/lang/core/type",
       "${tint_src_dir}/lang/spirv/reader/common",
       "${tint_src_dir}/lang/wgsl",
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel b/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
index 0fdbcd1..b89ad46 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
@@ -106,6 +106,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake b/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
index 1f1a04c..53e39c3 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
@@ -110,6 +110,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.gn b/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
index 9381efc..e6703a4 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
@@ -110,6 +110,7 @@
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/resolver",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/spirv/reader/reader.cc b/src/tint/lang/spirv/reader/reader.cc
index bc795ef..3e7ce9a 100644
--- a/src/tint/lang/spirv/reader/reader.cc
+++ b/src/tint/lang/spirv/reader/reader.cc
@@ -29,10 +29,16 @@
 
 #include <utility>
 
+#include "src/tint/lang/core/ir/module.h"
 #include "src/tint/lang/spirv/reader/ast_parser/parse.h"
 
 namespace tint::spirv::reader {
 
+Result<core::ir::Module> ReadIR(const std::vector<uint32_t>& input) {
+    (void)input;
+    return Failure("SPIR-V to IR reader is unimplemented");
+}
+
 Program Read(const std::vector<uint32_t>& input, const Options& options) {
     return ast_parser::Parse(input, options);
 }
diff --git a/src/tint/lang/spirv/reader/reader.h b/src/tint/lang/spirv/reader/reader.h
index b1cc888..9bcd99e 100644
--- a/src/tint/lang/spirv/reader/reader.h
+++ b/src/tint/lang/spirv/reader/reader.h
@@ -33,8 +33,20 @@
 #include "src/tint/lang/spirv/reader/common/options.h"
 #include "src/tint/lang/wgsl/program/program.h"
 
+// Forward declarations
+namespace tint::core::ir {
+class Module;
+}
+
 namespace tint::spirv::reader {
 
+/// Reads the SPIR-V source data, returning a core IR module.
+/// If the SPIR-V binary fails to parse then the result will contain diagnostic error messages.
+/// TODO(crbug.com/tint/1907): Rename when we remove the AST path.
+/// @param input the SPIR-V binary data
+/// @returns the Tint IR module
+Result<core::ir::Module> ReadIR(const std::vector<uint32_t>& input);
+
 /// Reads the SPIR-V source data, returning the parsed program.
 /// If the source data fails to parse then the returned
 /// `program.Diagnostics.contains_errors()` will be true, and the
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
index ac25dcc..e13d946 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
@@ -108,6 +108,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
index b79c8bb..9cd1d16 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
@@ -112,6 +112,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
index ba17c58..b18ddb5 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
@@ -112,6 +112,7 @@
         "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/BUILD.bazel b/src/tint/lang/wgsl/ast/BUILD.bazel
index c44c746..6eca7ad 100644
--- a/src/tint/lang/wgsl/ast/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/BUILD.bazel
@@ -318,6 +318,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/BUILD.cmake b/src/tint/lang/wgsl/ast/BUILD.cmake
index 3664cd7..767496f 100644
--- a/src/tint/lang/wgsl/ast/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/BUILD.cmake
@@ -310,6 +310,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/wgsl/ast/BUILD.gn b/src/tint/lang/wgsl/ast/BUILD.gn
index fe2138f..f42bd86 100644
--- a/src/tint/lang/wgsl/ast/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/BUILD.gn
@@ -310,6 +310,7 @@
       "${tint_src_dir}/lang/wgsl/program",
       "${tint_src_dir}/lang/wgsl/resolver",
       "${tint_src_dir}/lang/wgsl/sem",
+      "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
       "${tint_src_dir}/utils/containers",
       "${tint_src_dir}/utils/diagnostic",
       "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.bazel b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
index c8ff399..cb9c9b1 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
@@ -192,6 +192,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.cmake b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
index 35b0dcc..c432f09 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
@@ -193,6 +193,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.gn b/src/tint/lang/wgsl/ast/transform/BUILD.gn
index e0af19e..1214968 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.gn
@@ -194,6 +194,7 @@
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/resolver",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/intrinsic/data.cc b/src/tint/lang/wgsl/intrinsic/data.cc
index 13b1e8d..677c7ad 100644
--- a/src/tint/lang/wgsl/intrinsic/data.cc
+++ b/src/tint/lang/wgsl/intrinsic/data.cc
@@ -4802,89 +4802,91 @@
   /* [19] */ &core::constant::Eval::determinant,
   /* [20] */ &core::constant::Eval::distance,
   /* [21] */ &core::constant::Eval::dot,
-  /* [22] */ &core::constant::Eval::exp,
-  /* [23] */ &core::constant::Eval::exp2,
-  /* [24] */ &core::constant::Eval::extractBits,
-  /* [25] */ &core::constant::Eval::faceForward,
-  /* [26] */ &core::constant::Eval::firstLeadingBit,
-  /* [27] */ &core::constant::Eval::firstTrailingBit,
-  /* [28] */ &core::constant::Eval::floor,
-  /* [29] */ &core::constant::Eval::fma,
-  /* [30] */ &core::constant::Eval::fract,
-  /* [31] */ &core::constant::Eval::frexp,
-  /* [32] */ &core::constant::Eval::insertBits,
-  /* [33] */ &core::constant::Eval::inverseSqrt,
-  /* [34] */ &core::constant::Eval::ldexp,
-  /* [35] */ &core::constant::Eval::length,
-  /* [36] */ &core::constant::Eval::log,
-  /* [37] */ &core::constant::Eval::log2,
-  /* [38] */ &core::constant::Eval::max,
-  /* [39] */ &core::constant::Eval::min,
-  /* [40] */ &core::constant::Eval::mix,
-  /* [41] */ &core::constant::Eval::modf,
-  /* [42] */ &core::constant::Eval::normalize,
-  /* [43] */ &core::constant::Eval::pack2x16float,
-  /* [44] */ &core::constant::Eval::pack2x16snorm,
-  /* [45] */ &core::constant::Eval::pack2x16unorm,
-  /* [46] */ &core::constant::Eval::pack4x8snorm,
-  /* [47] */ &core::constant::Eval::pack4x8unorm,
-  /* [48] */ &core::constant::Eval::pow,
-  /* [49] */ &core::constant::Eval::quantizeToF16,
-  /* [50] */ &core::constant::Eval::radians,
-  /* [51] */ &core::constant::Eval::reflect,
-  /* [52] */ &core::constant::Eval::refract,
-  /* [53] */ &core::constant::Eval::reverseBits,
-  /* [54] */ &core::constant::Eval::round,
-  /* [55] */ &core::constant::Eval::saturate,
-  /* [56] */ &core::constant::Eval::select_bool,
-  /* [57] */ &core::constant::Eval::select_boolvec,
-  /* [58] */ &core::constant::Eval::sign,
-  /* [59] */ &core::constant::Eval::sin,
-  /* [60] */ &core::constant::Eval::sinh,
-  /* [61] */ &core::constant::Eval::smoothstep,
-  /* [62] */ &core::constant::Eval::sqrt,
-  /* [63] */ &core::constant::Eval::step,
-  /* [64] */ &core::constant::Eval::tan,
-  /* [65] */ &core::constant::Eval::tanh,
-  /* [66] */ &core::constant::Eval::transpose,
-  /* [67] */ &core::constant::Eval::trunc,
-  /* [68] */ &core::constant::Eval::unpack2x16float,
-  /* [69] */ &core::constant::Eval::unpack2x16snorm,
-  /* [70] */ &core::constant::Eval::unpack2x16unorm,
-  /* [71] */ &core::constant::Eval::unpack4x8snorm,
-  /* [72] */ &core::constant::Eval::unpack4x8unorm,
-  /* [73] */ &core::constant::Eval::Identity,
-  /* [74] */ &core::constant::Eval::Not,
-  /* [75] */ &core::constant::Eval::Complement,
-  /* [76] */ &core::constant::Eval::UnaryMinus,
-  /* [77] */ &core::constant::Eval::Plus,
-  /* [78] */ &core::constant::Eval::Minus,
-  /* [79] */ &core::constant::Eval::Multiply,
-  /* [80] */ &core::constant::Eval::MultiplyMatVec,
-  /* [81] */ &core::constant::Eval::MultiplyVecMat,
-  /* [82] */ &core::constant::Eval::MultiplyMatMat,
-  /* [83] */ &core::constant::Eval::Divide,
-  /* [84] */ &core::constant::Eval::Modulo,
-  /* [85] */ &core::constant::Eval::Xor,
-  /* [86] */ &core::constant::Eval::And,
-  /* [87] */ &core::constant::Eval::Or,
-  /* [88] */ &core::constant::Eval::LogicalAnd,
-  /* [89] */ &core::constant::Eval::LogicalOr,
-  /* [90] */ &core::constant::Eval::Equal,
-  /* [91] */ &core::constant::Eval::NotEqual,
-  /* [92] */ &core::constant::Eval::LessThan,
-  /* [93] */ &core::constant::Eval::GreaterThan,
-  /* [94] */ &core::constant::Eval::LessThanEqual,
-  /* [95] */ &core::constant::Eval::GreaterThanEqual,
-  /* [96] */ &core::constant::Eval::ShiftLeft,
-  /* [97] */ &core::constant::Eval::ShiftRight,
-  /* [98] */ &core::constant::Eval::Zero,
-  /* [99] */ &core::constant::Eval::Conv,
-  /* [100] */ &core::constant::Eval::VecSplat,
-  /* [101] */ &core::constant::Eval::VecInitS,
-  /* [102] */ &core::constant::Eval::VecInitM,
-  /* [103] */ &core::constant::Eval::MatInitS,
-  /* [104] */ &core::constant::Eval::MatInitV,
+  /* [22] */ &core::constant::Eval::dot4I8Packed,
+  /* [23] */ &core::constant::Eval::dot4U8Packed,
+  /* [24] */ &core::constant::Eval::exp,
+  /* [25] */ &core::constant::Eval::exp2,
+  /* [26] */ &core::constant::Eval::extractBits,
+  /* [27] */ &core::constant::Eval::faceForward,
+  /* [28] */ &core::constant::Eval::firstLeadingBit,
+  /* [29] */ &core::constant::Eval::firstTrailingBit,
+  /* [30] */ &core::constant::Eval::floor,
+  /* [31] */ &core::constant::Eval::fma,
+  /* [32] */ &core::constant::Eval::fract,
+  /* [33] */ &core::constant::Eval::frexp,
+  /* [34] */ &core::constant::Eval::insertBits,
+  /* [35] */ &core::constant::Eval::inverseSqrt,
+  /* [36] */ &core::constant::Eval::ldexp,
+  /* [37] */ &core::constant::Eval::length,
+  /* [38] */ &core::constant::Eval::log,
+  /* [39] */ &core::constant::Eval::log2,
+  /* [40] */ &core::constant::Eval::max,
+  /* [41] */ &core::constant::Eval::min,
+  /* [42] */ &core::constant::Eval::mix,
+  /* [43] */ &core::constant::Eval::modf,
+  /* [44] */ &core::constant::Eval::normalize,
+  /* [45] */ &core::constant::Eval::pack2x16float,
+  /* [46] */ &core::constant::Eval::pack2x16snorm,
+  /* [47] */ &core::constant::Eval::pack2x16unorm,
+  /* [48] */ &core::constant::Eval::pack4x8snorm,
+  /* [49] */ &core::constant::Eval::pack4x8unorm,
+  /* [50] */ &core::constant::Eval::pow,
+  /* [51] */ &core::constant::Eval::quantizeToF16,
+  /* [52] */ &core::constant::Eval::radians,
+  /* [53] */ &core::constant::Eval::reflect,
+  /* [54] */ &core::constant::Eval::refract,
+  /* [55] */ &core::constant::Eval::reverseBits,
+  /* [56] */ &core::constant::Eval::round,
+  /* [57] */ &core::constant::Eval::saturate,
+  /* [58] */ &core::constant::Eval::select_bool,
+  /* [59] */ &core::constant::Eval::select_boolvec,
+  /* [60] */ &core::constant::Eval::sign,
+  /* [61] */ &core::constant::Eval::sin,
+  /* [62] */ &core::constant::Eval::sinh,
+  /* [63] */ &core::constant::Eval::smoothstep,
+  /* [64] */ &core::constant::Eval::sqrt,
+  /* [65] */ &core::constant::Eval::step,
+  /* [66] */ &core::constant::Eval::tan,
+  /* [67] */ &core::constant::Eval::tanh,
+  /* [68] */ &core::constant::Eval::transpose,
+  /* [69] */ &core::constant::Eval::trunc,
+  /* [70] */ &core::constant::Eval::unpack2x16float,
+  /* [71] */ &core::constant::Eval::unpack2x16snorm,
+  /* [72] */ &core::constant::Eval::unpack2x16unorm,
+  /* [73] */ &core::constant::Eval::unpack4x8snorm,
+  /* [74] */ &core::constant::Eval::unpack4x8unorm,
+  /* [75] */ &core::constant::Eval::Identity,
+  /* [76] */ &core::constant::Eval::Not,
+  /* [77] */ &core::constant::Eval::Complement,
+  /* [78] */ &core::constant::Eval::UnaryMinus,
+  /* [79] */ &core::constant::Eval::Plus,
+  /* [80] */ &core::constant::Eval::Minus,
+  /* [81] */ &core::constant::Eval::Multiply,
+  /* [82] */ &core::constant::Eval::MultiplyMatVec,
+  /* [83] */ &core::constant::Eval::MultiplyVecMat,
+  /* [84] */ &core::constant::Eval::MultiplyMatMat,
+  /* [85] */ &core::constant::Eval::Divide,
+  /* [86] */ &core::constant::Eval::Modulo,
+  /* [87] */ &core::constant::Eval::Xor,
+  /* [88] */ &core::constant::Eval::And,
+  /* [89] */ &core::constant::Eval::Or,
+  /* [90] */ &core::constant::Eval::LogicalAnd,
+  /* [91] */ &core::constant::Eval::LogicalOr,
+  /* [92] */ &core::constant::Eval::Equal,
+  /* [93] */ &core::constant::Eval::NotEqual,
+  /* [94] */ &core::constant::Eval::LessThan,
+  /* [95] */ &core::constant::Eval::GreaterThan,
+  /* [96] */ &core::constant::Eval::LessThanEqual,
+  /* [97] */ &core::constant::Eval::GreaterThanEqual,
+  /* [98] */ &core::constant::Eval::ShiftLeft,
+  /* [99] */ &core::constant::Eval::ShiftRight,
+  /* [100] */ &core::constant::Eval::Zero,
+  /* [101] */ &core::constant::Eval::Conv,
+  /* [102] */ &core::constant::Eval::VecSplat,
+  /* [103] */ &core::constant::Eval::VecInitS,
+  /* [104] */ &core::constant::Eval::VecInitM,
+  /* [105] */ &core::constant::Eval::MatInitS,
+  /* [106] */ &core::constant::Eval::MatInitV,
 };
 
 static_assert(ConstEvalFunctionIndex::CanIndex(kConstEvalFunctions),
@@ -5526,7 +5528,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(96),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [49] */
@@ -5539,7 +5541,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [50] */
@@ -5552,7 +5554,7 @@
     /* parameters */ ParameterIndex(217),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [51] */
@@ -5565,7 +5567,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(100),
+    /* const_eval_fn */ ConstEvalFunctionIndex(102),
   },
   {
     /* [52] */
@@ -5578,7 +5580,7 @@
     /* parameters */ ParameterIndex(205),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(101),
+    /* const_eval_fn */ ConstEvalFunctionIndex(103),
   },
   {
     /* [53] */
@@ -5591,7 +5593,7 @@
     /* parameters */ ParameterIndex(295),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [54] */
@@ -5604,7 +5606,7 @@
     /* parameters */ ParameterIndex(298),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [55] */
@@ -5617,7 +5619,7 @@
     /* parameters */ ParameterIndex(301),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [56] */
@@ -5630,7 +5632,7 @@
     /* parameters */ ParameterIndex(362),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [57] */
@@ -5643,7 +5645,7 @@
     /* parameters */ ParameterIndex(364),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [58] */
@@ -5656,7 +5658,7 @@
     /* parameters */ ParameterIndex(366),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [59] */
@@ -5669,7 +5671,7 @@
     /* parameters */ ParameterIndex(383),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(28),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [60] */
@@ -5682,7 +5684,7 @@
     /* parameters */ ParameterIndex(383),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(100),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [61] */
@@ -5695,7 +5697,7 @@
     /* parameters */ ParameterIndex(383),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [62] */
@@ -5708,7 +5710,7 @@
     /* parameters */ ParameterIndex(383),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [63] */
@@ -5721,7 +5723,7 @@
     /* parameters */ ParameterIndex(383),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(102),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [64] */
@@ -6423,7 +6425,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(90),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [118] */
@@ -6436,7 +6438,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [119] */
@@ -6449,7 +6451,7 @@
     /* parameters */ ParameterIndex(213),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [120] */
@@ -6462,7 +6464,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(100),
+    /* const_eval_fn */ ConstEvalFunctionIndex(102),
   },
   {
     /* [121] */
@@ -6475,7 +6477,7 @@
     /* parameters */ ParameterIndex(205),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(101),
+    /* const_eval_fn */ ConstEvalFunctionIndex(103),
   },
   {
     /* [122] */
@@ -6488,7 +6490,7 @@
     /* parameters */ ParameterIndex(295),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [123] */
@@ -6501,7 +6503,7 @@
     /* parameters */ ParameterIndex(298),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(10),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(102),
+    /* const_eval_fn */ ConstEvalFunctionIndex(104),
   },
   {
     /* [124] */
@@ -6514,7 +6516,7 @@
     /* parameters */ ParameterIndex(382),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(54),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [125] */
@@ -6527,7 +6529,7 @@
     /* parameters */ ParameterIndex(382),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(92),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [126] */
@@ -6540,7 +6542,7 @@
     /* parameters */ ParameterIndex(382),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(64),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [127] */
@@ -6553,7 +6555,7 @@
     /* parameters */ ParameterIndex(382),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(40),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [128] */
@@ -6566,7 +6568,7 @@
     /* parameters */ ParameterIndex(382),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(94),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [129] */
@@ -6709,7 +6711,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(84),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [140] */
@@ -6722,7 +6724,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [141] */
@@ -6735,7 +6737,7 @@
     /* parameters */ ParameterIndex(209),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [142] */
@@ -6748,7 +6750,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(100),
+    /* const_eval_fn */ ConstEvalFunctionIndex(102),
   },
   {
     /* [143] */
@@ -6761,7 +6763,7 @@
     /* parameters */ ParameterIndex(205),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(101),
+    /* const_eval_fn */ ConstEvalFunctionIndex(103),
   },
   {
     /* [144] */
@@ -6774,7 +6776,7 @@
     /* parameters */ ParameterIndex(381),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(26),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [145] */
@@ -6787,7 +6789,7 @@
     /* parameters */ ParameterIndex(381),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(86),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [146] */
@@ -6800,7 +6802,7 @@
     /* parameters */ ParameterIndex(381),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(52),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [147] */
@@ -6813,7 +6815,7 @@
     /* parameters */ ParameterIndex(381),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [148] */
@@ -6826,7 +6828,7 @@
     /* parameters */ ParameterIndex(381),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(88),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [149] */
@@ -6839,7 +6841,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(79),
+    /* const_eval_fn */ ConstEvalFunctionIndex(81),
   },
   {
     /* [150] */
@@ -6852,7 +6854,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(79),
+    /* const_eval_fn */ ConstEvalFunctionIndex(81),
   },
   {
     /* [151] */
@@ -6865,7 +6867,7 @@
     /* parameters */ ParameterIndex(223),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(79),
+    /* const_eval_fn */ ConstEvalFunctionIndex(81),
   },
   {
     /* [152] */
@@ -6878,7 +6880,7 @@
     /* parameters */ ParameterIndex(350),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(79),
+    /* const_eval_fn */ ConstEvalFunctionIndex(81),
   },
   {
     /* [153] */
@@ -6891,7 +6893,7 @@
     /* parameters */ ParameterIndex(355),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(2),
-    /* const_eval_fn */ ConstEvalFunctionIndex(79),
+    /* const_eval_fn */ ConstEvalFunctionIndex(81),
   },
   {
     /* [154] */
@@ -6904,7 +6906,7 @@
     /* parameters */ ParameterIndex(354),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(2),
-    /* const_eval_fn */ ConstEvalFunctionIndex(79),
+    /* const_eval_fn */ ConstEvalFunctionIndex(81),
   },
   {
     /* [155] */
@@ -6917,7 +6919,7 @@
     /* parameters */ ParameterIndex(356),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(3),
-    /* const_eval_fn */ ConstEvalFunctionIndex(80),
+    /* const_eval_fn */ ConstEvalFunctionIndex(82),
   },
   {
     /* [156] */
@@ -6930,7 +6932,7 @@
     /* parameters */ ParameterIndex(358),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(81),
+    /* const_eval_fn */ ConstEvalFunctionIndex(83),
   },
   {
     /* [157] */
@@ -6943,7 +6945,7 @@
     /* parameters */ ParameterIndex(360),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(20),
-    /* const_eval_fn */ ConstEvalFunctionIndex(82),
+    /* const_eval_fn */ ConstEvalFunctionIndex(84),
   },
   {
     /* [158] */
@@ -7398,7 +7400,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [193] */
@@ -7411,7 +7413,7 @@
     /* parameters */ ParameterIndex(384),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [194] */
@@ -7424,7 +7426,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [195] */
@@ -7437,7 +7439,7 @@
     /* parameters */ ParameterIndex(209),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [196] */
@@ -7450,7 +7452,7 @@
     /* parameters */ ParameterIndex(385),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(106),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [197] */
@@ -7463,7 +7465,7 @@
     /* parameters */ ParameterIndex(386),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(108),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [198] */
@@ -7476,7 +7478,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [199] */
@@ -7489,7 +7491,7 @@
     /* parameters */ ParameterIndex(387),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [200] */
@@ -7502,7 +7504,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [201] */
@@ -7515,7 +7517,7 @@
     /* parameters */ ParameterIndex(213),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [202] */
@@ -7528,7 +7530,7 @@
     /* parameters */ ParameterIndex(388),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(112),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [203] */
@@ -7541,7 +7543,7 @@
     /* parameters */ ParameterIndex(389),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(114),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [204] */
@@ -7554,7 +7556,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [205] */
@@ -7567,7 +7569,7 @@
     /* parameters */ ParameterIndex(390),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [206] */
@@ -7580,7 +7582,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [207] */
@@ -7593,7 +7595,7 @@
     /* parameters */ ParameterIndex(217),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [208] */
@@ -7606,7 +7608,7 @@
     /* parameters */ ParameterIndex(391),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(118),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [209] */
@@ -7619,7 +7621,7 @@
     /* parameters */ ParameterIndex(392),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(120),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [210] */
@@ -7632,7 +7634,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [211] */
@@ -7645,7 +7647,7 @@
     /* parameters */ ParameterIndex(393),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [212] */
@@ -7658,7 +7660,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [213] */
@@ -7671,7 +7673,7 @@
     /* parameters */ ParameterIndex(209),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [214] */
@@ -7684,7 +7686,7 @@
     /* parameters */ ParameterIndex(394),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(124),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [215] */
@@ -7697,7 +7699,7 @@
     /* parameters */ ParameterIndex(395),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(126),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [216] */
@@ -7710,7 +7712,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [217] */
@@ -7723,7 +7725,7 @@
     /* parameters */ ParameterIndex(396),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [218] */
@@ -7736,7 +7738,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [219] */
@@ -7749,7 +7751,7 @@
     /* parameters */ ParameterIndex(213),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [220] */
@@ -7762,7 +7764,7 @@
     /* parameters */ ParameterIndex(397),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(130),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [221] */
@@ -7775,7 +7777,7 @@
     /* parameters */ ParameterIndex(398),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(132),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [222] */
@@ -7788,7 +7790,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [223] */
@@ -7801,7 +7803,7 @@
     /* parameters */ ParameterIndex(399),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [224] */
@@ -7814,7 +7816,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [225] */
@@ -7827,7 +7829,7 @@
     /* parameters */ ParameterIndex(217),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [226] */
@@ -7840,7 +7842,7 @@
     /* parameters */ ParameterIndex(400),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(136),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [227] */
@@ -7853,7 +7855,7 @@
     /* parameters */ ParameterIndex(401),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(138),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [228] */
@@ -7866,7 +7868,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [229] */
@@ -7879,7 +7881,7 @@
     /* parameters */ ParameterIndex(402),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [230] */
@@ -7892,7 +7894,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [231] */
@@ -7905,7 +7907,7 @@
     /* parameters */ ParameterIndex(209),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [232] */
@@ -7918,7 +7920,7 @@
     /* parameters */ ParameterIndex(403),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(142),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [233] */
@@ -7931,7 +7933,7 @@
     /* parameters */ ParameterIndex(404),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(144),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [234] */
@@ -7944,7 +7946,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [235] */
@@ -7957,7 +7959,7 @@
     /* parameters */ ParameterIndex(405),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [236] */
@@ -7970,7 +7972,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [237] */
@@ -7983,7 +7985,7 @@
     /* parameters */ ParameterIndex(213),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [238] */
@@ -7996,7 +7998,7 @@
     /* parameters */ ParameterIndex(406),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(148),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [239] */
@@ -8009,7 +8011,7 @@
     /* parameters */ ParameterIndex(407),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(150),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [240] */
@@ -8022,7 +8024,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [241] */
@@ -8035,7 +8037,7 @@
     /* parameters */ ParameterIndex(408),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [242] */
@@ -8048,7 +8050,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(103),
+    /* const_eval_fn */ ConstEvalFunctionIndex(105),
   },
   {
     /* [243] */
@@ -8061,7 +8063,7 @@
     /* parameters */ ParameterIndex(217),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(104),
+    /* const_eval_fn */ ConstEvalFunctionIndex(106),
   },
   {
     /* [244] */
@@ -8074,7 +8076,7 @@
     /* parameters */ ParameterIndex(409),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(154),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [245] */
@@ -8087,7 +8089,7 @@
     /* parameters */ ParameterIndex(410),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(156),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [246] */
@@ -8165,7 +8167,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(77),
+    /* const_eval_fn */ ConstEvalFunctionIndex(79),
   },
   {
     /* [252] */
@@ -8178,7 +8180,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(77),
+    /* const_eval_fn */ ConstEvalFunctionIndex(79),
   },
   {
     /* [253] */
@@ -8191,7 +8193,7 @@
     /* parameters */ ParameterIndex(223),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(77),
+    /* const_eval_fn */ ConstEvalFunctionIndex(79),
   },
   {
     /* [254] */
@@ -8204,7 +8206,7 @@
     /* parameters */ ParameterIndex(350),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(77),
+    /* const_eval_fn */ ConstEvalFunctionIndex(79),
   },
   {
     /* [255] */
@@ -8217,7 +8219,7 @@
     /* parameters */ ParameterIndex(353),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(2),
-    /* const_eval_fn */ ConstEvalFunctionIndex(77),
+    /* const_eval_fn */ ConstEvalFunctionIndex(79),
   },
   {
     /* [256] */
@@ -8230,7 +8232,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(78),
+    /* const_eval_fn */ ConstEvalFunctionIndex(80),
   },
   {
     /* [257] */
@@ -8243,7 +8245,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(78),
+    /* const_eval_fn */ ConstEvalFunctionIndex(80),
   },
   {
     /* [258] */
@@ -8256,7 +8258,7 @@
     /* parameters */ ParameterIndex(223),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(78),
+    /* const_eval_fn */ ConstEvalFunctionIndex(80),
   },
   {
     /* [259] */
@@ -8269,7 +8271,7 @@
     /* parameters */ ParameterIndex(350),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(78),
+    /* const_eval_fn */ ConstEvalFunctionIndex(80),
   },
   {
     /* [260] */
@@ -8282,7 +8284,7 @@
     /* parameters */ ParameterIndex(353),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(2),
-    /* const_eval_fn */ ConstEvalFunctionIndex(78),
+    /* const_eval_fn */ ConstEvalFunctionIndex(80),
   },
   {
     /* [261] */
@@ -8295,7 +8297,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(83),
+    /* const_eval_fn */ ConstEvalFunctionIndex(85),
   },
   {
     /* [262] */
@@ -8308,7 +8310,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(83),
+    /* const_eval_fn */ ConstEvalFunctionIndex(85),
   },
   {
     /* [263] */
@@ -8321,7 +8323,7 @@
     /* parameters */ ParameterIndex(223),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(83),
+    /* const_eval_fn */ ConstEvalFunctionIndex(85),
   },
   {
     /* [264] */
@@ -8334,7 +8336,7 @@
     /* parameters */ ParameterIndex(350),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(83),
+    /* const_eval_fn */ ConstEvalFunctionIndex(85),
   },
   {
     /* [265] */
@@ -8347,7 +8349,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(84),
+    /* const_eval_fn */ ConstEvalFunctionIndex(86),
   },
   {
     /* [266] */
@@ -8360,7 +8362,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(84),
+    /* const_eval_fn */ ConstEvalFunctionIndex(86),
   },
   {
     /* [267] */
@@ -8373,7 +8375,7 @@
     /* parameters */ ParameterIndex(223),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(84),
+    /* const_eval_fn */ ConstEvalFunctionIndex(86),
   },
   {
     /* [268] */
@@ -8386,7 +8388,7 @@
     /* parameters */ ParameterIndex(350),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(84),
+    /* const_eval_fn */ ConstEvalFunctionIndex(86),
   },
   {
     /* [269] */
@@ -8399,7 +8401,7 @@
     /* parameters */ ParameterIndex(226),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(86),
+    /* const_eval_fn */ ConstEvalFunctionIndex(88),
   },
   {
     /* [270] */
@@ -8412,7 +8414,7 @@
     /* parameters */ ParameterIndex(233),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(86),
+    /* const_eval_fn */ ConstEvalFunctionIndex(88),
   },
   {
     /* [271] */
@@ -8425,7 +8427,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(86),
+    /* const_eval_fn */ ConstEvalFunctionIndex(88),
   },
   {
     /* [272] */
@@ -8438,7 +8440,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(86),
+    /* const_eval_fn */ ConstEvalFunctionIndex(88),
   },
   {
     /* [273] */
@@ -8451,7 +8453,7 @@
     /* parameters */ ParameterIndex(226),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(87),
+    /* const_eval_fn */ ConstEvalFunctionIndex(89),
   },
   {
     /* [274] */
@@ -8464,7 +8466,7 @@
     /* parameters */ ParameterIndex(233),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(87),
+    /* const_eval_fn */ ConstEvalFunctionIndex(89),
   },
   {
     /* [275] */
@@ -8477,7 +8479,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(87),
+    /* const_eval_fn */ ConstEvalFunctionIndex(89),
   },
   {
     /* [276] */
@@ -8490,7 +8492,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(87),
+    /* const_eval_fn */ ConstEvalFunctionIndex(89),
   },
   {
     /* [277] */
@@ -8503,7 +8505,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(40),
+    /* const_eval_fn */ ConstEvalFunctionIndex(42),
   },
   {
     /* [278] */
@@ -8516,7 +8518,7 @@
     /* parameters */ ParameterIndex(221),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(40),
+    /* const_eval_fn */ ConstEvalFunctionIndex(42),
   },
   {
     /* [279] */
@@ -8529,7 +8531,7 @@
     /* parameters */ ParameterIndex(222),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(40),
+    /* const_eval_fn */ ConstEvalFunctionIndex(42),
   },
   {
     /* [280] */
@@ -8542,7 +8544,7 @@
     /* parameters */ ParameterIndex(224),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(56),
+    /* const_eval_fn */ ConstEvalFunctionIndex(58),
   },
   {
     /* [281] */
@@ -8555,7 +8557,7 @@
     /* parameters */ ParameterIndex(228),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(56),
+    /* const_eval_fn */ ConstEvalFunctionIndex(58),
   },
   {
     /* [282] */
@@ -8568,7 +8570,7 @@
     /* parameters */ ParameterIndex(231),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(57),
+    /* const_eval_fn */ ConstEvalFunctionIndex(59),
   },
   {
     /* [283] */
@@ -8581,7 +8583,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [284] */
@@ -8594,7 +8596,7 @@
     /* parameters */ ParameterIndex(379),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [285] */
@@ -8607,7 +8609,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [286] */
@@ -8620,7 +8622,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [287] */
@@ -8633,7 +8635,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [288] */
@@ -8646,7 +8648,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [289] */
@@ -8659,7 +8661,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(15),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [290] */
@@ -8672,7 +8674,7 @@
     /* parameters */ ParameterIndex(370),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(15),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [291] */
@@ -8685,7 +8687,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(15),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [292] */
@@ -8698,7 +8700,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(87),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [293] */
@@ -8711,7 +8713,7 @@
     /* parameters */ ParameterIndex(380),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(87),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [294] */
@@ -8724,7 +8726,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(87),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [295] */
@@ -8737,7 +8739,7 @@
     /* parameters */ ParameterIndex(/* invalid */),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(100),
   },
   {
     /* [296] */
@@ -8750,7 +8752,7 @@
     /* parameters */ ParameterIndex(226),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [297] */
@@ -8763,7 +8765,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
   {
     /* [298] */
@@ -9296,7 +9298,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(22),
+    /* const_eval_fn */ ConstEvalFunctionIndex(24),
   },
   {
     /* [339] */
@@ -9309,7 +9311,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(22),
+    /* const_eval_fn */ ConstEvalFunctionIndex(24),
   },
   {
     /* [340] */
@@ -9322,7 +9324,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(23),
+    /* const_eval_fn */ ConstEvalFunctionIndex(25),
   },
   {
     /* [341] */
@@ -9335,7 +9337,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(23),
+    /* const_eval_fn */ ConstEvalFunctionIndex(25),
   },
   {
     /* [342] */
@@ -9348,7 +9350,7 @@
     /* parameters */ ParameterIndex(16),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(24),
+    /* const_eval_fn */ ConstEvalFunctionIndex(26),
   },
   {
     /* [343] */
@@ -9361,7 +9363,7 @@
     /* parameters */ ParameterIndex(150),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(24),
+    /* const_eval_fn */ ConstEvalFunctionIndex(26),
   },
   {
     /* [344] */
@@ -9374,7 +9376,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(26),
+    /* const_eval_fn */ ConstEvalFunctionIndex(28),
   },
   {
     /* [345] */
@@ -9387,7 +9389,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(26),
+    /* const_eval_fn */ ConstEvalFunctionIndex(28),
   },
   {
     /* [346] */
@@ -9400,7 +9402,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(27),
+    /* const_eval_fn */ ConstEvalFunctionIndex(29),
   },
   {
     /* [347] */
@@ -9413,7 +9415,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(27),
+    /* const_eval_fn */ ConstEvalFunctionIndex(29),
   },
   {
     /* [348] */
@@ -9426,7 +9428,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(28),
+    /* const_eval_fn */ ConstEvalFunctionIndex(30),
   },
   {
     /* [349] */
@@ -9439,7 +9441,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(28),
+    /* const_eval_fn */ ConstEvalFunctionIndex(30),
   },
   {
     /* [350] */
@@ -9452,7 +9454,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(29),
+    /* const_eval_fn */ ConstEvalFunctionIndex(31),
   },
   {
     /* [351] */
@@ -9465,7 +9467,7 @@
     /* parameters */ ParameterIndex(221),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(29),
+    /* const_eval_fn */ ConstEvalFunctionIndex(31),
   },
   {
     /* [352] */
@@ -9478,7 +9480,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(30),
+    /* const_eval_fn */ ConstEvalFunctionIndex(32),
   },
   {
     /* [353] */
@@ -9491,7 +9493,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(30),
+    /* const_eval_fn */ ConstEvalFunctionIndex(32),
   },
   {
     /* [354] */
@@ -9504,7 +9506,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(16),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(31),
+    /* const_eval_fn */ ConstEvalFunctionIndex(33),
   },
   {
     /* [355] */
@@ -9517,7 +9519,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(18),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(31),
+    /* const_eval_fn */ ConstEvalFunctionIndex(33),
   },
   {
     /* [356] */
@@ -9530,7 +9532,7 @@
     /* parameters */ ParameterIndex(15),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(32),
+    /* const_eval_fn */ ConstEvalFunctionIndex(34),
   },
   {
     /* [357] */
@@ -9543,7 +9545,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(32),
+    /* const_eval_fn */ ConstEvalFunctionIndex(34),
   },
   {
     /* [358] */
@@ -9556,7 +9558,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(33),
+    /* const_eval_fn */ ConstEvalFunctionIndex(35),
   },
   {
     /* [359] */
@@ -9569,7 +9571,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(33),
+    /* const_eval_fn */ ConstEvalFunctionIndex(35),
   },
   {
     /* [360] */
@@ -9582,7 +9584,7 @@
     /* parameters */ ParameterIndex(304),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(34),
+    /* const_eval_fn */ ConstEvalFunctionIndex(36),
   },
   {
     /* [361] */
@@ -9595,7 +9597,7 @@
     /* parameters */ ParameterIndex(306),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(34),
+    /* const_eval_fn */ ConstEvalFunctionIndex(36),
   },
   {
     /* [362] */
@@ -9608,7 +9610,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(35),
+    /* const_eval_fn */ ConstEvalFunctionIndex(37),
   },
   {
     /* [363] */
@@ -9621,7 +9623,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(35),
+    /* const_eval_fn */ ConstEvalFunctionIndex(37),
   },
   {
     /* [364] */
@@ -9634,7 +9636,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(36),
+    /* const_eval_fn */ ConstEvalFunctionIndex(38),
   },
   {
     /* [365] */
@@ -9647,7 +9649,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(36),
+    /* const_eval_fn */ ConstEvalFunctionIndex(38),
   },
   {
     /* [366] */
@@ -9660,7 +9662,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(37),
+    /* const_eval_fn */ ConstEvalFunctionIndex(39),
   },
   {
     /* [367] */
@@ -9673,7 +9675,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(37),
+    /* const_eval_fn */ ConstEvalFunctionIndex(39),
   },
   {
     /* [368] */
@@ -9686,7 +9688,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(38),
+    /* const_eval_fn */ ConstEvalFunctionIndex(40),
   },
   {
     /* [369] */
@@ -9699,7 +9701,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(38),
+    /* const_eval_fn */ ConstEvalFunctionIndex(40),
   },
   {
     /* [370] */
@@ -9712,7 +9714,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(39),
+    /* const_eval_fn */ ConstEvalFunctionIndex(41),
   },
   {
     /* [371] */
@@ -9725,7 +9727,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(39),
+    /* const_eval_fn */ ConstEvalFunctionIndex(41),
   },
   {
     /* [372] */
@@ -9738,7 +9740,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(22),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(41),
+    /* const_eval_fn */ ConstEvalFunctionIndex(43),
   },
   {
     /* [373] */
@@ -9751,7 +9753,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(24),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(41),
+    /* const_eval_fn */ ConstEvalFunctionIndex(43),
   },
   {
     /* [374] */
@@ -9764,7 +9766,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(48),
+    /* const_eval_fn */ ConstEvalFunctionIndex(50),
   },
   {
     /* [375] */
@@ -9777,7 +9779,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(48),
+    /* const_eval_fn */ ConstEvalFunctionIndex(50),
   },
   {
     /* [376] */
@@ -9790,7 +9792,7 @@
     /* parameters */ ParameterIndex(370),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(15),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(49),
+    /* const_eval_fn */ ConstEvalFunctionIndex(51),
   },
   {
     /* [377] */
@@ -9803,7 +9805,7 @@
     /* parameters */ ParameterIndex(371),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(14),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(49),
+    /* const_eval_fn */ ConstEvalFunctionIndex(51),
   },
   {
     /* [378] */
@@ -9816,7 +9818,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(50),
+    /* const_eval_fn */ ConstEvalFunctionIndex(52),
   },
   {
     /* [379] */
@@ -9829,7 +9831,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(50),
+    /* const_eval_fn */ ConstEvalFunctionIndex(52),
   },
   {
     /* [380] */
@@ -9842,7 +9844,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(53),
+    /* const_eval_fn */ ConstEvalFunctionIndex(55),
   },
   {
     /* [381] */
@@ -9855,7 +9857,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(53),
+    /* const_eval_fn */ ConstEvalFunctionIndex(55),
   },
   {
     /* [382] */
@@ -9868,7 +9870,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(54),
+    /* const_eval_fn */ ConstEvalFunctionIndex(56),
   },
   {
     /* [383] */
@@ -9881,7 +9883,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(54),
+    /* const_eval_fn */ ConstEvalFunctionIndex(56),
   },
   {
     /* [384] */
@@ -9894,7 +9896,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(55),
+    /* const_eval_fn */ ConstEvalFunctionIndex(57),
   },
   {
     /* [385] */
@@ -9907,7 +9909,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(55),
+    /* const_eval_fn */ ConstEvalFunctionIndex(57),
   },
   {
     /* [386] */
@@ -9920,7 +9922,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(58),
+    /* const_eval_fn */ ConstEvalFunctionIndex(60),
   },
   {
     /* [387] */
@@ -9933,7 +9935,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(58),
+    /* const_eval_fn */ ConstEvalFunctionIndex(60),
   },
   {
     /* [388] */
@@ -9946,7 +9948,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(59),
+    /* const_eval_fn */ ConstEvalFunctionIndex(61),
   },
   {
     /* [389] */
@@ -9959,7 +9961,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(59),
+    /* const_eval_fn */ ConstEvalFunctionIndex(61),
   },
   {
     /* [390] */
@@ -9972,7 +9974,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(60),
+    /* const_eval_fn */ ConstEvalFunctionIndex(62),
   },
   {
     /* [391] */
@@ -9985,7 +9987,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(60),
+    /* const_eval_fn */ ConstEvalFunctionIndex(62),
   },
   {
     /* [392] */
@@ -9998,7 +10000,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(61),
+    /* const_eval_fn */ ConstEvalFunctionIndex(63),
   },
   {
     /* [393] */
@@ -10011,7 +10013,7 @@
     /* parameters */ ParameterIndex(221),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(61),
+    /* const_eval_fn */ ConstEvalFunctionIndex(63),
   },
   {
     /* [394] */
@@ -10024,7 +10026,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(62),
+    /* const_eval_fn */ ConstEvalFunctionIndex(64),
   },
   {
     /* [395] */
@@ -10037,7 +10039,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(62),
+    /* const_eval_fn */ ConstEvalFunctionIndex(64),
   },
   {
     /* [396] */
@@ -10050,7 +10052,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(63),
+    /* const_eval_fn */ ConstEvalFunctionIndex(65),
   },
   {
     /* [397] */
@@ -10063,7 +10065,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(63),
+    /* const_eval_fn */ ConstEvalFunctionIndex(65),
   },
   {
     /* [398] */
@@ -10076,7 +10078,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(64),
+    /* const_eval_fn */ ConstEvalFunctionIndex(66),
   },
   {
     /* [399] */
@@ -10089,7 +10091,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(64),
+    /* const_eval_fn */ ConstEvalFunctionIndex(66),
   },
   {
     /* [400] */
@@ -10102,7 +10104,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(65),
+    /* const_eval_fn */ ConstEvalFunctionIndex(67),
   },
   {
     /* [401] */
@@ -10115,7 +10117,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(65),
+    /* const_eval_fn */ ConstEvalFunctionIndex(67),
   },
   {
     /* [402] */
@@ -10128,7 +10130,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(67),
+    /* const_eval_fn */ ConstEvalFunctionIndex(69),
   },
   {
     /* [403] */
@@ -10141,7 +10143,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(67),
+    /* const_eval_fn */ ConstEvalFunctionIndex(69),
   },
   {
     /* [404] */
@@ -10206,7 +10208,7 @@
     /* parameters */ ParameterIndex(226),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(74),
+    /* const_eval_fn */ ConstEvalFunctionIndex(76),
   },
   {
     /* [409] */
@@ -10219,7 +10221,7 @@
     /* parameters */ ParameterIndex(233),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(74),
+    /* const_eval_fn */ ConstEvalFunctionIndex(76),
   },
   {
     /* [410] */
@@ -10232,7 +10234,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(75),
+    /* const_eval_fn */ ConstEvalFunctionIndex(77),
   },
   {
     /* [411] */
@@ -10245,7 +10247,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(75),
+    /* const_eval_fn */ ConstEvalFunctionIndex(77),
   },
   {
     /* [412] */
@@ -10258,7 +10260,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(76),
+    /* const_eval_fn */ ConstEvalFunctionIndex(78),
   },
   {
     /* [413] */
@@ -10271,7 +10273,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(76),
+    /* const_eval_fn */ ConstEvalFunctionIndex(78),
   },
   {
     /* [414] */
@@ -10284,7 +10286,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(85),
+    /* const_eval_fn */ ConstEvalFunctionIndex(87),
   },
   {
     /* [415] */
@@ -10297,7 +10299,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(85),
+    /* const_eval_fn */ ConstEvalFunctionIndex(87),
   },
   {
     /* [416] */
@@ -10310,7 +10312,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(90),
+    /* const_eval_fn */ ConstEvalFunctionIndex(92),
   },
   {
     /* [417] */
@@ -10323,7 +10325,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(90),
+    /* const_eval_fn */ ConstEvalFunctionIndex(92),
   },
   {
     /* [418] */
@@ -10336,7 +10338,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(91),
+    /* const_eval_fn */ ConstEvalFunctionIndex(93),
   },
   {
     /* [419] */
@@ -10349,7 +10351,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(91),
+    /* const_eval_fn */ ConstEvalFunctionIndex(93),
   },
   {
     /* [420] */
@@ -10362,7 +10364,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(92),
+    /* const_eval_fn */ ConstEvalFunctionIndex(94),
   },
   {
     /* [421] */
@@ -10375,7 +10377,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(92),
+    /* const_eval_fn */ ConstEvalFunctionIndex(94),
   },
   {
     /* [422] */
@@ -10388,7 +10390,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(93),
+    /* const_eval_fn */ ConstEvalFunctionIndex(95),
   },
   {
     /* [423] */
@@ -10401,7 +10403,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(93),
+    /* const_eval_fn */ ConstEvalFunctionIndex(95),
   },
   {
     /* [424] */
@@ -10414,7 +10416,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(94),
+    /* const_eval_fn */ ConstEvalFunctionIndex(96),
   },
   {
     /* [425] */
@@ -10427,7 +10429,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(94),
+    /* const_eval_fn */ ConstEvalFunctionIndex(96),
   },
   {
     /* [426] */
@@ -10440,7 +10442,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(95),
+    /* const_eval_fn */ ConstEvalFunctionIndex(97),
   },
   {
     /* [427] */
@@ -10453,7 +10455,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(8),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(95),
+    /* const_eval_fn */ ConstEvalFunctionIndex(97),
   },
   {
     /* [428] */
@@ -10466,7 +10468,7 @@
     /* parameters */ ParameterIndex(16),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(96),
+    /* const_eval_fn */ ConstEvalFunctionIndex(98),
   },
   {
     /* [429] */
@@ -10479,7 +10481,7 @@
     /* parameters */ ParameterIndex(351),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(96),
+    /* const_eval_fn */ ConstEvalFunctionIndex(98),
   },
   {
     /* [430] */
@@ -10492,7 +10494,7 @@
     /* parameters */ ParameterIndex(16),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(97),
+    /* const_eval_fn */ ConstEvalFunctionIndex(99),
   },
   {
     /* [431] */
@@ -10505,7 +10507,7 @@
     /* parameters */ ParameterIndex(351),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(97),
+    /* const_eval_fn */ ConstEvalFunctionIndex(99),
   },
   {
     /* [432] */
@@ -10570,7 +10572,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(22),
   },
   {
     /* [437] */
@@ -10583,7 +10585,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+    /* const_eval_fn */ ConstEvalFunctionIndex(23),
   },
   {
     /* [438] */
@@ -10596,7 +10598,7 @@
     /* parameters */ ParameterIndex(221),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(25),
+    /* const_eval_fn */ ConstEvalFunctionIndex(27),
   },
   {
     /* [439] */
@@ -10609,7 +10611,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(42),
+    /* const_eval_fn */ ConstEvalFunctionIndex(44),
   },
   {
     /* [440] */
@@ -10622,7 +10624,7 @@
     /* parameters */ ParameterIndex(372),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(43),
+    /* const_eval_fn */ ConstEvalFunctionIndex(45),
   },
   {
     /* [441] */
@@ -10635,7 +10637,7 @@
     /* parameters */ ParameterIndex(372),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(44),
+    /* const_eval_fn */ ConstEvalFunctionIndex(46),
   },
   {
     /* [442] */
@@ -10648,7 +10650,7 @@
     /* parameters */ ParameterIndex(372),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(45),
+    /* const_eval_fn */ ConstEvalFunctionIndex(47),
   },
   {
     /* [443] */
@@ -10661,7 +10663,7 @@
     /* parameters */ ParameterIndex(373),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(46),
+    /* const_eval_fn */ ConstEvalFunctionIndex(48),
   },
   {
     /* [444] */
@@ -10674,7 +10676,7 @@
     /* parameters */ ParameterIndex(373),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(47),
+    /* const_eval_fn */ ConstEvalFunctionIndex(49),
   },
   {
     /* [445] */
@@ -10687,7 +10689,7 @@
     /* parameters */ ParameterIndex(149),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(51),
+    /* const_eval_fn */ ConstEvalFunctionIndex(53),
   },
   {
     /* [446] */
@@ -10700,7 +10702,7 @@
     /* parameters */ ParameterIndex(222),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(6),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(1),
-    /* const_eval_fn */ ConstEvalFunctionIndex(52),
+    /* const_eval_fn */ ConstEvalFunctionIndex(54),
   },
   {
     /* [447] */
@@ -10726,7 +10728,7 @@
     /* parameters */ ParameterIndex(353),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(3),
-    /* const_eval_fn */ ConstEvalFunctionIndex(66),
+    /* const_eval_fn */ ConstEvalFunctionIndex(68),
   },
   {
     /* [449] */
@@ -10739,7 +10741,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(26),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(68),
+    /* const_eval_fn */ ConstEvalFunctionIndex(70),
   },
   {
     /* [450] */
@@ -10752,7 +10754,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(26),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(69),
+    /* const_eval_fn */ ConstEvalFunctionIndex(71),
   },
   {
     /* [451] */
@@ -10765,7 +10767,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(26),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(70),
+    /* const_eval_fn */ ConstEvalFunctionIndex(72),
   },
   {
     /* [452] */
@@ -10778,7 +10780,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(28),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(71),
+    /* const_eval_fn */ ConstEvalFunctionIndex(73),
   },
   {
     /* [453] */
@@ -10791,7 +10793,7 @@
     /* parameters */ ParameterIndex(17),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(28),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(72),
+    /* const_eval_fn */ ConstEvalFunctionIndex(74),
   },
   {
     /* [454] */
@@ -10895,7 +10897,7 @@
     /* parameters */ ParameterIndex(1),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(73),
+    /* const_eval_fn */ ConstEvalFunctionIndex(75),
   },
   {
     /* [462] */
@@ -10908,7 +10910,7 @@
     /* parameters */ ParameterIndex(226),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(88),
+    /* const_eval_fn */ ConstEvalFunctionIndex(90),
   },
   {
     /* [463] */
@@ -10921,7 +10923,7 @@
     /* parameters */ ParameterIndex(226),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(9),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(89),
+    /* const_eval_fn */ ConstEvalFunctionIndex(91),
   },
   {
     /* [464] */
@@ -10934,7 +10936,7 @@
     /* parameters */ ParameterIndex(213),
     /* return_type_matcher_indices */ TypeMatcherIndicesIndex(158),
     /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
-    /* const_eval_fn */ ConstEvalFunctionIndex(99),
+    /* const_eval_fn */ ConstEvalFunctionIndex(101),
   },
 };
 
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index 305beab..8e430d3 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -51,7 +51,9 @@
 
         auto disassembly = tint::core::ir::Disassemble(ir_module.Get());
 
-        auto output = wgsl::writer::WgslFromIR(ir_module.Get());
+        writer::ProgramOptions program_options;
+        program_options.allowed_features = AllowedFeatures::Everything();
+        auto output = wgsl::writer::WgslFromIR(ir_module.Get(), program_options);
         if (!output) {
             FAIL() << output.Failure() << std::endl  //
                    << "IR:" << std::endl             //
diff --git a/src/tint/lang/wgsl/program/BUILD.cmake b/src/tint/lang/wgsl/program/BUILD.cmake
index c55fc5a..75e0236 100644
--- a/src/tint/lang/wgsl/program/BUILD.cmake
+++ b/src/tint/lang/wgsl/program/BUILD.cmake
@@ -132,6 +132,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_bytes
   tint_utils_containers
   tint_utils_diagnostic
diff --git a/src/tint/lang/wgsl/program/BUILD.gn b/src/tint/lang/wgsl/program/BUILD.gn
index f3e03fd..98ce8db 100644
--- a/src/tint/lang/wgsl/program/BUILD.gn
+++ b/src/tint/lang/wgsl/program/BUILD.gn
@@ -127,6 +127,7 @@
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/resolver",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/bytes",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
diff --git a/src/tint/lang/wgsl/wgsl.def b/src/tint/lang/wgsl/wgsl.def
index 1a3bbee..6d3add1 100644
--- a/src/tint/lang/wgsl/wgsl.def
+++ b/src/tint/lang/wgsl/wgsl.def
@@ -451,8 +451,8 @@
 @must_use @const fn distance<T: fa_f32_f16>(T, T) -> T
 @must_use @const fn distance<N: num, T: fa_f32_f16>(vec<N, T>, vec<N, T>) -> T
 @must_use @const fn dot<N: num, T: fia_fiu32_f16>(vec<N, T>, vec<N, T>) -> T
-@must_use fn dot4I8Packed(u32, u32) -> i32
-@must_use fn dot4U8Packed(u32, u32) -> u32
+@must_use @const fn dot4I8Packed(u32, u32) -> i32
+@must_use @const fn dot4U8Packed(u32, u32) -> u32
 @must_use @stage("fragment") fn dpdx(f32) -> f32
 @must_use @stage("fragment") fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>
 @must_use @stage("fragment") fn dpdxCoarse(f32) -> f32
diff --git a/src/tint/lang/wgsl/writer/BUILD.bazel b/src/tint/lang/wgsl/writer/BUILD.bazel
index 2c39c85..ff06810 100644
--- a/src/tint/lang/wgsl/writer/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/BUILD.bazel
@@ -56,6 +56,8 @@
     "//src/tint/lang/core/type",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
+    "//src/tint/lang/wgsl/common",
+    "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
     "//src/tint/lang/wgsl/writer/ir_to_program",
@@ -97,8 +99,11 @@
     "//src/tint/lang/core/type",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
+    "//src/tint/lang/wgsl/common",
+    "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/wgsl/writer/BUILD.cmake b/src/tint/lang/wgsl/writer/BUILD.cmake
index 3add0aa..4e172c8 100644
--- a/src/tint/lang/wgsl/writer/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/BUILD.cmake
@@ -62,6 +62,8 @@
   tint_lang_core_type
   tint_lang_wgsl
   tint_lang_wgsl_ast
+  tint_lang_wgsl_common
+  tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
   tint_lang_wgsl_writer_ir_to_program
@@ -107,8 +109,11 @@
   tint_lang_core_type
   tint_lang_wgsl
   tint_lang_wgsl_ast
+  tint_lang_wgsl_common
+  tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/wgsl/writer/BUILD.gn b/src/tint/lang/wgsl/writer/BUILD.gn
index 95966a3..107e29b 100644
--- a/src/tint/lang/wgsl/writer/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/BUILD.gn
@@ -59,6 +59,8 @@
       "${tint_src_dir}/lang/core/type",
       "${tint_src_dir}/lang/wgsl",
       "${tint_src_dir}/lang/wgsl/ast",
+      "${tint_src_dir}/lang/wgsl/common",
+      "${tint_src_dir}/lang/wgsl/features",
       "${tint_src_dir}/lang/wgsl/program",
       "${tint_src_dir}/lang/wgsl/sem",
       "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
@@ -97,8 +99,11 @@
         "${tint_src_dir}/lang/core/type",
         "${tint_src_dir}/lang/wgsl",
         "${tint_src_dir}/lang/wgsl/ast",
+        "${tint_src_dir}/lang/wgsl/common",
+        "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
index 812a463..1c5947a 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
@@ -43,6 +43,7 @@
   ],
   hdrs = [
     "ir_to_program.h",
+    "program_options.h",
   ],
   deps = [
     "//src/tint/api/common",
@@ -99,6 +100,8 @@
     "//src/tint/lang/core/type",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
+    "//src/tint/lang/wgsl/common",
+    "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/intrinsic",
     "//src/tint/lang/wgsl/ir",
     "//src/tint/lang/wgsl/program",
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
index 6fd9f71..9828bc9 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
@@ -41,6 +41,7 @@
 tint_add_target(tint_lang_wgsl_writer_ir_to_program lib
   lang/wgsl/writer/ir_to_program/ir_to_program.cc
   lang/wgsl/writer/ir_to_program/ir_to_program.h
+  lang/wgsl/writer/ir_to_program/program_options.h
 )
 
 tint_target_add_dependencies(tint_lang_wgsl_writer_ir_to_program lib
@@ -92,6 +93,8 @@
   tint_lang_core_type
   tint_lang_wgsl
   tint_lang_wgsl_ast
+  tint_lang_wgsl_common
+  tint_lang_wgsl_features
   tint_lang_wgsl_intrinsic
   tint_lang_wgsl_ir
   tint_lang_wgsl_program
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
index ed032db..3f9583c 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
@@ -46,6 +46,7 @@
   sources = [
     "ir_to_program.cc",
     "ir_to_program.h",
+    "program_options.h",
   ]
   deps = [
     "${tint_src_dir}/api/common",
@@ -92,6 +93,8 @@
       "${tint_src_dir}/lang/core/type",
       "${tint_src_dir}/lang/wgsl",
       "${tint_src_dir}/lang/wgsl/ast",
+      "${tint_src_dir}/lang/wgsl/common",
+      "${tint_src_dir}/lang/wgsl/features",
       "${tint_src_dir}/lang/wgsl/intrinsic",
       "${tint_src_dir}/lang/wgsl/ir",
       "${tint_src_dir}/lang/wgsl/program",
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 9f83536..2d6b415 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
@@ -103,7 +103,7 @@
   public:
     explicit State(const core::ir::Module& m) : mod(m) {}
 
-    Program Run() {
+    Program Run(const ProgramOptions& options) {
         if (auto res = core::ir::Validate(mod); !res) {
             // IR module failed validation.
             b.Diagnostics() = res.Failure().reason;
@@ -116,7 +116,14 @@
         for (auto& fn : mod.functions) {
             Fn(fn);
         }
-        return Program{resolver::Resolve(b)};
+
+        if (options.allow_non_uniform_derivatives) {
+            // Suppress errors regarding non-uniform derivative operations if requested, by adding a
+            // diagnostic directive to the module.
+            b.DiagnosticDirective(wgsl::DiagnosticSeverity::kOff, "derivative_uniformity");
+        }
+
+        return Program{resolver::Resolve(b, options.allowed_features)};
     }
 
   private:
@@ -1230,8 +1237,8 @@
 
 }  // namespace
 
-Program IRToProgram(const core::ir::Module& i) {
-    return State{i}.Run();
+Program IRToProgram(const core::ir::Module& i, const ProgramOptions& options) {
+    return State{i}.Run(options);
 }
 
 }  // namespace tint::wgsl::writer
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
index 089a1e7..cf53fb6 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
@@ -29,6 +29,7 @@
 #define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_
 
 #include "src/tint/lang/wgsl/program/program.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/program_options.h"
 
 namespace tint::core::ir {
 class Module;
@@ -38,9 +39,10 @@
 
 /// Builds a tint::Program from an core::ir::Module
 /// @param module the IR module
+/// @param options the configuration options
 /// @return the tint::Program.
 /// @note Check the returned Program::Diagnostics() for any errors.
-Program IRToProgram(const core::ir::Module& module);
+Program IRToProgram(const core::ir::Module& module, const ProgramOptions& options = {});
 
 }  // namespace tint::wgsl::writer
 
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 d034c0d..8dc95e1 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
@@ -48,7 +48,9 @@
 
     result.ir = tint::core::ir::Disassemble(mod);
 
-    auto output_program = IRToProgram(mod);
+    ProgramOptions options;
+    options.allowed_features = AllowedFeatures::Everything();
+    auto output_program = IRToProgram(mod, options);
     if (!output_program.IsValid()) {
         result.err = output_program.Diagnostics().str();
         result.ast = Program::printer(output_program);
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/program_options.h b/src/tint/lang/wgsl/writer/ir_to_program/program_options.h
new file mode 100644
index 0000000..1b6ed6f
--- /dev/null
+++ b/src/tint/lang/wgsl/writer/ir_to_program/program_options.h
@@ -0,0 +1,45 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_PROGRAM_OPTIONS_H_
+#define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_PROGRAM_OPTIONS_H_
+
+#include "src/tint/lang/wgsl/common/allowed_features.h"
+
+namespace tint::wgsl::writer {
+
+/// Configuration options used for producing a WGSL program from an IR module.
+struct ProgramOptions {
+    /// Set to `true` to allow calls to derivative builtins in non-uniform control flow.
+    bool allow_non_uniform_derivatives = false;
+    /// The extensions and language features that are allowed to be used in the generated WGSL.
+    wgsl::AllowedFeatures allowed_features = {};
+};
+
+}  // namespace tint::wgsl::writer
+
+#endif  // SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_PROGRAM_OPTIONS_H_
diff --git a/src/tint/lang/wgsl/writer/writer.cc b/src/tint/lang/wgsl/writer/writer.cc
index a9ef260..6cc8422 100644
--- a/src/tint/lang/wgsl/writer/writer.cc
+++ b/src/tint/lang/wgsl/writer/writer.cc
@@ -67,13 +67,13 @@
     return output;
 }
 
-Result<Output> WgslFromIR(core::ir::Module& module) {
+Result<Output> WgslFromIR(core::ir::Module& module, const ProgramOptions& options) {
     // core-dialect -> WGSL-dialect
     if (auto res = Raise(module); !res) {
         return res.Failure();
     }
 
-    auto program = IRToProgram(module);
+    auto program = IRToProgram(module, options);
     if (!program.IsValid()) {
         return Failure{program.Diagnostics()};
     }
diff --git a/src/tint/lang/wgsl/writer/writer.h b/src/tint/lang/wgsl/writer/writer.h
index cb9124b..64a1525 100644
--- a/src/tint/lang/wgsl/writer/writer.h
+++ b/src/tint/lang/wgsl/writer/writer.h
@@ -30,6 +30,7 @@
 
 #include <string>
 
+#include "src/tint/lang/wgsl/writer/ir_to_program/program_options.h"
 #include "src/tint/lang/wgsl/writer/options.h"
 #include "src/tint/lang/wgsl/writer/output.h"
 #include "src/tint/utils/diagnostic/diagnostic.h"
@@ -54,8 +55,9 @@
 
 /// Generate WGSL from a core-dialect ir::Module.
 /// @param module the core-dialect ir::Module.
+/// @param options the configuration options to use when generating WGSL
 /// @returns the resulting WGSL, or failure
-Result<Output> WgslFromIR(core::ir::Module& module);
+Result<Output> WgslFromIR(core::ir::Module& module, const ProgramOptions& options);
 
 }  // namespace tint::wgsl::writer