src: Reimplement IntrinsicTable from intrisics.def

Add a template file to generate intrinsic_table.inl and
include this from intrinsic_table.cc.

Speeds up execution of the unittests by 20 - 30%, and
reduces the executable size by a couple of percent.

Bug: tint:832
Change-Id: Ifa7f3c42202c92e97b46ed1716ece48660dd29dd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/52504
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 913add2..04c5cd7 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -436,6 +436,7 @@
     "inspector/scalar.h",
     "intrinsic_table.cc",
     "intrinsic_table.h",
+    "intrinsic_table.inl",
     "program.cc",
     "program.h",
     "program_builder.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b1934d0..a040999 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -221,6 +221,7 @@
   inspector/scalar.h
   intrinsic_table.cc
   intrinsic_table.h
+  intrinsic_table.inl
   program_builder.cc
   program_builder.h
   program_id.cc
diff --git a/src/intrinsic_table.cc b/src/intrinsic_table.cc
index 7dd0984..2073e80 100644
--- a/src/intrinsic_table.cc
+++ b/src/intrinsic_table.cc
@@ -25,1316 +25,625 @@
 #include "src/sem/multisampled_texture_type.h"
 #include "src/sem/sampled_texture_type.h"
 #include "src/sem/storage_texture_type.h"
+#include "src/utils/scoped_assignment.h"
 
 namespace tint {
 namespace {
 
-/// OpenTypes are the symbols used for templated types in overload signatures
-enum class OpenType {
-  T,
-  Count,  // Number of entries in the enum. Not a usable symbol.
-};
+// Forward declarations
+struct OverloadInfo;
+class Matchers;
+class NumberMatcher;
+class TypeMatcher;
 
-/// OpenNumber are the symbols used for templated integers in overload
-/// signatures
-enum class OpenNumber {
-  N,  // Typically used for vecN
-  M,  // Typically used for matNxM
-  F,  // Typically used F in for texture_storage_2d<F, A>
-  A,  // Typically used for A in texture_storage_2d<F, A>
-};
-
-/// @return a string of the OpenType symbol `ty`
-const char* str(OpenType ty) {
-  switch (ty) {
-    case OpenType::T:
-      return "T";
-
-    case OpenType::Count:
-      break;
-  }
-  return "";
-}
-
-/// @return a string of the OpenNumber symbol `num`
-const char* str(OpenNumber num) {
-  switch (num) {
-    case OpenNumber::N:
-      return "N";
-    case OpenNumber::M:
-      return "M";
-    case OpenNumber::F:
-      return "F";
-    case OpenNumber::A:
-      return "A";
-  }
-  return "";
-}
-
-/// A Matcher is an interface of a class used to match an overload parameter,
-/// return type, or open type.
-class Matcher {
+/// A special type that matches all TypeMatchers
+class Any : public Castable<Any, sem::Type> {
  public:
-  /// Current state passed to Match()
-  struct MatchState {
-    /// The map of open types. A new entry is assigned the first time an
-    /// OpenType is encountered. If the OpenType is encountered again, a
-    /// comparison is made to see if the type is consistent.
-    std::unordered_map<OpenType, const sem::Type*> open_types;
-    /// The map of open numbers. A new entry is assigned the first time an
-    /// OpenNumber is encountered. If the OpenNumber is encountered again, a
-    /// comparison is made to see if the number is consistent.
-    std::unordered_map<OpenNumber, uint32_t> open_numbers;
+  Any() = default;
+  ~Any() override = default;
+  std::string type_name() const override { return "<any>"; }
+  std::string FriendlyName(const SymbolTable&) const override {
+    return "<any>";
+  }
+};
+
+/// Number is an 32 bit unsigned integer, which can be in one of three states:
+/// * Invalid - Number has not been assigned a value
+/// * Valid   - a fixed integer value
+/// * Any     - matches any other non-invalid number
+struct Number {
+  static const Number any;
+  static const Number invalid;
+
+  /// Constructed as a valid number with the value v
+  explicit Number(uint32_t v) : value_(v), state_(kValid) {}
+
+  /// @returns the value of the number
+  inline uint32_t Value() const { return value_; }
+
+  /// @returns the true if the number is valid
+  inline bool IsValid() const { return state_ == kValid; }
+
+  /// @returns the true if the number is any
+  inline bool IsAny() const { return state_ == kAny; }
+
+  /// Assignment operator.
+  /// The number becomes valid, with the value n
+  inline Number& operator=(uint32_t n) {
+    value_ = n;
+    state_ = kValid;
+    return *this;
+  }
+
+ private:
+  enum State {
+    kInvalid,
+    kValid,
+    kAny,
   };
 
+  constexpr explicit Number(State state) : state_(state) {}
+
+  uint32_t value_ = 0;
+  State state_ = kInvalid;
+};
+
+const Number Number::any{Number::kAny};
+const Number Number::invalid{Number::kInvalid};
+
+/// ClosedState holds the state of the open / closed numbers and types.
+/// Used by the MatchState.
+class ClosedState {
+ public:
+  explicit ClosedState(ProgramBuilder& b) : builder(b) {}
+
+  /// If the type with index `idx` is open, then it is closed with type `ty` and
+  /// Type() returns true. If the type is closed, then `Type()` returns true iff
+  /// it is equal to `ty`.
+  bool Type(uint32_t idx, const sem::Type* ty) {
+    auto res = types_.emplace(idx, ty);
+    return res.second || res.first->second == ty;
+  }
+
+  /// If the number with index `idx` is open, then it is closed with number
+  /// `number` and Num() returns true. If the number is closed, then `Num()`
+  /// returns true iff it is equal to `ty`.
+  bool Num(uint32_t idx, Number number) {
+    auto res = numbers_.emplace(idx, number.Value());
+    return res.second || res.first->second == number.Value();
+  }
+
+  /// Type returns the closed type with index `idx`.
+  /// An ICE is raised if the type is not closed.
+  const sem::Type* Type(uint32_t idx) const {
+    auto it = types_.find(idx);
+    if (it == types_.end()) {
+      TINT_ICE(builder.Diagnostics())
+          << "type with index " << idx << " is not closed";
+      return nullptr;
+    }
+    TINT_ASSERT(it != types_.end());
+    return it->second;
+  }
+
+  /// Type returns the number type with index `idx`.
+  /// An ICE is raised if the number is not closed.
+  Number Num(uint32_t idx) const {
+    auto it = numbers_.find(idx);
+    if (it == numbers_.end()) {
+      TINT_ICE(builder.Diagnostics())
+          << "number with index " << idx << " is not closed";
+      return Number::invalid;
+    }
+    return Number(it->second);
+  }
+
+ private:
+  ProgramBuilder& builder;
+  std::unordered_map<uint32_t, const sem::Type*> types_;
+  std::unordered_map<uint32_t, uint32_t> numbers_;
+};
+
+/// Index type used for matcher indices
+using MatcherIndex = uint8_t;
+
+/// Index value used for open types / numbers that do not have a constraint
+constexpr MatcherIndex kNoMatcher = std::numeric_limits<MatcherIndex>::max();
+
+/// MatchState holds the state used to match an overload.
+class MatchState {
+ public:
+  MatchState(ProgramBuilder& b,
+             ClosedState& c,
+             const Matchers& m,
+             const OverloadInfo& o,
+             MatcherIndex const* matcher_indices)
+      : builder(b),
+        closed(c),
+        matchers(m),
+        overload(o),
+        matcher_indices_(matcher_indices) {}
+
+  /// The program builder
+  ProgramBuilder& builder;
+  /// The open / closed types and numbers
+  ClosedState& closed;
+  /// The type and number matchers
+  Matchers const& matchers;
+  /// The current overload being evaluated
+  OverloadInfo const& overload;
+
+  /// Type uses the next TypeMatcher from the matcher indices to match the type
+  /// `ty`. If the type matches, the canonical expected type is returned. If the
+  /// type `ty` does not match, then nullptr is returned.
+  /// @note: The matcher indices are progressed on calling.
+  const sem::Type* Type(const sem::Type* ty);
+
+  /// Num uses the next NumMatcher from the matcher indices to match the number
+  /// `num`. If the number matches, the canonical expected number is returned.
+  /// If the number `num` does not match, then an invalid number is returned.
+  /// @note: The matcher indices are progressed on calling.
+  Number Num(Number num);
+
+  /// @returns a string representation of the next TypeMatcher from the matcher
+  /// indices.
+  /// @note: The matcher indices are progressed on calling.
+  std::string TypeName();
+
+  /// @returns a string representation of the next NumberMatcher from the
+  /// matcher indices.
+  /// @note: The matcher indices are progressed on calling.
+  std::string NumName();
+
+ private:
+  MatcherIndex const* matcher_indices_ = nullptr;
+};
+
+/// A TypeMatcher is the interface used to match an type used as part of an
+/// overload's parameter or return type.
+class TypeMatcher {
+ public:
   /// Destructor
-  virtual ~Matcher() = default;
+  virtual ~TypeMatcher() = default;
 
-  /// Checks whether the given argument type matches.
-  /// Match may add to, or compare against the open types and numbers in state.
-  /// @returns true if the argument type is as expected.
-  virtual bool Match(MatchState& state,
-                     const sem::Type* argument_type) const = 0;
-
-  /// @return true if the matcher is expecting a pointer. If this method returns
-  /// false and the argument is a pointer type, then the argument should be
-  /// dereferenced before calling.
-  virtual bool ExpectsPointer() const { return false; }
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may close open types and numbers in state.
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  virtual const sem::Type* Match(MatchState& state,
+                                 const sem::Type* type) const = 0;
 
   /// @return a string representation of the matcher. Used for printing error
   /// messages when no overload is found.
-  virtual std::string str() const = 0;
-
- protected:
-  /// Checks `state.open_type` to see if the OpenType `t` is equal to the type
-  /// `ty`. If `state.open_type` does not contain an entry for `t`, then `ty`
-  /// is added and returns true.
-  bool MatchOpenType(MatchState& state, OpenType t, const sem::Type* ty) const {
-    auto it = state.open_types.find(t);
-    if (it != state.open_types.end()) {
-      return it->second == ty;
-    }
-    state.open_types[t] = ty;
-    return true;
-  }
-
-  /// Checks `state.open_numbers` to see if the OpenNumber `n` is equal to
-  /// `val`. If `state.open_numbers` does not contain an entry for `n`, then
-  /// `val` is added and returns true.
-  bool MatchOpenNumber(MatchState& state, OpenNumber n, uint32_t val) const {
-    auto it = state.open_numbers.find(n);
-    if (it != state.open_numbers.end()) {
-      return it->second == val;
-    }
-    state.open_numbers[n] = val;
-    return true;
-  }
+  virtual std::string String(MatchState& state) const = 0;
 };
 
-/// Builder is an extension of the Matcher interface that can also build the
-/// expected type. Builders are used to generate the parameter and return types
-/// on successful overload match.
-class Builder : public Matcher {
+/// A NumberMatcher is the interface used to match a number or enumerator used
+/// as part of an overload's parameter or return type.
+class NumberMatcher {
  public:
-  /// Final matched state passed to Build()
-  struct BuildState {
-    /// The type manager used to construct new types
-    sem::Manager& ty_mgr;
-    /// The final resolved list of open types
-    std::unordered_map<OpenType, const sem::Type*> const open_types;
-    /// The final resolved list of open numbers
-    std::unordered_map<OpenNumber, uint32_t> const open_numbers;
-  };
-
   /// Destructor
-  ~Builder() override = default;
+  virtual ~NumberMatcher() = default;
 
-  /// Constructs and returns the expected type
-  virtual const sem::Type* Build(BuildState& state) const = 0;
+  /// Checks whether the given number matches the matcher rules.
+  /// Match may close open numbers in state.
+  /// @param number the number to match
+  /// @returns true if the argument type is as expected.
+  virtual Number Match(MatchState& state, Number number) const = 0;
+
+  /// @return a string representation of the matcher. Used for printing error
+  /// messages when no overload is found.
+  virtual std::string String(MatchState& state) const = 0;
 };
 
-/// OpenTypeBuilder is a Matcher / Builder for an open type (T etc).
-/// The OpenTypeBuilder will match against any type (so long as it is consistent
-/// for the overload), and Build() will build the type it matched against.
-class OpenTypeBuilder : public Builder {
+/// OpenTypeMatcher is a Matcher for an open type.
+/// The OpenTypeMatcher will match against any type (so long as it is consistent
+/// across all uses in the overload)
+class OpenTypeMatcher : public TypeMatcher {
  public:
-  explicit OpenTypeBuilder(OpenType open_type) : open_type_(open_type) {}
+  /// Constructor
+  explicit OpenTypeMatcher(uint32_t index) : index_(index) {}
 
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    return MatchOpenType(state, open_type_, ty);
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override {
+    if (type->Is<Any>()) {
+      return state.closed.Type(index_);
+    }
+    return state.closed.Type(index_, type) ? type : nullptr;
   }
 
-  const sem::Type* Build(BuildState& state) const override {
-    return state.open_types.at(open_type_);
-  }
-
-  std::string str() const override { return tint::str(open_type_); }
+  std::string String(MatchState& state) const override;
 
  private:
-  OpenType open_type_;
+  uint32_t index_;
 };
 
-/// VoidBuilder is a Matcher / Builder for void types.
-class VoidBuilder : public Builder {
+/// OpenNumberMatcher is a Matcher for an open number.
+/// The OpenNumberMatcher will match against any number (so long as it is
+/// consistent for the overload)
+class OpenNumberMatcher : public NumberMatcher {
  public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::Void>();
-  }
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::Void>();
-  }
-  std::string str() const override { return "void"; }
-};
+  explicit OpenNumberMatcher(uint32_t index) : index_(index) {}
 
-/// BoolBuilder is a Matcher / Builder for boolean types.
-class BoolBuilder : public Builder {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::Bool>();
-  }
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::Bool>();
-  }
-  std::string str() const override { return "bool"; }
-};
-
-/// F32Builder is a Matcher / Builder for f32 types.
-class F32Builder : public Builder {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::F32>();
-  }
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::F32>();
-  }
-  std::string str() const override { return "f32"; }
-};
-
-/// U32Builder is a Matcher / Builder for u32 types.
-class U32Builder : public Builder {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::U32>();
-  }
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::U32>();
-  }
-  std::string str() const override { return "u32"; }
-};
-
-/// I32Builder is a Matcher / Builder for i32 types.
-class I32Builder : public Builder {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::I32>();
-  }
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::I32>();
-  }
-  std::string str() const override { return "i32"; }
-};
-
-/// IU32Matcher is a Matcher for i32 or u32 types.
-class IU32Matcher : public Matcher {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::I32>() || ty->Is<sem::U32>();
-  }
-  std::string str() const override { return "i32 or u32"; }
-};
-
-/// FIU32Matcher is a Matcher for f32, i32 or u32 types.
-class FIU32Matcher : public Matcher {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::F32>() || ty->Is<sem::I32>() || ty->Is<sem::U32>();
-  }
-  std::string str() const override { return "f32, i32 or u32"; }
-};
-
-/// ScalarMatcher is a Matcher for f32, i32, u32 or boolean types.
-class ScalarMatcher : public Matcher {
- public:
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->is_scalar();
-  }
-  std::string str() const override { return "scalar"; }
-};
-
-/// OpenSizeVecBuilder is a Matcher / Builder for vector types of an open number
-/// size.
-class OpenSizeVecBuilder : public Builder {
- public:
-  OpenSizeVecBuilder(OpenNumber size, Builder* element_builder)
-      : size_(size), element_builder_(element_builder) {}
-
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* vec = ty->As<sem::Vector>()) {
-      if (!MatchOpenNumber(state, size_, vec->size())) {
-        return false;
-      }
-      return element_builder_->Match(state, vec->type());
+  Number Match(MatchState& state, Number number) const override {
+    if (number.IsAny()) {
+      return state.closed.Num(index_);
     }
-    return false;
+    return state.closed.Num(index_, number) ? number : Number::invalid;
   }
 
-  sem::Type* Build(BuildState& state) const override {
-    auto* el = element_builder_->Build(state);
-    auto n = state.open_numbers.at(size_);
-    return state.ty_mgr.Get<sem::Vector>(el, n);
-  }
-
-  std::string str() const override {
-    return "vec" + std::string(tint::str(size_)) + "<" +
-           element_builder_->str() + ">";
-  }
-
- protected:
-  OpenNumber const size_;
-  Builder* const element_builder_;
-};
-
-/// VecBuilder is a Matcher / Builder for vector types of a fixed size.
-class VecBuilder : public Builder {
- public:
-  VecBuilder(uint32_t size, Builder* element_builder)
-      : size_(size), element_builder_(element_builder) {}
-
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* vec = ty->As<sem::Vector>()) {
-      if (vec->size() == size_) {
-        return element_builder_->Match(state, vec->type());
-      }
-    }
-    return false;
-  }
-
-  sem::Type* Build(BuildState& state) const override {
-    auto* el = element_builder_->Build(state);
-    return state.ty_mgr.Get<sem::Vector>(el, size_);
-  }
-
-  std::string str() const override {
-    return "vec" + std::to_string(size_) + "<" + element_builder_->str() + ">";
-  }
-
- protected:
-  const uint32_t size_;
-  Builder* const element_builder_;
-};
-
-/// OpenSizeVecBuilder is a Matcher / Builder for matrix types of an open number
-/// column and row size.
-class OpenSizeMatBuilder : public Builder {
- public:
-  OpenSizeMatBuilder(OpenNumber columns,
-                     OpenNumber rows,
-                     Builder* element_builder)
-      : columns_(columns), rows_(rows), element_builder_(element_builder) {}
-
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* mat = ty->As<sem::Matrix>()) {
-      if (!MatchOpenNumber(state, columns_, mat->columns())) {
-        return false;
-      }
-      if (!MatchOpenNumber(state, rows_, mat->rows())) {
-        return false;
-      }
-      return element_builder_->Match(state, mat->type());
-    }
-    return false;
-  }
-
-  sem::Type* Build(BuildState& state) const override {
-    auto* el = element_builder_->Build(state);
-    auto columns = state.open_numbers.at(columns_);
-    auto rows = state.open_numbers.at(rows_);
-    auto* column_type =
-        state.ty_mgr.Get<sem::Vector>(const_cast<sem::Type*>(el), rows);
-    return state.ty_mgr.Get<sem::Matrix>(column_type, columns);
-  }
-
-  std::string str() const override {
-    return "mat" + std::string(tint::str(columns_)) + "x" +
-           std::string(tint::str(rows_)) + "<" + element_builder_->str() + ">";
-  }
-
- protected:
-  OpenNumber const columns_;
-  OpenNumber const rows_;
-  Builder* const element_builder_;
-};
-
-/// PtrBuilder is a Matcher / Builder for pointer types.
-class PtrBuilder : public Builder {
- public:
-  explicit PtrBuilder(Builder* element_builder)
-      : element_builder_(element_builder) {}
-
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* ptr = ty->As<sem::Pointer>()) {
-      return element_builder_->Match(state, ptr->StoreType());
-    }
-    return false;
-  }
-
-  sem::Type* Build(BuildState& state) const override {
-    auto* el = element_builder_->Build(state);
-    return state.ty_mgr.Get<sem::Pointer>(const_cast<sem::Type*>(el),
-                                          ast::StorageClass::kNone);
-  }
-
-  bool ExpectsPointer() const override { return true; }
-
-  std::string str() const override {
-    return "ptr<" + element_builder_->str() + ">";
-  }
+  std::string String(MatchState& state) const override;
 
  private:
-  Builder* const element_builder_;
+  uint32_t index_;
 };
 
-/// ArrayBuilder is a Matcher / Builder for runtime sized array types.
-class ArrayBuilder : public Builder {
- public:
-  explicit ArrayBuilder(Builder* element_builder)
-      : element_builder_(element_builder) {}
+////////////////////////////////////////////////////////////////////////////////
+// Binding functions for use in the generated intrinsic_table.inl
+// TODO(bclayton): See if we can move more of this hand-rolled code to the
+// template
+////////////////////////////////////////////////////////////////////////////////
+using TexelFormat = ast::ImageFormat;
+using AccessControl = ast::AccessControl::Access;
+using StorageClass = ast::StorageClass;
+using ParameterUsage = sem::ParameterUsage;
 
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* arr = ty->As<sem::Array>()) {
-      if (arr->IsRuntimeSized()) {
-        return element_builder_->Match(state, arr->ElemType());
-      }
+bool match_bool(const sem::Type* ty) {
+  return ty->IsAnyOf<Any, sem::Bool>();
+}
+
+const sem::Bool* build_bool(MatchState& state) {
+  return state.builder.create<sem::Bool>();
+}
+
+bool match_f32(const sem::Type* ty) {
+  return ty->IsAnyOf<Any, sem::F32>();
+}
+
+const sem::I32* build_i32(MatchState& state) {
+  return state.builder.create<sem::I32>();
+}
+
+bool match_i32(const sem::Type* ty) {
+  return ty->IsAnyOf<Any, sem::I32>();
+}
+
+const sem::U32* build_u32(MatchState& state) {
+  return state.builder.create<sem::U32>();
+}
+
+bool match_u32(const sem::Type* ty) {
+  return ty->IsAnyOf<Any, sem::U32>();
+}
+
+const sem::F32* build_f32(MatchState& state) {
+  return state.builder.create<sem::F32>();
+}
+
+bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    N = Number::any;
+    T = ty;
+    return true;
+  }
+
+  if (auto* v = ty->As<sem::Vector>()) {
+    N = v->size();
+    T = v->type();
+    return true;
+  }
+  return false;
+}
+
+const sem::Vector* build_vec(MatchState& state, Number N, const sem::Type* el) {
+  return state.builder.create<sem::Vector>(el, N.Value());
+}
+
+template <int N>
+bool match_vec(const sem::Type* ty, const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    T = ty;
+    return true;
+  }
+
+  if (auto* v = ty->As<sem::Vector>()) {
+    if (v->size() == N) {
+      T = v->type();
+      return true;
     }
-    return false;
+  }
+  return false;
+}
+
+bool match_vec2(const sem::Type* ty, const sem::Type*& T) {
+  return match_vec<2>(ty, T);
+}
+
+const sem::Vector* build_vec2(MatchState& state, const sem::Type* T) {
+  return build_vec(state, Number(2), T);
+}
+
+bool match_vec3(const sem::Type* ty, const sem::Type*& T) {
+  return match_vec<3>(ty, T);
+}
+
+const sem::Vector* build_vec3(MatchState& state, const sem::Type* T) {
+  return build_vec(state, Number(3), T);
+}
+
+bool match_vec4(const sem::Type* ty, const sem::Type*& T) {
+  return match_vec<4>(ty, T);
+}
+
+const sem::Vector* build_vec4(MatchState& state, const sem::Type* T) {
+  return build_vec(state, Number(4), T);
+}
+
+bool match_mat(const sem::Type* ty, Number& M, Number& N, const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    M = Number::any;
+    N = Number::any;
+    T = ty;
+    return true;
+  }
+  if (auto* m = ty->As<sem::Matrix>()) {
+    M = m->columns();
+    N = m->ColumnType()->size();
+    T = m->type();
+    return true;
+  }
+  return false;
+}
+
+const sem::Matrix* build_mat(MatchState& state,
+                             Number N,
+                             Number M,
+                             const sem::Type* T) {
+  auto* column_type = state.builder.create<sem::Vector>(T, N.Value());
+  return state.builder.create<sem::Matrix>(column_type, M.Value());
+}
+
+bool match_array(const sem::Type* ty, const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    T = ty;
+    return true;
   }
 
-  sem::Type* Build(BuildState& state) const override {
-    auto* el = element_builder_->Build(state);
-    return state.ty_mgr.Get<sem::Array>(el, 0, 0, 0, 0, true);
-  }
-
-  std::string str() const override {
-    return "array<" + element_builder_->str() + ">";
-  }
-
- private:
-  Builder* const element_builder_;
-};
-
-/// SampledTextureBuilder is a Matcher / Builder for sampled texture types.
-class SampledTextureBuilder : public Builder {
- public:
-  explicit SampledTextureBuilder(ast::TextureDimension dimensions,
-                                 Builder* type_builder)
-      : dimensions_(dimensions), type_builder_(type_builder) {}
-
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* tex = ty->As<sem::SampledTexture>()) {
-      if (tex->dim() == dimensions_) {
-        return type_builder_->Match(state, tex->type());
-      }
+  if (auto* a = ty->As<sem::Array>()) {
+    if (a->Count() == 0) {
+      T = a->ElemType();
+      return true;
     }
-    return false;
+  }
+  return false;
+}
+
+const sem::Array* build_array(MatchState& state, const sem::Type* el) {
+  return state.builder.create<sem::Array>(el,
+                                          /* count */ 0,
+                                          /* align */ 0,
+                                          /* size */ 0,
+                                          /* stride */ 0,
+                                          /* stride_implicit */ 0);
+}
+
+bool match_ptr(const sem::Type* ty, Number& S, const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    S = Number::any;
+    T = ty;
+    return true;
   }
 
-  sem::Type* Build(BuildState& state) const override {
-    auto* type = type_builder_->Build(state);
-    return state.ty_mgr.Get<sem::SampledTexture>(dimensions_, type);
+  if (auto* p = ty->As<sem::Pointer>()) {
+    S = Number(static_cast<uint32_t>(p->StorageClass()));
+    T = p->StoreType();
+    return true;
   }
+  return false;
+}
 
-  std::string str() const override {
-    std::stringstream ss;
-    ss << "texture_" << dimensions_ << "<" << type_builder_->str() << ">";
-    return ss.str();
+const sem::Pointer* build_ptr(MatchState& state, Number S, const sem::Type* T) {
+  return state.builder.create<sem::Pointer>(
+      T, static_cast<ast::StorageClass>(S.Value()));
+}
+
+bool match_sampler(const sem::Type* ty) {
+  if (ty->Is<Any>()) {
+    return true;
   }
+  return ty->Is<sem::Sampler>([](const sem::Sampler* s) {
+    return s->kind() == ast::SamplerKind::kSampler;
+  });
+}
 
- private:
-  ast::TextureDimension const dimensions_;
-  Builder* const type_builder_;
-};
+const sem::Sampler* build_sampler(MatchState& state) {
+  return state.builder.create<sem::Sampler>(ast::SamplerKind::kSampler);
+}
 
-/// MultisampledTextureBuilder is a Matcher / Builder for multisampled texture
-/// types.
-class MultisampledTextureBuilder : public Builder {
- public:
-  explicit MultisampledTextureBuilder(ast::TextureDimension dimensions,
-                                      Builder* type_builder)
-      : dimensions_(dimensions), type_builder_(type_builder) {}
+bool match_sampler_comparison(const sem::Type* ty) {
+  if (ty->Is<Any>()) {
+    return true;
+  }
+  return ty->Is<sem::Sampler>([](const sem::Sampler* s) {
+    return s->kind() == ast::SamplerKind::kComparisonSampler;
+  });
+}
 
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* tex = ty->As<sem::MultisampledTexture>()) {
-      if (tex->dim() == dimensions_) {
-        return type_builder_->Match(state, tex->type());
-      }
+const sem::Sampler* build_sampler_comparison(MatchState& state) {
+  return state.builder.create<sem::Sampler>(
+      ast::SamplerKind::kComparisonSampler);
+}
+
+bool match_texture(const sem::Type* ty,
+                   ast::TextureDimension dim,
+                   const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    T = ty;
+    return true;
+  }
+  if (auto* v = ty->As<sem::SampledTexture>()) {
+    if (v->dim() == dim) {
+      T = v->type();
+      return true;
     }
-    return false;
+  }
+  return false;
+}
+
+#define JOIN(a, b) a##b
+
+#define DECLARE_SAMPLED_TEXTURE(suffix, dim)                  \
+  bool JOIN(match_texture_, suffix)(const sem::Type* ty,      \
+                                    const sem::Type*& T) {    \
+    return match_texture(ty, dim, T);                         \
+  }                                                           \
+  const sem::SampledTexture* JOIN(build_texture_, suffix)(    \
+      MatchState & state, const sem::Type* T) {               \
+    return state.builder.create<sem::SampledTexture>(dim, T); \
   }
 
-  sem::Type* Build(BuildState& state) const override {
-    auto* type = type_builder_->Build(state);
-    return state.ty_mgr.Get<sem::MultisampledTexture>(dimensions_, type);
+DECLARE_SAMPLED_TEXTURE(1d, ast::TextureDimension::k1d)
+DECLARE_SAMPLED_TEXTURE(2d, ast::TextureDimension::k2d)
+DECLARE_SAMPLED_TEXTURE(2d_array, ast::TextureDimension::k2dArray)
+DECLARE_SAMPLED_TEXTURE(3d, ast::TextureDimension::k3d)
+DECLARE_SAMPLED_TEXTURE(cube, ast::TextureDimension::kCube)
+DECLARE_SAMPLED_TEXTURE(cube_array, ast::TextureDimension::kCubeArray)
+#undef DECLARE_SAMPLED_TEXTURE
+
+bool match_texture_multisampled(const sem::Type* ty,
+                                ast::TextureDimension dim,
+                                const sem::Type*& T) {
+  if (ty->Is<Any>()) {
+    T = ty;
+    return true;
   }
-
-  std::string str() const override {
-    std::stringstream ss;
-    ss << "texture_multisampled_" << dimensions_ << "<" << type_builder_->str()
-       << ">";
-    return ss.str();
-  }
-
- private:
-  ast::TextureDimension const dimensions_;
-  Builder* const type_builder_;
-};
-
-/// DepthTextureBuilder is a Matcher / Builder for depth texture types.
-class DepthTextureBuilder : public Builder {
- public:
-  explicit DepthTextureBuilder(ast::TextureDimension dimensions)
-      : dimensions_(dimensions) {}
-
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    if (auto* tex = ty->As<sem::DepthTexture>()) {
-      return tex->dim() == dimensions_;
+  if (auto* v = ty->As<sem::MultisampledTexture>()) {
+    if (v->dim() == dim) {
+      T = v->type();
+      return true;
     }
-    return false;
+  }
+  return false;
+}
+
+#define DECLARE_MULTISAMPLED_TEXTURE(suffix, dim)                            \
+  bool JOIN(match_texture_multisampled_, suffix)(const sem::Type* ty,        \
+                                                 const sem::Type*& T) {      \
+    return match_texture_multisampled(ty, dim, T);                           \
+  }                                                                          \
+  const sem::MultisampledTexture* JOIN(build_texture_multisampled_, suffix)( \
+      MatchState & state, const sem::Type* T) {                              \
+    return state.builder.create<sem::MultisampledTexture>(dim, T);           \
   }
 
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::DepthTexture>(dimensions_);
+DECLARE_MULTISAMPLED_TEXTURE(2d, ast::TextureDimension::k2d)
+#undef DECLARE_MULTISAMPLED_TEXTURE
+
+bool match_texture_depth(const sem::Type* ty, ast::TextureDimension dim) {
+  if (ty->Is<Any>()) {
+    return true;
+  }
+  return ty->Is<sem::DepthTexture>([&](auto t) { return t->dim() == dim; });
+}
+
+#define DECLARE_DEPTH_TEXTURE(suffix, dim)                       \
+  bool JOIN(match_texture_depth_, suffix)(const sem::Type* ty) { \
+    return match_texture_depth(ty, dim);                         \
+  }                                                              \
+  const sem::DepthTexture* JOIN(build_texture_depth_,            \
+                                suffix)(MatchState & state) {    \
+    return state.builder.create<sem::DepthTexture>(dim);         \
   }
 
-  std::string str() const override {
-    std::stringstream ss;
-    ss << "texture_depth_" << dimensions_;
-    return ss.str();
+DECLARE_DEPTH_TEXTURE(2d, ast::TextureDimension::k2d)
+DECLARE_DEPTH_TEXTURE(2d_array, ast::TextureDimension::k2dArray)
+DECLARE_DEPTH_TEXTURE(cube, ast::TextureDimension::kCube)
+DECLARE_DEPTH_TEXTURE(cube_array, ast::TextureDimension::kCubeArray)
+#undef DECLARE_DEPTH_TEXTURE
+
+bool match_texture_storage(const sem::Type* ty,
+                           ast::TextureDimension dim,
+                           Number& F,
+                           Number& A) {
+  if (ty->Is<Any>()) {
+    F = Number::any;
+    A = Number::any;
+    return true;
   }
-
- private:
-  ast::TextureDimension const dimensions_;
-};
-
-/// StorageTextureBuilder is a Matcher / Builder for storage texture types of
-/// the given texel and channel formats.
-class StorageTextureBuilder : public Builder {
- public:
-  StorageTextureBuilder(ast::TextureDimension dimensions,
-                        ast::AccessControl::Access access,
-                        OpenNumber texel_format,  // a.k.a "image format"
-                        OpenType channel_format)  // a.k.a "storage subtype"
-      : dimensions_(dimensions),
-        access_(access),
-        access_is_open_num_(false),
-        texel_format_(texel_format),
-        channel_format_(channel_format) {}
-
-  StorageTextureBuilder(ast::TextureDimension dimensions,
-                        OpenNumber access,
-                        OpenNumber texel_format,  // a.k.a "image format"
-                        OpenType channel_format)  // a.k.a "storage subtype"
-      : dimensions_(dimensions),
-        access_(access),
-        access_is_open_num_(true),
-        texel_format_(texel_format),
-        channel_format_(channel_format) {}
-
-  bool Match(MatchState& state, const sem::Type* ty) const override {
-    if (auto* tex = ty->As<sem::StorageTexture>()) {
-      if (MatchOpenNumber(state, texel_format_,
-                          static_cast<uint32_t>(tex->image_format()))) {
-        if (MatchOpenType(state, channel_format_, tex->type())) {
-          if (access_is_open_num_) {
-            if (!MatchOpenNumber(
-                    state, access_.open_num,
-                    static_cast<uint32_t>(tex->access_control()))) {
-              return false;
-            }
-          } else {
-            if (access_.enum_val != tex->access_control()) {
-              return false;
-            }
-          }
-
-          return tex->dim() == dimensions_;
-        }
-      }
+  if (auto* v = ty->As<sem::StorageTexture>()) {
+    if (v->dim() == dim) {
+      F = Number(static_cast<uint32_t>(v->image_format()));
+      A = Number(static_cast<uint32_t>(v->access_control()));
+      return true;
     }
-    return false;
+  }
+  return false;
+}
+
+#define DECLARE_STORAGE_TEXTURE(suffix, dim)                                  \
+  bool JOIN(match_texture_storage_, suffix)(const sem::Type* ty, Number& F,   \
+                                            Number& A) {                      \
+    return match_texture_storage(ty, dim, F, A);                              \
+  }                                                                           \
+  const sem::StorageTexture* JOIN(build_texture_storage_, suffix)(            \
+      MatchState & state, Number F, Number A) {                               \
+    auto format = static_cast<TexelFormat>(F.Value());                        \
+    auto access = static_cast<AccessControl>(A.Value());                      \
+    auto* T = sem::StorageTexture::SubtypeFor(format, state.builder.Types()); \
+    return state.builder.create<sem::StorageTexture>(dim, format, access, T); \
   }
 
-  sem::Type* Build(BuildState& state) const override {
-    auto texel_format =
-        static_cast<ast::ImageFormat>(state.open_numbers.at(texel_format_));
-    auto access = access_is_open_num_
-                      ? static_cast<ast::AccessControl::Access>(
-                            state.open_numbers.at(access_.open_num))
-                      : access_.enum_val;
-    auto* channel_format = state.open_types.at(channel_format_);
-    return state.ty_mgr.Get<sem::StorageTexture>(
-        dimensions_, texel_format, access,
-        const_cast<sem::Type*>(channel_format));
-  }
+DECLARE_STORAGE_TEXTURE(1d, ast::TextureDimension::k1d)
+DECLARE_STORAGE_TEXTURE(2d, ast::TextureDimension::k2d)
+DECLARE_STORAGE_TEXTURE(2d_array, ast::TextureDimension::k2dArray)
+DECLARE_STORAGE_TEXTURE(3d, ast::TextureDimension::k3d)
+#undef DECLARE_STORAGE_TEXTURE
 
-  std::string str() const override {
-    std::stringstream ss;
+bool match_texture_external(const sem::Type* ty) {
+  return ty->IsAnyOf<Any, sem::ExternalTexture>();
+}
 
-    ss << "texture_storage_" << dimensions_ << "<F, ";
-    if (access_is_open_num_) {
-      ss << "A";
-    } else {
-      ss << access_.enum_val;
-    }
-    ss << ">";
+const sem::ExternalTexture* build_texture_external(MatchState& state) {
+  return state.builder.create<sem::ExternalTexture>();
+}
 
-    return ss.str();
-  }
-
- private:
-  ast::TextureDimension const dimensions_;
-  union Access {
-    Access(OpenNumber in) : open_num(in) {}
-    Access(ast::AccessControl::Access in) : enum_val(in) {}
-
-    OpenNumber const open_num;
-    ast::AccessControl::Access const enum_val;
-  } access_;
-  bool access_is_open_num_;
-  OpenNumber const texel_format_;
-  OpenType const channel_format_;
-};
-
-/// ExternalTextureBuilder is a Matcher / Builder for external textures.
-class ExternalTextureBuilder : public Builder {
- public:
-  ExternalTextureBuilder() {}
-
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    return ty->Is<sem::ExternalTexture>();
-  }
-
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::ExternalTexture>();
-  }
-
-  std::string str() const override { return "texture_external"; }
-};
-
-/// SamplerBuilder is a Matcher / Builder for sampler types of the given kind.
-class SamplerBuilder : public Builder {
- public:
-  explicit SamplerBuilder(ast::SamplerKind kind) : kind_(kind) {}
-
-  bool Match(MatchState&, const sem::Type* ty) const override {
-    if (auto* sampler = ty->As<sem::Sampler>()) {
-      return sampler->kind() == kind_;
-    }
-    return false;
-  }
-
-  sem::Type* Build(BuildState& state) const override {
-    return state.ty_mgr.Get<sem::Sampler>(kind_);
-  }
-
-  std::string str() const override {
-    switch (kind_) {
-      case ast::SamplerKind::kSampler:
-        return "sampler";
-      case ast::SamplerKind::kComparisonSampler:
-        return "sampler_comparison";
-    }
-    return "sampler";
-  }
-
- private:
-  ast::SamplerKind const kind_;
-};
+#include "intrinsic_table.inl"
 
 /// Impl is the private implementation of the IntrinsicTable interface.
 class Impl : public IntrinsicTable {
  public:
-  Impl();
+  explicit Impl(ProgramBuilder& builder);
 
-  IntrinsicTable::Result Lookup(ProgramBuilder& builder,
-                                sem::IntrinsicType type,
-                                const std::vector<const sem::Type*>& args,
-                                const Source& source) const override;
-
-  /// Holds the information about a single overload parameter used for matching
-  struct Parameter {
-    Parameter(
-        Builder* m)  // NOLINT - implicit constructor required for Register()
-        : matcher(m) {}
-    Parameter(sem::ParameterUsage u, Builder* m) : matcher(m), usage(u) {}
-
-    Builder* const matcher;
-    sem::ParameterUsage const usage = sem::ParameterUsage::kNone;
-  };
-
-  /// A single overload definition.
-  struct Overload {
-    /// Attempts to match this overload given the IntrinsicType and argument
-    /// types. If a match is made, the build intrinsic is returned, otherwise
-    /// `match_score` is assigned a score of how closely the overload matched
-    /// (positive representing a greater match), and nullptr is returned.
-    sem::Intrinsic* Match(ProgramBuilder& builder,
-                          sem::IntrinsicType type,
-                          const std::vector<const sem::Type*>& arg_types,
-                          diag::List& diagnostics,
-                          int& match_score) const;
-
-    sem::IntrinsicType type;
-    Builder* return_type;
-    std::vector<Parameter> parameters;
-    std::unordered_map<OpenType, Matcher*> open_type_matchers;
-  };
+  const sem::Intrinsic* Lookup(sem::IntrinsicType intrinsic_type,
+                               const std::vector<const sem::Type*>& args,
+                               const Source& source) const override;
 
  private:
-  /// Allocator for the built Matcher / Builders
-  BlockAllocator<Matcher> matcher_allocator_;
+  const sem::Intrinsic* Match(sem::IntrinsicType intrinsic_type,
+                              const OverloadInfo& overload,
+                              const std::vector<const sem::Type*>& args,
+                              int& match_score) const;
 
-  /// Commonly used Matcher / Builders
-  struct {
-    VoidBuilder void_;
-    BoolBuilder bool_;
-    F32Builder f32;
-    I32Builder i32;
-    IU32Matcher iu32;
-    FIU32Matcher fiu32;
-    ScalarMatcher scalar;
-    U32Builder u32;
-    OpenTypeBuilder T{OpenType::T};
-  } matchers_;
+  MatchState Match(ClosedState& closed,
+                   const OverloadInfo& overload,
+                   MatcherIndex const* matcher_indices) const;
 
-  // TODO(bclayton): Sort by type, or array these by IntrinsicType
-  std::vector<Overload> overloads_;
+  void PrintOverload(std::ostream& ss,
+                     const OverloadInfo& overload,
+                     sem::IntrinsicType intrinsic_type) const;
 
-  /// @returns a Matcher / Builder that matches a pointer with the given element
-  /// type
-  Builder* ptr(Builder* element_builder) {
-    return matcher_allocator_.Create<PtrBuilder>(element_builder);
-  }
-
-  /// @returns a Matcher / Builder that matches a vector of size OpenNumber::N
-  /// with the given element type
-  Builder* vecN(Builder* element_builder) {
-    return matcher_allocator_.Create<OpenSizeVecBuilder>(OpenNumber::N,
-                                                         element_builder);
-  }
-
-  /// @returns a Matcher / Builder that matches a vector of the given size and
-  /// element type
-  Builder* vec(uint32_t size, Builder* element_builder) {
-    return matcher_allocator_.Create<VecBuilder>(size, element_builder);
-  }
-
-  /// @returns a Matcher / Builder that matches a runtime sized array with the
-  /// given element type
-  Builder* array(Builder* element_builder) {
-    return matcher_allocator_.Create<ArrayBuilder>(element_builder);
-  }
-
-  /// @returns a Matcher / Builder that matches a matrix with the given size and
-  /// element type
-  Builder* mat(OpenNumber columns, OpenNumber rows, Builder* element_builder) {
-    return matcher_allocator_.Create<OpenSizeMatBuilder>(columns, rows,
-                                                         element_builder);
-  }
-
-  /// @returns a Matcher / Builder that matches a square matrix with the column
-  /// / row count of OpenNumber::N
-  template <typename T>
-  auto matNxN(T&& in) {
-    return mat(OpenNumber::N, OpenNumber::N, std::forward<T>(in));
-  }
-
-  /// @returns a Matcher / Builder that matches a sampled texture with the given
-  /// dimensions and type
-  Builder* sampled_texture(ast::TextureDimension dimensions, Builder* type) {
-    return matcher_allocator_.Create<SampledTextureBuilder>(dimensions, type);
-  }
-
-  /// @returns a Matcher / Builder that matches a multisampled texture with the
-  /// given dimensions and type
-  Builder* multisampled_texture(ast::TextureDimension dimensions,
-                                Builder* type) {
-    return matcher_allocator_.Create<MultisampledTextureBuilder>(dimensions,
-                                                                 type);
-  }
-
-  /// @returns a Matcher / Builder that matches a depth texture with the
-  /// given dimensions
-  Builder* depth_texture(ast::TextureDimension dimensions) {
-    return matcher_allocator_.Create<DepthTextureBuilder>(dimensions);
-  }
-
-  /// @returns a Matcher / Builder that matches a storage texture of the given
-  /// format with the given dimensions
-  Builder* storage_texture(ast::TextureDimension dimensions,
-                           ast::AccessControl::Access access,
-                           OpenNumber texel_format,
-                           OpenType channel_format) {
-    return matcher_allocator_.Create<StorageTextureBuilder>(
-        dimensions, access, texel_format, channel_format);
-  }
-
-  Builder* storage_texture(ast::TextureDimension dimensions,
-                           OpenNumber access,
-                           OpenNumber texel_format,
-                           OpenType channel_format) {
-    return matcher_allocator_.Create<StorageTextureBuilder>(
-        dimensions, access, texel_format, channel_format);
-  }
-
-  /// @returns a Matcher / Builder that matches an external texture
-  Builder* external_texture() {
-    return matcher_allocator_.Create<ExternalTextureBuilder>();
-  }
-
-  /// @returns a Matcher / Builder that matches a sampler type
-  Builder* sampler(ast::SamplerKind kind) {
-    return matcher_allocator_.Create<SamplerBuilder>(kind);
-  }
-
-  /// Registers an overload with the given intrinsic type, return type Matcher /
-  /// Builder, and parameter Matcher / Builders.
-  /// This overload of Register does not constrain any OpenTypes.
-  void Register(sem::IntrinsicType type,
-                Builder* return_type,
-                std::vector<Parameter> parameters) {
-    Overload overload{type, return_type, std::move(parameters), {}};
-    overloads_.emplace_back(std::move(overload));
-  }
-
-  /// Registers an overload with the given intrinsic type, return type Matcher /
-  /// Builder, and parameter Matcher / Builders.
-  /// A single OpenType is contained with the given Matcher in
-  /// open_type_matcher.
-  void Register(sem::IntrinsicType type,
-                Builder* return_type,
-                std::vector<Parameter> parameters,
-                std::pair<OpenType, Matcher*> open_type_matcher) {
-    Overload overload{
-        type, return_type, std::move(parameters), {open_type_matcher}};
-    overloads_.emplace_back(std::move(overload));
-  }
+  ProgramBuilder& builder;
+  Matchers matchers;
 };
 
-Impl::Impl() {
-  using I = sem::IntrinsicType;
-  using Dim = ast::TextureDimension;
-
-  auto* void_ = &matchers_.void_;      // void
-  auto* bool_ = &matchers_.bool_;      // bool
-  auto* f32 = &matchers_.f32;          // f32
-  auto* i32 = &matchers_.i32;          // i32
-  auto* u32 = &matchers_.u32;          // u32
-  auto* iu32 = &matchers_.iu32;        // i32 or u32
-  auto* fiu32 = &matchers_.fiu32;      // f32, i32 or u32
-  auto* scalar = &matchers_.scalar;    // f32, i32, u32 or bool
-  auto* T = &matchers_.T;              // Any T type
-  auto* array_T = array(T);            // array<T>
-  auto* vec2_f32 = vec(2, f32);        // vec2<f32>
-  auto* vec3_f32 = vec(3, f32);        // vec3<f32>
-  auto* vec4_f32 = vec(4, f32);        // vec4<f32>
-  auto* vec4_T = vec(4, T);            // vec4<T>
-  auto* vec2_i32 = vec(2, i32);        // vec2<i32>
-  auto* vec3_i32 = vec(3, i32);        // vec3<i32>
-  auto* vecN_f32 = vecN(f32);          // vecN<f32>
-  auto* vecN_T = vecN(T);              // vecN<T>
-  auto* vecN_bool = vecN(bool_);       // vecN<bool>
-  auto* matNxN_f32 = matNxN(f32);      // matNxN<f32>
-  auto* ptr_T = ptr(T);                // ptr<T>
-  auto* ptr_f32 = ptr(f32);            // ptr<f32>
-  auto* ptr_vecN_T = ptr(vecN_T);      // ptr<vecN<T>>
-  auto* ptr_vecN_f32 = ptr(vecN_f32);  // ptr<vecN<f32>>
-
-  constexpr size_t overloads_reserve_size = 300;
-  overloads_.reserve(overloads_reserve_size);
-
-  // Intrinsic overloads are registered with a call to the Register().
-  //
-  // The best way to explain Register() and the lookup process is by example.
-  //
-  // Let's begin with a simple overload declaration:
-  //
-  //   Register(I::kIsInf, bool_, {f32});
-  //
-  //   I     - is an alias to sem::IntrinsicType.
-  //           I::kIsInf is shorthand for sem::IntrinsicType::kIsInf.
-  //   bool_ - is a pointer to a pre-constructed BoolBuilder which matches and
-  //           builds sem::Bool types.
-  //   {f32} - is the list of parameter Builders for the overload.
-  //           Builders are a type of Matcher that can also build the the type.
-  //           All Builders are Matchers, not all Matchers are Builders.
-  //   f32     is a pointer to a pre-constructed F32Builder which matches and
-  //           builds sem::F32 types.
-  //
-  // This call registers the overload for the `isInf(f32) -> bool` intrinsic.
-  //
-  // Let's now see the process of Overload::Match() when passed a single f32
-  // argument:
-  //
-  //   (1) Overload::Match() begins by attempting to match the argument types
-  //       from left to right.
-  //       F32Builder::Match() is called with the sem::F32 argument type.
-  //       F32Builder (only) matches the sem::F32 type, so F32Builder::Match()
-  //       returns true.
-  //   (2) All the parameters have had their Matcher::Match() methods return
-  //       true, there are no open-types (more about these later), so the
-  //       overload has matched.
-  //   (3) The sem::Intrinsic now needs to be built, so we begin by
-  //       building the overload's parameter types (these may not exactly match
-  //       the argument types). Build() is called for each parameter Builder,
-  //       returning the parameter type.
-  //   (4) Finally, Builder::Build() is called for the return_type, and the
-  //       sem::Intrinsic is constructed and returned.
-  //       Job done.
-  //
-  // Overload resolution also supports basic pattern matching through the use of
-  // open-types and open-numbers.
-  //
-  // OpenTypeBuilder is a Matcher that matches a single open-type.
-  //
-  // An 'open-type' can be thought as a template type that is determined by the
-  // arguments to the intrinsic.
-  //
-  // At the beginning of Overload::Match(), all open-types are undefined.
-  // Open-types are closed (pinned to a fixed type) on the first attempt to
-  // match against that open-type (e.g. via OpenTypeBuilder::Match()).
-  // Once open-types are closed, they remain that type, and
-  // OpenTypeBuilder::Match() will only ever return true if the queried type
-  // matches the closed type.
-  //
-  // To better understand, let's consider the following hypothetical overload
-  // declaration:
-  //
-  //    Register(I::kFoo, T, {T, T}, {OpenType::T, scalar});
-  //
-  //    T                  - is the matcher for the open-type OpenType::T.
-  //    scalar             - is a pointer to a pre-constructed ScalarMatcher
-  //                         which matches scalar types (f32, i32, u32, bool).
-  // {OpenType::T, scalar} - is a constraint on the open-type OpenType::T that
-  //                         it needs to resolve to a scalar.
-  //
-  // This call to Register() declares the foo intrinsic which accepts the
-  // identical scalar type for both arguments, and returns that scalar type.
-  //
-  // The process for resolving this overload is as follows:
-  //
-  //   (1) Overload::Match() begins by attempting to match the argument types
-  //       from left to right.
-  //       OpenTypeBuilder::Match() is called for the first parameter, being
-  //       passed the type of the first argument.
-  //       The OpenType::T has not been closed yet, so the OpenType::T is closed
-  //       as the type of the first argument.
-  //       There's no verification that the T type is a scalar at this stage.
-  //   (2) OpenTypeBuilder::Match() is called again for the second parameter
-  //       with the type of the second argument.
-  //       As the OpenType::T is now closed, the argument type is compared
-  //       against the value of the closed-type of OpenType::T.
-  //       OpenTypeBuilder::Match() returns true if these type match, otherwise
-  //       false and the overload match fails.
-  //   (3) If all the parameters have had their Matcher::Match() methods return
-  //       true, then the open-type constraints need to be checked next.
-  //       The Matcher::Match() is called for each closed type. If any return
-  //       false then the overload match fails.
-  //   (4) Overload::Match() now needs to build and return the output
-  //       sem::Intrinsic holding the matched overload signature.
-  //   (5) The parameter types are built by calling OpenTypeBuilder::Build().
-  //       This simply returns the closed type.
-  //   (6) OpenTypeBuilder::Build() is called again for the return_type, and the
-  //       sem::Intrinsic is constructed and returned.
-  //       Job done.
-  //
-  // Open-numbers are very similar to open-types, except they match against
-  // integers instead of types. The rules for open-numbers are almost identical
-  // to open-types, except open-numbers do not support constraints.
-  //
-  // vecN(f32) is an example of a Matcher that uses open-numbers.
-  // vecN() constructs a OpenSizeVecBuilder that will match a vector of size
-  // OpenNumber::N and of element type f32. As vecN() always uses the
-  // OpenNumber::N, using vecN() multiple times in the same overload signature
-  // will ensure that the vector size is identical for all vector types.
-  //
-  // Some Matcher implementations accept other Matchers for matching sub-types.
-  // Consider:
-  //
-  //   Register(I::kClamp, vecN(T), {vecN(T), vecN(T), vecN(T)},
-  //           {OpenType::T, fiu32});
-  //
-  // vecN(T) is a OpenSizeVecBuilder that matches a vector of size OpenNumber::N
-  // and of element type OpenType::T, where T must be either a f32, i32, or u32.
-
-  // clang-format off
-
-  //       name                 return type  parameter types                    open type constraints    // NOLINT
-  Register(I::kAbs,             T,           {T},                               {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kAbs,             vecN_T,      {vecN_T},                          {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kAcos,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kAcos,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kAll,             bool_,       {vecN_bool}                                              ); // NOLINT
-  Register(I::kAny,             bool_,       {vecN_bool}                                              ); // NOLINT
-  Register(I::kArrayLength,     u32,         {array_T}                                                ); // NOLINT
-  Register(I::kAsin,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kAsin,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kAtan,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kAtan,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kAtan2,           f32,         {f32, f32}                                               ); // NOLINT
-  Register(I::kAtan2,           vecN_f32,    {vecN_f32, vecN_f32}                                     ); // NOLINT
-  Register(I::kCeil,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kCeil,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kClamp,           T,           {T, T, T},                         {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kClamp,           vecN_T,      {vecN_T, vecN_T, vecN_T},          {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kCos,             f32,         {f32}                                                    ); // NOLINT
-  Register(I::kCos,             vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kCosh,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kCosh,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kCountOneBits,    T,           {T},                               {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kCountOneBits,    vecN_T,      {vecN_T},                          {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kCross,           vec3_f32,    {vec3_f32, vec3_f32}                                     ); // NOLINT
-  Register(I::kDeterminant,     f32,         {matNxN_f32}                                             ); // NOLINT
-  Register(I::kDistance,        f32,         {f32, f32}                                               ); // NOLINT
-  Register(I::kDistance,        f32,         {vecN_f32, vecN_f32}                                     ); // NOLINT
-  Register(I::kDot,             f32,         {vecN_f32, vecN_f32}                                     ); // NOLINT
-  Register(I::kDpdx,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kDpdx,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kDpdxCoarse,      f32,         {f32}                                                    ); // NOLINT
-  Register(I::kDpdxCoarse,      vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kDpdxFine,        f32,         {f32}                                                    ); // NOLINT
-  Register(I::kDpdxFine,        vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kDpdy,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kDpdy,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kDpdyCoarse,      f32,         {f32}                                                    ); // NOLINT
-  Register(I::kDpdyCoarse,      vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kDpdyFine,        f32,         {f32}                                                    ); // NOLINT
-  Register(I::kDpdyFine,        vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kExp,             f32,         {f32}                                                    ); // NOLINT
-  Register(I::kExp,             vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kExp2,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kExp2,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kFaceForward,     f32,         {f32, f32, f32}                                          ); // NOLINT
-  Register(I::kFaceForward,     vecN_f32,    {vecN_f32, vecN_f32, vecN_f32}                           ); // NOLINT
-  Register(I::kFloor,           f32,         {f32}                                                    ); // NOLINT
-  Register(I::kFloor,           vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kFma,             f32,         {f32, f32, f32}                                          ); // NOLINT
-  Register(I::kFma,             vecN_f32,    {vecN_f32, vecN_f32, vecN_f32}                           ); // NOLINT
-  Register(I::kFract,           f32,         {f32}                                                    ); // NOLINT
-  Register(I::kFract,           vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kFrexp,           f32,         {f32, ptr_T},                      {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kFrexp,           vecN_f32,    {vecN_f32, ptr_vecN_T},            {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kFwidth,          f32,         {f32}                                                    ); // NOLINT
-  Register(I::kFwidth,          vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kFwidthCoarse,    f32,         {f32}                                                    ); // NOLINT
-  Register(I::kFwidthCoarse,    vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kFwidthFine,      f32,         {f32}                                                    ); // NOLINT
-  Register(I::kFwidthFine,      vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kInverseSqrt,     f32,         {f32}                                                    ); // NOLINT
-  Register(I::kInverseSqrt,     vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kIsFinite,        bool_,       {f32}                                                    ); // NOLINT
-  Register(I::kIsFinite,        vecN_bool,   {vecN_f32}                                               ); // NOLINT
-  Register(I::kIsInf,           bool_,       {f32}                                                    ); // NOLINT
-  Register(I::kIsInf,           vecN_bool,   {vecN_f32}                                               ); // NOLINT
-  Register(I::kIsNan,           bool_,       {f32}                                                    ); // NOLINT
-  Register(I::kIsNan,           vecN_bool,   {vecN_f32}                                               ); // NOLINT
-  Register(I::kIsNormal,        bool_,       {f32}                                                    ); // NOLINT
-  Register(I::kIsNormal,        vecN_bool,   {vecN_f32}                                               ); // NOLINT
-  Register(I::kLdexp,           f32,         {f32, T},                          {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kLdexp,           vecN_f32,    {vecN_f32, vecN_T},                {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kLength,          f32,         {f32}                                                    ); // NOLINT
-  Register(I::kLength,          f32,         {vecN_f32}                                               ); // NOLINT
-  Register(I::kLog,             f32,         {f32}                                                    ); // NOLINT
-  Register(I::kLog,             vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kLog2,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kLog2,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kMax,             T,           {T, T},                            {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kMax,             vecN_T,      {vecN_T, vecN_T},                  {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kMin,             T,           {T, T},                            {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kMin,             vecN_T,      {vecN_T, vecN_T},                  {OpenType::T, fiu32}  ); // NOLINT
-  Register(I::kMix,             f32,         {f32, f32, f32}                                          ); // NOLINT
-  Register(I::kMix,             vecN_f32,    {vecN_f32, vecN_f32, vecN_f32}                           ); // NOLINT
-  Register(I::kModf,            f32,         {f32, ptr_f32}                                           ); // NOLINT
-  Register(I::kModf,            vecN_f32,    {vecN_f32, ptr_vecN_f32}                                 ); // NOLINT
-  Register(I::kNormalize,       vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kPack2x16float,   u32,         {vec2_f32}                                               ); // NOLINT
-  Register(I::kPack2x16snorm,   u32,         {vec2_f32}                                               ); // NOLINT
-  Register(I::kPack2x16unorm,   u32,         {vec2_f32}                                               ); // NOLINT
-  Register(I::kPack4x8snorm,    u32,         {vec4_f32}                                               ); // NOLINT
-  Register(I::kPack4x8unorm,    u32,         {vec4_f32}                                               ); // NOLINT
-  Register(I::kPow,             f32,         {f32, f32}                                               ); // NOLINT
-  Register(I::kPow,             vecN_f32,    {vecN_f32, vecN_f32}                                     ); // NOLINT
-  Register(I::kReflect,         f32,         {f32, f32}                                               ); // NOLINT
-  Register(I::kReflect,         vecN_f32,    {vecN_f32, vecN_f32}                                     ); // NOLINT
-  Register(I::kReverseBits,     T,           {T},                               {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kReverseBits,     vecN_T,      {vecN_T},                          {OpenType::T, iu32}   ); // NOLINT
-  Register(I::kRound,           f32,         {f32}                                                    ); // NOLINT
-  Register(I::kRound,           vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kSelect,          T,           {T, T, bool_},                     {OpenType::T, scalar} ); // NOLINT
-  Register(I::kSelect,          vecN_T,      {vecN_T, vecN_T, vecN_bool},       {OpenType::T, scalar} ); // NOLINT
-  Register(I::kSign,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kSign,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kSin,             f32,         {f32}                                                    ); // NOLINT
-  Register(I::kSin,             vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kSinh,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kSinh,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kSmoothStep,      f32,         {f32, f32, f32}                                          ); // NOLINT
-  Register(I::kSmoothStep,      vecN_f32,    {vecN_f32, vecN_f32, vecN_f32}                           ); // NOLINT
-  Register(I::kSqrt,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kSqrt,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kStep,            f32,         {f32, f32}                                               ); // NOLINT
-  Register(I::kStep,            vecN_f32,    {vecN_f32, vecN_f32}                                     ); // NOLINT
-  Register(I::kStorageBarrier,  void_,       {}                                                       ); // NOLINT
-  Register(I::kTan,             f32,         {f32}                                                    ); // NOLINT
-  Register(I::kTan,             vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kTanh,            f32,         {f32}                                                    ); // NOLINT
-  Register(I::kTanh,            vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kTrunc,           f32,         {f32}                                                    ); // NOLINT
-  Register(I::kTrunc,           vecN_f32,    {vecN_f32}                                               ); // NOLINT
-  Register(I::kUnpack2x16float, vec2_f32,    {u32}                                                    ); // NOLINT
-  Register(I::kUnpack2x16snorm, vec2_f32,    {u32}                                                    ); // NOLINT
-  Register(I::kUnpack2x16unorm, vec2_f32,    {u32}                                                    ); // NOLINT
-  Register(I::kUnpack4x8snorm,  vec4_f32,    {u32}                                                    ); // NOLINT
-  Register(I::kUnpack4x8unorm,  vec4_f32,    {u32}                                                    ); // NOLINT
-  Register(I::kWorkgroupBarrier,void_,       {}                                                       ); // NOLINT
-  // clang-format on
-
-  auto* tex_1d_f32 = sampled_texture(Dim::k1d, f32);
-  auto* tex_1d_T = sampled_texture(Dim::k1d, T);
-  auto* tex_2d_f32 = sampled_texture(Dim::k2d, f32);
-  auto* tex_2d_T = sampled_texture(Dim::k2d, T);
-  auto* tex_2d_array_f32 = sampled_texture(Dim::k2dArray, f32);
-  auto* tex_2d_array_T = sampled_texture(Dim::k2dArray, T);
-  auto* tex_3d_f32 = sampled_texture(Dim::k3d, f32);
-  auto* tex_3d_T = sampled_texture(Dim::k3d, T);
-  auto* tex_cube_f32 = sampled_texture(Dim::kCube, f32);
-  auto* tex_cube_T = sampled_texture(Dim::kCube, T);
-  auto* tex_cube_array_f32 = sampled_texture(Dim::kCubeArray, f32);
-  auto* tex_cube_array_T = sampled_texture(Dim::kCubeArray, T);
-  auto* tex_ms_2d_T = multisampled_texture(Dim::k2d, T);
-  auto* tex_ms_2d_array_T = multisampled_texture(Dim::k2dArray, T);
-  auto* tex_depth_2d = depth_texture(Dim::k2d);
-  auto* tex_depth_2d_array = depth_texture(Dim::k2dArray);
-  auto* tex_depth_cube = depth_texture(Dim::kCube);
-  auto* tex_depth_cube_array = depth_texture(Dim::kCubeArray);
-  auto* tex_external = external_texture();
-  auto* tex_storage_1d_FT =
-      storage_texture(Dim::k1d, OpenNumber::A, OpenNumber::F, OpenType::T);
-  auto* tex_storage_2d_FT =
-      storage_texture(Dim::k2d, OpenNumber::A, OpenNumber::F, OpenType::T);
-  auto* tex_storage_2d_array_FT =
-      storage_texture(Dim::k2dArray, OpenNumber::A, OpenNumber::F, OpenType::T);
-  auto* tex_storage_3d_FT =
-      storage_texture(Dim::k3d, OpenNumber::A, OpenNumber::F, OpenType::T);
-  auto* tex_storage_ro_1d_FT = storage_texture(
-      Dim::k1d, ast::AccessControl::kRead, OpenNumber::F, OpenType::T);
-  auto* tex_storage_ro_2d_FT = storage_texture(
-      Dim::k2d, ast::AccessControl::kRead, OpenNumber::F, OpenType::T);
-  auto* tex_storage_ro_2d_array_FT = storage_texture(
-      Dim::k2dArray, ast::AccessControl::kRead, OpenNumber::F, OpenType::T);
-  auto* tex_storage_ro_3d_FT = storage_texture(
-      Dim::k3d, ast::AccessControl::kRead, OpenNumber::F, OpenType::T);
-  auto* tex_storage_wo_1d_FT = storage_texture(
-      Dim::k1d, ast::AccessControl::kWrite, OpenNumber::F, OpenType::T);
-  auto* tex_storage_wo_2d_FT = storage_texture(
-      Dim::k2d, ast::AccessControl::kWrite, OpenNumber::F, OpenType::T);
-  auto* tex_storage_wo_2d_array_FT = storage_texture(
-      Dim::k2dArray, ast::AccessControl::kWrite, OpenNumber::F, OpenType::T);
-  auto* tex_storage_wo_3d_FT = storage_texture(
-      Dim::k3d, ast::AccessControl::kWrite, OpenNumber::F, OpenType::T);
-
-  auto* sampler = this->sampler(ast::SamplerKind::kSampler);
-  auto* sampler_comparison =
-      this->sampler(ast::SamplerKind::kComparisonSampler);
-  auto t = sem::ParameterUsage::kTexture;
-  auto s = sem::ParameterUsage::kSampler;
-  auto coords = sem::ParameterUsage::kCoords;
-  auto array_index = sem::ParameterUsage::kArrayIndex;
-  auto ddx = sem::ParameterUsage::kDdx;
-  auto ddy = sem::ParameterUsage::kDdy;
-  auto depth_ref = sem::ParameterUsage::kDepthRef;
-  auto bias = sem::ParameterUsage::kBias;
-  auto level = sem::ParameterUsage::kLevel;
-  auto offset = sem::ParameterUsage::kOffset;
-  auto value = sem::ParameterUsage::kValue;
-  auto sample_index = sem::ParameterUsage::kSampleIndex;
-
-  // clang-format off
-
-  //       name                   return type  parameter types
-  Register(I::kTextureDimensions, i32,      {{t, tex_1d_T},                              }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_2d_T},                              }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_2d_T},                {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_2d_array_T},                        }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_2d_array_T},          {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_3d_T},                              }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_3d_T},                {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_cube_T},                            }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_cube_T},              {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_cube_array_T},                      }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_cube_array_T},        {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_ms_2d_T},                           }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_ms_2d_array_T},                     }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_depth_2d},                          }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_depth_2d},            {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_depth_2d_array},                    }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_depth_2d_array},      {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_depth_cube},                        }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_depth_cube},          {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_depth_cube_array},                  }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_depth_cube_array},    {level, i32}, }); // NOLINT
-  Register(I::kTextureDimensions, i32,      {{t, tex_storage_1d_FT},                     }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_storage_2d_FT},                     }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_storage_2d_array_FT},               }); // NOLINT
-  Register(I::kTextureDimensions, vec3_i32, {{t, tex_storage_3d_FT},                     }); // NOLINT
-  Register(I::kTextureDimensions, vec2_i32, {{t, tex_external},                          }); // NOLINT
-
-  Register(I::kTextureNumLayers,  i32, {{t, tex_2d_array_T},          });
-  Register(I::kTextureNumLayers,  i32, {{t, tex_cube_array_T},        });
-  Register(I::kTextureNumLayers,  i32, {{t, tex_ms_2d_array_T},       });
-  Register(I::kTextureNumLayers,  i32, {{t, tex_depth_2d_array},      });
-  Register(I::kTextureNumLayers,  i32, {{t, tex_depth_cube_array},    });
-  Register(I::kTextureNumLayers,  i32, {{t, tex_storage_2d_array_FT}, });
-
-  Register(I::kTextureNumLevels,  i32, {{t, tex_2d_T},             });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_2d_array_T},       });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_3d_T},             });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_cube_T},           });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_cube_array_T},     });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_depth_2d},         });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_depth_2d_array},   });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_depth_cube},       });
-  Register(I::kTextureNumLevels,  i32, {{t, tex_depth_cube_array}, });
-
-  Register(I::kTextureNumSamples, i32, {{t, tex_ms_2d_T},       });
-  Register(I::kTextureNumSamples, i32, {{t, tex_ms_2d_array_T}, });
-
-  Register(I::kTextureSample, vec4_f32, {{t, tex_1d_f32},           {s, sampler}, {coords, f32},                                              }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_2d_f32},           {s, sampler}, {coords, vec2_f32},                                         }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_2d_f32},           {s, sampler}, {coords, vec2_f32},                     {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_2d_array_f32},     {s, sampler}, {coords, vec2_f32}, {array_index, i32},                     }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_2d_array_f32},     {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_3d_f32},           {s, sampler}, {coords, vec3_f32},                                         }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_3d_f32},           {s, sampler}, {coords, vec3_f32},                     {offset, vec3_i32}, }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_cube_f32},         {s, sampler}, {coords, vec3_f32},                                         }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_cube_array_f32},   {s, sampler}, {coords, vec3_f32}, {array_index, i32},                     }); // NOLINT
-  Register(I::kTextureSample, f32,      {{t, tex_depth_2d},         {s, sampler}, {coords, vec2_f32},                                         }); // NOLINT
-  Register(I::kTextureSample, f32,      {{t, tex_depth_2d},         {s, sampler}, {coords, vec2_f32},                     {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSample, f32,      {{t, tex_depth_2d_array},   {s, sampler}, {coords, vec2_f32}, {array_index, i32},                     }); // NOLINT
-  Register(I::kTextureSample, f32,      {{t, tex_depth_2d_array},   {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSample, f32,      {{t, tex_depth_cube},       {s, sampler}, {coords, vec3_f32},                                         }); // NOLINT
-  Register(I::kTextureSample, f32,      {{t, tex_depth_cube_array}, {s, sampler}, {coords, vec3_f32}, {array_index, i32},                     }); // NOLINT
-  Register(I::kTextureSample, vec4_f32, {{t, tex_external},         {s, sampler}, {coords, vec2_f32},                                         }); // NOLINT
-
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_2d_f32},           {s, sampler}, {coords, vec2_f32},                     {bias, f32},                     }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_2d_f32},           {s, sampler}, {coords, vec2_f32},                     {bias, f32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_2d_array_f32},     {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {bias, f32},                     }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_2d_array_f32},     {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {bias, f32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_3d_f32},           {s, sampler}, {coords, vec3_f32},                     {bias, f32},                     }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_3d_f32},           {s, sampler}, {coords, vec3_f32},                     {bias, f32}, {offset, vec3_i32}, }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_cube_f32},         {s, sampler}, {coords, vec3_f32},                     {bias, f32},                     }); // NOLINT
-  Register(I::kTextureSampleBias, vec4_f32,    {{t, tex_cube_array_f32},   {s, sampler}, {coords, vec3_f32}, {array_index, i32}, {bias, f32},                     }); // NOLINT
-
-  Register(I::kTextureSampleCompare, f32,      {{t, tex_depth_2d},         {s, sampler_comparison}, {coords, vec2_f32},                     {depth_ref, f32},                         }); // NOLINT
-  Register(I::kTextureSampleCompare, f32,      {{t, tex_depth_2d},         {s, sampler_comparison}, {coords, vec2_f32},                     {depth_ref, f32}, {offset, vec2_i32},     }); // NOLINT
-  Register(I::kTextureSampleCompare, f32,      {{t, tex_depth_2d_array},   {s, sampler_comparison}, {coords, vec2_f32}, {array_index, i32}, {depth_ref, f32},                         }); // NOLINT
-  Register(I::kTextureSampleCompare, f32,      {{t, tex_depth_2d_array},   {s, sampler_comparison}, {coords, vec2_f32}, {array_index, i32}, {depth_ref, f32}, {offset, vec2_i32},     }); // NOLINT
-  Register(I::kTextureSampleCompare, f32,      {{t, tex_depth_cube},       {s, sampler_comparison}, {coords, vec3_f32},                     {depth_ref, f32},                         }); // NOLINT
-  Register(I::kTextureSampleCompare, f32,      {{t, tex_depth_cube_array}, {s, sampler_comparison}, {coords, vec3_f32}, {array_index, i32}, {depth_ref, f32},                         }); // NOLINT
-
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_2d_f32},         {s, sampler}, {coords, vec2_f32},                     {ddx, vec2_f32}, {ddy, vec2_f32},                     }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_2d_f32},         {s, sampler}, {coords, vec2_f32},                     {ddx, vec2_f32}, {ddy, vec2_f32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_2d_array_f32},   {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {ddx, vec2_f32}, {ddy, vec2_f32},                     }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_2d_array_f32},   {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {ddx, vec2_f32}, {ddy, vec2_f32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_3d_f32},         {s, sampler}, {coords, vec3_f32},                     {ddx, vec3_f32}, {ddy, vec3_f32},                     }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_3d_f32},         {s, sampler}, {coords, vec3_f32},                     {ddx, vec3_f32}, {ddy, vec3_f32}, {offset, vec3_i32}, }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_cube_f32},       {s, sampler}, {coords, vec3_f32},                     {ddx, vec3_f32}, {ddy, vec3_f32},                     }); // NOLINT
-  Register(I::kTextureSampleGrad, vec4_f32,      {{t, tex_cube_array_f32}, {s, sampler}, {coords, vec3_f32}, {array_index, i32}, {ddx, vec3_f32}, {ddy, vec3_f32},                     }); // NOLINT
-
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_2d_f32},          {s, sampler}, {coords, vec2_f32},                     {level, f32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_2d_f32},          {s, sampler}, {coords, vec2_f32},                     {level, f32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_2d_array_f32},    {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {level, f32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_2d_array_f32},    {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {level, f32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_3d_f32},          {s, sampler}, {coords, vec3_f32},                     {level, f32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_3d_f32},          {s, sampler}, {coords, vec3_f32},                     {level, f32}, {offset, vec3_i32}, }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_cube_f32},        {s, sampler}, {coords, vec3_f32},                     {level, f32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_cube_array_f32},  {s, sampler}, {coords, vec3_f32}, {array_index, i32}, {level, f32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, f32,          {{t, tex_depth_2d},        {s, sampler}, {coords, vec2_f32},                     {level, i32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, f32,          {{t, tex_depth_2d},        {s, sampler}, {coords, vec2_f32},                     {level, i32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleLevel, f32,          {{t, tex_depth_2d_array},  {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {level, i32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, f32,          {{t, tex_depth_2d_array},  {s, sampler}, {coords, vec2_f32}, {array_index, i32}, {level, i32}, {offset, vec2_i32}, }); // NOLINT
-  Register(I::kTextureSampleLevel, f32,          {{t, tex_depth_cube},      {s, sampler}, {coords, vec3_f32},                     {level, i32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, f32,          {{t, tex_depth_cube_array},{s, sampler}, {coords, vec3_f32}, {array_index, i32}, {level, i32},                     }); // NOLINT
-  Register(I::kTextureSampleLevel, vec4_f32,     {{t, tex_external},        {s, sampler}, {coords, vec2_f32},                                                       }); // NOLINT
-
-  Register(I::kTextureStore, void_, {{t, tex_storage_wo_1d_FT},      {coords, i32},                          {value, vec4_T}, }); // NOLINT
-  Register(I::kTextureStore, void_, {{t, tex_storage_wo_2d_FT},      {coords, vec2_i32},                     {value, vec4_T}, }); // NOLINT
-  Register(I::kTextureStore, void_, {{t, tex_storage_wo_2d_array_FT},{coords, vec2_i32}, {array_index, i32}, {value, vec4_T}, }); // NOLINT
-  Register(I::kTextureStore, void_, {{t, tex_storage_wo_3d_FT},      {coords, vec3_i32},                     {value, vec4_T}, }); // NOLINT
-
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_1d_T},                  {coords, i32},                           {level, i32},                      }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_2d_T},                  {coords, vec2_i32},                      {level, i32},                      }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_2d_array_T},            {coords, vec2_i32}, {array_index, i32},  {level, i32},                      }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_3d_T},                  {coords, vec3_i32},                      {level, i32},                      }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_ms_2d_T},               {coords, vec2_i32},                                    {sample_index, i32}, }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_ms_2d_array_T},         {coords, vec2_i32}, {array_index, i32},                {sample_index, i32}, }); // NOLINT
-  Register(I::kTextureLoad, f32,        {{t, tex_depth_2d},              {coords, vec2_i32},                      {level, i32},                      }); // NOLINT
-  Register(I::kTextureLoad, f32,        {{t, tex_depth_2d_array},        {coords, vec2_i32}, {array_index, i32},  {level, i32},                      }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_storage_ro_1d_FT},      {coords, i32},                                                              }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_storage_ro_2d_FT},      {coords, vec2_i32},                                                         }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_storage_ro_2d_array_FT},{coords, vec2_i32}, {array_index, i32},                                     }); // NOLINT
-  Register(I::kTextureLoad, vec4_T,     {{t, tex_storage_ro_3d_FT},      {coords, vec3_i32},                                                         }); // NOLINT
-  Register(I::kTextureLoad, vec4_f32,   {{t, tex_external},              {coords, vec2_i32}                                                          }); // NOLINT
-
-  // clang-format on
-
-  // If this assert trips, increase the reserve size.
-  TINT_ASSERT(overloads_.size() <= overloads_reserve_size);
-}
-
-/// @returns a human readable string representation of the overload
-std::string str(const Impl::Overload& overload) {
-  std::stringstream ss;
-  ss << overload.type << "(";
-  {
-    bool first = true;
-    for (auto param : overload.parameters) {
-      if (!first) {
-        ss << ", ";
-      }
-      first = false;
-      if (param.usage != sem::ParameterUsage::kNone) {
-        ss << sem::str(param.usage) << " : ";
-      }
-      ss << param.matcher->str();
-    }
-  }
-  ss << ") -> ";
-  ss << overload.return_type->str();
-
-  if (!overload.open_type_matchers.empty()) {
-    ss << "  where: ";
-
-    for (uint32_t i = 0; i < static_cast<uint32_t>(OpenType::Count); i++) {
-      auto open_type = static_cast<OpenType>(i);
-      auto it = overload.open_type_matchers.find(open_type);
-      if (it != overload.open_type_matchers.end()) {
-        if (i > 0) {
-          ss << ", ";
-        }
-        ss << tint::str(open_type) << " is " << it->second->str();
-      }
-    }
-  }
-  return ss.str();
-}
-
 /// @return a string representing a call to an intrinsic with the given argument
 /// types.
 std::string CallSignature(ProgramBuilder& builder,
-                          sem::IntrinsicType type,
+                          sem::IntrinsicType intrinsic_type,
                           const std::vector<const sem::Type*>& args) {
   std::stringstream ss;
-  ss << sem::str(type) << "(";
+  ss << sem::str(intrinsic_type) << "(";
   {
     bool first = true;
     for (auto* arg : args) {
@@ -1350,28 +659,35 @@
   return ss.str();
 }
 
-IntrinsicTable::Result Impl::Lookup(ProgramBuilder& builder,
-                                    sem::IntrinsicType type,
-                                    const std::vector<const sem::Type*>& args,
-                                    const Source& source) const {
-  diag::List diagnostics;
+std::string OpenTypeMatcher::String(MatchState& state) const {
+  return state.overload.open_types[index_].name;
+}
+
+std::string OpenNumberMatcher::String(MatchState& state) const {
+  return state.overload.open_numbers[index_].name;
+}
+
+Impl::Impl(ProgramBuilder& b) : builder(b) {}
+
+const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
+                                   const std::vector<const sem::Type*>& args,
+                                   const Source& source) const {
   // Candidate holds information about a mismatched overload that could be what
   // the user intended to call.
   struct Candidate {
-    const Overload* overload;
+    const OverloadInfo* overload;
     int score;
   };
 
   // The list of failed matches that had promise.
   std::vector<Candidate> candidates;
 
-  // TODO(bclayton) Sort overloads_, or place them into a map keyed by intrinsic
-  // type. This is horribly inefficient.
-  for (auto& overload : overloads_) {
-    int match_score = 0;
-    if (auto* intrinsic =
-            overload.Match(builder, type, args, diagnostics, match_score)) {
-      return Result{intrinsic, {}};  // Match found
+  auto& intrinsic = kIntrinsics[static_cast<uint32_t>(intrinsic_type)];
+  for (uint32_t o = 0; o < intrinsic.num_overloads; o++) {
+    int match_score = 1000;
+    auto& overload = intrinsic.overloads[o];
+    if (auto* match = Match(intrinsic_type, overload, args, match_score)) {
+      return match;
     }
     if (match_score > 0) {
       candidates.emplace_back(Candidate{&overload, match_score});
@@ -1385,127 +701,206 @@
 
   // Generate an error message
   std::stringstream ss;
-  ss << "no matching call to " << CallSignature(builder, type, args)
+  ss << "no matching call to " << CallSignature(builder, intrinsic_type, args)
      << std::endl;
   if (!candidates.empty()) {
     ss << std::endl;
     ss << candidates.size() << " candidate function"
        << (candidates.size() > 1 ? "s:" : ":") << std::endl;
     for (auto& candidate : candidates) {
-      ss << "  " << str(*candidate.overload) << std::endl;
+      ss << "  ";
+      PrintOverload(ss, *candidate.overload, intrinsic_type);
+      ss << std::endl;
     }
   }
-  diagnostics.add_error(ss.str(), source);
-
-  return Result{nullptr, std::move(diagnostics)};
+  builder.Diagnostics().add_error(ss.str(), source);
+  return nullptr;
 }
 
-sem::Intrinsic* Impl::Overload::Match(ProgramBuilder& builder,
-                                      sem::IntrinsicType intrinsic,
-                                      const std::vector<const sem::Type*>& args,
-                                      diag::List& diagnostics,
-                                      int& match_score) const {
-  if (type != intrinsic) {
-    match_score = std::numeric_limits<int>::min();
-    return nullptr;  // Incorrect function
+const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
+                                  const OverloadInfo& overload,
+                                  const std::vector<const sem::Type*>& args,
+                                  int& match_score) const {
+  // Score wait for argument <-> parameter count matches / mismatches
+  constexpr int kScorePerParamArgMismatch = -1;
+  constexpr int kScorePerMatchedParam = 2;
+  constexpr int kScorePerMatchedOpenType = 1;
+  constexpr int kScorePerMatchedOpenNumber = 1;
+
+  auto num_parameters = overload.num_parameters;
+  auto num_arguments = static_cast<decltype(num_parameters)>(args.size());
+
+  bool overload_matched = true;
+
+  if (num_parameters != num_arguments) {
+    match_score +=
+        kScorePerParamArgMismatch * (std::max(num_parameters, num_arguments) -
+                                     std::min(num_parameters, num_arguments));
+    overload_matched = false;
   }
 
-  // Penalize argument <-> parameter count mismatches
-  match_score = 1000;
-  match_score -= std::max(parameters.size(), args.size()) -
-                 std::min(parameters.size(), args.size());
+  ClosedState closed(builder);
 
-  bool matched = parameters.size() == args.size();
+  sem::ParameterList parameters;
 
-  Matcher::MatchState matcher_state;
-
-  // Check that each of the parameters match.
-  // This stage also populates the open_types and open_numbers.
-  auto count = std::min(parameters.size(), args.size());
-  for (size_t i = 0; i < count; i++) {
-    if (!args[i]) {
-      TINT_ICE(diagnostics) << "args[" << i << "] is nullptr";
-      return nullptr;
-    }
-
-    auto* arg_ty = args[i]->UnwrapRef();
-    if (parameters[i].matcher->Match(matcher_state, arg_ty)) {
-      // A correct parameter match is scored higher than number of parameters to
-      // arguments.
-      match_score += 2;
+  auto num_params = std::min(num_parameters, num_arguments);
+  for (uint32_t p = 0; p < num_params; p++) {
+    auto& parameter = overload.parameters[p];
+    auto* indices = parameter.matcher_indices;
+    auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
+    if (type) {
+      parameters.emplace_back(
+          sem::Parameter{const_cast<sem::Type*>(type), parameter.usage});
+      match_score += kScorePerMatchedParam;
     } else {
-      matched = false;
+      overload_matched = false;
     }
   }
-  if (!matched) {
-    return nullptr;
-  }
 
-  // If any of the open-types are constrained, check that they match.
-  for (auto matcher_it : open_type_matchers) {
-    OpenType open_type = matcher_it.first;
-    auto* matcher = matcher_it.second;
-    auto type_it = matcher_state.open_types.find(open_type);
-    if (type_it == matcher_state.open_types.end()) {
-      // We have an overload that claims to have matched, but didn't actually
-      // resolve the open type. This is a bug that needs fixing.
-      TINT_ICE(diagnostics)
-          << "IntrinsicTable overload matched for "
-          << CallSignature(builder, intrinsic, args)
-          << ", but didn't resolve the open type " << str(open_type);
-      return nullptr;
+  if (overload_matched) {
+    // Check all constrained open types matched
+    for (uint32_t ot = 0; ot < overload.num_open_types; ot++) {
+      auto& open_type = overload.open_types[ot];
+      if (open_type.matcher_index != kNoMatcher) {
+        auto* index = &open_type.matcher_index;
+        if (Match(closed, overload, index).Type(closed.Type(ot))) {
+          match_score += kScorePerMatchedOpenType;
+        } else {
+          overload_matched = false;
+        }
+      }
     }
-    auto* resolved_type = type_it->second;
-    if (resolved_type == nullptr) {
-      // We have an overload that claims to have matched, but has a nullptr
-      // resolved open type. This is a bug that needs fixing.
-      TINT_ICE(diagnostics)
-          << "IntrinsicTable overload matched for "
-          << CallSignature(builder, intrinsic, args) << ", but open type "
-          << str(open_type) << " is nullptr";
-      return nullptr;
-    }
-    if (!matcher->Match(matcher_state, resolved_type)) {
-      matched = false;
-      continue;
-    }
-    match_score++;
-  }
-  if (!matched) {
-    return nullptr;
   }
 
-  // Overload matched!
+  if (overload_matched) {
+    // Check all constrained open numbers matched
+    for (uint32_t on = 0; on < overload.num_open_numbers; on++) {
+      auto& open_number = overload.open_numbers[on];
+      if (open_number.matcher_index != kNoMatcher) {
+        auto* index = &open_number.matcher_index;
+        if (Match(closed, overload, index).Num(closed.Num(on)).IsValid()) {
+          match_score += kScorePerMatchedOpenNumber;
+        } else {
+          overload_matched = false;
+        }
+      }
+    }
+  }
+
+  if (!overload_matched) {
+    return nullptr;
+  }
 
   // Build the return type
-  Builder::BuildState builder_state{builder.Types(), matcher_state.open_types,
-                                    matcher_state.open_numbers};
-  auto* ret = return_type->Build(builder_state);
-  if (!ret) {
-    TINT_ICE(diagnostics) << "Build() did not return a type";
-    return nullptr;
+  const sem::Type* return_type = nullptr;
+  if (auto* indices = overload.return_matcher_indices) {
+    Any any;
+    return_type = Match(closed, overload, indices).Type(&any);
+    if (!return_type) {
+      std::stringstream ss;
+      PrintOverload(ss, overload, intrinsic_type);
+      TINT_ICE(builder.Diagnostics())
+          << "MatchState.Match() returned null for " << ss.str();
+      return nullptr;
+    }
+  } else {
+    return_type = builder.create<sem::Void>();
   }
 
-  // Build the semantic parameters
-  sem::ParameterList params;
-  params.reserve(parameters.size());
-  for (size_t i = 0; i < args.size(); i++) {
-    auto& parameter = parameters[i];
-    auto* ty = parameter.matcher->Build(builder_state);
-    params.emplace_back(
-        sem::Parameter{const_cast<sem::Type*>(ty), parameter.usage});
+  return builder.create<sem::Intrinsic>(intrinsic_type,
+                                        const_cast<sem::Type*>(return_type),
+                                        std::move(parameters));
+}
+
+MatchState Impl::Match(ClosedState& closed,
+                       const OverloadInfo& overload,
+                       MatcherIndex const* matcher_indices) const {
+  return MatchState(builder, closed, matchers, overload, matcher_indices);
+}
+
+void Impl::PrintOverload(std::ostream& ss,
+                         const OverloadInfo& overload,
+                         sem::IntrinsicType intrinsic_type) const {
+  ClosedState closed(builder);
+
+  ss << intrinsic_type << "(";
+  for (uint32_t p = 0; p < overload.num_parameters; p++) {
+    auto& parameter = overload.parameters[p];
+    if (p > 0) {
+      ss << ", ";
+    }
+    if (parameter.usage != ParameterUsage::kNone) {
+      ss << sem::str(parameter.usage) << ": ";
+    }
+    auto* indices = parameter.matcher_indices;
+    ss << Match(closed, overload, indices).TypeName();
+  }
+  ss << ")";
+  if (overload.return_matcher_indices) {
+    ss << " -> ";
+    auto* indices = overload.return_matcher_indices;
+    ss << Match(closed, overload, indices).TypeName();
   }
 
-  return builder.create<sem::Intrinsic>(intrinsic, const_cast<sem::Type*>(ret),
-                                        params);
+  bool first = true;
+  auto separator = [&] {
+    ss << (first ? "  where: " : ", ");
+    first = false;
+  };
+  for (uint32_t i = 0; i < overload.num_open_types; i++) {
+    auto& open_type = overload.open_types[i];
+    if (open_type.matcher_index != kNoMatcher) {
+      separator();
+      ss << open_type.name;
+      auto* index = &open_type.matcher_index;
+      ss << " is " << Match(closed, overload, index).TypeName();
+    }
+  }
+  for (uint32_t i = 0; i < overload.num_open_numbers; i++) {
+    auto& open_number = overload.open_numbers[i];
+    if (open_number.matcher_index != kNoMatcher) {
+      separator();
+      ss << open_number.name;
+      auto* index = &open_number.matcher_index;
+      ss << " is " << Match(closed, overload, index).NumName();
+    }
+  }
+}
+
+const sem::Type* MatchState::Type(const sem::Type* ty) {
+  MatcherIndex matcher_index = *matcher_indices_++;
+  auto* matcher = matchers.type[matcher_index];
+  return matcher->Match(*this, ty);
+}
+
+Number MatchState::Num(Number number) {
+  MatcherIndex matcher_index = *matcher_indices_++;
+  auto* matcher = matchers.number[matcher_index];
+  return matcher->Match(*this, number);
+}
+
+std::string MatchState::TypeName() {
+  MatcherIndex matcher_index = *matcher_indices_++;
+  auto* matcher = matchers.type[matcher_index];
+  return matcher->String(*this);
+}
+
+std::string MatchState::NumName() {
+  MatcherIndex matcher_index = *matcher_indices_++;
+  auto* matcher = matchers.number[matcher_index];
+  return matcher->String(*this);
 }
 
 }  // namespace
 
-std::unique_ptr<IntrinsicTable> IntrinsicTable::Create() {
-  return std::make_unique<Impl>();
+std::unique_ptr<IntrinsicTable> IntrinsicTable::Create(
+    ProgramBuilder& builder) {
+  return std::make_unique<Impl>(builder);
 }
 
 IntrinsicTable::~IntrinsicTable() = default;
 
+/// TypeInfo for the Any type declared in the anonymous namespace above
+TINT_INSTANTIATE_TYPEINFO(Any);
+
 }  // namespace tint
diff --git a/src/intrinsic_table.h b/src/intrinsic_table.h
index d908296..6802e55 100644
--- a/src/intrinsic_table.h
+++ b/src/intrinsic_table.h
@@ -29,30 +29,23 @@
 /// IntrinsicTable is a lookup table of all the WGSL intrinsic functions
 class IntrinsicTable {
  public:
+  /// @param builder the program builder
   /// @return a pointer to a newly created IntrinsicTable
-  static std::unique_ptr<IntrinsicTable> Create();
+  static std::unique_ptr<IntrinsicTable> Create(ProgramBuilder& builder);
 
   /// Destructor
   virtual ~IntrinsicTable();
 
-  /// Result is returned by Lookup
-  struct Result {
-    /// The intrinsic, if the lookup succeeded, otherwise nullptr
-    sem::Intrinsic* intrinsic;
-    /// Diagnostic messages
-    diag::List diagnostics;
-  };
-
-  /// Lookup looks for the intrinsic overload with the given signature.
-  /// @param builder the program builder
+  /// Lookup looks for the intrinsic overload with the given signature, raising
+  /// an error diagnostic if the intrinsic was not found.
   /// @param type the intrinsic type
   /// @param args the argument types passed to the intrinsic function
   /// @param source the source of the intrinsic call
   /// @return the semantic intrinsic if found, otherwise nullptr
-  virtual Result Lookup(ProgramBuilder& builder,
-                        sem::IntrinsicType type,
-                        const std::vector<const sem::Type*>& args,
-                        const Source& source) const = 0;
+  virtual const sem::Intrinsic* Lookup(
+      sem::IntrinsicType type,
+      const std::vector<const sem::Type*>& args,
+      const Source& source) const = 0;
 };
 
 }  // namespace tint
diff --git a/src/intrinsic_table.inl b/src/intrinsic_table.inl
new file mode 100644
index 0000000..1d11aaa
--- /dev/null
+++ b/src/intrinsic_table.inl
@@ -0,0 +1,7551 @@
+// Copyright 2021 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/intrinsic-gen
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+// clang-format off
+
+/// ParameterInfo describes a parameter
+struct ParameterInfo {
+  /// The parameter usage (parameter name in definition file)
+  ParameterUsage const usage;
+
+  /// Pointer to a list of indices that are used to match the parameter type.
+  /// The matcher indices index on Matchers::type and / or Matchers::number.
+  /// These indices are consumed by the matchers themselves.
+  /// The first index is always a TypeMatcher.
+  MatcherIndex const* const matcher_indices;
+};
+
+/// OpenTypeInfo describes an open type
+struct OpenTypeInfo {
+  /// Name of the open type (e.g. 'T')
+  const char* name;
+  /// Optional type matcher constraint.
+  /// Either an index in Matchers::type, or kNoMatcher
+  MatcherIndex const matcher_index;
+};
+
+/// OpenNumberInfo describes an open number
+struct OpenNumberInfo {
+  /// Name of the open number (e.g. 'N')
+  const char* name;
+  /// Optional number matcher constraint.
+  /// Either an index in Matchers::number, or kNoMatcher
+  MatcherIndex const matcher_index;
+};
+
+/// OverloadInfo describes a single function overload
+struct OverloadInfo {
+  /// Total number of parameters for the overload
+  uint8_t const num_parameters;
+  /// Total number of open types for the overload
+  uint8_t const num_open_types;
+  /// Total number of open numbers for the overload
+  uint8_t const num_open_numbers;
+  /// Pointer to the first open type
+  OpenTypeInfo const* const open_types;
+  /// Pointer to the first open number
+  OpenNumberInfo const* const open_numbers;
+  /// Pointer to the first parameter
+  ParameterInfo const* const parameters;
+  /// Pointer to a list of matcher indices that index on Matchers::type and
+  /// Matchers::number, used to build the return type. If the function has no
+  /// return type then this is null.
+  MatcherIndex const* const return_matcher_indices;
+};
+
+/// IntrinsicInfo describes an intrinsic function
+struct IntrinsicInfo {
+  /// Number of overloads of the intrinsic function
+  uint8_t const num_overloads;
+  /// Pointer to the start of the overloads for the function
+  OverloadInfo const* const overloads;
+};
+
+/// TypeMatcher for 'type bool'
+/// @see src/intrinsics.def:68:6
+class Bool : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Bool::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_bool(ty)) {
+    return nullptr;
+  }
+  return build_bool(state);
+}
+
+std::string Bool::String(MatchState&) const {
+  return "bool";
+}
+
+/// TypeMatcher for 'type f32'
+/// @see src/intrinsics.def:69:6
+class F32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* F32::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_f32(ty)) {
+    return nullptr;
+  }
+  return build_f32(state);
+}
+
+std::string F32::String(MatchState&) const {
+  return "f32";
+}
+
+/// TypeMatcher for 'type i32'
+/// @see src/intrinsics.def:70:6
+class I32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* I32::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_i32(ty)) {
+    return nullptr;
+  }
+  return build_i32(state);
+}
+
+std::string I32::String(MatchState&) const {
+  return "i32";
+}
+
+/// TypeMatcher for 'type u32'
+/// @see src/intrinsics.def:71:6
+class U32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* U32::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_u32(ty)) {
+    return nullptr;
+  }
+  return build_u32(state);
+}
+
+std::string U32::String(MatchState&) const {
+  return "u32";
+}
+
+/// TypeMatcher for 'type vec2'
+/// @see src/intrinsics.def:72:6
+class Vec2 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Vec2::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_vec2(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_vec2(state, T);
+}
+
+std::string Vec2::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "vec2<" + T + ">";
+}
+
+/// TypeMatcher for 'type vec3'
+/// @see src/intrinsics.def:73:6
+class Vec3 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Vec3::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_vec3(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_vec3(state, T);
+}
+
+std::string Vec3::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "vec3<" + T + ">";
+}
+
+/// TypeMatcher for 'type vec4'
+/// @see src/intrinsics.def:74:6
+class Vec4 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Vec4::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_vec4(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_vec4(state, T);
+}
+
+std::string Vec4::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "vec4<" + T + ">";
+}
+
+/// TypeMatcher for 'type vec'
+/// @see src/intrinsics.def:75:37
+class Vec : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Vec::Match(MatchState& state, const sem::Type* ty) const {
+  Number N = Number::invalid;
+  const sem::Type* T = nullptr;
+  if (!match_vec(ty, N, T)) {
+    return nullptr;
+  }
+  N = state.Num(N);
+  if (!N.IsValid()) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_vec(state, N, T);
+}
+
+std::string Vec::String(MatchState& state) const {
+  const std::string N = state.NumName();
+  const std::string T = state.TypeName();
+  std::stringstream ss;
+  ss << "vec" << N << "<" << T << ">";
+  return ss.str();
+}
+
+/// TypeMatcher for 'type mat'
+/// @see src/intrinsics.def:76:37
+class Mat : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Mat::Match(MatchState& state, const sem::Type* ty) const {
+  Number N = Number::invalid;
+  Number M = Number::invalid;
+  const sem::Type* T = nullptr;
+  if (!match_mat(ty, N, M, T)) {
+    return nullptr;
+  }
+  N = state.Num(N);
+  if (!N.IsValid()) {
+    return nullptr;
+  }
+  M = state.Num(M);
+  if (!M.IsValid()) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat(state, N, M, T);
+}
+
+std::string Mat::String(MatchState& state) const {
+  const std::string N = state.NumName();
+  const std::string M = state.NumName();
+  const std::string T = state.TypeName();
+  std::stringstream ss;
+  ss << "mat" << N << "x" << M << "<" << T << ">";
+  return ss.str();
+}
+
+/// TypeMatcher for 'type ptr'
+/// @see src/intrinsics.def:77:37
+class Ptr : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Ptr::Match(MatchState& state, const sem::Type* ty) const {
+  Number S = Number::invalid;
+  const sem::Type* T = nullptr;
+  if (!match_ptr(ty, S, T)) {
+    return nullptr;
+  }
+  S = state.Num(S);
+  if (!S.IsValid()) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_ptr(state, S, T);
+}
+
+std::string Ptr::String(MatchState& state) const {
+  const std::string S = state.NumName();
+  const std::string T = state.TypeName();
+  std::stringstream ss;
+  ss << "ptr<" << T << ">";
+  return ss.str();
+}
+
+/// TypeMatcher for 'type array'
+/// @see src/intrinsics.def:78:6
+class Array : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Array::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_array(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_array(state, T);
+}
+
+std::string Array::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "array<" + T + ">";
+}
+
+/// TypeMatcher for 'type sampler'
+/// @see src/intrinsics.def:79:6
+class Sampler : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Sampler::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_sampler(ty)) {
+    return nullptr;
+  }
+  return build_sampler(state);
+}
+
+std::string Sampler::String(MatchState&) const {
+  return "sampler";
+}
+
+/// TypeMatcher for 'type sampler_comparison'
+/// @see src/intrinsics.def:80:6
+class SamplerComparison : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* SamplerComparison::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_sampler_comparison(ty)) {
+    return nullptr;
+  }
+  return build_sampler_comparison(state);
+}
+
+std::string SamplerComparison::String(MatchState&) const {
+  return "sampler_comparison";
+}
+
+/// TypeMatcher for 'type texture_1d'
+/// @see src/intrinsics.def:81:6
+class Texture1D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Texture1D::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_1d(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_1d(state, T);
+}
+
+std::string Texture1D::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_1d<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_2d'
+/// @see src/intrinsics.def:82:6
+class Texture2D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Texture2D::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_2d(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_2d(state, T);
+}
+
+std::string Texture2D::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_2d<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_2d_array'
+/// @see src/intrinsics.def:83:6
+class Texture2DArray : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Texture2DArray::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_2d_array(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_2d_array(state, T);
+}
+
+std::string Texture2DArray::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_2d_array<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_3d'
+/// @see src/intrinsics.def:84:6
+class Texture3D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Texture3D::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_3d(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_3d(state, T);
+}
+
+std::string Texture3D::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_3d<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_cube'
+/// @see src/intrinsics.def:85:6
+class TextureCube : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureCube::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_cube(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_cube(state, T);
+}
+
+std::string TextureCube::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_cube<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_cube_array'
+/// @see src/intrinsics.def:86:6
+class TextureCubeArray : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureCubeArray::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_cube_array(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_cube_array(state, T);
+}
+
+std::string TextureCubeArray::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_cube_array<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_multisampled_2d'
+/// @see src/intrinsics.def:87:6
+class TextureMultisampled2D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureMultisampled2D::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_texture_multisampled_2d(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_texture_multisampled_2d(state, T);
+}
+
+std::string TextureMultisampled2D::String(MatchState& state) const {
+  const std::string T = state.TypeName();
+  return "texture_multisampled_2d<" + T + ">";
+}
+
+/// TypeMatcher for 'type texture_depth_2d'
+/// @see src/intrinsics.def:88:6
+class TextureDepth2D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureDepth2D::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_texture_depth_2d(ty)) {
+    return nullptr;
+  }
+  return build_texture_depth_2d(state);
+}
+
+std::string TextureDepth2D::String(MatchState&) const {
+  return "texture_depth_2d";
+}
+
+/// TypeMatcher for 'type texture_depth_2d_array'
+/// @see src/intrinsics.def:89:6
+class TextureDepth2DArray : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureDepth2DArray::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_texture_depth_2d_array(ty)) {
+    return nullptr;
+  }
+  return build_texture_depth_2d_array(state);
+}
+
+std::string TextureDepth2DArray::String(MatchState&) const {
+  return "texture_depth_2d_array";
+}
+
+/// TypeMatcher for 'type texture_depth_cube'
+/// @see src/intrinsics.def:90:6
+class TextureDepthCube : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureDepthCube::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_texture_depth_cube(ty)) {
+    return nullptr;
+  }
+  return build_texture_depth_cube(state);
+}
+
+std::string TextureDepthCube::String(MatchState&) const {
+  return "texture_depth_cube";
+}
+
+/// TypeMatcher for 'type texture_depth_cube_array'
+/// @see src/intrinsics.def:91:6
+class TextureDepthCubeArray : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureDepthCubeArray::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_texture_depth_cube_array(ty)) {
+    return nullptr;
+  }
+  return build_texture_depth_cube_array(state);
+}
+
+std::string TextureDepthCubeArray::String(MatchState&) const {
+  return "texture_depth_cube_array";
+}
+
+/// TypeMatcher for 'type texture_storage_1d'
+/// @see src/intrinsics.def:92:6
+class TextureStorage1D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureStorage1D::Match(MatchState& state, const sem::Type* ty) const {
+  Number F = Number::invalid;
+  Number A = Number::invalid;
+  if (!match_texture_storage_1d(ty, F, A)) {
+    return nullptr;
+  }
+  F = state.Num(F);
+  if (!F.IsValid()) {
+    return nullptr;
+  }
+  A = state.Num(A);
+  if (!A.IsValid()) {
+    return nullptr;
+  }
+  return build_texture_storage_1d(state, F, A);
+}
+
+std::string TextureStorage1D::String(MatchState& state) const {
+  const std::string F = state.NumName();
+  const std::string A = state.NumName();
+  return "texture_storage_1d<" + F + ", " + A + ">";
+}
+
+/// TypeMatcher for 'type texture_storage_2d'
+/// @see src/intrinsics.def:93:6
+class TextureStorage2D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureStorage2D::Match(MatchState& state, const sem::Type* ty) const {
+  Number F = Number::invalid;
+  Number A = Number::invalid;
+  if (!match_texture_storage_2d(ty, F, A)) {
+    return nullptr;
+  }
+  F = state.Num(F);
+  if (!F.IsValid()) {
+    return nullptr;
+  }
+  A = state.Num(A);
+  if (!A.IsValid()) {
+    return nullptr;
+  }
+  return build_texture_storage_2d(state, F, A);
+}
+
+std::string TextureStorage2D::String(MatchState& state) const {
+  const std::string F = state.NumName();
+  const std::string A = state.NumName();
+  return "texture_storage_2d<" + F + ", " + A + ">";
+}
+
+/// TypeMatcher for 'type texture_storage_2d_array'
+/// @see src/intrinsics.def:94:6
+class TextureStorage2DArray : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureStorage2DArray::Match(MatchState& state, const sem::Type* ty) const {
+  Number F = Number::invalid;
+  Number A = Number::invalid;
+  if (!match_texture_storage_2d_array(ty, F, A)) {
+    return nullptr;
+  }
+  F = state.Num(F);
+  if (!F.IsValid()) {
+    return nullptr;
+  }
+  A = state.Num(A);
+  if (!A.IsValid()) {
+    return nullptr;
+  }
+  return build_texture_storage_2d_array(state, F, A);
+}
+
+std::string TextureStorage2DArray::String(MatchState& state) const {
+  const std::string F = state.NumName();
+  const std::string A = state.NumName();
+  return "texture_storage_2d_array<" + F + ", " + A + ">";
+}
+
+/// TypeMatcher for 'type texture_storage_3d'
+/// @see src/intrinsics.def:95:6
+class TextureStorage3D : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureStorage3D::Match(MatchState& state, const sem::Type* ty) const {
+  Number F = Number::invalid;
+  Number A = Number::invalid;
+  if (!match_texture_storage_3d(ty, F, A)) {
+    return nullptr;
+  }
+  F = state.Num(F);
+  if (!F.IsValid()) {
+    return nullptr;
+  }
+  A = state.Num(A);
+  if (!A.IsValid()) {
+    return nullptr;
+  }
+  return build_texture_storage_3d(state, F, A);
+}
+
+std::string TextureStorage3D::String(MatchState& state) const {
+  const std::string F = state.NumName();
+  const std::string A = state.NumName();
+  return "texture_storage_3d<" + F + ", " + A + ">";
+}
+
+/// TypeMatcher for 'type texture_external'
+/// @see src/intrinsics.def:96:6
+class TextureExternal : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* TextureExternal::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_texture_external(ty)) {
+    return nullptr;
+  }
+  return build_texture_external(state);
+}
+
+std::string TextureExternal::String(MatchState&) const {
+  return "texture_external";
+}
+
+/// TypeMatcher for 'match fiu32'
+/// @see src/intrinsics.def:104:7
+class Fiu32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Fiu32::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
+  return nullptr;
+}
+
+std::string Fiu32::String(MatchState&) const {
+  return "f32, i32 or u32";
+}
+
+/// TypeMatcher for 'match iu32'
+/// @see src/intrinsics.def:105:7
+class Iu32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Iu32::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
+  return nullptr;
+}
+
+std::string Iu32::String(MatchState&) const {
+  return "i32 or u32";
+}
+
+/// TypeMatcher for 'match scalar'
+/// @see src/intrinsics.def:106:7
+class Scalar : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* Scalar::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
+  if (match_bool(ty)) {
+    return build_bool(state);
+  }
+  return nullptr;
+}
+
+std::string Scalar::String(MatchState&) const {
+  return "f32, i32, u32 or bool";
+}
+
+/// EnumMatcher for 'match f32_texel_format'
+/// @see src/intrinsics.def:117:7
+class F32TexelFormat : public NumberMatcher {
+ public:
+  /// Checks whether the given number matches the enum matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param number the enum value as a Number
+  /// @return true if the enum value matches the set
+  Number Match(MatchState& state, Number number) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+Number F32TexelFormat::Match(MatchState&, Number number) const {
+  switch (static_cast<TexelFormat>(number.Value())) {
+    case TexelFormat::kRgba8Unorm:
+    case TexelFormat::kRgba8Snorm:
+    case TexelFormat::kRgba16Float:
+    case TexelFormat::kR32Float:
+    case TexelFormat::kRg32Float:
+    case TexelFormat::kRgba32Float:
+      return number;
+    default:
+      return Number::invalid;
+  }
+}
+
+std::string F32TexelFormat::String(MatchState&) const {
+  return "f32_texel_format";
+}
+
+/// EnumMatcher for 'match i32_texel_format'
+/// @see src/intrinsics.def:119:7
+class I32TexelFormat : public NumberMatcher {
+ public:
+  /// Checks whether the given number matches the enum matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param number the enum value as a Number
+  /// @return true if the enum value matches the set
+  Number Match(MatchState& state, Number number) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+Number I32TexelFormat::Match(MatchState&, Number number) const {
+  switch (static_cast<TexelFormat>(number.Value())) {
+    case TexelFormat::kRgba8Sint:
+    case TexelFormat::kRgba16Sint:
+    case TexelFormat::kR32Sint:
+    case TexelFormat::kRg32Sint:
+    case TexelFormat::kRgba32Sint:
+      return number;
+    default:
+      return Number::invalid;
+  }
+}
+
+std::string I32TexelFormat::String(MatchState&) const {
+  return "i32_texel_format";
+}
+
+/// EnumMatcher for 'match u32_texel_format'
+/// @see src/intrinsics.def:121:7
+class U32TexelFormat : public NumberMatcher {
+ public:
+  /// Checks whether the given number matches the enum matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param number the enum value as a Number
+  /// @return true if the enum value matches the set
+  Number Match(MatchState& state, Number number) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+Number U32TexelFormat::Match(MatchState&, Number number) const {
+  switch (static_cast<TexelFormat>(number.Value())) {
+    case TexelFormat::kRgba8Uint:
+    case TexelFormat::kRgba16Uint:
+    case TexelFormat::kR32Uint:
+    case TexelFormat::kRg32Uint:
+    case TexelFormat::kRgba32Uint:
+      return number;
+    default:
+      return Number::invalid;
+  }
+}
+
+std::string U32TexelFormat::String(MatchState&) const {
+  return "u32_texel_format";
+}
+
+/// EnumMatcher for 'match write'
+class Write : public NumberMatcher {
+ public:
+  /// Checks whether the given number matches the enum matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param number the enum value as a Number
+  /// @return true if the enum value matches the set
+  Number Match(MatchState& state, Number number) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+Number Write::Match(MatchState&, Number number) const {
+  if (number.IsAny() || number.Value() == static_cast<uint32_t>(AccessControl::kWrite)) {
+    return Number(AccessControl::kWrite);
+  }
+  return Number::invalid;
+}
+
+std::string Write::String(MatchState&) const {
+  return "write";
+}
+
+/// EnumMatcher for 'match read'
+class Read : public NumberMatcher {
+ public:
+  /// Checks whether the given number matches the enum matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param number the enum value as a Number
+  /// @return true if the enum value matches the set
+  Number Match(MatchState& state, Number number) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+Number Read::Match(MatchState&, Number number) const {
+  if (number.IsAny() || number.Value() == static_cast<uint32_t>(AccessControl::kRead)) {
+    return Number(AccessControl::kRead);
+  }
+  return Number::invalid;
+}
+
+std::string Read::String(MatchState&) const {
+  return "read";
+}
+
+/// Matchers holds type and number matchers
+class Matchers {
+ private:
+  OpenTypeMatcher open_type_0_{0};
+  OpenNumberMatcher open_number_0_{0};
+  OpenNumberMatcher open_number_1_{1};
+  Bool Bool_;
+  F32 F32_;
+  I32 I32_;
+  U32 U32_;
+  Vec2 Vec2_;
+  Vec3 Vec3_;
+  Vec4 Vec4_;
+  Vec Vec_;
+  Mat Mat_;
+  Ptr Ptr_;
+  Array Array_;
+  Sampler Sampler_;
+  SamplerComparison SamplerComparison_;
+  Texture1D Texture1D_;
+  Texture2D Texture2D_;
+  Texture2DArray Texture2DArray_;
+  Texture3D Texture3D_;
+  TextureCube TextureCube_;
+  TextureCubeArray TextureCubeArray_;
+  TextureMultisampled2D TextureMultisampled2D_;
+  TextureDepth2D TextureDepth2D_;
+  TextureDepth2DArray TextureDepth2DArray_;
+  TextureDepthCube TextureDepthCube_;
+  TextureDepthCubeArray TextureDepthCubeArray_;
+  TextureStorage1D TextureStorage1D_;
+  TextureStorage2D TextureStorage2D_;
+  TextureStorage2DArray TextureStorage2DArray_;
+  TextureStorage3D TextureStorage3D_;
+  TextureExternal TextureExternal_;
+  Fiu32 Fiu32_;
+  Iu32 Iu32_;
+  Scalar Scalar_;
+  F32TexelFormat F32TexelFormat_;
+  I32TexelFormat I32TexelFormat_;
+  U32TexelFormat U32TexelFormat_;
+  Write Write_;
+  Read Read_;
+
+ public:
+  /// Constructor
+  Matchers();
+  /// Destructor
+  ~Matchers();
+
+  /// The open-types, types, and type matchers
+  TypeMatcher const* const type[33] = {
+    /* [0] */ &open_type_0_,
+    /* [1] */ &Bool_,
+    /* [2] */ &F32_,
+    /* [3] */ &I32_,
+    /* [4] */ &U32_,
+    /* [5] */ &Vec2_,
+    /* [6] */ &Vec3_,
+    /* [7] */ &Vec4_,
+    /* [8] */ &Vec_,
+    /* [9] */ &Mat_,
+    /* [10] */ &Ptr_,
+    /* [11] */ &Array_,
+    /* [12] */ &Sampler_,
+    /* [13] */ &SamplerComparison_,
+    /* [14] */ &Texture1D_,
+    /* [15] */ &Texture2D_,
+    /* [16] */ &Texture2DArray_,
+    /* [17] */ &Texture3D_,
+    /* [18] */ &TextureCube_,
+    /* [19] */ &TextureCubeArray_,
+    /* [20] */ &TextureMultisampled2D_,
+    /* [21] */ &TextureDepth2D_,
+    /* [22] */ &TextureDepth2DArray_,
+    /* [23] */ &TextureDepthCube_,
+    /* [24] */ &TextureDepthCubeArray_,
+    /* [25] */ &TextureStorage1D_,
+    /* [26] */ &TextureStorage2D_,
+    /* [27] */ &TextureStorage2DArray_,
+    /* [28] */ &TextureStorage3D_,
+    /* [29] */ &TextureExternal_,
+    /* [30] */ &Fiu32_,
+    /* [31] */ &Iu32_,
+    /* [32] */ &Scalar_,
+  };
+
+  /// The open-numbers, and number matchers
+  NumberMatcher const* const number[7] = {
+    /* [0] */ &open_number_0_,
+    /* [1] */ &open_number_1_,
+    /* [2] */ &F32TexelFormat_,
+    /* [3] */ &I32TexelFormat_,
+    /* [4] */ &U32TexelFormat_,
+    /* [5] */ &Write_,
+    /* [6] */ &Read_,
+  };
+};
+
+Matchers::Matchers() = default;
+Matchers::~Matchers() = default;
+
+constexpr MatcherIndex kMatcherIndices[] = {
+  /* [0] */ 10,
+  /* [1] */ 1,
+  /* [2] */ 8,
+  /* [3] */ 0,
+  /* [4] */ 0,
+  /* [5] */ 10,
+  /* [6] */ 1,
+  /* [7] */ 8,
+  /* [8] */ 0,
+  /* [9] */ 2,
+  /* [10] */ 9,
+  /* [11] */ 0,
+  /* [12] */ 0,
+  /* [13] */ 2,
+  /* [14] */ 26,
+  /* [15] */ 2,
+  /* [16] */ 5,
+  /* [17] */ 3,
+  /* [18] */ 28,
+  /* [19] */ 0,
+  /* [20] */ 1,
+  /* [21] */ 27,
+  /* [22] */ 0,
+  /* [23] */ 1,
+  /* [24] */ 8,
+  /* [25] */ 0,
+  /* [26] */ 1,
+  /* [27] */ 28,
+  /* [28] */ 4,
+  /* [29] */ 6,
+  /* [30] */ 2,
+  /* [31] */ 26,
+  /* [32] */ 0,
+  /* [33] */ 1,
+  /* [34] */ 25,
+  /* [35] */ 0,
+  /* [36] */ 1,
+  /* [37] */ 27,
+  /* [38] */ 4,
+  /* [39] */ 6,
+  /* [40] */ 3,
+  /* [41] */ 26,
+  /* [42] */ 4,
+  /* [43] */ 6,
+  /* [44] */ 25,
+  /* [45] */ 4,
+  /* [46] */ 6,
+  /* [47] */ 28,
+  /* [48] */ 3,
+  /* [49] */ 6,
+  /* [50] */ 27,
+  /* [51] */ 3,
+  /* [52] */ 6,
+  /* [53] */ 26,
+  /* [54] */ 3,
+  /* [55] */ 6,
+  /* [56] */ 25,
+  /* [57] */ 3,
+  /* [58] */ 6,
+  /* [59] */ 28,
+  /* [60] */ 2,
+  /* [61] */ 6,
+  /* [62] */ 27,
+  /* [63] */ 2,
+  /* [64] */ 6,
+  /* [65] */ 26,
+  /* [66] */ 2,
+  /* [67] */ 6,
+  /* [68] */ 25,
+  /* [69] */ 2,
+  /* [70] */ 6,
+  /* [71] */ 28,
+  /* [72] */ 4,
+  /* [73] */ 5,
+  /* [74] */ 2,
+  /* [75] */ 10,
+  /* [76] */ 0,
+  /* [77] */ 2,
+  /* [78] */ 27,
+  /* [79] */ 4,
+  /* [80] */ 5,
+  /* [81] */ 26,
+  /* [82] */ 4,
+  /* [83] */ 5,
+  /* [84] */ 10,
+  /* [85] */ 0,
+  /* [86] */ 0,
+  /* [87] */ 25,
+  /* [88] */ 4,
+  /* [89] */ 5,
+  /* [90] */ 28,
+  /* [91] */ 3,
+  /* [92] */ 5,
+  /* [93] */ 27,
+  /* [94] */ 3,
+  /* [95] */ 5,
+  /* [96] */ 26,
+  /* [97] */ 3,
+  /* [98] */ 5,
+  /* [99] */ 25,
+  /* [100] */ 3,
+  /* [101] */ 5,
+  /* [102] */ 28,
+  /* [103] */ 2,
+  /* [104] */ 5,
+  /* [105] */ 25,
+  /* [106] */ 2,
+  /* [107] */ 5,
+  /* [108] */ 27,
+  /* [109] */ 2,
+  /* [110] */ 5,
+  /* [111] */ 7,
+  /* [112] */ 2,
+  /* [113] */ 7,
+  /* [114] */ 3,
+  /* [115] */ 19,
+  /* [116] */ 2,
+  /* [117] */ 7,
+  /* [118] */ 4,
+  /* [119] */ 18,
+  /* [120] */ 2,
+  /* [121] */ 14,
+  /* [122] */ 0,
+  /* [123] */ 17,
+  /* [124] */ 2,
+  /* [125] */ 7,
+  /* [126] */ 0,
+  /* [127] */ 15,
+  /* [128] */ 0,
+  /* [129] */ 16,
+  /* [130] */ 2,
+  /* [131] */ 16,
+  /* [132] */ 0,
+  /* [133] */ 17,
+  /* [134] */ 0,
+  /* [135] */ 20,
+  /* [136] */ 0,
+  /* [137] */ 15,
+  /* [138] */ 2,
+  /* [139] */ 18,
+  /* [140] */ 0,
+  /* [141] */ 19,
+  /* [142] */ 0,
+  /* [143] */ 11,
+  /* [144] */ 0,
+  /* [145] */ 14,
+  /* [146] */ 2,
+  /* [147] */ 12,
+  /* [148] */ 22,
+  /* [149] */ 23,
+  /* [150] */ 21,
+  /* [151] */ 24,
+  /* [152] */ 29,
+  /* [153] */ 13,
+};
+
+// Assert that the MatcherIndex is big enough to index all the matchers, plus
+// kNoMatcher.
+static_assert(static_cast<int>(sizeof(kMatcherIndices) / sizeof(kMatcherIndices[0])) <
+              static_cast<int>(std::numeric_limits<MatcherIndex>::max() - 1),
+              "MatcherIndex is not large enough to index kMatcherIndices");
+
+constexpr ParameterInfo kParameters[] = {
+  {
+    /* [0] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [1] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [2] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [3] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [4] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [5] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [6] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [7] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [8] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [9] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [10] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [11] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [12] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [13] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [14] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [15] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [16] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [17] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [18] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [19] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [20] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [21] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [22] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [23] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [24] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [25] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [26] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[153],
+  },
+  {
+    /* [27] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [28] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [29] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [30] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [31] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [32] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [33] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [34] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [35] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [36] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [37] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [38] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [39] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [40] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [41] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [42] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [43] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [44] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [45] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [46] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [47] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [48] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [49] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [50] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [51] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [52] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [53] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [54] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [55] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [56] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[153],
+  },
+  {
+    /* [57] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [58] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [59] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [60] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [61] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [62] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [63] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [64] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [65] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [66] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [67] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [68] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [69] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [70] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [71] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[153],
+  },
+  {
+    /* [72] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [73] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [74] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [75] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [76] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [77] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [78] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [79] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [80] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [81] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [82] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [83] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [84] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [85] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [86] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [87] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [88] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [89] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [90] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [91] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [92] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [93] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [94] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [95] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [96] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [97] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [98] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [99] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [100] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [101] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [102] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [103] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [104] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [105] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [106] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [107] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [108] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [109] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [110] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [111] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[153],
+  },
+  {
+    /* [112] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [113] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [114] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [115] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [116] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [117] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [118] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [119] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [120] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [121] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [122] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [123] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [124] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [125] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [126] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [127] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [128] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [129] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [130] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [131] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [132] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [133] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [134] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [135] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [136] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [137] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [138] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [139] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [140] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [141] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [142] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [143] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [144] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [145] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [146] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [147] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [148] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [149] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [150] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [151] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [152] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [153] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [154] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [155] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [156] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [157] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [158] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[78],
+  },
+  {
+    /* [159] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [160] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [161] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [162] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[93],
+  },
+  {
+    /* [163] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [164] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [165] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [166] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [167] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [168] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [169] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [170] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [171] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [172] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [173] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [174] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [175] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [176] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [177] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [178] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[108],
+  },
+  {
+    /* [179] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [180] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [181] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [182] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[149],
+  },
+  {
+    /* [183] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[153],
+  },
+  {
+    /* [184] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [185] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [186] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [187] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [188] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [189] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [190] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [191] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [192] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [193] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [194] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [195] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [196] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [197] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [198] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[149],
+  },
+  {
+    /* [199] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [200] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [201] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [202] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [203] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [204] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [205] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [206] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [207] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[153],
+  },
+  {
+    /* [208] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [209] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [210] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [211] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [212] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [213] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [214] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [215] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [216] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [217] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [218] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [219] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [220] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [221] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [222] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [223] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [224] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [225] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [226] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [227] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [228] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [229] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [230] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [231] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [232] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [233] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [234] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [235] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [236] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [237] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [238] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[99],
+  },
+  {
+    /* [239] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [240] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [241] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [242] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [243] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [244] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [245] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [246] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [247] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [248] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [249] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [250] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [251] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [252] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [253] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [254] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [255] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [256] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[152],
+  },
+  {
+    /* [257] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [258] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [259] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[14],
+  },
+  {
+    /* [260] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [261] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [262] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[102],
+  },
+  {
+    /* [263] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [264] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [265] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[90],
+  },
+  {
+    /* [266] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [267] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [268] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[87],
+  },
+  {
+    /* [269] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [270] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [271] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[81],
+  },
+  {
+    /* [272] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [273] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [274] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [275] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [276] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [277] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [278] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [279] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [280] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [281] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [282] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [283] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[71],
+  },
+  {
+    /* [284] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [285] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [286] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [287] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [288] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [289] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[127],
+  },
+  {
+    /* [290] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [291] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [292] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [293] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [294] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [295] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[135],
+  },
+  {
+    /* [296] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [297] */
+    /* usage */ ParameterUsage::kSampleIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [298] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [299] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [300] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [301] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [302] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [303] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [304] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [305] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [306] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [307] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [308] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [309] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [310] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [311] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [312] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [313] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [314] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [315] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [316] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[149],
+  },
+  {
+    /* [317] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [318] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [319] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[137],
+  },
+  {
+    /* [320] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [321] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [322] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[50],
+  },
+  {
+    /* [323] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [324] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [325] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[152],
+  },
+  {
+    /* [326] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [327] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [328] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[145],
+  },
+  {
+    /* [329] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[147],
+  },
+  {
+    /* [330] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [331] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [332] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [333] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [334] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [335] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [336] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [337] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [338] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [339] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [340] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[105],
+  },
+  {
+    /* [341] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [342] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [343] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [344] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [345] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [346] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[96],
+  },
+  {
+    /* [347] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [348] */
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [349] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [350] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [351] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [352] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[75],
+  },
+  {
+    /* [353] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [354] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [355] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [356] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [357] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [358] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [359] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [360] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [361] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [362] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [363] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [364] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [365] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [366] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [367] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [368] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [369] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[152],
+  },
+  {
+    /* [370] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [371] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [372] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [373] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [374] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [375] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [376] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[0],
+  },
+  {
+    /* [377] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [378] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[84],
+  },
+  {
+    /* [379] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[127],
+  },
+  {
+    /* [380] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [381] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [382] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [383] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [384] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [385] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [386] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [387] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [388] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [389] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [390] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [391] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [392] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [393] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[68],
+  },
+  {
+    /* [394] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [395] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[65],
+  },
+  {
+    /* [396] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [397] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[59],
+  },
+  {
+    /* [398] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [399] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [400] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [401] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [402] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [403] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[27],
+  },
+  {
+    /* [404] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [405] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[56],
+  },
+  {
+    /* [406] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [407] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[53],
+  },
+  {
+    /* [408] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [409] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[47],
+  },
+  {
+    /* [410] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [411] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [412] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [413] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [414] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [415] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[149],
+  },
+  {
+    /* [416] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [417] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [418] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [419] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [420] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [421] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
+  },
+  {
+    /* [422] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [423] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
+  },
+  {
+    /* [424] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [425] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [426] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [427] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[41],
+  },
+  {
+    /* [428] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [429] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [430] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [431] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[127],
+  },
+  {
+    /* [432] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[127],
+  },
+  {
+    /* [433] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [434] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [435] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [436] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [437] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
+  },
+  {
+    /* [438] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [439] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
+  },
+  {
+    /* [440] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [441] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[135],
+  },
+  {
+    /* [442] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [443] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [444] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [445] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [446] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[149],
+  },
+  {
+    /* [447] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [448] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [449] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [450] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[34],
+  },
+  {
+    /* [451] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [452] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[21],
+  },
+  {
+    /* [453] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[18],
+  },
+  {
+    /* [454] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[152],
+  },
+  {
+    /* [455] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [456] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
+  },
+  {
+    /* [457] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [458] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [459] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[21],
+  },
+  {
+    /* [460] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [461] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [462] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [463] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
+  },
+  {
+    /* [464] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
+  },
+  {
+    /* [465] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[150],
+  },
+  {
+    /* [466] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[148],
+  },
+  {
+    /* [467] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[149],
+  },
+  {
+    /* [468] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[151],
+  },
+  {
+    /* [469] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[135],
+  },
+  {
+    /* [470] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [471] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [472] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [473] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [474] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [475] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [476] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [477] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [478] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [479] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [480] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [481] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [482] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [483] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [484] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [485] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [486] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [487] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [488] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [489] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [490] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [491] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [492] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [493] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [494] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [495] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [496] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [497] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [498] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [499] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [500] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [501] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [502] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [503] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [504] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [505] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [506] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [507] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [508] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [509] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [510] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [511] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [512] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [513] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [514] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [515] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [516] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [517] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [518] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [519] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [520] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [521] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [522] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [523] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [524] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [525] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [526] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [527] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [528] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [529] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [530] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [531] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [532] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [533] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[10],
+  },
+  {
+    /* [534] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [535] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [536] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [537] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [538] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [539] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [540] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [541] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [542] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [543] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [544] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [545] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [546] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[143],
+  },
+  {
+    /* [547] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [548] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [549] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [550] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [551] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [552] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[3],
+  },
+};
+
+constexpr OpenTypeInfo kOpenTypes[] = {
+  {
+    /* [0] */
+    /* name */ "T",
+    /* matcher index */ 31,
+  },
+  {
+    /* [1] */
+    /* name */ "T",
+    /* matcher index */ 30,
+  },
+  {
+    /* [2] */
+    /* name */ "T",
+    /* matcher index */ kNoMatcher,
+  },
+  {
+    /* [3] */
+    /* name */ "T",
+    /* matcher index */ 32,
+  },
+};
+
+constexpr OpenNumberInfo kOpenNumbers[] = {
+  {
+    /* [0] */
+    /* name */ "F",
+    /* matcher index */ kNoMatcher,
+  },
+  {
+    /* [1] */
+    /* name */ "A",
+    /* matcher index */ kNoMatcher,
+  },
+  {
+    /* [2] */
+    /* name */ "N",
+    /* matcher index */ kNoMatcher,
+  },
+  {
+    /* [3] */
+    /* name */ "S",
+    /* matcher index */ kNoMatcher,
+  },
+};
+
+constexpr OverloadInfo kOverloads[] = {
+  {
+    /* [0] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[434],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [1] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[432],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [2] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[379],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [3] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[433],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [4] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[429],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [5] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[435],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [6] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[425],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [7] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[437],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [8] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[423],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [9] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[439],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [10] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[421],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [11] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[441],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [12] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[442],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [13] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[419],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [14] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[444],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [15] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[417],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [16] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[446],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [17] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[415],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [18] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[448],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [19] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[413],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [20] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[0],
+    /* parameters */ &kParameters[450],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [21] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[0],
+    /* parameters */ &kParameters[451],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [22] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[0],
+    /* parameters */ &kParameters[452],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [23] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[0],
+    /* parameters */ &kParameters[453],
+    /* return matcher indices */ &kMatcherIndices[39],
+  },
+  {
+    /* [24] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[454],
+    /* return matcher indices */ &kMatcherIndices[16],
+  },
+  {
+    /* [25] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[286],
+    /* return matcher indices */ &kMatcherIndices[125],
+  },
+  {
+    /* [26] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[289],
+    /* return matcher indices */ &kMatcherIndices[125],
+  },
+  {
+    /* [27] */
+    /* num parameters */ 4,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[150],
+    /* return matcher indices */ &kMatcherIndices[125],
+  },
+  {
+    /* [28] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[292],
+    /* return matcher indices */ &kMatcherIndices[125],
+  },
+  {
+    /* [29] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[295],
+    /* return matcher indices */ &kMatcherIndices[125],
+  },
+  {
+    /* [30] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[304],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [31] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[194],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [32] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[393],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [33] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[395],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [34] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[313],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [35] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[397],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [36] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[405],
+    /* return matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [37] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[407],
+    /* return matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [38] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[322],
+    /* return matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [39] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[409],
+    /* return matcher indices */ &kMatcherIndices[113],
+  },
+  {
+    /* [40] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[411],
+    /* return matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [41] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[427],
+    /* return matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [42] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[331],
+    /* return matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [43] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[403],
+    /* return matcher indices */ &kMatcherIndices[117],
+  },
+  {
+    /* [44] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[369],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [45] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[328],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [46] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[319],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [47] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[234],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [48] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[214],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [49] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[60],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [50] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[307],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [51] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[170],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [52] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[277],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [53] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[154],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [54] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[274],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [55] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[166],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [56] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[190],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [57] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[85],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [58] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[316],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [59] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[226],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [60] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[325],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [61] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[174],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [62] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[100],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [63] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[90],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [64] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[43],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [65] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[218],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [66] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[135],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [67] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[202],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [68] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[95],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [69] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[222],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [70] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[125],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [71] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[65],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [72] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[37],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [73] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[198],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [74] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[75],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [75] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[256],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [76] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[340],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [77] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[259],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [78] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[178],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [79] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[262],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [80] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[238],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [81] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[346],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [82] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[162],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [83] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[265],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [84] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[268],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [85] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[271],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [86] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[158],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [87] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[283],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [88] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[431],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [89] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[461],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [90] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[462],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [91] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[463],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [92] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[464],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [93] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[465],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [94] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[466],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [95] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[467],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [96] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[468],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [97] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[230],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [98] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[105],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [99] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[130],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [100] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[49],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [101] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[210],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [102] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[80],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [103] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[186],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [104] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[120],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [105] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[115],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [106] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[7],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [107] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[19],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [108] */
+    /* num parameters */ 7,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[0],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [109] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[145],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [110] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[31],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [111] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[140],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [112] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[13],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [113] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[206],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [114] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[70],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [115] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[55],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [116] */
+    /* num parameters */ 6,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[25],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [117] */
+    /* num parameters */ 4,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[182],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [118] */
+    /* num parameters */ 5,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[110],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [119] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[455],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [120] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[456],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [121] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[457],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [122] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[458],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [123] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[0],
+    /* parameters */ &kParameters[459],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [124] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[391],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [125] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[389],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [126] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[537],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [127] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[536],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [128] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[535],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [129] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[534],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [130] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[539],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [131] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[538],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [132] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[399],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [133] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[401],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [134] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[385],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [135] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[383],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [136] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[301],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [137] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[298],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [138] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[532],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [139] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[531],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [140] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[530],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [141] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[529],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [142] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[528],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [143] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[527],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [144] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[526],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [145] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[525],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [146] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[524],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [147] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[523],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [148] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[522],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [149] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[521],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [150] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[520],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [151] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[519],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [152] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[518],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [153] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[517],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [154] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[253],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [155] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[250],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [156] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[516],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [157] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[515],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [158] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[280],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [159] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[241],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [160] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[514],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [161] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[513],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [162] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[3],
+    /* parameters */ &kParameters[377],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [163] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[375],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [164] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[512],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [165] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[511],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [166] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[510],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [167] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[509],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [168] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[508],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [169] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[507],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [170] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[506],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [171] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[505],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [172] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[504],
+    /* return matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [173] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[503],
+    /* return matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [174] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[502],
+    /* return matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [175] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[501],
+    /* return matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [176] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[500],
+    /* return matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [177] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[499],
+    /* return matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [178] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[498],
+    /* return matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [179] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[497],
+    /* return matcher indices */ &kMatcherIndices[24],
+  },
+  {
+    /* [180] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[373],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [181] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[371],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [182] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[496],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [183] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[495],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [184] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[494],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [185] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[493],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [186] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[492],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [187] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[491],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [188] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[541],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [189] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[540],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [190] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[355],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [191] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[353],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [192] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[334],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [193] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[337],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [194] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[3],
+    /* parameters */ &kParameters[351],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [195] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 2,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[349],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [196] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[543],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [197] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[542],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [198] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[474],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [199] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[473],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [200] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[545],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [201] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[544],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [202] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[449],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [203] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[447],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [204] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[470],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [205] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[460],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [206] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[472],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [207] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[471],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [208] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[359],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [209] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[361],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [210] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[363],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [211] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[365],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [212] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[550],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [213] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[549],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [214] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[482],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [215] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[481],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [216] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[3],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[247],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [217] */
+    /* num parameters */ 3,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[3],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[244],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [218] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[480],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [219] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[479],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [220] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[478],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [221] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[477],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [222] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[476],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [223] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[475],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [224] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[310],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [225] */
+    /* num parameters */ 3,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[343],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [226] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[484],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [227] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[0],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[483],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [228] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[367],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [229] */
+    /* num parameters */ 2,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[357],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [230] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[552],
+    /* return matcher indices */ &kMatcherIndices[3],
+  },
+  {
+    /* [231] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[1],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[551],
+    /* return matcher indices */ &kMatcherIndices[2],
+  },
+  {
+    /* [232] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[488],
+    /* return matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [233] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[486],
+    /* return matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [234] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[487],
+    /* return matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [235] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[445],
+    /* return matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [236] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[443],
+    /* return matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [237] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[440],
+    /* return matcher indices */ &kMatcherIndices[73],
+  },
+  {
+    /* [238] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[438],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [239] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[436],
+    /* return matcher indices */ &kMatcherIndices[111],
+  },
+  {
+    /* [240] */
+    /* num parameters */ 0,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[553],
+    /* return matcher indices */ nullptr,
+  },
+  {
+    /* [241] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[485],
+    /* return matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [242] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[489],
+    /* return matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [243] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[490],
+    /* return matcher indices */ &kMatcherIndices[7],
+  },
+  {
+    /* [244] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[469],
+    /* return matcher indices */ &kMatcherIndices[17],
+  },
+  {
+    /* [245] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[381],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [246] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[533],
+    /* return matcher indices */ &kMatcherIndices[9],
+  },
+  {
+    /* [247] */
+    /* num parameters */ 2,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[387],
+    /* return matcher indices */ &kMatcherIndices[29],
+  },
+  {
+    /* [248] */
+    /* num parameters */ 1,
+    /* num open types */ 1,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[2],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[546],
+    /* return matcher indices */ &kMatcherIndices[28],
+  },
+  {
+    /* [249] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[547],
+    /* return matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [250] */
+    /* num parameters */ 1,
+    /* num open types */ 0,
+    /* num open numbers */ 1,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[2],
+    /* parameters */ &kParameters[548],
+    /* return matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [251] */
+    /* num parameters */ 0,
+    /* num open types */ 0,
+    /* num open numbers */ 0,
+    /* open types */ &kOpenTypes[4],
+    /* open numbers */ &kOpenNumbers[4],
+    /* parameters */ &kParameters[553],
+    /* return matcher indices */ nullptr,
+  },
+};
+
+constexpr IntrinsicInfo kIntrinsics[] = {
+  {
+    /* [0] */
+    /* fn abs<T : fiu32>(T) -> T */
+    /* fn abs<N : num, T : fiu32>(vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[230],
+  },
+  {
+    /* [1] */
+    /* fn acos(f32) -> f32 */
+    /* fn acos<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[212],
+  },
+  {
+    /* [2] */
+    /* fn all<N : num>(vec<N, bool>) -> bool */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[250],
+  },
+  {
+    /* [3] */
+    /* fn any<N : num>(vec<N, bool>) -> bool */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[249],
+  },
+  {
+    /* [4] */
+    /* fn arrayLength<T>(array<T>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[248],
+  },
+  {
+    /* [5] */
+    /* fn asin(f32) -> f32 */
+    /* fn asin<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[200],
+  },
+  {
+    /* [6] */
+    /* fn atan(f32) -> f32 */
+    /* fn atan<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[196],
+  },
+  {
+    /* [7] */
+    /* fn atan2(f32, f32) -> f32 */
+    /* fn atan2<N : num>(vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[124],
+  },
+  {
+    /* [8] */
+    /* fn ceil(f32) -> f32 */
+    /* fn ceil<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[188],
+  },
+  {
+    /* [9] */
+    /* fn clamp<T : fiu32>(T, T, T) -> T */
+    /* fn clamp<N : num, T : fiu32>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[136],
+  },
+  {
+    /* [10] */
+    /* fn cos(f32) -> f32 */
+    /* fn cos<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[130],
+  },
+  {
+    /* [11] */
+    /* fn cosh(f32) -> f32 */
+    /* fn cosh<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[126],
+  },
+  {
+    /* [12] */
+    /* fn countOneBits<T : iu32>(T) -> T */
+    /* fn countOneBits<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[128],
+  },
+  {
+    /* [13] */
+    /* fn cross(vec3<f32>, vec3<f32>) -> vec3<f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[247],
+  },
+  {
+    /* [14] */
+    /* fn determinant<N : num>(mat<N, N, f32>) -> f32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[246],
+  },
+  {
+    /* [15] */
+    /* fn distance(f32, f32) -> f32 */
+    /* fn distance<N : num>(vec<N, f32>, vec<N, f32>) -> f32 */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[134],
+  },
+  {
+    /* [16] */
+    /* fn dot<N : num>(vec<N, f32>, vec<N, f32>) -> f32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[245],
+  },
+  {
+    /* [17] */
+    /* fn dpdx(f32) -> f32 */
+    /* fn dpdx<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[138],
+  },
+  {
+    /* [18] */
+    /* fn dpdxCoarse(f32) -> f32 */
+    /* fn dpdxCoarse<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[140],
+  },
+  {
+    /* [19] */
+    /* fn dpdxFine(f32) -> f32 */
+    /* fn dpdxFine<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[142],
+  },
+  {
+    /* [20] */
+    /* fn dpdy(f32) -> f32 */
+    /* fn dpdy<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[144],
+  },
+  {
+    /* [21] */
+    /* fn dpdyCoarse(f32) -> f32 */
+    /* fn dpdyCoarse<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[146],
+  },
+  {
+    /* [22] */
+    /* fn dpdyFine(f32) -> f32 */
+    /* fn dpdyFine<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[148],
+  },
+  {
+    /* [23] */
+    /* fn exp(f32) -> f32 */
+    /* fn exp<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[150],
+  },
+  {
+    /* [24] */
+    /* fn exp2(f32) -> f32 */
+    /* fn exp2<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[152],
+  },
+  {
+    /* [25] */
+    /* fn faceForward(f32, f32, f32) -> f32 */
+    /* fn faceForward<N : num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[154],
+  },
+  {
+    /* [26] */
+    /* fn floor(f32) -> f32 */
+    /* fn floor<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[156],
+  },
+  {
+    /* [27] */
+    /* fn fma(f32, f32, f32) -> f32 */
+    /* fn fma<N : num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[158],
+  },
+  {
+    /* [28] */
+    /* fn fract(f32) -> f32 */
+    /* fn fract<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[160],
+  },
+  {
+    /* [29] */
+    /* fn frexp<T : iu32, S : storage_class>(f32, ptr<S, T>) -> f32 */
+    /* fn frexp<N : num, T : iu32, S : storage_class>(vec<N, f32>, ptr<S, vec<N, T>>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[162],
+  },
+  {
+    /* [30] */
+    /* fn fwidth(f32) -> f32 */
+    /* fn fwidth<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[164],
+  },
+  {
+    /* [31] */
+    /* fn fwidthCoarse(f32) -> f32 */
+    /* fn fwidthCoarse<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[166],
+  },
+  {
+    /* [32] */
+    /* fn fwidthFine(f32) -> f32 */
+    /* fn fwidthFine<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[168],
+  },
+  {
+    /* [33] */
+    /* fn inverseSqrt(f32) -> f32 */
+    /* fn inverseSqrt<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[170],
+  },
+  {
+    /* [34] */
+    /* fn isFinite(f32) -> bool */
+    /* fn isFinite<N : num>(vec<N, f32>) -> vec<N, bool> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[172],
+  },
+  {
+    /* [35] */
+    /* fn isInf(f32) -> bool */
+    /* fn isInf<N : num>(vec<N, f32>) -> vec<N, bool> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[174],
+  },
+  {
+    /* [36] */
+    /* fn isNan(f32) -> bool */
+    /* fn isNan<N : num>(vec<N, f32>) -> vec<N, bool> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[176],
+  },
+  {
+    /* [37] */
+    /* fn isNormal(f32) -> bool */
+    /* fn isNormal<N : num>(vec<N, f32>) -> vec<N, bool> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[178],
+  },
+  {
+    /* [38] */
+    /* fn ldexp<T : iu32>(f32, T) -> f32 */
+    /* fn ldexp<N : num, T : iu32>(vec<N, f32>, vec<N, T>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[180],
+  },
+  {
+    /* [39] */
+    /* fn length(f32) -> f32 */
+    /* fn length<N : num>(vec<N, f32>) -> f32 */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[182],
+  },
+  {
+    /* [40] */
+    /* fn log(f32) -> f32 */
+    /* fn log<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[184],
+  },
+  {
+    /* [41] */
+    /* fn log2(f32) -> f32 */
+    /* fn log2<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[186],
+  },
+  {
+    /* [42] */
+    /* fn max<T : fiu32>(T, T) -> T */
+    /* fn max<N : num, T : fiu32>(vec<N, T>, vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[228],
+  },
+  {
+    /* [43] */
+    /* fn min<T : fiu32>(T, T) -> T */
+    /* fn min<N : num, T : fiu32>(vec<N, T>, vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[190],
+  },
+  {
+    /* [44] */
+    /* fn mix(f32, f32, f32) -> f32 */
+    /* fn mix<N : num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[192],
+  },
+  {
+    /* [45] */
+    /* fn modf<S : storage_class>(f32, ptr<S, f32>) -> f32 */
+    /* fn modf<N : num, S : storage_class>(vec<N, f32>, ptr<S, vec<N, f32>>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[194],
+  },
+  {
+    /* [46] */
+    /* fn normalize<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[243],
+  },
+  {
+    /* [47] */
+    /* fn pack2x16float(vec2<f32>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[242],
+  },
+  {
+    /* [48] */
+    /* fn pack2x16snorm(vec2<f32>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[232],
+  },
+  {
+    /* [49] */
+    /* fn pack2x16unorm(vec2<f32>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[234],
+  },
+  {
+    /* [50] */
+    /* fn pack4x8snorm(vec4<f32>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[233],
+  },
+  {
+    /* [51] */
+    /* fn pack4x8unorm(vec4<f32>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[241],
+  },
+  {
+    /* [52] */
+    /* fn pow(f32, f32) -> f32 */
+    /* fn pow<N : num>(vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[208],
+  },
+  {
+    /* [53] */
+    /* fn reflect(f32, f32) -> f32 */
+    /* fn reflect<N : num>(vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[210],
+  },
+  {
+    /* [54] */
+    /* fn reverseBits<T : iu32>(T) -> T */
+    /* fn reverseBits<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[226],
+  },
+  {
+    /* [55] */
+    /* fn round(f32) -> f32 */
+    /* fn round<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[214],
+  },
+  {
+    /* [56] */
+    /* fn select<T : scalar>(T, T, bool) -> T */
+    /* fn select<N : num, T : scalar>(vec<N, T>, vec<N, T>, vec<N, bool>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[216],
+  },
+  {
+    /* [57] */
+    /* fn sign(f32) -> f32 */
+    /* fn sign<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[218],
+  },
+  {
+    /* [58] */
+    /* fn sin(f32) -> f32 */
+    /* fn sin<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[220],
+  },
+  {
+    /* [59] */
+    /* fn sinh(f32) -> f32 */
+    /* fn sinh<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[222],
+  },
+  {
+    /* [60] */
+    /* fn smoothStep(f32, f32, f32) -> f32 */
+    /* fn smoothStep<N : num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[224],
+  },
+  {
+    /* [61] */
+    /* fn sqrt(f32) -> f32 */
+    /* fn sqrt<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[198],
+  },
+  {
+    /* [62] */
+    /* fn step(f32, f32) -> f32 */
+    /* fn step<N : num>(vec<N, f32>, vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[132],
+  },
+  {
+    /* [63] */
+    /* fn storageBarrier() */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[251],
+  },
+  {
+    /* [64] */
+    /* fn tan(f32) -> f32 */
+    /* fn tan<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[206],
+  },
+  {
+    /* [65] */
+    /* fn tanh(f32) -> f32 */
+    /* fn tanh<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[204],
+  },
+  {
+    /* [66] */
+    /* fn trunc(f32) -> f32 */
+    /* fn trunc<N : num>(vec<N, f32>) -> vec<N, f32> */
+    /* num overloads */ 2,
+    /* overloads */ &kOverloads[202],
+  },
+  {
+    /* [67] */
+    /* fn unpack2x16float(u32) -> vec2<f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[235],
+  },
+  {
+    /* [68] */
+    /* fn unpack2x16snorm(u32) -> vec2<f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[236],
+  },
+  {
+    /* [69] */
+    /* fn unpack2x16unorm(u32) -> vec2<f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[237],
+  },
+  {
+    /* [70] */
+    /* fn unpack4x8snorm(u32) -> vec4<f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[238],
+  },
+  {
+    /* [71] */
+    /* fn unpack4x8unorm(u32) -> vec4<f32> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[239],
+  },
+  {
+    /* [72] */
+    /* fn workgroupBarrier() */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[240],
+  },
+  {
+    /* [73] */
+    /* fn textureDimensions<T>(texture: texture_1d<T>) -> i32 */
+    /* fn textureDimensions<T>(texture: texture_2d<T>) -> vec2<i32> */
+    /* fn textureDimensions<T>(texture: texture_2d<T>, level: i32) -> vec2<i32> */
+    /* fn textureDimensions<T>(texture: texture_2d_array<T>) -> vec2<i32> */
+    /* fn textureDimensions<T>(texture: texture_2d_array<T>, level: i32) -> vec2<i32> */
+    /* fn textureDimensions<T>(texture: texture_3d<T>) -> vec3<i32> */
+    /* fn textureDimensions<T>(texture: texture_3d<T>, level: i32) -> vec3<i32> */
+    /* fn textureDimensions<T>(texture: texture_cube<T>) -> vec3<i32> */
+    /* fn textureDimensions<T>(texture: texture_cube<T>, level: i32) -> vec3<i32> */
+    /* fn textureDimensions<T>(texture: texture_cube_array<T>) -> vec3<i32> */
+    /* fn textureDimensions<T>(texture: texture_cube_array<T>, level: i32) -> vec3<i32> */
+    /* fn textureDimensions<T>(texture: texture_multisampled_2d<T>) -> vec2<i32> */
+    /* fn textureDimensions(texture: texture_depth_2d) -> vec2<i32> */
+    /* fn textureDimensions(texture: texture_depth_2d, level: i32) -> vec2<i32> */
+    /* fn textureDimensions(texture: texture_depth_2d_array) -> vec2<i32> */
+    /* fn textureDimensions(texture: texture_depth_2d_array, level: i32) -> vec2<i32> */
+    /* fn textureDimensions(texture: texture_depth_cube) -> vec3<i32> */
+    /* fn textureDimensions(texture: texture_depth_cube, level: i32) -> vec3<i32> */
+    /* fn textureDimensions(texture: texture_depth_cube_array) -> vec3<i32> */
+    /* fn textureDimensions(texture: texture_depth_cube_array, level: i32) -> vec3<i32> */
+    /* fn textureDimensions<F : texel_format, A : access_control>(texture: texture_storage_1d<F, A>) -> i32 */
+    /* fn textureDimensions<F : texel_format, A : access_control>(texture: texture_storage_2d<F, A>) -> vec2<i32> */
+    /* fn textureDimensions<F : texel_format, A : access_control>(texture: texture_storage_2d_array<F, A>) -> vec2<i32> */
+    /* fn textureDimensions<F : texel_format, A : access_control>(texture: texture_storage_3d<F, A>) -> vec3<i32> */
+    /* fn textureDimensions(texture: texture_external) -> vec2<i32> */
+    /* num overloads */ 25,
+    /* overloads */ &kOverloads[0],
+  },
+  {
+    /* [74] */
+    /* fn textureNumLayers<T>(texture: texture_2d_array<T>) -> i32 */
+    /* fn textureNumLayers<T>(texture: texture_cube_array<T>) -> i32 */
+    /* fn textureNumLayers(texture: texture_depth_2d_array) -> i32 */
+    /* fn textureNumLayers(texture: texture_depth_cube_array) -> i32 */
+    /* fn textureNumLayers<F : texel_format, A : access_control>(texture: texture_storage_2d_array<F, A>) -> i32 */
+    /* num overloads */ 5,
+    /* overloads */ &kOverloads[119],
+  },
+  {
+    /* [75] */
+    /* fn textureNumLevels<T>(texture: texture_2d<T>) -> i32 */
+    /* fn textureNumLevels<T>(texture: texture_2d_array<T>) -> i32 */
+    /* fn textureNumLevels<T>(texture: texture_3d<T>) -> i32 */
+    /* fn textureNumLevels<T>(texture: texture_cube<T>) -> i32 */
+    /* fn textureNumLevels<T>(texture: texture_cube_array<T>) -> i32 */
+    /* fn textureNumLevels(texture: texture_depth_2d) -> i32 */
+    /* fn textureNumLevels(texture: texture_depth_2d_array) -> i32 */
+    /* fn textureNumLevels(texture: texture_depth_cube) -> i32 */
+    /* fn textureNumLevels(texture: texture_depth_cube_array) -> i32 */
+    /* num overloads */ 9,
+    /* overloads */ &kOverloads[88],
+  },
+  {
+    /* [76] */
+    /* fn textureNumSamples<T>(texture: texture_multisampled_2d<T>) -> i32 */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[244],
+  },
+  {
+    /* [77] */
+    /* fn textureSample(texture: texture_1d<f32>, sampler: sampler, coords: f32) -> vec4<f32> */
+    /* fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>) -> vec4<f32> */
+    /* fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSample(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32) -> vec4<f32> */
+    /* fn textureSample(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSample(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>) -> vec4<f32> */
+    /* fn textureSample(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, offset: vec3<i32>) -> vec4<f32> */
+    /* fn textureSample(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>) -> vec4<f32> */
+    /* fn textureSample(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32) -> vec4<f32> */
+    /* fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>) -> f32 */
+    /* fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>, offset: vec2<i32>) -> f32 */
+    /* fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32) -> f32 */
+    /* fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32, offset: vec2<i32>) -> f32 */
+    /* fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3<f32>) -> f32 */
+    /* fn textureSample(texture: texture_depth_cube_array, sampler: sampler, coords: vec3<f32>, array_index: i32) -> f32 */
+    /* fn textureSample(texture: texture_external, sampler: sampler, coords: vec2<f32>) -> vec4<f32> */
+    /* num overloads */ 16,
+    /* overloads */ &kOverloads[45],
+  },
+  {
+    /* [78] */
+    /* fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, bias: f32) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, bias: f32, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, bias: f32, offset: vec3<i32>) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32> */
+    /* fn textureSampleBias(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32, bias: f32) -> vec4<f32> */
+    /* num overloads */ 8,
+    /* overloads */ &kOverloads[97],
+  },
+  {
+    /* [79] */
+    /* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32 */
+    /* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32 */
+    /* fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32) -> f32 */
+    /* fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: i32, depth_ref: f32, offset: vec2<i32>) -> f32 */
+    /* fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32 */
+    /* fn textureSampleCompare(texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3<f32>, array_index: i32, depth_ref: f32) -> f32 */
+    /* num overloads */ 6,
+    /* overloads */ &kOverloads[113],
+  },
+  {
+    /* [80] */
+    /* fn textureSampleGrad(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, ddx: vec2<f32>, ddy: vec2<f32>, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>, offset: vec3<i32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32> */
+    /* fn textureSampleGrad(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32> */
+    /* num overloads */ 8,
+    /* overloads */ &kOverloads[105],
+  },
+  {
+    /* [81] */
+    /* fn textureSampleLevel(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, level: f32) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, level: f32, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, level: f32) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: i32, level: f32, offset: vec2<i32>) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, level: f32) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_3d<f32>, sampler: sampler, coords: vec3<f32>, level: f32, offset: vec3<i32>) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_cube<f32>, sampler: sampler, coords: vec3<f32>, level: f32) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_cube_array<f32>, sampler: sampler, coords: vec3<f32>, array_index: i32, level: f32) -> vec4<f32> */
+    /* fn textureSampleLevel(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>, level: i32) -> f32 */
+    /* fn textureSampleLevel(texture: texture_depth_2d, sampler: sampler, coords: vec2<f32>, level: i32, offset: vec2<i32>) -> f32 */
+    /* fn textureSampleLevel(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32, level: i32) -> f32 */
+    /* fn textureSampleLevel(texture: texture_depth_2d_array, sampler: sampler, coords: vec2<f32>, array_index: i32, level: i32, offset: vec2<i32>) -> f32 */
+    /* fn textureSampleLevel(texture: texture_depth_cube, sampler: sampler, coords: vec3<f32>, level: i32) -> f32 */
+    /* fn textureSampleLevel(texture: texture_depth_cube_array, sampler: sampler, coords: vec3<f32>, array_index: i32, level: i32) -> f32 */
+    /* fn textureSampleLevel(texture: texture_external, sampler: sampler, coords: vec2<f32>) -> vec4<f32> */
+    /* num overloads */ 15,
+    /* overloads */ &kOverloads[61],
+  },
+  {
+    /* [82] */
+    /* fn textureStore(texture: texture_storage_1d<f32_texel_format, write>, coords: i32, value: vec4<f32>) */
+    /* fn textureStore(texture: texture_storage_2d<f32_texel_format, write>, coords: vec2<i32>, value: vec4<f32>) */
+    /* fn textureStore(texture: texture_storage_2d_array<f32_texel_format, write>, coords: vec2<i32>, array_index: i32, value: vec4<f32>) */
+    /* fn textureStore(texture: texture_storage_3d<f32_texel_format, write>, coords: vec3<i32>, value: vec4<f32>) */
+    /* fn textureStore(texture: texture_storage_1d<i32_texel_format, write>, coords: i32, value: vec4<i32>) */
+    /* fn textureStore(texture: texture_storage_2d<i32_texel_format, write>, coords: vec2<i32>, value: vec4<i32>) */
+    /* fn textureStore(texture: texture_storage_2d_array<i32_texel_format, write>, coords: vec2<i32>, array_index: i32, value: vec4<i32>) */
+    /* fn textureStore(texture: texture_storage_3d<i32_texel_format, write>, coords: vec3<i32>, value: vec4<i32>) */
+    /* fn textureStore(texture: texture_storage_1d<u32_texel_format, write>, coords: i32, value: vec4<u32>) */
+    /* fn textureStore(texture: texture_storage_2d<u32_texel_format, write>, coords: vec2<i32>, value: vec4<u32>) */
+    /* fn textureStore(texture: texture_storage_2d_array<u32_texel_format, write>, coords: vec2<i32>, array_index: i32, value: vec4<u32>) */
+    /* fn textureStore(texture: texture_storage_3d<u32_texel_format, write>, coords: vec3<i32>, value: vec4<u32>) */
+    /* num overloads */ 12,
+    /* overloads */ &kOverloads[76],
+  },
+  {
+    /* [83] */
+    /* fn textureLoad<T>(texture: texture_1d<T>, coords: i32, level: i32) -> vec4<T> */
+    /* fn textureLoad<T>(texture: texture_2d<T>, coords: vec2<i32>, level: i32) -> vec4<T> */
+    /* fn textureLoad<T>(texture: texture_2d_array<T>, coords: vec2<i32>, array_index: i32, level: i32) -> vec4<T> */
+    /* fn textureLoad<T>(texture: texture_3d<T>, coords: vec3<i32>, level: i32) -> vec4<T> */
+    /* fn textureLoad<T>(texture: texture_multisampled_2d<T>, coords: vec2<i32>, sample_index: i32) -> vec4<T> */
+    /* fn textureLoad(texture: texture_depth_2d, coords: vec2<i32>, level: i32) -> f32 */
+    /* fn textureLoad(texture: texture_depth_2d_array, coords: vec2<i32>, array_index: i32, level: i32) -> f32 */
+    /* fn textureLoad(texture: texture_storage_1d<f32_texel_format, read>, coords: i32) -> vec4<f32> */
+    /* fn textureLoad(texture: texture_storage_2d<f32_texel_format, read>, coords: vec2<i32>) -> vec4<f32> */
+    /* fn textureLoad(texture: texture_storage_2d_array<f32_texel_format, read>, coords: vec2<i32>, array_index: i32) -> vec4<f32> */
+    /* fn textureLoad(texture: texture_storage_3d<f32_texel_format, read>, coords: vec3<i32>) -> vec4<f32> */
+    /* fn textureLoad(texture: texture_storage_1d<i32_texel_format, read>, coords: i32) -> vec4<i32> */
+    /* fn textureLoad(texture: texture_storage_2d<i32_texel_format, read>, coords: vec2<i32>) -> vec4<i32> */
+    /* fn textureLoad(texture: texture_storage_2d_array<i32_texel_format, read>, coords: vec2<i32>, array_index: i32) -> vec4<i32> */
+    /* fn textureLoad(texture: texture_storage_3d<i32_texel_format, read>, coords: vec3<i32>) -> vec4<i32> */
+    /* fn textureLoad(texture: texture_storage_1d<u32_texel_format, read>, coords: i32) -> vec4<u32> */
+    /* fn textureLoad(texture: texture_storage_2d<u32_texel_format, read>, coords: vec2<i32>) -> vec4<u32> */
+    /* fn textureLoad(texture: texture_storage_2d_array<u32_texel_format, read>, coords: vec2<i32>, array_index: i32) -> vec4<u32> */
+    /* fn textureLoad(texture: texture_storage_3d<u32_texel_format, read>, coords: vec3<i32>) -> vec4<u32> */
+    /* fn textureLoad(texture: texture_external, coords: vec2<i32>) -> vec4<f32> */
+    /* num overloads */ 20,
+    /* overloads */ &kOverloads[25],
+  },
+};
+
+// clang-format on
diff --git a/src/intrinsic_table.inl.tmpl b/src/intrinsic_table.inl.tmpl
new file mode 100644
index 0000000..a6687d5
--- /dev/null
+++ b/src/intrinsic_table.inl.tmpl
@@ -0,0 +1,447 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/intrinsic-gen to generate intrinsic_table.inl
+Used by IntrinsicTable.cc for intrinsic overload resolution.
+
+See:
+* tools/cmd/intrinsic-gen/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+// clang-format off
+
+/// ParameterInfo describes a parameter
+struct ParameterInfo {
+  /// The parameter usage (parameter name in definition file)
+  ParameterUsage const usage;
+
+  /// Pointer to a list of indices that are used to match the parameter type.
+  /// The matcher indices index on Matchers::type and / or Matchers::number.
+  /// These indices are consumed by the matchers themselves.
+  /// The first index is always a TypeMatcher.
+  MatcherIndex const* const matcher_indices;
+};
+
+/// OpenTypeInfo describes an open type
+struct OpenTypeInfo {
+  /// Name of the open type (e.g. 'T')
+  const char* name;
+  /// Optional type matcher constraint.
+  /// Either an index in Matchers::type, or kNoMatcher
+  MatcherIndex const matcher_index;
+};
+
+/// OpenNumberInfo describes an open number
+struct OpenNumberInfo {
+  /// Name of the open number (e.g. 'N')
+  const char* name;
+  /// Optional number matcher constraint.
+  /// Either an index in Matchers::number, or kNoMatcher
+  MatcherIndex const matcher_index;
+};
+
+/// OverloadInfo describes a single function overload
+struct OverloadInfo {
+  /// Total number of parameters for the overload
+  uint8_t const num_parameters;
+  /// Total number of open types for the overload
+  uint8_t const num_open_types;
+  /// Total number of open numbers for the overload
+  uint8_t const num_open_numbers;
+  /// Pointer to the first open type
+  OpenTypeInfo const* const open_types;
+  /// Pointer to the first open number
+  OpenNumberInfo const* const open_numbers;
+  /// Pointer to the first parameter
+  ParameterInfo const* const parameters;
+  /// Pointer to a list of matcher indices that index on Matchers::type and
+  /// Matchers::number, used to build the return type. If the function has no
+  /// return type then this is null.
+  MatcherIndex const* const return_matcher_indices;
+};
+
+/// IntrinsicInfo describes an intrinsic function
+struct IntrinsicInfo {
+  /// Number of overloads of the intrinsic function
+  uint8_t const num_overloads;
+  /// Pointer to the start of the overloads for the function
+  OverloadInfo const* const overloads;
+};
+
+{{  with .Sem -}}
+{{    range .Types -}}
+{{      template "Type" . }}
+{{    end -}}
+{{    range .TypeMatchers -}}
+{{      template "TypeMatcher" . }}
+{{    end -}}
+{{    range .EnumMatchers -}}
+{{      template "EnumMatcher" . }}
+{{    end -}}
+{{- end -}}
+
+{{- with IntrinsicTable -}}
+{{- template "Matchers" . }}
+
+constexpr MatcherIndex kMatcherIndices[] = {
+{{- range $i, $idx := .MatcherIndices }}
+  /* [{{$i}}] */ {{$idx}},
+{{- end }}
+};
+
+// Assert that the MatcherIndex is big enough to index all the matchers, plus
+// kNoMatcher.
+static_assert(static_cast<int>(sizeof(kMatcherIndices) / sizeof(kMatcherIndices[0])) <
+              static_cast<int>(std::numeric_limits<MatcherIndex>::max() - 1),
+              "MatcherIndex is not large enough to index kMatcherIndices");
+
+constexpr ParameterInfo kParameters[] = {
+{{- range $i, $p := .Parameters }}
+  {
+    /* [{{$i}}] */
+    /* usage */ ParameterUsage::
+{{-   if $p.Usage }}k{{PascalCase $p.Usage}}
+{{-   else        }}kNone
+{{-   end         }},
+    /* matcher indices */ &kMatcherIndices[{{$p.MatcherIndicesOffset}}],
+  },
+{{- end }}
+};
+
+constexpr OpenTypeInfo kOpenTypes[] = {
+{{- range $i, $o := .OpenTypes }}
+  {
+    /* [{{$i}}] */
+    /* name */ "{{$o.Name}}",
+    /* matcher index */
+{{-   if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
+{{-   else                    }} kNoMatcher
+{{-   end                     }},
+  },
+{{- end }}
+};
+
+constexpr OpenNumberInfo kOpenNumbers[] = {
+{{- range $i, $o := .OpenNumbers }}
+  {
+    /* [{{$i}}] */
+    /* name */ "{{$o.Name}}",
+    /* matcher index */
+{{-   if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
+{{-   else                    }} kNoMatcher
+{{-   end                     }},
+  },
+{{- end }}
+};
+
+constexpr OverloadInfo kOverloads[] = {
+{{- range $i, $o := .Overloads }}
+  {
+    /* [{{$i}}] */
+    /* num parameters */ {{$o.NumParameters}},
+    /* num open types */ {{$o.NumOpenTypes}},
+    /* num open numbers */ {{$o.NumOpenNumbers}},
+    /* open types */
+{{-   if $o.OpenTypesOffset }} &kOpenTypes[{{$o.OpenTypesOffset}}],
+{{-   else                  }} nullptr,
+{{-   end }}
+    /* open numbers */
+{{-   if $o.OpenNumbersOffset }} &kOpenNumbers[{{$o.OpenNumbersOffset}}]
+{{-   else                    }} nullptr
+{{-   end }},
+    /* parameters */ &kParameters[{{$o.ParametersOffset}}],
+    /* return matcher indices */
+{{-   if $o.ReturnMatcherIndicesOffset }} &kMatcherIndices[{{$o.ReturnMatcherIndicesOffset}}]
+{{-   else                             }} nullptr
+{{-   end }},
+  },
+{{- end }}
+};
+
+constexpr IntrinsicInfo kIntrinsics[] = {
+{{- range $i, $f := .Functions }}
+  {
+    /* [{{$i}}] */
+{{-   range $f.OverloadDescriptions }}
+    /* {{.}} */
+{{-   end }}
+    /* num overloads */ {{$f.NumOverloads}},
+    /* overloads */ &kOverloads[{{$f.OverloadsOffset}}],
+  },
+{{- end }}
+};
+
+// clang-format on
+{{ end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                              define "Type"                               -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{- $class := PascalCase .Name -}}
+/// TypeMatcher for 'type {{.Name}}'
+{{- if .Decl.Source.S.Filepath  }}
+/// @see {{.Decl.Source}}
+{{- end  }}
+class {{$class}} : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
+{{- range .TemplateParams }}
+{{-   template "DeclareLocalTemplateParam" . }}
+{{- end  }}
+  if (!match_{{.Name}}(ty{{range .TemplateParams}}, {{.GetName}}{{end}})) {
+    return nullptr;
+  }
+{{- range .TemplateParams }}
+  {{.Name}} = {{ template "MatchTemplateParam" .}}({{.Name}});
+  if ({{ template "IsTemplateParamInvalid" .}}) {
+    return nullptr;
+  }
+{{- end  }}
+  return build_{{.Name}}(state{{range .TemplateParams}}, {{.GetName}}{{end}});
+}
+
+std::string {{$class}}::String(MatchState&{{if .TemplateParams}} state{{end}}) const {
+{{- range .TemplateParams }}
+{{-   template "DeclareLocalTemplateParamName" . }}
+{{- end  }}
+
+{{- if .DisplayName }}
+  std::stringstream ss;
+  ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
+  return ss.str();
+{{- else if .TemplateParams }}
+  return "{{.Name}}<"{{template "AppendTemplateParamNames" .TemplateParams}} + ">";
+{{- else }}
+  return "{{.Name}}";
+{{- end  }}
+}
+{{  end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                          define "TypeMatcher"                            -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{- $class := PascalCase .Name -}}
+/// TypeMatcher for 'match {{.Name}}'
+{{- if .Decl.Source.S.Filepath  }}
+/// @see {{.Decl.Source}}
+{{- end  }}
+class {{$class}} : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
+{{- range .Types }}
+  if (match_{{.Name}}(ty)) {
+    return build_{{.Name}}(state);
+  }
+{{- end }}
+  return nullptr;
+}
+
+std::string {{$class}}::String(MatchState&) const {
+  return "
+{{- range .Types -}}
+{{-   if      IsFirstIn . $.Types }}{{.Name}}
+{{-   else if IsLastIn  . $.Types }} or {{.Name}}
+{{-   else                        }}, {{.Name}}
+{{- end -}}
+{{- end -}}
+  ";
+}
+{{  end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                          define "EnumMatcher"                            -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{- $class := PascalCase .Name -}}
+{{- $enum := PascalCase .Enum.Name -}}
+/// EnumMatcher for 'match {{.Name}}'
+{{- if .Decl.Source.S.Filepath  }}
+/// @see {{.Decl.Source}}
+{{- end  }}
+class {{$class}} : public NumberMatcher {
+ public:
+  /// Checks whether the given number matches the enum matcher rules.
+  /// Match may close open types and numbers in state.
+  /// @param state the MatchState
+  /// @param number the enum value as a Number
+  /// @return true if the enum value matches the set
+  Number Match(MatchState& state, Number number) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState& state) const override;
+};
+
+{{ if eq 1 (len .Options) -}}
+{{-   $option := index .Options 0 }}
+{{-   $entry := printf "k%v" (PascalCase $option.Name) -}}
+Number {{$class}}::Match(MatchState&, Number number) const {
+  if (number.IsAny() || number.Value() == static_cast<uint32_t>({{$enum}}::{{$entry}})) {
+    return Number({{$enum}}::{{$entry}});
+  }
+  return Number::invalid;
+}
+{{- else -}}
+Number {{$class}}::Match(MatchState&, Number number) const {
+  switch (static_cast<{{$enum}}>(number.Value())) {
+{{-   range .Options }}
+    case {{$enum}}::k{{PascalCase .Name}}:
+{{-   end }}
+      return number;
+    default:
+      return Number::invalid;
+  }
+}
+{{- end }}
+
+std::string {{$class}}::String(MatchState&) const {
+  return "{{.Name}}";
+}
+{{  end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                            define "Matchers"                             -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+/// Matchers holds type and number matchers
+class Matchers {
+ private:
+{{- $t_names := Map -}}
+{{- $n_names := Map -}}
+{{- range Iterate .Sem.MaxOpenTypes -}}
+{{-   $name := printf "open_type_%v" . -}}
+{{-   $t_names.Put . $name }}
+  OpenTypeMatcher {{$name}}_{ {{- . -}} };
+{{- end }}
+{{- range Iterate .Sem.MaxOpenNumbers -}}
+{{-   $name := printf "open_number_%v" . -}}
+{{-   $n_names.Put . $name }}
+  OpenNumberMatcher {{$name}}_{ {{- . -}} };
+{{- end }}
+{{- range .Sem.Types -}}
+{{-   $name := PascalCase .Name -}}
+{{-   $t_names.Put . $name }}
+  {{$name}} {{$name}}_;
+{{- end }}
+{{- range .Sem.TypeMatchers -}}
+{{-   $name := PascalCase .Name -}}
+{{-   $t_names.Put . $name }}
+  {{$name}} {{$name}}_;
+{{- end }}
+{{- range .Sem.EnumMatchers -}}
+{{-   $name := PascalCase .Name -}}
+{{-   $n_names.Put . $name }}
+  {{$name}} {{$name}}_;
+{{- end }}
+
+ public:
+  /// Constructor
+  Matchers();
+  /// Destructor
+  ~Matchers();
+
+  /// The open-types, types, and type matchers
+  TypeMatcher const* const type[{{len .TMatchers}}] = {
+{{- range $i, $m := .TMatchers }}
+    /* [{{$i}}] */
+{{-   if $m }} &{{$t_names.Get $m}}_,
+{{-   else  }} &{{$t_names.Get $i}}_,
+{{-   end   }}
+{{- end }}
+  };
+
+  /// The open-numbers, and number matchers
+  NumberMatcher const* const number[{{len .NMatchers}}] = {
+{{- range $i, $m := .NMatchers }}
+    /* [{{$i}}] */
+{{-   if $m }} &{{$n_names.Get $m}}_,
+{{-   else  }} &{{$n_names.Get $i}}_,
+{{-   end   }}
+{{- end }}
+  };
+};
+
+Matchers::Matchers() = default;
+Matchers::~Matchers() = default;
+{{- end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                     define "DeclareLocalTemplateParam"                   -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-   if      IsTemplateTypeParam . }}
+  const sem::Type* {{.Name}} = nullptr;
+{{-   else if IsTemplateNumberParam . }}
+  Number {{.Name}} = Number::invalid;
+{{-   else if IsTemplateEnumParam . }}
+  Number {{.Name}} = Number::invalid;
+{{-   end -}}
+{{- end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                   define "DeclareLocalTemplateParamName"                 -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-   if      IsTemplateTypeParam . }}
+  const std::string {{.Name}} = state.TypeName();
+{{-   else if IsTemplateNumberParam . }}
+  const std::string {{.Name}} = state.NumName();
+{{-   else if IsTemplateEnumParam . }}
+  const std::string {{.Name}} = state.NumName();
+{{-   end -}}
+{{- end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                       define "MatchTemplateParam"                        -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-   if      IsTemplateTypeParam . -}}
+  state.Type
+{{-   else if IsTemplateNumberParam . -}}
+  state.Num
+{{-   else if IsTemplateEnumParam . -}}
+  state.Num
+{{-   end -}}
+{{- end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                       define "IsTemplateParamInvalid"                    -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-   if      IsTemplateTypeParam . -}}
+  {{.Name}} == nullptr
+{{-   else if IsTemplateNumberParam . -}}
+  !{{.Name}}.IsValid()
+{{-   else if IsTemplateEnumParam . -}}
+  !{{.Name}}.IsValid()
+{{-   end -}}
+{{- end -}}
+
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-                      define "AppendTemplateParamNames"                   -}}
+{{- /* ------------------------------------------------------------------ */ -}}
+{{-   range $i, $ := . -}}
+{{-     if $i }} + ", " + {{.Name}}
+{{-     else }} + {{.Name}}
+{{-     end -}}
+{{-   end -}}
+{{- end -}}
diff --git a/src/intrinsic_table_test.cc b/src/intrinsic_table_test.cc
index 7a9125f..06b7e8b 100644
--- a/src/intrinsic_table_test.cc
+++ b/src/intrinsic_table_test.cc
@@ -35,45 +35,45 @@
 
 class IntrinsicTableTest : public testing::Test, public ProgramBuilder {
  public:
-  std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create();
+  std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create(*this);
 };
 
 TEST_F(IntrinsicTableTest, MatchF32) {
   auto* f32 = create<sem::F32>();
-  auto result = table->Lookup(*this, IntrinsicType::kCos, {f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kCos);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(), ElementsAre(Parameter{f32}));
+  auto* result = table->Lookup(IntrinsicType::kCos, {f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kCos);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(), ElementsAre(Parameter{f32}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchF32) {
   auto* i32 = create<sem::I32>();
-  auto result = table->Lookup(*this, IntrinsicType::kCos, {i32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result = table->Lookup(IntrinsicType::kCos, {i32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchU32) {
   auto* f32 = create<sem::F32>();
   auto* u32 = create<sem::U32>();
   auto* vec2_f32 = create<sem::Vector>(f32, 2);
-  auto result =
-      table->Lookup(*this, IntrinsicType::kUnpack2x16float, {u32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kUnpack2x16float);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec2_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(), ElementsAre(Parameter{u32}));
+  auto* result =
+      table->Lookup(IntrinsicType::kUnpack2x16float, {u32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kUnpack2x16float);
+  EXPECT_THAT(result->ReturnType(), vec2_f32);
+  EXPECT_THAT(result->Parameters(), ElementsAre(Parameter{u32}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchU32) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kUnpack2x16float, {f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kUnpack2x16float, {f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchI32) {
@@ -81,13 +81,13 @@
   auto* i32 = create<sem::I32>();
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {tex, i32, i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureLoad);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec4_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kTextureLoad, {tex, i32, i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureLoad);
+  EXPECT_THAT(result->ReturnType(), vec4_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{i32, ParameterUsage::kCoords},
                           Parameter{i32, ParameterUsage::kLevel}));
@@ -96,146 +96,139 @@
 TEST_F(IntrinsicTableTest, MismatchI32) {
   auto* f32 = create<sem::F32>();
   auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
-  auto result =
-      table->Lookup(*this, IntrinsicType::kTextureLoad, {tex, f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kTextureLoad, {tex, f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchIU32AsI32) {
   auto* i32 = create<sem::I32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kCountOneBits, {i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kCountOneBits);
-  EXPECT_THAT(result.intrinsic->ReturnType(), i32);
-  EXPECT_THAT(result.intrinsic->Parameters(), ElementsAre(Parameter{i32}));
+  auto* result = table->Lookup(IntrinsicType::kCountOneBits, {i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kCountOneBits);
+  EXPECT_THAT(result->ReturnType(), i32);
+  EXPECT_THAT(result->Parameters(), ElementsAre(Parameter{i32}));
 }
 
 TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
   auto* u32 = create<sem::U32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kCountOneBits, {u32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kCountOneBits);
-  EXPECT_THAT(result.intrinsic->ReturnType(), u32);
-  EXPECT_THAT(result.intrinsic->Parameters(), ElementsAre(Parameter{u32}));
+  auto* result = table->Lookup(IntrinsicType::kCountOneBits, {u32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kCountOneBits);
+  EXPECT_THAT(result->ReturnType(), u32);
+  EXPECT_THAT(result->Parameters(), ElementsAre(Parameter{u32}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchIU32) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kCountOneBits, {f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result = table->Lookup(IntrinsicType::kCountOneBits, {f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
   auto* i32 = create<sem::I32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kClamp, {i32, i32, i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kClamp);
-  EXPECT_THAT(result.intrinsic->ReturnType(), i32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {i32, i32, i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kClamp);
+  EXPECT_THAT(result->ReturnType(), i32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{i32}, Parameter{i32}, Parameter{i32}));
 }
 
 TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
   auto* u32 = create<sem::U32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kClamp, {u32, u32, u32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kClamp);
-  EXPECT_THAT(result.intrinsic->ReturnType(), u32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {u32, u32, u32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kClamp);
+  EXPECT_THAT(result->ReturnType(), u32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{u32}, Parameter{u32}, Parameter{u32}));
 }
 
 TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kClamp, {f32, f32, f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kClamp);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {f32, f32, f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kClamp);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{f32}, Parameter{f32}, Parameter{f32}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchFIU32) {
   auto* bool_ = create<sem::Bool>();
-  auto result = table->Lookup(*this, IntrinsicType::kClamp,
-                              {bool_, bool_, bool_}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {bool_, bool_, bool_}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchBool) {
   auto* f32 = create<sem::F32>();
   auto* bool_ = create<sem::Bool>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kSelect, {f32, f32, bool_}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kSelect);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kSelect);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{f32}, Parameter{f32}, Parameter{bool_}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchBool) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kSelect, {f32, f32, f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kSelect, {f32, f32, f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchPointer) {
   auto* f32 = create<sem::F32>();
   auto* ptr = create<sem::Pointer>(f32, ast::StorageClass::kNone);
-  auto result =
-      table->Lookup(*this, IntrinsicType::kModf, {f32, ptr}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kModf);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kModf, {f32, ptr}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kModf);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{f32}, Parameter{ptr}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchPointer) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kModf, {f32, f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result = table->Lookup(IntrinsicType::kModf, {f32, f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchArray) {
   auto* arr = create<sem::Array>(create<sem::U32>(), 0, 4, 4, 4, true);
-  auto result =
-      table->Lookup(*this, IntrinsicType::kArrayLength, {arr}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kArrayLength);
-  EXPECT_TRUE(result.intrinsic->ReturnType()->Is<sem::U32>());
-  ASSERT_EQ(result.intrinsic->Parameters().size(), 1u);
-  EXPECT_TRUE(result.intrinsic->Parameters()[0].type->Is<sem::Array>());
+  auto* result = table->Lookup(IntrinsicType::kArrayLength, {arr}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kArrayLength);
+  EXPECT_TRUE(result->ReturnType()->Is<sem::U32>());
+  ASSERT_EQ(result->Parameters().size(), 1u);
+  EXPECT_TRUE(result->Parameters()[0].type->Is<sem::Array>());
 }
 
 TEST_F(IntrinsicTableTest, MismatchArray) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kArrayLength, {f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result = table->Lookup(IntrinsicType::kArrayLength, {f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchSampler) {
@@ -244,13 +237,13 @@
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
   auto* sampler = create<sem::Sampler>(ast::SamplerKind::kSampler);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureSample,
-                              {tex, sampler, vec2_f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureSample);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec4_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kTextureSample,
+                               {tex, sampler, vec2_f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureSample);
+  EXPECT_THAT(result->ReturnType(), vec4_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{sampler, ParameterUsage::kSampler},
                           Parameter{vec2_f32, ParameterUsage::kCoords}));
@@ -260,10 +253,10 @@
   auto* f32 = create<sem::F32>();
   auto* vec2_f32 = create<sem::Vector>(f32, 2);
   auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureSample,
-                              {tex, f32, vec2_f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result = table->Lookup(IntrinsicType::kTextureSample,
+                               {tex, f32, vec2_f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchSampledTexture) {
@@ -272,13 +265,13 @@
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {tex, vec2_i32, i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureLoad);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec4_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kTextureLoad,
+                               {tex, vec2_i32, i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureLoad);
+  EXPECT_THAT(result->ReturnType(), vec4_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{vec2_i32, ParameterUsage::kCoords},
                           Parameter{i32, ParameterUsage::kLevel}));
@@ -290,13 +283,13 @@
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* tex = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {tex, vec2_i32, i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureLoad);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec4_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kTextureLoad,
+                               {tex, vec2_i32, i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureLoad);
+  EXPECT_THAT(result->ReturnType(), vec4_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{vec2_i32, ParameterUsage::kCoords},
                           Parameter{i32, ParameterUsage::kSampleIndex}));
@@ -307,13 +300,13 @@
   auto* i32 = create<sem::I32>();
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
   auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {tex, vec2_i32, i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureLoad);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kTextureLoad,
+                               {tex, vec2_i32, i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureLoad);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{vec2_i32, ParameterUsage::kCoords},
                           Parameter{i32, ParameterUsage::kLevel}));
@@ -325,13 +318,13 @@
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* tex = create<sem::ExternalTexture>();
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {tex, vec2_i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureLoad);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec4_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kTextureLoad, {tex, vec2_i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureLoad);
+  EXPECT_THAT(result->ReturnType(), vec4_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{vec2_i32, ParameterUsage::kCoords}));
 }
@@ -342,18 +335,18 @@
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* subtype =
-      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR16Float, Types());
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types());
   auto* tex = create<sem::StorageTexture>(ast::TextureDimension::k2d,
-                                          ast::ImageFormat::kR16Float,
+                                          ast::ImageFormat::kR32Float,
                                           ast::AccessControl::kRead, subtype);
 
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {tex, vec2_i32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureLoad);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec4_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kTextureLoad, {tex, vec2_i32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureLoad);
+  EXPECT_THAT(result->ReturnType(), vec4_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{vec2_i32, ParameterUsage::kCoords}));
 }
@@ -364,18 +357,18 @@
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
   auto* vec4_f32 = create<sem::Vector>(f32, 4);
   auto* subtype =
-      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR16Float, Types());
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types());
   auto* tex = create<sem::StorageTexture>(ast::TextureDimension::k2d,
-                                          ast::ImageFormat::kR16Float,
+                                          ast::ImageFormat::kR32Float,
                                           ast::AccessControl::kWrite, subtype);
 
-  auto result = table->Lookup(*this, IntrinsicType::kTextureStore,
-                              {tex, vec2_i32, vec4_f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kTextureStore);
-  EXPECT_TRUE(result.intrinsic->ReturnType()->Is<sem::Void>());
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kTextureStore,
+                               {tex, vec2_i32, vec4_f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kTextureStore);
+  EXPECT_TRUE(result->ReturnType()->Is<sem::Void>());
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{tex, ParameterUsage::kTexture},
                           Parameter{vec2_i32, ParameterUsage::kCoords},
                           Parameter{vec4_f32, ParameterUsage::kValue}));
@@ -385,55 +378,55 @@
   auto* f32 = create<sem::F32>();
   auto* i32 = create<sem::I32>();
   auto* vec2_i32 = create<sem::Vector>(i32, 2);
-  auto result = table->Lookup(*this, IntrinsicType::kTextureLoad,
-                              {f32, vec2_i32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kTextureLoad, {f32, vec2_i32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
   auto* f32 = create<sem::F32>();
-  auto result = table->Lookup(
-      *this, IntrinsicType::kCos,
+  auto* result = table->Lookup(
+      IntrinsicType::kCos,
       {create<sem::Reference>(f32, ast::StorageClass::kNone)}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kCos);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(), ElementsAre(Parameter{f32}));
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kCos);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(), ElementsAre(Parameter{f32}));
 }
 
 TEST_F(IntrinsicTableTest, MatchOpenType) {
   auto* f32 = create<sem::F32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kClamp, {f32, f32, f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kClamp);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {f32, f32, f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kClamp);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{f32}, Parameter{f32}, Parameter{f32}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchOpenType) {
   auto* f32 = create<sem::F32>();
   auto* u32 = create<sem::U32>();
-  auto result =
-      table->Lookup(*this, IntrinsicType::kClamp, {f32, u32, f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {f32, u32, f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
   auto* f32 = create<sem::F32>();
   auto* vec2_f32 = create<sem::Vector>(f32, 2);
-  auto result = table->Lookup(*this, IntrinsicType::kClamp,
-                              {vec2_f32, vec2_f32, vec2_f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kClamp);
-  EXPECT_THAT(result.intrinsic->ReturnType(), vec2_f32);
-  EXPECT_THAT(result.intrinsic->Parameters(),
+  auto* result = table->Lookup(IntrinsicType::kClamp,
+                               {vec2_f32, vec2_f32, vec2_f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kClamp);
+  EXPECT_THAT(result->ReturnType(), vec2_f32);
+  EXPECT_THAT(result->Parameters(),
               ElementsAre(Parameter{vec2_f32}, Parameter{vec2_f32},
                           Parameter{vec2_f32}));
 }
@@ -442,110 +435,106 @@
   auto* f32 = create<sem::F32>();
   auto* u32 = create<sem::U32>();
   auto* vec2_f32 = create<sem::Vector>(f32, 2);
-  auto result = table->Lookup(*this, IntrinsicType::kClamp,
-                              {vec2_f32, u32, vec2_f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kClamp, {vec2_f32, u32, vec2_f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, MatchOpenSizeMatrix) {
   auto* f32 = create<sem::F32>();
   auto* vec3_f32 = create<sem::Vector>(f32, 3);
   auto* mat3_f32 = create<sem::Matrix>(vec3_f32, 3);
-  auto result =
-      table->Lookup(*this, IntrinsicType::kDeterminant, {mat3_f32}, Source{});
-  ASSERT_NE(result.intrinsic, nullptr);
-  ASSERT_EQ(result.diagnostics.str(), "");
-  EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kDeterminant);
-  EXPECT_THAT(result.intrinsic->ReturnType(), f32);
-  EXPECT_THAT(result.intrinsic->Parameters(), ElementsAre(Parameter{mat3_f32}));
+  auto* result =
+      table->Lookup(IntrinsicType::kDeterminant, {mat3_f32}, Source{});
+  ASSERT_NE(result, nullptr) << Diagnostics().str();
+  ASSERT_EQ(Diagnostics().str(), "");
+  EXPECT_THAT(result->Type(), IntrinsicType::kDeterminant);
+  EXPECT_THAT(result->ReturnType(), f32);
+  EXPECT_THAT(result->Parameters(), ElementsAre(Parameter{mat3_f32}));
 }
 
 TEST_F(IntrinsicTableTest, MismatchOpenSizeMatrix) {
   auto* f32 = create<sem::F32>();
   auto* vec2_f32 = create<sem::Vector>(f32, 2);
   auto* mat3x2_f32 = create<sem::Matrix>(vec2_f32, 3);
-  auto result =
-      table->Lookup(*this, IntrinsicType::kDeterminant, {mat3x2_f32}, Source{});
-  ASSERT_EQ(result.intrinsic, nullptr);
-  ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call"));
+  auto* result =
+      table->Lookup(IntrinsicType::kDeterminant, {mat3x2_f32}, Source{});
+  ASSERT_EQ(result, nullptr);
+  ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
 }
 
 TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) {
   // None of the arguments match, so expect the overloads with 2 parameters to
   // come first
   auto* bool_ = create<sem::Bool>();
-  auto result = table->Lookup(*this, IntrinsicType::kTextureDimensions,
-                              {bool_, bool_}, Source{});
-  ASSERT_EQ(result.diagnostics.str(),
+  table->Lookup(IntrinsicType::kTextureDimensions, {bool_, bool_}, Source{});
+  ASSERT_EQ(Diagnostics().str(),
             R"(error: no matching call to textureDimensions(bool, bool)
 
-26 candidate functions:
-  textureDimensions(texture : texture_2d<T>, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_2d_array<T>, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_3d<T>, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_cube<T>, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_cube_array<T>, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_depth_2d, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_depth_2d_array, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_depth_cube, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_depth_cube_array, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_1d<T>) -> i32
-  textureDimensions(texture : texture_2d<T>) -> vec2<i32>
-  textureDimensions(texture : texture_2d_array<T>) -> vec2<i32>
-  textureDimensions(texture : texture_3d<T>) -> vec3<i32>
-  textureDimensions(texture : texture_cube<T>) -> vec3<i32>
-  textureDimensions(texture : texture_cube_array<T>) -> vec3<i32>
-  textureDimensions(texture : texture_multisampled_2d<T>) -> vec2<i32>
-  textureDimensions(texture : texture_multisampled_2d_array<T>) -> vec2<i32>
-  textureDimensions(texture : texture_depth_2d) -> vec2<i32>
-  textureDimensions(texture : texture_depth_2d_array) -> vec2<i32>
-  textureDimensions(texture : texture_depth_cube) -> vec3<i32>
-  textureDimensions(texture : texture_depth_cube_array) -> vec3<i32>
-  textureDimensions(texture : texture_storage_1d<F, A>) -> i32
-  textureDimensions(texture : texture_storage_2d<F, A>) -> vec2<i32>
-  textureDimensions(texture : texture_storage_2d_array<F, A>) -> vec2<i32>
-  textureDimensions(texture : texture_storage_3d<F, A>) -> vec3<i32>
-  textureDimensions(texture : texture_external) -> vec2<i32>
+25 candidate functions:
+  textureDimensions(texture: texture_2d<T>, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_2d_array<T>, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_3d<T>, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_cube<T>, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_cube_array<T>, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_depth_2d, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_depth_2d_array, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_depth_cube, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_depth_cube_array, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_1d<T>) -> i32
+  textureDimensions(texture: texture_2d<T>) -> vec2<i32>
+  textureDimensions(texture: texture_2d_array<T>) -> vec2<i32>
+  textureDimensions(texture: texture_3d<T>) -> vec3<i32>
+  textureDimensions(texture: texture_cube<T>) -> vec3<i32>
+  textureDimensions(texture: texture_cube_array<T>) -> vec3<i32>
+  textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<i32>
+  textureDimensions(texture: texture_depth_2d) -> vec2<i32>
+  textureDimensions(texture: texture_depth_2d_array) -> vec2<i32>
+  textureDimensions(texture: texture_depth_cube) -> vec3<i32>
+  textureDimensions(texture: texture_depth_cube_array) -> vec3<i32>
+  textureDimensions(texture: texture_storage_1d<F, A>) -> i32
+  textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<i32>
+  textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<i32>
+  textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<i32>
+  textureDimensions(texture: texture_external) -> vec2<i32>
 )");
 }
 
 TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) {
   auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
   auto* bool_ = create<sem::Bool>();
-  auto result = table->Lookup(*this, IntrinsicType::kTextureDimensions,
-                              {tex, bool_}, Source{});
+  table->Lookup(IntrinsicType::kTextureDimensions, {tex, bool_}, Source{});
   ASSERT_EQ(
-      result.diagnostics.str(),
+      Diagnostics().str(),
       R"(error: no matching call to textureDimensions(texture_depth_2d, bool)
 
-26 candidate functions:
-  textureDimensions(texture : texture_depth_2d, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_depth_2d) -> vec2<i32>
-  textureDimensions(texture : texture_2d<T>, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_2d_array<T>, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_3d<T>, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_cube<T>, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_cube_array<T>, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_depth_2d_array, level : i32) -> vec2<i32>
-  textureDimensions(texture : texture_depth_cube, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_depth_cube_array, level : i32) -> vec3<i32>
-  textureDimensions(texture : texture_1d<T>) -> i32
-  textureDimensions(texture : texture_2d<T>) -> vec2<i32>
-  textureDimensions(texture : texture_2d_array<T>) -> vec2<i32>
-  textureDimensions(texture : texture_3d<T>) -> vec3<i32>
-  textureDimensions(texture : texture_cube<T>) -> vec3<i32>
-  textureDimensions(texture : texture_cube_array<T>) -> vec3<i32>
-  textureDimensions(texture : texture_multisampled_2d<T>) -> vec2<i32>
-  textureDimensions(texture : texture_multisampled_2d_array<T>) -> vec2<i32>
-  textureDimensions(texture : texture_depth_2d_array) -> vec2<i32>
-  textureDimensions(texture : texture_depth_cube) -> vec3<i32>
-  textureDimensions(texture : texture_depth_cube_array) -> vec3<i32>
-  textureDimensions(texture : texture_storage_1d<F, A>) -> i32
-  textureDimensions(texture : texture_storage_2d<F, A>) -> vec2<i32>
-  textureDimensions(texture : texture_storage_2d_array<F, A>) -> vec2<i32>
-  textureDimensions(texture : texture_storage_3d<F, A>) -> vec3<i32>
-  textureDimensions(texture : texture_external) -> vec2<i32>
+25 candidate functions:
+  textureDimensions(texture: texture_depth_2d, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_depth_2d) -> vec2<i32>
+  textureDimensions(texture: texture_2d<T>, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_2d_array<T>, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_3d<T>, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_cube<T>, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_cube_array<T>, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_depth_2d_array, level: i32) -> vec2<i32>
+  textureDimensions(texture: texture_depth_cube, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_depth_cube_array, level: i32) -> vec3<i32>
+  textureDimensions(texture: texture_1d<T>) -> i32
+  textureDimensions(texture: texture_2d<T>) -> vec2<i32>
+  textureDimensions(texture: texture_2d_array<T>) -> vec2<i32>
+  textureDimensions(texture: texture_3d<T>) -> vec3<i32>
+  textureDimensions(texture: texture_cube<T>) -> vec3<i32>
+  textureDimensions(texture: texture_cube_array<T>) -> vec3<i32>
+  textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<i32>
+  textureDimensions(texture: texture_depth_2d_array) -> vec2<i32>
+  textureDimensions(texture: texture_depth_cube) -> vec3<i32>
+  textureDimensions(texture: texture_depth_cube_array) -> vec3<i32>
+  textureDimensions(texture: texture_storage_1d<F, A>) -> i32
+  textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<i32>
+  textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<i32>
+  textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<i32>
+  textureDimensions(texture: texture_external) -> vec2<i32>
 )");
 }
 
diff --git a/src/resolver/intrinsic_test.cc b/src/resolver/intrinsic_test.cc
index 2633d5f..8c27acf 100644
--- a/src/resolver/intrinsic_test.cc
+++ b/src/resolver/intrinsic_test.cc
@@ -468,8 +468,8 @@
             R"(error: no matching call to select()
 
 2 candidate functions:
-  select(T, T, bool) -> T  where: T is scalar
-  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is scalar
+  select(T, T, bool) -> T  where: T is f32, i32, u32 or bool
+  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is f32, i32, u32 or bool
 )");
 }
 
@@ -483,8 +483,8 @@
             R"(error: no matching call to select(i32, i32, i32)
 
 2 candidate functions:
-  select(T, T, bool) -> T  where: T is scalar
-  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is scalar
+  select(T, T, bool) -> T  where: T is f32, i32, u32 or bool
+  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is f32, i32, u32 or bool
 )");
 }
 
@@ -500,8 +500,8 @@
             R"(error: no matching call to select(mat2x2<f32>, mat2x2<f32>, bool)
 
 2 candidate functions:
-  select(T, T, bool) -> T  where: T is scalar
-  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is scalar
+  select(T, T, bool) -> T  where: T is f32, i32, u32 or bool
+  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is f32, i32, u32 or bool
 )");
 }
 
@@ -515,8 +515,8 @@
             R"(error: no matching call to select(f32, vec2<f32>, bool)
 
 2 candidate functions:
-  select(T, T, bool) -> T  where: T is scalar
-  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is scalar
+  select(T, T, bool) -> T  where: T is f32, i32, u32 or bool
+  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is f32, i32, u32 or bool
 )");
 }
 
@@ -531,8 +531,8 @@
             R"(error: no matching call to select(vec2<f32>, vec3<f32>, bool)
 
 2 candidate functions:
-  select(T, T, bool) -> T  where: T is scalar
-  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is scalar
+  select(T, T, bool) -> T  where: T is f32, i32, u32 or bool
+  select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>  where: T is f32, i32, u32 or bool
 )");
 }
 
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 92be75e..956d091 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -126,7 +126,7 @@
 Resolver::Resolver(ProgramBuilder* builder)
     : builder_(builder),
       diagnostics_(builder->Diagnostics()),
-      intrinsic_table_(IntrinsicTable::Create()) {}
+      intrinsic_table_(IntrinsicTable::Create(*builder)) {}
 
 Resolver::~Resolver() = default;
 
@@ -1694,17 +1694,15 @@
     arg_tys.emplace_back(TypeOf(expr));
   }
 
-  auto result = intrinsic_table_->Lookup(*builder_, intrinsic_type, arg_tys,
-                                         call->source());
-  if (!result.intrinsic) {
-    // Intrinsic lookup failed.
-    diagnostics_.add(result.diagnostics);
+  auto* result =
+      intrinsic_table_->Lookup(intrinsic_type, arg_tys, call->source());
+  if (!result) {
     return false;
   }
 
-  builder_->Sem().Add(call, builder_->create<sem::Call>(call, result.intrinsic,
-                                                        current_statement_));
-  SetType(call, result.intrinsic->ReturnType());
+  builder_->Sem().Add(
+      call, builder_->create<sem::Call>(call, result, current_statement_));
+  SetType(call, result->ReturnType());
   return true;
 }
 
diff --git a/tools/src/cmd/intrinsic-gen/ast/ast.go b/tools/src/cmd/intrinsic-gen/ast/ast.go
index 9299f53..75133d4 100644
--- a/tools/src/cmd/intrinsic-gen/ast/ast.go
+++ b/tools/src/cmd/intrinsic-gen/ast/ast.go
@@ -127,7 +127,7 @@
 // Format implements the fmt.Formatter interface
 func (p Parameter) Format(w fmt.State, verb rune) {
 	if p.Name != "" {
-		fmt.Fprintf(w, "%v ", p.Name)
+		fmt.Fprintf(w, "%v: ", p.Name)
 	}
 	p.Type.Format(w, verb)
 }
diff --git a/tools/src/cmd/intrinsic-gen/gen/generate.go b/tools/src/cmd/intrinsic-gen/gen/generate.go
index a797840..50ad354 100644
--- a/tools/src/cmd/intrinsic-gen/gen/generate.go
+++ b/tools/src/cmd/intrinsic-gen/gen/generate.go
@@ -26,7 +26,10 @@
 )
 
 type generator struct {
-	s *sem.Sem
+	s      *sem.Sem
+	cached struct {
+		intrinsicTable *IntrinsicTable // lazily built by intrinsicTable()
+	}
 }
 
 // Generate executes the template tmpl using the provided semantic
@@ -52,6 +55,7 @@
 			"IsTemplateEnumParam":   is(&sem.TemplateEnumParam{}),
 			"IsFirstIn":             isFirstIn,
 			"IsLastIn":              isLastIn,
+			"IntrinsicTable":        g.intrinsicTable,
 		}).
 		Option("missingkey=error").
 		Parse(tmpl)
@@ -63,6 +67,19 @@
 	})
 }
 
+// intrinsicTable lazily calls and returns the result of buildIntrinsicTable(),
+// caching the result for repeated calls.
+func (g *generator) intrinsicTable() (*IntrinsicTable, error) {
+	if g.cached.intrinsicTable == nil {
+		var err error
+		g.cached.intrinsicTable, err = buildIntrinsicTable(g.s)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return g.cached.intrinsicTable, nil
+}
+
 // Map is a simple generic key-value map, which can be used in the template
 type Map map[interface{}]interface{}
 
diff --git a/tools/src/cmd/intrinsic-gen/gen/intrinsic_table.go b/tools/src/cmd/intrinsic-gen/gen/intrinsic_table.go
new file mode 100644
index 0000000..e5c7244
--- /dev/null
+++ b/tools/src/cmd/intrinsic-gen/gen/intrinsic_table.go
@@ -0,0 +1,381 @@
+// Copyright 2021 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package gen
+
+import (
+	"fmt"
+
+	"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/sem"
+	"dawn.googlesource.com/tint/tools/src/list"
+	"dawn.googlesource.com/tint/tools/src/lut"
+)
+
+// IntrinsicTable holds data specific to the intrinsic_table.inl.tmpl template
+type IntrinsicTable struct {
+	// The semantic info
+	Sem *sem.Sem
+
+	// TMatchers are all the sem.OpenType, sem.Type and sem.TypeMatchers.
+	// These are all implemented by classes deriving from tint::TypeMatcher
+	TMatchers     []sem.Named
+	TMatcherIndex map[sem.Named]int // [object -> index] in TMatcher
+
+	// NMatchers are all the sem.OpenNumber and sem.EnumMatchers.
+	// These are all implemented by classes deriving from tint::NumberMatcher
+	NMatchers     []sem.Named
+	NMatcherIndex map[sem.Named]int // [object -> index] in NMatchers
+
+	MatcherIndices []int        // kMatcherIndices table content
+	OpenTypes      []OpenType   // kOpenTypes table content
+	OpenNumbers    []OpenNumber // kOpenNumbers table content
+	Parameters     []Parameter  // kParameters table content
+	Overloads      []Overload   // kOverloads table content
+	Functions      []Function   // kIntrinsics table content
+}
+
+// OpenType is used to create the C++ OpenTypeInfo structure
+type OpenType struct {
+	// Name of the open type (e.g. 'T')
+	Name string
+	// Optional type matcher constraint.
+	// Either an index in Matchers::type, or -1
+	MatcherIndex int
+}
+
+// OpenNumber is used to create the C++ OpenNumberInfo structure
+type OpenNumber struct {
+	// Name of the open number (e.g. 'N')
+	Name string
+	// Optional type matcher constraint.
+	// Either an index in Matchers::type, or -1
+	MatcherIndex int
+}
+
+// Parameter is used to create the C++ ParameterInfo structure
+type Parameter struct {
+	// The parameter usage (parameter name)
+	Usage string
+
+	// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
+	// required to match the parameter type. The matcher indices index
+	// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
+	// These indices are consumed by the matchers themselves.
+	// The first index is always a TypeMatcher.
+	MatcherIndicesOffset *int
+}
+
+// Overload is used to create the C++ OverloadInfo structure
+type Overload struct {
+	// Total number of parameters for the overload
+	NumParameters int
+	// Total number of open types for the overload
+	NumOpenTypes int
+	// Total number of open numbers for the overload
+	NumOpenNumbers int
+	// Index to the first open type in IntrinsicTable.OpenTypes
+	OpenTypesOffset *int
+	// Index to the first open number in IntrinsicTable.OpenNumbers
+	OpenNumbersOffset *int
+	// Index to the first parameter in IntrinsicTable.Parameters
+	ParametersOffset *int
+	// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
+	// required to match the return type. The matcher indices index
+	// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
+	// These indices are consumed by the matchers themselves.
+	// The first index is always a TypeMatcher.
+	ReturnMatcherIndicesOffset *int
+}
+
+// Function is used to create the C++ IntrinsicInfo structure
+type Function struct {
+	OverloadDescriptions []string
+	NumOverloads         int
+	OverloadsOffset      *int
+}
+
+// Helper for building the IntrinsicTable
+type intrinsicTableBuilder struct {
+	// The output of the builder
+	IntrinsicTable
+
+	// Lookup tables.
+	// These are packed (compressed) once all the entries have been added.
+	lut struct {
+		matcherIndices lut.LUT
+		openTypes      lut.LUT
+		openNumbers    lut.LUT
+		parameters     lut.LUT
+		overloads      lut.LUT
+	}
+}
+
+// Helper for building a single overload
+type overloadBuilder struct {
+	*intrinsicTableBuilder
+	// Maps TemplateParam to index in openTypes
+	openTypeIndex map[sem.TemplateParam]int
+	// Maps TemplateParam to index in openNumbers
+	openNumberIndex map[sem.TemplateParam]int
+	// Open types used by the overload
+	openTypes []OpenType
+	// Open numbers used by the overload
+	openNumbers []OpenNumber
+	// All parameters declared by the overload
+	parameters []Parameter
+	// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
+	// required to match the return type. The matcher indices index
+	// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
+	// These indices are consumed by the matchers themselves.
+	// The first index is always a TypeMatcher.
+	returnTypeMatcherIndicesOffset *int
+}
+
+// layoutMatchers assigns each of the TMatchers and NMatchers a unique index
+// in the C++ Matchers::type and Matchers::number arrays, respectively.
+func (b *intrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
+	// First MaxOpenTypes of TMatchers are open types
+	b.TMatchers = make([]sem.Named, s.MaxOpenTypes)
+	for _, m := range s.Types {
+		b.TMatcherIndex[m] = len(b.TMatchers)
+		b.TMatchers = append(b.TMatchers, m)
+	}
+	for _, m := range s.TypeMatchers {
+		b.TMatcherIndex[m] = len(b.TMatchers)
+		b.TMatchers = append(b.TMatchers, m)
+	}
+
+	// First MaxOpenNumbers of NMatchers are open numbers
+	b.NMatchers = make([]sem.Named, s.MaxOpenNumbers)
+	for _, m := range s.EnumMatchers {
+		b.NMatcherIndex[m] = len(b.NMatchers)
+		b.NMatchers = append(b.NMatchers, m)
+	}
+}
+
+// buildOverload constructs an Overload for a sem.Overload
+func (b *intrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error) {
+	ob := overloadBuilder{
+		intrinsicTableBuilder: b,
+		openTypeIndex:         map[sem.TemplateParam]int{},
+		openNumberIndex:       map[sem.TemplateParam]int{},
+	}
+
+	if err := ob.buildOpenTypes(o); err != nil {
+		return Overload{}, err
+	}
+	if err := ob.buildOpenNumbers(o); err != nil {
+		return Overload{}, err
+	}
+	if err := ob.buildParameters(o); err != nil {
+		return Overload{}, err
+	}
+	if err := ob.buildReturnType(o); err != nil {
+		return Overload{}, err
+	}
+
+	return Overload{
+		NumParameters:              len(ob.parameters),
+		NumOpenTypes:               len(ob.openTypes),
+		NumOpenNumbers:             len(ob.openNumbers),
+		OpenTypesOffset:            b.lut.openTypes.Add(ob.openTypes),
+		OpenNumbersOffset:          b.lut.openNumbers.Add(ob.openNumbers),
+		ParametersOffset:           b.lut.parameters.Add(ob.parameters),
+		ReturnMatcherIndicesOffset: ob.returnTypeMatcherIndicesOffset,
+	}, nil
+}
+
+// buildOpenTypes constructs the OpenTypes used by the overload, populating
+// b.openTypes
+func (b *overloadBuilder) buildOpenTypes(o *sem.Overload) error {
+	b.openTypes = make([]OpenType, len(o.OpenTypes))
+	for i, t := range o.OpenTypes {
+		b.openTypeIndex[t] = i
+		matcherIndex := -1
+		if t.Type != nil {
+			var err error
+			matcherIndex, err = b.matcherIndex(t.Type)
+			if err != nil {
+				return err
+			}
+		}
+		b.openTypes[i] = OpenType{
+			Name:         t.Name,
+			MatcherIndex: matcherIndex,
+		}
+	}
+	return nil
+}
+
+// buildOpenNumbers constructs the OpenNumbers used by the overload, populating
+// b.openNumbers
+func (b *overloadBuilder) buildOpenNumbers(o *sem.Overload) error {
+	b.openNumbers = make([]OpenNumber, len(o.OpenNumbers))
+	for i, t := range o.OpenNumbers {
+		b.openNumberIndex[t] = i
+		matcherIndex := -1
+		if e, ok := t.(*sem.TemplateEnumParam); ok && e.Matcher != nil {
+			var err error
+			matcherIndex, err = b.matcherIndex(e.Matcher)
+			if err != nil {
+				return err
+			}
+		}
+		b.openNumbers[i] = OpenNumber{
+			Name:         t.GetName(),
+			MatcherIndex: matcherIndex,
+		}
+	}
+	return nil
+}
+
+// buildParameters constructs the Parameters used by the overload, populating
+// b.parameters
+func (b *overloadBuilder) buildParameters(o *sem.Overload) error {
+	b.parameters = make([]Parameter, len(o.Parameters))
+	for i, p := range o.Parameters {
+		indices, err := b.collectMatcherIndices(p.Type)
+		if err != nil {
+			return err
+		}
+
+		b.parameters[i] = Parameter{
+			Usage:                p.Name,
+			MatcherIndicesOffset: b.lut.matcherIndices.Add(indices),
+		}
+	}
+	return nil
+}
+
+// buildParameters calculates the matcher indices required to match the
+// overload's return type (if the overload has a return value), possibly
+// populating b.returnTypeMatcherIndicesOffset
+func (b *overloadBuilder) buildReturnType(o *sem.Overload) error {
+	if o.ReturnType != nil {
+		indices, err := b.collectMatcherIndices(*o.ReturnType)
+		if err != nil {
+			return err
+		}
+		b.returnTypeMatcherIndicesOffset = b.lut.matcherIndices.Add(indices)
+	}
+	return nil
+}
+
+// matcherIndex returns the index of TMatcher or NMatcher in
+// IntrinsicTable.TMatcher or IntrinsicTable.NMatcher, respectively.
+func (b *overloadBuilder) matcherIndex(n sem.Named) (int, error) {
+	switch n := n.(type) {
+	case *sem.Type, *sem.TypeMatcher:
+		if i, ok := b.TMatcherIndex[n]; ok {
+			return i, nil
+		}
+		return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
+	case *sem.TemplateTypeParam:
+		if i, ok := b.openTypeIndex[n]; ok {
+			return i, nil
+		}
+		return 0, fmt.Errorf("openTypeIndex missing entry for %v %T", n.Name, n)
+	case *sem.EnumMatcher:
+		if i, ok := b.NMatcherIndex[n]; ok {
+			return i, nil
+		}
+		return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
+	case *sem.TemplateEnumParam:
+		if i, ok := b.openNumberIndex[n]; ok {
+			return i, nil
+		}
+		return 0, fmt.Errorf("openNumberIndex missing entry for %v %T", n, n)
+	case *sem.TemplateNumberParam:
+		if i, ok := b.openNumberIndex[n]; ok {
+			return i, nil
+		}
+		return 0, fmt.Errorf("openNumberIndex missing entry for %v %T", n, n)
+	default:
+		return 0, fmt.Errorf("overload.matcherIndex() does not handle %v %T", n, n)
+	}
+}
+
+// collectMatcherIndices returns the full list of matcher indices required to
+// match the fully-qualified-name. For names that have do not have templated
+// arguments, collectMatcherIndices() will return a single TMatcher index.
+// For names that do have templated arguments, collectMatcherIndices() returns
+// a list of type matcher indices, starting with the target of the fully
+// qualified name, then followed by each of the template arguments from left to
+// right. Note that template arguments may themselves have template arguments,
+// and so collectMatcherIndices() may call itself.
+// The order of returned matcher indices is always the order of the fully
+// qualified name as read from left to right.
+// For example, calling collectMatcherIndices() for the fully qualified name:
+//    A<B<C, D>, E<F, G<H>, I>
+// Would return the matcher indices:
+//    A, B, C, D, E, F, G, H, I
+func (b *overloadBuilder) collectMatcherIndices(fqn sem.FullyQualifiedName) ([]int, error) {
+	idx, err := b.matcherIndex(fqn.Target)
+	if err != nil {
+		return nil, err
+	}
+	out := []int{idx}
+	for _, arg := range fqn.TemplateArguments {
+		indices, err := b.collectMatcherIndices(arg)
+		if err != nil {
+			return nil, err
+		}
+		out = append(out, indices...)
+	}
+	return out, nil
+}
+
+// buildIntrinsicTable builds the IntrinsicTable from the semantic info
+func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
+	b := intrinsicTableBuilder{
+		IntrinsicTable: IntrinsicTable{
+			Sem:           s,
+			TMatcherIndex: map[sem.Named]int{},
+			NMatcherIndex: map[sem.Named]int{},
+		},
+	}
+	b.lut.matcherIndices = lut.New(list.Wrap(&b.MatcherIndices))
+	b.lut.openTypes = lut.New(list.Wrap(&b.OpenTypes))
+	b.lut.openNumbers = lut.New(list.Wrap(&b.OpenNumbers))
+	b.lut.parameters = lut.New(list.Wrap(&b.Parameters))
+	b.lut.overloads = lut.New(list.Wrap(&b.Overloads))
+
+	b.layoutMatchers(s)
+
+	for _, f := range s.Functions {
+		overloads := make([]Overload, len(f.Overloads))
+		overloadDescriptions := make([]string, len(f.Overloads))
+		for i, o := range f.Overloads {
+			overloadDescriptions[i] = fmt.Sprint(o.Decl)
+			var err error
+			if overloads[i], err = b.buildOverload(o); err != nil {
+				return nil, err
+			}
+		}
+
+		b.Functions = append(b.Functions, Function{
+			OverloadDescriptions: overloadDescriptions,
+			NumOverloads:         len(overloads),
+			OverloadsOffset:      b.lut.overloads.Add(overloads),
+		})
+	}
+
+	b.lut.matcherIndices.Compact()
+	b.lut.openTypes.Compact()
+	b.lut.openNumbers.Compact()
+	b.lut.parameters.Compact()
+	b.lut.overloads.Compact()
+
+	return &b.IntrinsicTable, nil
+}
diff --git a/tools/src/cmd/intrinsic-gen/main.go b/tools/src/cmd/intrinsic-gen/main.go
index 51dc799..8271fc1 100644
--- a/tools/src/cmd/intrinsic-gen/main.go
+++ b/tools/src/cmd/intrinsic-gen/main.go
@@ -32,6 +32,8 @@
 	"dawn.googlesource.com/tint/tools/src/glob"
 )
 
+const defProjectRelPath = "src/intrinsics.def"
+
 func main() {
 	if err := run(); err != nil {
 		fmt.Println(err)
@@ -58,7 +60,7 @@
 func run() error {
 	// Load the intrinsics definition file
 	projectRoot := fileutils.ProjectRoot()
-	defPath := filepath.Join(projectRoot, "src/intrinsics.def")
+	defPath := filepath.Join(projectRoot, defProjectRelPath)
 
 	defSource, err := ioutil.ReadFile(defPath)
 	if err != nil {
@@ -66,7 +68,7 @@
 	}
 
 	// Parse the definition file to produce an AST
-	ast, err := parser.Parse(string(defSource), defPath)
+	ast, err := parser.Parse(string(defSource), defProjectRelPath)
 	if err != nil {
 		return err
 	}