Combine generated enums to single file in wgsl/

In wgsl/ instead of creating individual files for each of the enum types
(resulting in 6 files per enum) create a single `enums` set of files
which generates all of the enums.

Change-Id: Ide75b1e9004123a7938ae60dcc3da14735765795
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/248814
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/docs/tint/intrinsic_definition_files.md b/docs/tint/intrinsic_definition_files.md
index a450ad9..c73a984 100644
--- a/docs/tint/intrinsic_definition_files.md
+++ b/docs/tint/intrinsic_definition_files.md
@@ -42,7 +42,7 @@
 ```
 
 These enum declarations can be used by templates to generate an equivalent C++ enum, along with a parser and printer helper method, using the helper template [`src/tint/utils/templates/enums.tmpl.inc`](../../src/tint/utils/templates/enums.tmpl.inc). \
-See [`src/tint/lang/wgsl/extension.h.tmpl`](../../src/tint/lang/wgsl/extension.h.tmpl) as an example.
+See [`src/tint/lang/wgsl/enums.h.tmpl`](../../src/tint/lang/wgsl/enums.h.tmpl) as an example.
 
 Enum declarations can also be used as constraints on type template parameters and overload template parameters.
 
diff --git a/src/dawn/native/Instance.h b/src/dawn/native/Instance.h
index f0b8074..073c49f 100644
--- a/src/dawn/native/Instance.h
+++ b/src/dawn/native/Instance.h
@@ -50,7 +50,7 @@
 #include "dawn/native/Toggles.h"
 #include "dawn/native/dawn_platform.h"
 #include "partition_alloc/pointers/raw_ptr.h"
-#include "tint/lang/wgsl/language_feature.h"
+#include "tint/lang/wgsl/enums.h"
 
 namespace dawn::platform {
 class Platform;
diff --git a/src/dawn/wire/client/Instance.cpp b/src/dawn/wire/client/Instance.cpp
index cb05b77..8a549db 100644
--- a/src/dawn/wire/client/Instance.cpp
+++ b/src/dawn/wire/client/Instance.cpp
@@ -39,8 +39,8 @@
 #include "dawn/wire/client/EventManager.h"
 #include "dawn/wire/client/webgpu.h"
 #include "partition_alloc/pointers/raw_ptr.h"
+#include "tint/lang/wgsl/enums.h"
 #include "tint/lang/wgsl/feature_status.h"
-#include "tint/lang/wgsl/language_feature.h"
 
 namespace dawn::wire::client {
 namespace {
diff --git a/src/tint/cmd/bench/BUILD.bazel b/src/tint/cmd/bench/BUILD.bazel
index 37c9d84..e6ce020 100644
--- a/src/tint/cmd/bench/BUILD.bazel
+++ b/src/tint/cmd/bench/BUILD.bazel
@@ -42,10 +42,8 @@
   srcs = [
     "bench.cc",
     "bench.h",
-    "diagnostic_rule_bench.cc",
-    "diagnostic_severity_bench.cc",
     "enums_core_bench.cc",
-    "extension_bench.cc",
+    "enums_wgsl_bench.cc",
     "validator_bench.cc",
   ],
   deps = [
diff --git a/src/tint/cmd/bench/BUILD.cmake b/src/tint/cmd/bench/BUILD.cmake
index fc55af0..308d1b9 100644
--- a/src/tint/cmd/bench/BUILD.cmake
+++ b/src/tint/cmd/bench/BUILD.cmake
@@ -125,10 +125,8 @@
 tint_add_target(tint_cmd_bench_bench bench
   cmd/bench/bench.cc
   cmd/bench/bench.h
-  cmd/bench/diagnostic_rule_bench.cc
-  cmd/bench/diagnostic_severity_bench.cc
   cmd/bench/enums_core_bench.cc
-  cmd/bench/extension_bench.cc
+  cmd/bench/enums_wgsl_bench.cc
   cmd/bench/validator_bench.cc
 )
 
diff --git a/src/tint/cmd/bench/BUILD.gn b/src/tint/cmd/bench/BUILD.gn
index 74e4bcf..534862e 100644
--- a/src/tint/cmd/bench/BUILD.gn
+++ b/src/tint/cmd/bench/BUILD.gn
@@ -48,10 +48,8 @@
       sources = [
         "bench.cc",
         "bench.h",
-        "diagnostic_rule_bench.cc",
-        "diagnostic_severity_bench.cc",
         "enums_core_bench.cc",
-        "extension_bench.cc",
+        "enums_wgsl_bench.cc",
         "validator_bench.cc",
       ]
       deps = [
diff --git a/src/tint/cmd/bench/diagnostic_rule_bench.cc b/src/tint/cmd/bench/diagnostic_rule_bench.cc
deleted file mode 100644
index edb08ec..0000000
--- a/src/tint/cmd/bench/diagnostic_rule_bench.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/cmd/bench/diagnostic_rule_bench.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-
-#include <array>
-
-#include "benchmark/benchmark.h"
-
-namespace tint::wgsl {
-namespace {
-
-void CoreDiagnosticRuleParser(::benchmark::State& state) {
-    const char* kStrings[] = {
-        "deriative_unccformity",   "dlivative_3iformiy",    "derivative_uniforVity",
-        "derivative_uniformity",   "derivative_uniform1ty", "derivativeJunifqrmity",
-        "derivative_unifllrmit77", "subgopppqquniformitHH", "subgrou_cformity",
-        "subgGoup_unifombty",      "subgroup_uniformity",   "suvgroup_uniformiiiy",
-        "subgroWWp8uniformity",    "subgroup_uifoxxmiMy",
-    };
-    for (auto _ : state) {
-        for (auto* str : kStrings) {
-            auto result = ParseCoreDiagnosticRule(str);
-            benchmark::DoNotOptimize(result);
-        }
-    }
-}  // NOLINT(readability/fn_size)
-
-BENCHMARK(CoreDiagnosticRuleParser);
-
-void ChromiumDiagnosticRuleParser(::benchmark::State& state) {
-    const char* kStrings[] = {
-        "sbgroup_ggatrix_uniformXty",
-        "suVroup_matrx_uniforXitu",
-        "subgroup_ma3rix_uniformity",
-        "subgroup_matrix_uniformity",
-        "subgroup_matrix_uniformitE",
-        "subgroup_atrix_uniTTPormity",
-        "suxxdgroup_matri_uniformity",
-        "44nreachable_code",
-        "unreaVVhabSSe_code",
-        "unre22chabR_Rode",
-        "unreachable_code",
-        "nFeachable_9ode",
-        "unrachable_code",
-        "VnreacaRRlH_OOode",
-    };
-    for (auto _ : state) {
-        for (auto* str : kStrings) {
-            auto result = ParseChromiumDiagnosticRule(str);
-            benchmark::DoNotOptimize(result);
-        }
-    }
-}  // NOLINT(readability/fn_size)
-
-BENCHMARK(ChromiumDiagnosticRuleParser);
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/cmd/bench/diagnostic_severity_bench.cc b/src/tint/cmd/bench/diagnostic_severity_bench.cc
deleted file mode 100644
index 87d88ba..0000000
--- a/src/tint/cmd/bench/diagnostic_severity_bench.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/cmd/bench/diagnostic_severity_bench.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
-
-#include <array>
-
-#include "benchmark/benchmark.h"
-
-namespace tint::wgsl {
-namespace {
-
-void DiagnosticSeverityParser(::benchmark::State& state) {
-    const char* kStrings[] = {
-        "erccr",    "3o",        "eVror",   "error",   "erro1",  "qqrJr",  "errll7r",
-        "ppqnfH",   "c",         "iGf",     "info",    "invii",  "inWWo",  "Mxxo",
-        "ogg",      "X",         "3ff",     "off",     "oEf",    "oPTT",   "dxxf",
-        "w44rning", "waSSniVVg", "RarR22g", "warning", "wFni9g", "waring", "VOORRHng",
-    };
-    for (auto _ : state) {
-        for (auto* str : kStrings) {
-            auto result = ParseDiagnosticSeverity(str);
-            benchmark::DoNotOptimize(result);
-        }
-    }
-}  // NOLINT(readability/fn_size)
-
-BENCHMARK(DiagnosticSeverityParser);
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/cmd/bench/diagnostic_severity_bench.cc.tmpl b/src/tint/cmd/bench/diagnostic_severity_bench.cc.tmpl
deleted file mode 100644
index a925938..0000000
--- a/src/tint/cmd/bench/diagnostic_severity_bench.cc.tmpl
+++ /dev/null
@@ -1,26 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control_bench.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
-
-#include <array>
-
-#include "benchmark/benchmark.h"
-
-namespace tint::wgsl {
-namespace {
-
-{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "diagnostic_severity")}}
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/cmd/bench/enums_wgsl_bench.cc b/src/tint/cmd/bench/enums_wgsl_bench.cc
new file mode 100644
index 0000000..4116024
--- /dev/null
+++ b/src/tint/cmd/bench/enums_wgsl_bench.cc
@@ -0,0 +1,195 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by 'tools/src/cmd/gen' using the template:
+//   src/tint/cmd/bench/enums_wgsl_bench.cc.tmpl
+//
+// To regenerate run: './tools/run gen'
+//
+//                       Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+#include <array>
+
+#include "benchmark/benchmark.h"
+#include "src/tint/lang/wgsl/enums.h"
+
+namespace tint::wgsl {
+namespace {
+
+void CoreDiagnosticRuleParser(::benchmark::State& state) {
+    const char* kStrings[] = {
+        "deriative_unccformity",   "dlivative_3iformiy",    "derivative_uniforVity",
+        "derivative_uniformity",   "derivative_uniform1ty", "derivativeJunifqrmity",
+        "derivative_unifllrmit77", "subgopppqquniformitHH", "subgrou_cformity",
+        "subgGoup_unifombty",      "subgroup_uniformity",   "suvgroup_uniformiiiy",
+        "subgroWWp8uniformity",    "subgroup_uifoxxmiMy",
+    };
+    for (auto _ : state) {
+        for (auto* str : kStrings) {
+            auto result = ParseCoreDiagnosticRule(str);
+            benchmark::DoNotOptimize(result);
+        }
+    }
+}  // NOLINT(readability/fn_size)
+
+BENCHMARK(CoreDiagnosticRuleParser);
+void ChromiumDiagnosticRuleParser(::benchmark::State& state) {
+    const char* kStrings[] = {
+        "sbgroup_ggatrix_uniformXty",
+        "suVroup_matrx_uniforXitu",
+        "subgroup_ma3rix_uniformity",
+        "subgroup_matrix_uniformity",
+        "subgroup_matrix_uniformitE",
+        "subgroup_atrix_uniTTPormity",
+        "suxxdgroup_matri_uniformity",
+        "44nreachable_code",
+        "unreaVVhabSSe_code",
+        "unre22chabR_Rode",
+        "unreachable_code",
+        "nFeachable_9ode",
+        "unrachable_code",
+        "VnreacaRRlH_OOode",
+    };
+    for (auto _ : state) {
+        for (auto* str : kStrings) {
+            auto result = ParseChromiumDiagnosticRule(str);
+            benchmark::DoNotOptimize(result);
+        }
+    }
+}  // NOLINT(readability/fn_size)
+
+BENCHMARK(ChromiumDiagnosticRuleParser);
+void DiagnosticSeverityParser(::benchmark::State& state) {
+    const char* kStrings[] = {
+        "rryr",   "n77rrlrGr", "erro40",   "error",   "oor",    "erzz",     "1ippor",
+        "XXnfo",  "55nII9nn",  "iSSfHHaa", "info",    "kk",     "gRR",      "ib",
+        "ojf",    "of",        "q",        "off",     "oNN",    "ov",       "Qff",
+        "waffir", "warnijg",   "wNNwnin8", "warning", "waring", "wrrrning", "Garning",
+    };
+    for (auto _ : state) {
+        for (auto* str : kStrings) {
+            auto result = ParseDiagnosticSeverity(str);
+            benchmark::DoNotOptimize(result);
+        }
+    }
+}  // NOLINT(readability/fn_size)
+
+BENCHMARK(DiagnosticSeverityParser);
+void ExtensionParser(::benchmark::State& state) {
+    const char* kStrings[] = {
+        "chromium_disable_uniformity_analyFFis",
+        "chromium_diEabl_uniformty_analyis",
+        "crrromium_diable_uniformity_analysis",
+        "chromium_disable_uniformity_analysis",
+        "chromiumdisabl_uniformity_analysis",
+        "chromium_JJXDabe_uniformity_analysis",
+        "8hromium_isable_uiformiy_analysis",
+        "chromium_experim1kntalfamebufer_fetch",
+        "chromium_experimentalframebuffer_fetch",
+        "chJomium_experimental_framebuffer_fetc",
+        "chromium_experimental_framebuffer_fetch",
+        "chromium_experimencal_framebuffer_fetch",
+        "chromium_experimental_Oramebuffer_fetch",
+        "chrttmium_experimental_fv__amebuffer_KKetch",
+        "chromium_experim5ntal8immxdiate",
+        "chromi__m_experimntal_imqqeiaFe",
+        "chromqqum_experimenal_immediate",
+        "chromium_experimental_immediate",
+        "33hroium_experimental_66mmeOiate",
+        "9hromiuQQ_e6perimental_immedttaooe",
+        "66romium_experimental_immediate",
+        "chrmiuO_exp66rimentalzzpixxl_local",
+        "chromium_experimental_yyixel_local",
+        "hromiZ_experimZnHHal_pixel_local",
+        "chromium_experimental_pixel_local",
+        "chromium_e44peimental_WWixel_qocal",
+        "chromiu_experimenOOal_pixel_local",
+        "chromYum_expoorienal_pihel_local",
+        "chromium_expermental_sbgrop_matrix",
+        "chromim_experimentaF_subgroup_matrix",
+        "hromium_experimenwal_subgroup_matrix",
+        "chromium_experimental_subgroup_matrix",
+        "GhromiKmexfferimental_subgrup_matrix",
+        "chrqmium_experimenKKal_subgroup_matrix",
+        "chFomi3m_experimental_subgrmmup_matrix",
+        "chromium_internal_grapite",
+        "chromium_nternal_graphitq",
+        "hromium_internab_grapbbite",
+        "chromium_internal_graphite",
+        "chromiuminternaii_graphit",
+        "chromiOOm_internl_gqaphite",
+        "TThromiuvv_internal_graphite",
+        "chFFomium_internal_input_attachments",
+        "chrofiuP_i00ternal_Qnputattachments",
+        "chromium_internal_input_attacPments",
+        "chromium_internal_input_attachments",
+        "chromium_internal_isspu77_atachments",
+        "chromium_internbbl_inpuC_attaRRhments",
+        "chromiumXXinternal_input_attachments",
+        "clip_qisancCCOOO",
+        "clis_distnueL",
+        "cXip_distances",
+        "clip_distances",
+        "clip_distanes",
+        "cqqiO_istces",
+        "clip_22istances",
+        "du0XX_szzurce_bleydin",
+        "dual_Porce_VVleiding",
+        "dual_souce_blCndnnng",
+        "dual_source_blending",
+        "ual_sourcHHqqbledinAA",
+        "dual_source_lending",
+        "dual_sourcKKfblendi",
+        "gg",
+        "f1",
+        "NT46",
+        "f16",
+        "pl16",
+        "gN1",
+        "uXXb",
+        "subgoups",
+        "Qg88oupK",
+        "su9roqps",
+        "subgroups",
+        "subgrou11s",
+        "suiiF22ups",
+        "s77broups",
+    };
+    for (auto _ : state) {
+        for (auto* str : kStrings) {
+            auto result = ParseExtension(str);
+            benchmark::DoNotOptimize(result);
+        }
+    }
+}  // NOLINT(readability/fn_size)
+
+BENCHMARK(ExtensionParser);
+
+}  // namespace
+}  // namespace tint::wgsl
diff --git a/src/tint/cmd/bench/diagnostic_rule_bench.cc.tmpl b/src/tint/cmd/bench/enums_wgsl_bench.cc.tmpl
similarity index 66%
rename from src/tint/cmd/bench/diagnostic_rule_bench.cc.tmpl
rename to src/tint/cmd/bench/enums_wgsl_bench.cc.tmpl
index cf1b20f..6c77ad2 100644
--- a/src/tint/cmd/bench/diagnostic_rule_bench.cc.tmpl
+++ b/src/tint/cmd/bench/enums_wgsl_bench.cc.tmpl
@@ -1,6 +1,9 @@
 {{- /*
 --------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control_bench.cc
+Template file for use with tools/src/cmd/gen to generate enums_wgsl_bench.cc
+
+To update the generated file, run:
+    ./tools/run gen
 
 See:
 * tools/src/cmd/gen for structures used by this template
@@ -11,18 +14,18 @@
 {{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
 {{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
 
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-
 #include <array>
 
 #include "benchmark/benchmark.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 namespace tint::wgsl {
 namespace {
 
-{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "core_diagnostic_rule")}}
-
-{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "chromium_diagnostic_rule")}}
+{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "core_diagnostic_rule") }}
+{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "chromium_diagnostic_rule") }}
+{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "diagnostic_severity") }}
+{{ Eval "BenchmarkParseEnum" ($I.Sem.Enum "extension") }}
 
 }  // namespace
-}  // namespace tint::wgsl
+}  // namespace tint::core
diff --git a/src/tint/cmd/bench/extension_bench.cc b/src/tint/cmd/bench/extension_bench.cc
deleted file mode 100644
index 51c14aa..0000000
--- a/src/tint/cmd/bench/extension_bench.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/cmd/bench/extension_bench.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/extension.h"
-
-#include <array>
-
-#include "benchmark/benchmark.h"
-
-namespace tint::wgsl {
-namespace {
-
-void ExtensionParser(::benchmark::State& state) {
-    const char* kStrings[] = {
-        "chromium_disableuniformiccy_analysis",
-        "chromil3_disable_unifority_analss",
-        "chromium_disable_Vniformity_analysis",
-        "chromium_disable_uniformity_analysis",
-        "chromium_dis1ble_uniformity_analysis",
-        "chromium_qqisable_unifomity_anaJysis",
-        "chrollium_disable_uniformity_analysi77",
-        "cqqromium_eppperimental_framebuffe_fetcHH",
-        "chrmium_experimvntal_frcmebufer_ftch",
-        "chromium_expebimental_framGbufer_fetch",
-        "chromium_experimental_framebuffer_fetch",
-        "chromium_experimental_vramebuffeii_fetch",
-        "chro8WWum_experimental_framebuffer_fetch",
-        "chromium_eperimenxxMl_framebuffer_fetch",
-        "chromiuX_experimentl_imggediate",
-        "chromiu_exuerimntal_XVmediate",
-        "chromium_experimen3al_immediate",
-        "chromium_experimental_immediate",
-        "cEromium_experimental_immediate",
-        "TThromium_experiPPental_imediate",
-        "chddomium_experimental_immedixxe",
-        "chromium_experi44ental_pixel_local",
-        "chromium_experimental_VVSixel_local",
-        "chroRium_experimental_pix22Rlocal",
-        "chromium_experimental_pixel_local",
-        "chromiuF_experiment9lpixel_local",
-        "chromium_experimental_pixel_loca",
-        "Vhromium_expeOOimentalHpixRRl_lcal",
-        "chromium_eyperimental_subgoup_matrix",
-        "Ghromium_experrim77nllal_subgnnoup_matrix",
-        "ch4omium_experimental00subgroup_matrix",
-        "chromium_experimental_subgroup_matrix",
-        "chromium_exeimoontal_subgroup_atrix",
-        "chromium_experimnal_subgroup_mazzrix",
-        "chro11ium_experienial_subgrppup_matrix",
-        "chXXomium_internal_graphite",
-        "chromi55m_internnal_gra99hiIIe",
-        "chSSomiuY_internal_aarHHphrrte",
-        "chromium_internal_graphite",
-        "kkhromium_nternal_rahHte",
-        "chromium_nRegnaj_graphite",
-        "chromium_ntebnal_gaphite",
-        "chromium_internal_input_atjachments",
-        "chromium_internal_inpt_attachments",
-        "chromium_nteral_iqput_attachments",
-        "chromium_internal_input_attachments",
-        "chromium_internal_input_aNNtachents",
-        "chromium_internalinpt_attavvhments",
-        "chromium_internal_inut_attacQQments",
-        "clip_drstffcs",
-        "clip_distancjs",
-        "clip_istNNwnce8",
-        "clip_distances",
-        "cli_distances",
-        "clip_disrrances",
-        "clip_diGtances",
-        "dual_source_blendFFng",
-        "dEl_surce_bending",
-        "drra_source_blending",
-        "dual_source_blending",
-        "dual_suce_blending",
-        "dul_DoXrcJJ_blending",
-        "dul_source_lening",
-        "k",
-        "16",
-        "J1",
-        "f16",
-        "c16",
-        "fO6",
-        "_KKttvv",
-        "xubgro5p8",
-        "suFq__ups",
-        "sqqgroups",
-        "subgroups",
-        "subgr6u33O",
-        "s96grQttupoo",
-        "sugro66ps",
-    };
-    for (auto _ : state) {
-        for (auto* str : kStrings) {
-            auto result = ParseExtension(str);
-            benchmark::DoNotOptimize(result);
-        }
-    }
-}  // NOLINT(readability/fn_size)
-
-BENCHMARK(ExtensionParser);
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/cmd/bench/extension_bench.cc.tmpl b/src/tint/cmd/bench/extension_bench.cc.tmpl
deleted file mode 100644
index 7fc8c5c..0000000
--- a/src/tint/cmd/bench/extension_bench.cc.tmpl
+++ /dev/null
@@ -1,27 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate extension_bench.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "extension") -}}
-
-#include "src/tint/lang/wgsl/extension.h"
-
-#include <array>
-
-#include "benchmark/benchmark.h"
-
-namespace tint::wgsl {
-namespace {
-
-{{ Eval "BenchmarkParseEnum" $enum }}
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/cmd/fuzz/wgsl/fuzz.cc b/src/tint/cmd/fuzz/wgsl/fuzz.cc
index 578a9a1..6fdfbaa 100644
--- a/src/tint/cmd/fuzz/wgsl/fuzz.cc
+++ b/src/tint/cmd/fuzz/wgsl/fuzz.cc
@@ -40,7 +40,7 @@
 #include "src/tint/lang/wgsl/ast/module.h"
 #include "src/tint/lang/wgsl/ast/struct.h"
 #include "src/tint/lang/wgsl/ast/variable.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/reader/options.h"
 #include "src/tint/lang/wgsl/reader/reader.h"
 #include "src/tint/utils/containers/vector.h"
diff --git a/src/tint/lang/spirv/reader/ast_lower/atomics.h b/src/tint/lang/spirv/reader/ast_lower/atomics.h
index ac379ad..65f4f98 100644
--- a/src/tint/lang/spirv/reader/ast_lower/atomics.h
+++ b/src/tint/lang/spirv/reader/ast_lower/atomics.h
@@ -32,7 +32,7 @@
 
 #include "src/tint/lang/spirv/reader/ast_lower/transform.h"
 #include "src/tint/lang/wgsl/ast/internal_attribute.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 namespace tint::spirv::reader {
 
diff --git a/src/tint/lang/spirv/reader/ast_parser/parse.cc b/src/tint/lang/spirv/reader/ast_parser/parse.cc
index d0a74ec..76ad2e6 100644
--- a/src/tint/lang/spirv/reader/ast_parser/parse.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/parse.cc
@@ -40,7 +40,7 @@
 #include "src/tint/lang/spirv/reader/ast_lower/transpose_row_major.h"
 #include "src/tint/lang/spirv/reader/ast_lower/unshadow.h"
 #include "src/tint/lang/spirv/reader/ast_parser/ast_parser.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/program/clone_context.h"
 #include "src/tint/lang/wgsl/resolver/resolve.h"
 
diff --git a/src/tint/lang/spirv/reader/common/BUILD.bazel b/src/tint/lang/spirv/reader/common/BUILD.bazel
index 7bbe53f..f9a54bf 100644
--- a/src/tint/lang/spirv/reader/common/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/common/BUILD.bazel
@@ -49,11 +49,13 @@
     "//src/tint/lang/wgsl",
     "//src/tint/utils",
     "//src/tint/utils/containers",
+    "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
     "//src/tint/utils/macros",
     "//src/tint/utils/math",
     "//src/tint/utils/memory",
     "//src/tint/utils/rtti",
+    "//src/tint/utils/text",
     "//src/utils",
   ],
   copts = COPTS,
diff --git a/src/tint/lang/spirv/reader/common/BUILD.cmake b/src/tint/lang/spirv/reader/common/BUILD.cmake
index bfcd886..1ddfd3b 100644
--- a/src/tint/lang/spirv/reader/common/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/common/BUILD.cmake
@@ -50,11 +50,13 @@
   tint_lang_wgsl
   tint_utils
   tint_utils_containers
+  tint_utils_diagnostic
   tint_utils_ice
   tint_utils_macros
   tint_utils_math
   tint_utils_memory
   tint_utils_rtti
+  tint_utils_text
 )
 
 tint_target_add_external_dependencies(tint_lang_spirv_reader_common lib
diff --git a/src/tint/lang/spirv/reader/common/BUILD.gn b/src/tint/lang/spirv/reader/common/BUILD.gn
index 1ea681b..58e2d9d 100644
--- a/src/tint/lang/spirv/reader/common/BUILD.gn
+++ b/src/tint/lang/spirv/reader/common/BUILD.gn
@@ -54,11 +54,13 @@
       "${tint_src_dir}/lang/wgsl",
       "${tint_src_dir}/utils",
       "${tint_src_dir}/utils/containers",
+      "${tint_src_dir}/utils/diagnostic",
       "${tint_src_dir}/utils/ice",
       "${tint_src_dir}/utils/macros",
       "${tint_src_dir}/utils/math",
       "${tint_src_dir}/utils/memory",
       "${tint_src_dir}/utils/rtti",
+      "${tint_src_dir}/utils/text",
     ]
   }
 }
diff --git a/src/tint/lang/wgsl/BUILD.bazel b/src/tint/lang/wgsl/BUILD.bazel
index ab45c5d..f5268a0 100644
--- a/src/tint/lang/wgsl/BUILD.bazel
+++ b/src/tint/lang/wgsl/BUILD.bazel
@@ -39,22 +39,14 @@
 cc_library(
   name = "wgsl",
   srcs = [
-    "builtin_fn.cc",
-    "diagnostic_rule.cc",
-    "diagnostic_severity.cc",
-    "extension.cc",
+    "enums.cc",
     "feature_status.cc",
-    "language_feature.cc",
     "reserved_words.cc",
   ],
   hdrs = [
     "allowed_features.h",
-    "builtin_fn.h",
-    "diagnostic_rule.h",
-    "diagnostic_severity.h",
-    "extension.h",
+    "enums.h",
     "feature_status.h",
-    "language_feature.h",
     "reserved_words.h",
   ],
   deps = [
@@ -77,11 +69,8 @@
   alwayslink = True,
   srcs = [
     "allowed_features_test.cc",
-    "diagnostic_rule_test.cc",
-    "diagnostic_severity_test.cc",
-    "extension_test.cc",
+    "enums_test.cc",
     "language_feature_status_test.cc",
-    "language_feature_test.cc",
   ] + select({
     "//conditions:default": [],
   }) + select({
diff --git a/src/tint/lang/wgsl/BUILD.cmake b/src/tint/lang/wgsl/BUILD.cmake
index c4baf01..45de3a2 100644
--- a/src/tint/lang/wgsl/BUILD.cmake
+++ b/src/tint/lang/wgsl/BUILD.cmake
@@ -51,18 +51,10 @@
 ################################################################################
 tint_add_target(tint_lang_wgsl lib
   lang/wgsl/allowed_features.h
-  lang/wgsl/builtin_fn.cc
-  lang/wgsl/builtin_fn.h
-  lang/wgsl/diagnostic_rule.cc
-  lang/wgsl/diagnostic_rule.h
-  lang/wgsl/diagnostic_severity.cc
-  lang/wgsl/diagnostic_severity.h
-  lang/wgsl/extension.cc
-  lang/wgsl/extension.h
+  lang/wgsl/enums.cc
+  lang/wgsl/enums.h
   lang/wgsl/feature_status.cc
   lang/wgsl/feature_status.h
-  lang/wgsl/language_feature.cc
-  lang/wgsl/language_feature.h
   lang/wgsl/reserved_words.cc
   lang/wgsl/reserved_words.h
 )
@@ -89,11 +81,8 @@
 ################################################################################
 tint_add_target(tint_lang_wgsl_test test
   lang/wgsl/allowed_features_test.cc
-  lang/wgsl/diagnostic_rule_test.cc
-  lang/wgsl/diagnostic_severity_test.cc
-  lang/wgsl/extension_test.cc
+  lang/wgsl/enums_test.cc
   lang/wgsl/language_feature_status_test.cc
-  lang/wgsl/language_feature_test.cc
 )
 
 tint_target_add_dependencies(tint_lang_wgsl_test test
diff --git a/src/tint/lang/wgsl/BUILD.gn b/src/tint/lang/wgsl/BUILD.gn
index 3e27659..269353c 100644
--- a/src/tint/lang/wgsl/BUILD.gn
+++ b/src/tint/lang/wgsl/BUILD.gn
@@ -46,18 +46,10 @@
 libtint_source_set("wgsl") {
   sources = [
     "allowed_features.h",
-    "builtin_fn.cc",
-    "builtin_fn.h",
-    "diagnostic_rule.cc",
-    "diagnostic_rule.h",
-    "diagnostic_severity.cc",
-    "diagnostic_severity.h",
-    "extension.cc",
-    "extension.h",
+    "enums.cc",
+    "enums.h",
     "feature_status.cc",
     "feature_status.h",
-    "language_feature.cc",
-    "language_feature.h",
     "reserved_words.cc",
     "reserved_words.h",
   ]
@@ -78,11 +70,8 @@
   tint_unittests_source_set("unittests") {
     sources = [
       "allowed_features_test.cc",
-      "diagnostic_rule_test.cc",
-      "diagnostic_severity_test.cc",
-      "extension_test.cc",
+      "enums_test.cc",
       "language_feature_status_test.cc",
-      "language_feature_test.cc",
     ]
     deps = [
       "${dawn_root}/src/utils:utils",
diff --git a/src/tint/lang/wgsl/allowed_features.h b/src/tint/lang/wgsl/allowed_features.h
index f242021..4d4ae4b 100644
--- a/src/tint/lang/wgsl/allowed_features.h
+++ b/src/tint/lang/wgsl/allowed_features.h
@@ -30,8 +30,7 @@
 
 #include <unordered_set>
 
-#include "src/tint/lang/wgsl/extension.h"
-#include "src/tint/lang/wgsl/language_feature.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/reflection.h"
 
 namespace tint::wgsl {
diff --git a/src/tint/lang/wgsl/ast/builder.h b/src/tint/lang/wgsl/ast/builder.h
index aca9afc..384b350 100644
--- a/src/tint/lang/wgsl/ast/builder.h
+++ b/src/tint/lang/wgsl/ast/builder.h
@@ -97,8 +97,7 @@
 #include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
 #include "src/tint/lang/wgsl/ast/while_statement.h"
 #include "src/tint/lang/wgsl/ast/workgroup_attribute.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/generation_id.h"
 #include "src/tint/utils/memory/block_allocator.h"
 #include "src/tint/utils/symbol/symbol_table.h"
diff --git a/src/tint/lang/wgsl/ast/diagnostic_control.cc b/src/tint/lang/wgsl/ast/diagnostic_control.cc
index fb20f48..772551f 100644
--- a/src/tint/lang/wgsl/ast/diagnostic_control.cc
+++ b/src/tint/lang/wgsl/ast/diagnostic_control.cc
@@ -31,7 +31,7 @@
 
 #include "src/tint/lang/wgsl/ast/identifier.h"
 #include "src/tint/lang/wgsl/ast/templated_identifier.h"
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 namespace tint::ast {
 
diff --git a/src/tint/lang/wgsl/ast/diagnostic_control.h b/src/tint/lang/wgsl/ast/diagnostic_control.h
index 4962d84..9441c51 100644
--- a/src/tint/lang/wgsl/ast/diagnostic_control.h
+++ b/src/tint/lang/wgsl/ast/diagnostic_control.h
@@ -31,7 +31,7 @@
 #include <string>
 #include <unordered_map>
 
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/diagnostic/diagnostic.h"
 
 // Forward declarations
diff --git a/src/tint/lang/wgsl/ast/diagnostic_control_test.cc b/src/tint/lang/wgsl/ast/diagnostic_control_test.cc
index 244ea67..07d0842 100644
--- a/src/tint/lang/wgsl/ast/diagnostic_control_test.cc
+++ b/src/tint/lang/wgsl/ast/diagnostic_control_test.cc
@@ -29,7 +29,7 @@
 
 #include "src/tint/lang/wgsl/ast/diagnostic_control.h"
 #include "src/tint/lang/wgsl/ast/helper_test.h"
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 namespace tint::ast {
 namespace {
diff --git a/src/tint/lang/wgsl/ast/extension.h b/src/tint/lang/wgsl/ast/extension.h
index cf25e08..15f0062 100644
--- a/src/tint/lang/wgsl/ast/extension.h
+++ b/src/tint/lang/wgsl/ast/extension.h
@@ -29,7 +29,7 @@
 #define SRC_TINT_LANG_WGSL_AST_EXTENSION_H_
 
 #include "src/tint/lang/wgsl/ast/node.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 namespace tint::ast {
 
diff --git a/src/tint/lang/wgsl/ast/requires.h b/src/tint/lang/wgsl/ast/requires.h
index 6a281a0..d427d44 100644
--- a/src/tint/lang/wgsl/ast/requires.h
+++ b/src/tint/lang/wgsl/ast/requires.h
@@ -33,7 +33,7 @@
 #include <vector>
 
 #include "src/tint/lang/wgsl/ast/node.h"
-#include "src/tint/lang/wgsl/language_feature.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/containers/unique_vector.h"
 
 namespace tint::ast {
diff --git a/src/tint/lang/wgsl/diagnostic_rule.cc b/src/tint/lang/wgsl/diagnostic_rule.cc
deleted file mode 100644
index 45f4286..0000000
--- a/src/tint/lang/wgsl/diagnostic_rule.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/diagnostic_rule.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-
-#include <string>
-
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
-CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str) {
-    if (str == "derivative_uniformity") {
-        return CoreDiagnosticRule::kDerivativeUniformity;
-    }
-    if (str == "subgroup_uniformity") {
-        return CoreDiagnosticRule::kSubgroupUniformity;
-    }
-    return CoreDiagnosticRule::kUndefined;
-}
-
-std::string_view ToString(CoreDiagnosticRule value) {
-    switch (value) {
-        case CoreDiagnosticRule::kUndefined:
-            return "undefined";
-        case CoreDiagnosticRule::kDerivativeUniformity:
-            return "derivative_uniformity";
-        case CoreDiagnosticRule::kSubgroupUniformity:
-            return "subgroup_uniformity";
-    }
-    return "<unknown>";
-}
-
-/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be
-/// parsed.
-ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str) {
-    if (str == "subgroup_matrix_uniformity") {
-        return ChromiumDiagnosticRule::kSubgroupMatrixUniformity;
-    }
-    if (str == "unreachable_code") {
-        return ChromiumDiagnosticRule::kUnreachableCode;
-    }
-    return ChromiumDiagnosticRule::kUndefined;
-}
-
-std::string_view ToString(ChromiumDiagnosticRule value) {
-    switch (value) {
-        case ChromiumDiagnosticRule::kUndefined:
-            return "undefined";
-        case ChromiumDiagnosticRule::kSubgroupMatrixUniformity:
-            return "subgroup_matrix_uniformity";
-        case ChromiumDiagnosticRule::kUnreachableCode:
-            return "unreachable_code";
-    }
-    return "<unknown>";
-}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_rule.cc.tmpl b/src/tint/lang/wgsl/diagnostic_rule.cc.tmpl
deleted file mode 100644
index f544c3c..0000000
--- a/src/tint/lang/wgsl/diagnostic_rule.cc.tmpl
+++ /dev/null
@@ -1,30 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-
-#include <string>
-
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-{{ Eval "ParseEnum" ($I.Sem.Enum "core_diagnostic_rule")}}
-
-{{ Eval "EnumOStream" ($I.Sem.Enum "core_diagnostic_rule")}}
-
-{{ Eval "ParseEnum" ($I.Sem.Enum "chromium_diagnostic_rule")}}
-
-{{ Eval "EnumOStream" ($I.Sem.Enum "chromium_diagnostic_rule")}}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_rule.h b/src/tint/lang/wgsl/diagnostic_rule.h
deleted file mode 100644
index b6d3efb..0000000
--- a/src/tint/lang/wgsl/diagnostic_rule.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/diagnostic_rule.h.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef SRC_TINT_LANG_WGSL_DIAGNOSTIC_RULE_H_
-#define SRC_TINT_LANG_WGSL_DIAGNOSTIC_RULE_H_
-
-#include <cstdint>
-#include <variant>
-
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-/// WGSL core diagnostic rules.
-enum class CoreDiagnosticRule : uint8_t {
-    kUndefined,
-    kDerivativeUniformity,
-    kSubgroupUniformity,
-};
-
-/// @param value the enum value
-/// @returns the string for the given enum value
-std::string_view ToString(CoreDiagnosticRule value);
-
-/// @param out the stream to write to
-/// @param value the CoreDiagnosticRule
-/// @returns @p out so calls can be chained
-template <typename STREAM>
-    requires(traits::IsOStream<STREAM>)
-auto& operator<<(STREAM& out, CoreDiagnosticRule value) {
-    return out << ToString(value);
-}
-
-/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
-CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str);
-
-constexpr std::string_view kCoreDiagnosticRuleStrings[] = {
-    "derivative_uniformity",
-    "subgroup_uniformity",
-};
-
-/// Chromium-specific diagnostic rules.
-enum class ChromiumDiagnosticRule : uint8_t {
-    kUndefined,
-    kSubgroupMatrixUniformity,
-    kUnreachableCode,
-};
-
-/// @param value the enum value
-/// @returns the string for the given enum value
-std::string_view ToString(ChromiumDiagnosticRule value);
-
-/// @param out the stream to write to
-/// @param value the ChromiumDiagnosticRule
-/// @returns @p out so calls can be chained
-template <typename STREAM>
-    requires(traits::IsOStream<STREAM>)
-auto& operator<<(STREAM& out, ChromiumDiagnosticRule value) {
-    return out << ToString(value);
-}
-
-/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be
-/// parsed.
-ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str);
-
-constexpr std::string_view kChromiumDiagnosticRuleStrings[] = {
-    "subgroup_matrix_uniformity",
-    "unreachable_code",
-};
-
-/// All diagnostic rules understood by Tint.
-using DiagnosticRule = std::variant<CoreDiagnosticRule, ChromiumDiagnosticRule>;
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_DIAGNOSTIC_RULE_H_
diff --git a/src/tint/lang/wgsl/diagnostic_rule.h.tmpl b/src/tint/lang/wgsl/diagnostic_rule.h.tmpl
deleted file mode 100644
index 208d5de..0000000
--- a/src/tint/lang/wgsl/diagnostic_rule.h.tmpl
+++ /dev/null
@@ -1,35 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control.h
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-
-#ifndef SRC_TINT_LANG_WGSL_DIAGNOSTIC_RULE_H_
-#define SRC_TINT_LANG_WGSL_DIAGNOSTIC_RULE_H_
-
-#include <cstdint>
-#include <variant>
-
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-/// WGSL core diagnostic rules.
-{{ Eval "DeclareEnum" ($I.Sem.Enum "core_diagnostic_rule") }}
-
-/// Chromium-specific diagnostic rules.
-{{ Eval "DeclareEnum" ($I.Sem.Enum "chromium_diagnostic_rule") }}
-
-/// All diagnostic rules understood by Tint.
-using DiagnosticRule = std::variant<CoreDiagnosticRule, ChromiumDiagnosticRule>;
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_DIAGNOSTIC_RULE_H_
diff --git a/src/tint/lang/wgsl/diagnostic_rule_test.cc b/src/tint/lang/wgsl/diagnostic_rule_test.cc
deleted file mode 100644
index ae7f040..0000000
--- a/src/tint/lang/wgsl/diagnostic_rule_test.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/diagnostic_rule_test.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include <string>
-
-#include "gtest/gtest.h"
-
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-namespace core_diagnostic_rule_tests {
-
-namespace parse_print_tests {
-
-struct CoreDiagnosticRuleCase {
-    const char* string;
-    CoreDiagnosticRule value;
-};
-
-inline std::ostream& operator<<(std::ostream& out, CoreDiagnosticRuleCase c) {
-    return out << "'" << std::string(c.string) << "'";
-}
-
-static constexpr CoreDiagnosticRuleCase kValidCoreDiagnosticRuleCases[] = {
-    {"derivative_uniformity", CoreDiagnosticRule::kDerivativeUniformity},
-    {"subgroup_uniformity", CoreDiagnosticRule::kSubgroupUniformity},
-};
-
-static constexpr CoreDiagnosticRuleCase kInvalidCoreDiagnosticRuleCases[] = {
-    {"deriative_unccformity", CoreDiagnosticRule::kUndefined},
-    {"dlivative_3iformiy", CoreDiagnosticRule::kUndefined},
-    {"derivative_uniforVity", CoreDiagnosticRule::kUndefined},
-    {"s1bgroup_uniformity", CoreDiagnosticRule::kUndefined},
-    {"subgrouqq_unifJrmty", CoreDiagnosticRule::kUndefined},
-    {"sub77roup_ulliformity", CoreDiagnosticRule::kUndefined},
-};
-
-using CoreDiagnosticRuleParseTest = testing::TestWithParam<CoreDiagnosticRuleCase>;
-
-TEST_P(CoreDiagnosticRuleParseTest, Parse) {
-    const char* string = GetParam().string;
-    CoreDiagnosticRule expect = GetParam().value;
-    EXPECT_EQ(expect, ParseCoreDiagnosticRule(string));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidCoreDiagnosticRuleCases,
-                         CoreDiagnosticRuleParseTest,
-                         testing::ValuesIn(kValidCoreDiagnosticRuleCases));
-INSTANTIATE_TEST_SUITE_P(InvalidCoreDiagnosticRuleCases,
-                         CoreDiagnosticRuleParseTest,
-                         testing::ValuesIn(kInvalidCoreDiagnosticRuleCases));
-
-using CoreDiagnosticRulePrintTest = testing::TestWithParam<CoreDiagnosticRuleCase>;
-
-TEST_P(CoreDiagnosticRulePrintTest, Print) {
-    CoreDiagnosticRule value = GetParam().value;
-    const char* expect = GetParam().string;
-    EXPECT_EQ(expect, ToString(value));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidCoreDiagnosticRuleCases,
-                         CoreDiagnosticRulePrintTest,
-                         testing::ValuesIn(kValidCoreDiagnosticRuleCases));
-
-}  // namespace parse_print_tests
-
-}  // namespace core_diagnostic_rule_tests
-
-namespace chromium_diagnostic_rule_tests {
-
-namespace parse_print_tests {
-
-struct ChromiumDiagnosticRuleCase {
-    const char* string;
-    ChromiumDiagnosticRule value;
-};
-
-inline std::ostream& operator<<(std::ostream& out, ChromiumDiagnosticRuleCase c) {
-    return out << "'" << std::string(c.string) << "'";
-}
-
-static constexpr ChromiumDiagnosticRuleCase kValidChromiumDiagnosticRuleCases[] = {
-    {"subgroup_matrix_uniformity", ChromiumDiagnosticRule::kSubgroupMatrixUniformity},
-    {"unreachable_code", ChromiumDiagnosticRule::kUnreachableCode},
-};
-
-static constexpr ChromiumDiagnosticRuleCase kInvalidChromiumDiagnosticRuleCases[] = {
-    {"subgroppHp_matriqq_uiformity", ChromiumDiagnosticRule::kUndefined},
-    {"subroup_matrcx_niformit", ChromiumDiagnosticRule::kUndefined},
-    {"subroupGmatrbx_uniformity", ChromiumDiagnosticRule::kUndefined},
-    {"vnriiachable_code", ChromiumDiagnosticRule::kUndefined},
-    {"unreac8ablWW_code", ChromiumDiagnosticRule::kUndefined},
-    {"unreMchablxxcode", ChromiumDiagnosticRule::kUndefined},
-};
-
-using ChromiumDiagnosticRuleParseTest = testing::TestWithParam<ChromiumDiagnosticRuleCase>;
-
-TEST_P(ChromiumDiagnosticRuleParseTest, Parse) {
-    const char* string = GetParam().string;
-    ChromiumDiagnosticRule expect = GetParam().value;
-    EXPECT_EQ(expect, ParseChromiumDiagnosticRule(string));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidChromiumDiagnosticRuleCases,
-                         ChromiumDiagnosticRuleParseTest,
-                         testing::ValuesIn(kValidChromiumDiagnosticRuleCases));
-INSTANTIATE_TEST_SUITE_P(InvalidChromiumDiagnosticRuleCases,
-                         ChromiumDiagnosticRuleParseTest,
-                         testing::ValuesIn(kInvalidChromiumDiagnosticRuleCases));
-
-using ChromiumDiagnosticRulePrintTest = testing::TestWithParam<ChromiumDiagnosticRuleCase>;
-
-TEST_P(ChromiumDiagnosticRulePrintTest, Print) {
-    ChromiumDiagnosticRule value = GetParam().value;
-    const char* expect = GetParam().string;
-    EXPECT_EQ(expect, ToString(value));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidChromiumDiagnosticRuleCases,
-                         ChromiumDiagnosticRulePrintTest,
-                         testing::ValuesIn(kValidChromiumDiagnosticRuleCases));
-
-}  // namespace parse_print_tests
-
-}  // namespace chromium_diagnostic_rule_tests
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_severity.cc b/src/tint/lang/wgsl/diagnostic_severity.cc
deleted file mode 100644
index 4fd7c55..0000000
--- a/src/tint/lang/wgsl/diagnostic_severity.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/diagnostic_severity.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
-
-#include <string>
-
-namespace tint::wgsl {
-
-diag::Severity ToSeverity(DiagnosticSeverity sc) {
-    switch (sc) {
-        case DiagnosticSeverity::kError:
-            return diag::Severity::Error;
-        case DiagnosticSeverity::kWarning:
-            return diag::Severity::Warning;
-        case DiagnosticSeverity::kInfo:
-            return diag::Severity::Note;
-        default:
-            return diag::Severity::Error;
-    }
-}
-
-/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or DiagnosticSeverity::kUndefined if the string could not be parsed.
-DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str) {
-    if (str == "error") {
-        return DiagnosticSeverity::kError;
-    }
-    if (str == "info") {
-        return DiagnosticSeverity::kInfo;
-    }
-    if (str == "off") {
-        return DiagnosticSeverity::kOff;
-    }
-    if (str == "warning") {
-        return DiagnosticSeverity::kWarning;
-    }
-    return DiagnosticSeverity::kUndefined;
-}
-
-std::string_view ToString(DiagnosticSeverity value) {
-    switch (value) {
-        case DiagnosticSeverity::kUndefined:
-            return "undefined";
-        case DiagnosticSeverity::kError:
-            return "error";
-        case DiagnosticSeverity::kInfo:
-            return "info";
-        case DiagnosticSeverity::kOff:
-            return "off";
-        case DiagnosticSeverity::kWarning:
-            return "warning";
-    }
-    return "<unknown>";
-}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl b/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl
deleted file mode 100644
index ff0f70e..0000000
--- a/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl
+++ /dev/null
@@ -1,37 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
-
-#include <string>
-
-namespace tint::wgsl {
-
-diag::Severity ToSeverity(DiagnosticSeverity sc) {
-    switch (sc) {
-        case DiagnosticSeverity::kError:
-            return diag::Severity::Error;
-        case DiagnosticSeverity::kWarning:
-            return diag::Severity::Warning;
-        case DiagnosticSeverity::kInfo:
-            return diag::Severity::Note;
-        default:
-            return diag::Severity::Error;
-    }
-}
-
-{{ Eval "ParseEnum" ($I.Sem.Enum "diagnostic_severity")}}
-
-{{ Eval "EnumOStream" ($I.Sem.Enum "diagnostic_severity")}}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_severity.h b/src/tint/lang/wgsl/diagnostic_severity.h
deleted file mode 100644
index 75d6bd6..0000000
--- a/src/tint/lang/wgsl/diagnostic_severity.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/diagnostic_severity.h.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
-#define SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
-
-#include <string>
-
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-#include "src/tint/utils/containers/hashmap.h"
-#include "src/tint/utils/diagnostic/diagnostic.h"
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-/// The diagnostic severity control.
-enum class DiagnosticSeverity : uint8_t {
-    kUndefined,
-    kError,
-    kInfo,
-    kOff,
-    kWarning,
-};
-
-/// @param value the enum value
-/// @returns the string for the given enum value
-std::string_view ToString(DiagnosticSeverity value);
-
-/// @param out the stream to write to
-/// @param value the DiagnosticSeverity
-/// @returns @p out so calls can be chained
-template <typename STREAM>
-    requires(traits::IsOStream<STREAM>)
-auto& operator<<(STREAM& out, DiagnosticSeverity value) {
-    return out << ToString(value);
-}
-
-/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or DiagnosticSeverity::kUndefined if the string could not be parsed.
-DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str);
-
-constexpr std::string_view kDiagnosticSeverityStrings[] = {
-    "error",
-    "info",
-    "off",
-    "warning",
-};
-
-/// Convert a DiagnosticSeverity to the corresponding diag::Severity.
-diag::Severity ToSeverity(DiagnosticSeverity sc);
-
-/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity.
-using DiagnosticRuleSeverities = Hashmap<DiagnosticRule, DiagnosticSeverity, 1>;
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
diff --git a/src/tint/lang/wgsl/diagnostic_severity.h.tmpl b/src/tint/lang/wgsl/diagnostic_severity.h.tmpl
deleted file mode 100644
index 7866560..0000000
--- a/src/tint/lang/wgsl/diagnostic_severity.h.tmpl
+++ /dev/null
@@ -1,37 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control.h
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-
-#ifndef SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
-#define SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
-
-#include <string>
-
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
-#include "src/tint/utils/containers/hashmap.h"
-#include "src/tint/utils/diagnostic/diagnostic.h"
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-/// The diagnostic severity control.
-{{ Eval "DeclareEnum" ($I.Sem.Enum "diagnostic_severity") }}
-
-/// Convert a DiagnosticSeverity to the corresponding diag::Severity.
-diag::Severity ToSeverity(DiagnosticSeverity sc);
-
-/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity.
-using DiagnosticRuleSeverities = Hashmap<DiagnosticRule, DiagnosticSeverity, 1>;
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
diff --git a/src/tint/lang/wgsl/diagnostic_severity_test.cc b/src/tint/lang/wgsl/diagnostic_severity_test.cc
deleted file mode 100644
index 9d9f5a6..0000000
--- a/src/tint/lang/wgsl/diagnostic_severity_test.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/diagnostic_severity_test.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include <string>
-
-#include "gtest/gtest.h"
-
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-namespace diagnostic_severity_tests {
-
-namespace parse_print_tests {
-
-struct DiagnosticSeverityCase {
-    const char* string;
-    DiagnosticSeverity value;
-};
-
-inline std::ostream& operator<<(std::ostream& out, DiagnosticSeverityCase c) {
-    return out << "'" << std::string(c.string) << "'";
-}
-
-static constexpr DiagnosticSeverityCase kValidDiagnosticSeverityCases[] = {
-    {"error", DiagnosticSeverity::kError},
-    {"info", DiagnosticSeverity::kInfo},
-    {"off", DiagnosticSeverity::kOff},
-    {"warning", DiagnosticSeverity::kWarning},
-};
-
-static constexpr DiagnosticSeverityCase kInvalidDiagnosticSeverityCases[] = {
-    {"erccr", DiagnosticSeverity::kUndefined},    {"3o", DiagnosticSeverity::kUndefined},
-    {"eVror", DiagnosticSeverity::kUndefined},    {"1nfo", DiagnosticSeverity::kUndefined},
-    {"iqfJ", DiagnosticSeverity::kUndefined},     {"illf77", DiagnosticSeverity::kUndefined},
-    {"oppqH", DiagnosticSeverity::kUndefined},    {"", DiagnosticSeverity::kUndefined},
-    {"Gb", DiagnosticSeverity::kUndefined},       {"warniivg", DiagnosticSeverity::kUndefined},
-    {"8WWrning", DiagnosticSeverity::kUndefined}, {"wxxning", DiagnosticSeverity::kUndefined},
-};
-
-using DiagnosticSeverityParseTest = testing::TestWithParam<DiagnosticSeverityCase>;
-
-TEST_P(DiagnosticSeverityParseTest, Parse) {
-    const char* string = GetParam().string;
-    DiagnosticSeverity expect = GetParam().value;
-    EXPECT_EQ(expect, ParseDiagnosticSeverity(string));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidDiagnosticSeverityCases,
-                         DiagnosticSeverityParseTest,
-                         testing::ValuesIn(kValidDiagnosticSeverityCases));
-INSTANTIATE_TEST_SUITE_P(InvalidDiagnosticSeverityCases,
-                         DiagnosticSeverityParseTest,
-                         testing::ValuesIn(kInvalidDiagnosticSeverityCases));
-
-using DiagnosticSeverityPrintTest = testing::TestWithParam<DiagnosticSeverityCase>;
-
-TEST_P(DiagnosticSeverityPrintTest, Print) {
-    DiagnosticSeverity value = GetParam().value;
-    const char* expect = GetParam().string;
-    EXPECT_EQ(expect, ToString(value));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidDiagnosticSeverityCases,
-                         DiagnosticSeverityPrintTest,
-                         testing::ValuesIn(kValidDiagnosticSeverityCases));
-
-}  // namespace parse_print_tests
-
-}  // namespace diagnostic_severity_tests
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_severity_test.cc.tmpl b/src/tint/lang/wgsl/diagnostic_severity_test.cc.tmpl
deleted file mode 100644
index f8a29aa..0000000
--- a/src/tint/lang/wgsl/diagnostic_severity_test.cc.tmpl
+++ /dev/null
@@ -1,31 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control_test.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-
-#include <string>
-
-#include "gtest/gtest.h"
-
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-namespace diagnostic_severity_tests {
-
-{{ Eval "TestParsePrintEnum" ($I.Sem.Enum "diagnostic_severity")}}
-
-}  // namespace diagnostic_severity_tests
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/builtin_fn.cc b/src/tint/lang/wgsl/enums.cc
similarity index 76%
rename from src/tint/lang/wgsl/builtin_fn.cc
rename to src/tint/lang/wgsl/enums.cc
index d052aa4..9c3b1b5 100644
--- a/src/tint/lang/wgsl/builtin_fn.cc
+++ b/src/tint/lang/wgsl/enums.cc
@@ -1,4 +1,4 @@
-// Copyright 2023 The Dawn & Tint Authors
+// Copyright 2025 The Dawn & Tint Authors
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
@@ -27,17 +27,255 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/builtin_fn.cc.tmpl
+//   src/tint/lang/wgsl/enums.cc.tmpl
 //
 // To regenerate run: './tools/run gen'
 //
 //                       Do not modify this file directly
 ////////////////////////////////////////////////////////////////////////////////
 
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
+
+#include <string>
+
+#include "src/tint/utils/rtti/traits.h"
 
 namespace tint::wgsl {
 
+/// ParseExtension parses a Extension from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or Extension::kUndefined if the string could not be parsed.
+Extension ParseExtension(std::string_view str) {
+    if (str == "chromium_disable_uniformity_analysis") {
+        return Extension::kChromiumDisableUniformityAnalysis;
+    }
+    if (str == "chromium_experimental_framebuffer_fetch") {
+        return Extension::kChromiumExperimentalFramebufferFetch;
+    }
+    if (str == "chromium_experimental_immediate") {
+        return Extension::kChromiumExperimentalImmediate;
+    }
+    if (str == "chromium_experimental_pixel_local") {
+        return Extension::kChromiumExperimentalPixelLocal;
+    }
+    if (str == "chromium_experimental_subgroup_matrix") {
+        return Extension::kChromiumExperimentalSubgroupMatrix;
+    }
+    if (str == "chromium_internal_graphite") {
+        return Extension::kChromiumInternalGraphite;
+    }
+    if (str == "chromium_internal_input_attachments") {
+        return Extension::kChromiumInternalInputAttachments;
+    }
+    if (str == "clip_distances") {
+        return Extension::kClipDistances;
+    }
+    if (str == "dual_source_blending") {
+        return Extension::kDualSourceBlending;
+    }
+    if (str == "f16") {
+        return Extension::kF16;
+    }
+    if (str == "subgroups") {
+        return Extension::kSubgroups;
+    }
+    return Extension::kUndefined;
+}
+std::string_view ToString(Extension value) {
+    switch (value) {
+        case Extension::kUndefined:
+            return "undefined";
+        case Extension::kChromiumDisableUniformityAnalysis:
+            return "chromium_disable_uniformity_analysis";
+        case Extension::kChromiumExperimentalFramebufferFetch:
+            return "chromium_experimental_framebuffer_fetch";
+        case Extension::kChromiumExperimentalImmediate:
+            return "chromium_experimental_immediate";
+        case Extension::kChromiumExperimentalPixelLocal:
+            return "chromium_experimental_pixel_local";
+        case Extension::kChromiumExperimentalSubgroupMatrix:
+            return "chromium_experimental_subgroup_matrix";
+        case Extension::kChromiumInternalGraphite:
+            return "chromium_internal_graphite";
+        case Extension::kChromiumInternalInputAttachments:
+            return "chromium_internal_input_attachments";
+        case Extension::kClipDistances:
+            return "clip_distances";
+        case Extension::kDualSourceBlending:
+            return "dual_source_blending";
+        case Extension::kF16:
+            return "f16";
+        case Extension::kSubgroups:
+            return "subgroups";
+    }
+    return "<unknown>";
+}
+
+/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
+CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str) {
+    if (str == "derivative_uniformity") {
+        return CoreDiagnosticRule::kDerivativeUniformity;
+    }
+    if (str == "subgroup_uniformity") {
+        return CoreDiagnosticRule::kSubgroupUniformity;
+    }
+    return CoreDiagnosticRule::kUndefined;
+}
+std::string_view ToString(CoreDiagnosticRule value) {
+    switch (value) {
+        case CoreDiagnosticRule::kUndefined:
+            return "undefined";
+        case CoreDiagnosticRule::kDerivativeUniformity:
+            return "derivative_uniformity";
+        case CoreDiagnosticRule::kSubgroupUniformity:
+            return "subgroup_uniformity";
+    }
+    return "<unknown>";
+}
+
+/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be
+/// parsed.
+ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str) {
+    if (str == "subgroup_matrix_uniformity") {
+        return ChromiumDiagnosticRule::kSubgroupMatrixUniformity;
+    }
+    if (str == "unreachable_code") {
+        return ChromiumDiagnosticRule::kUnreachableCode;
+    }
+    return ChromiumDiagnosticRule::kUndefined;
+}
+std::string_view ToString(ChromiumDiagnosticRule value) {
+    switch (value) {
+        case ChromiumDiagnosticRule::kUndefined:
+            return "undefined";
+        case ChromiumDiagnosticRule::kSubgroupMatrixUniformity:
+            return "subgroup_matrix_uniformity";
+        case ChromiumDiagnosticRule::kUnreachableCode:
+            return "unreachable_code";
+    }
+    return "<unknown>";
+}
+
+/// ParseLanguageFeature parses a LanguageFeature from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or LanguageFeature::kUndefined if the string could not be parsed.
+LanguageFeature ParseLanguageFeature(std::string_view str) {
+    if (str == "chromium_testing_experimental") {
+        return LanguageFeature::kChromiumTestingExperimental;
+    }
+    if (str == "chromium_testing_shipped") {
+        return LanguageFeature::kChromiumTestingShipped;
+    }
+    if (str == "chromium_testing_shipped_with_killswitch") {
+        return LanguageFeature::kChromiumTestingShippedWithKillswitch;
+    }
+    if (str == "chromium_testing_unimplemented") {
+        return LanguageFeature::kChromiumTestingUnimplemented;
+    }
+    if (str == "chromium_testing_unsafe_experimental") {
+        return LanguageFeature::kChromiumTestingUnsafeExperimental;
+    }
+    if (str == "packed_4x8_integer_dot_product") {
+        return LanguageFeature::kPacked4X8IntegerDotProduct;
+    }
+    if (str == "pointer_composite_access") {
+        return LanguageFeature::kPointerCompositeAccess;
+    }
+    if (str == "readonly_and_readwrite_storage_textures") {
+        return LanguageFeature::kReadonlyAndReadwriteStorageTextures;
+    }
+    if (str == "sized_binding_array") {
+        return LanguageFeature::kSizedBindingArray;
+    }
+    if (str == "texel_buffers") {
+        return LanguageFeature::kTexelBuffers;
+    }
+    if (str == "unrestricted_pointer_parameters") {
+        return LanguageFeature::kUnrestrictedPointerParameters;
+    }
+    return LanguageFeature::kUndefined;
+}
+std::string_view ToString(LanguageFeature value) {
+    switch (value) {
+        case LanguageFeature::kUndefined:
+            return "undefined";
+        case LanguageFeature::kChromiumTestingExperimental:
+            return "chromium_testing_experimental";
+        case LanguageFeature::kChromiumTestingShipped:
+            return "chromium_testing_shipped";
+        case LanguageFeature::kChromiumTestingShippedWithKillswitch:
+            return "chromium_testing_shipped_with_killswitch";
+        case LanguageFeature::kChromiumTestingUnimplemented:
+            return "chromium_testing_unimplemented";
+        case LanguageFeature::kChromiumTestingUnsafeExperimental:
+            return "chromium_testing_unsafe_experimental";
+        case LanguageFeature::kPacked4X8IntegerDotProduct:
+            return "packed_4x8_integer_dot_product";
+        case LanguageFeature::kPointerCompositeAccess:
+            return "pointer_composite_access";
+        case LanguageFeature::kReadonlyAndReadwriteStorageTextures:
+            return "readonly_and_readwrite_storage_textures";
+        case LanguageFeature::kSizedBindingArray:
+            return "sized_binding_array";
+        case LanguageFeature::kTexelBuffers:
+            return "texel_buffers";
+        case LanguageFeature::kUnrestrictedPointerParameters:
+            return "unrestricted_pointer_parameters";
+    }
+    return "<unknown>";
+}
+
+diag::Severity ToSeverity(DiagnosticSeverity sc) {
+    switch (sc) {
+        case DiagnosticSeverity::kError:
+            return diag::Severity::Error;
+        case DiagnosticSeverity::kWarning:
+            return diag::Severity::Warning;
+        case DiagnosticSeverity::kInfo:
+            return diag::Severity::Note;
+        default:
+            return diag::Severity::Error;
+    }
+}
+
+/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or DiagnosticSeverity::kUndefined if the string could not be parsed.
+DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str) {
+    if (str == "error") {
+        return DiagnosticSeverity::kError;
+    }
+    if (str == "info") {
+        return DiagnosticSeverity::kInfo;
+    }
+    if (str == "off") {
+        return DiagnosticSeverity::kOff;
+    }
+    if (str == "warning") {
+        return DiagnosticSeverity::kWarning;
+    }
+    return DiagnosticSeverity::kUndefined;
+}
+std::string_view ToString(DiagnosticSeverity value) {
+    switch (value) {
+        case DiagnosticSeverity::kUndefined:
+            return "undefined";
+        case DiagnosticSeverity::kError:
+            return "error";
+        case DiagnosticSeverity::kInfo:
+            return "info";
+        case DiagnosticSeverity::kOff:
+            return "off";
+        case DiagnosticSeverity::kWarning:
+            return "warning";
+    }
+    return "<unknown>";
+}
+
 BuiltinFn ParseBuiltinFn(std::string_view name) {
     if (name == "abs") {
         return BuiltinFn::kAbs;
diff --git a/src/tint/lang/wgsl/builtin_fn.cc.tmpl b/src/tint/lang/wgsl/enums.cc.tmpl
similarity index 84%
rename from src/tint/lang/wgsl/builtin_fn.cc.tmpl
rename to src/tint/lang/wgsl/enums.cc.tmpl
index cbab4d9..9e0b3ca 100644
--- a/src/tint/lang/wgsl/builtin_fn.cc.tmpl
+++ b/src/tint/lang/wgsl/enums.cc.tmpl
@@ -1,9 +1,6 @@
 {{- /*
 --------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate builtin_fn.cc
-
-To update the generated file, run:
-    ./tools/run gen
+Template file for use with tools/src/cmd/gen to generate enums.cc
 
 See:
 * tools/src/cmd/gen for structures used by this template
@@ -12,10 +9,45 @@
 */ -}}
 
 {{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-#include "src/tint/lang/wgsl/builtin_fn.h"
+{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
+
+#include "src/tint/lang/wgsl/enums.h"
+
+#include <string>
+
+#include "src/tint/utils/rtti/traits.h"
 
 namespace tint::wgsl {
 
+{{ Eval "ParseEnum" ($I.Sem.Enum "extension") }}
+{{ Eval "EnumOStream" ($I.Sem.Enum "extension") }}
+
+{{ Eval "ParseEnum" ($I.Sem.Enum "core_diagnostic_rule")}}
+{{ Eval "EnumOStream" ($I.Sem.Enum "core_diagnostic_rule")}}
+
+{{ Eval "ParseEnum" ($I.Sem.Enum "chromium_diagnostic_rule")}}
+{{ Eval "EnumOStream" ($I.Sem.Enum "chromium_diagnostic_rule")}}
+
+{{ Eval "ParseEnum" ($I.Sem.Enum "language_feature") }}
+{{ Eval "EnumOStream" ($I.Sem.Enum "language_feature") }}
+
+diag::Severity ToSeverity(DiagnosticSeverity sc) {
+    switch (sc) {
+        case DiagnosticSeverity::kError:
+            return diag::Severity::Error;
+        case DiagnosticSeverity::kWarning:
+            return diag::Severity::Warning;
+        case DiagnosticSeverity::kInfo:
+            return diag::Severity::Note;
+        default:
+            return diag::Severity::Error;
+    }
+}
+
+{{ Eval "ParseEnum" ($I.Sem.Enum "diagnostic_severity")}}
+{{ Eval "EnumOStream" ($I.Sem.Enum "diagnostic_severity")}}
+
+
 BuiltinFn ParseBuiltinFn(std::string_view name) {
 {{- range $I.Sem.Builtins  }}
     if (name == "{{.Name}}") {
diff --git a/src/tint/lang/wgsl/builtin_fn.h b/src/tint/lang/wgsl/enums.h
similarity index 66%
rename from src/tint/lang/wgsl/builtin_fn.h
rename to src/tint/lang/wgsl/enums.h
index d752c23..c6a3402 100644
--- a/src/tint/lang/wgsl/builtin_fn.h
+++ b/src/tint/lang/wgsl/enums.h
@@ -1,4 +1,4 @@
-// Copyright 2023 The Dawn & Tint Authors
+// Copyright 2025 The Dawn & Tint Authors
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
@@ -27,24 +27,253 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/builtin_fn.h.tmpl
+//   src/tint/lang/wgsl/enums.h.tmpl
 //
 // To regenerate run: './tools/run gen'
 //
 //                       Do not modify this file directly
 ////////////////////////////////////////////////////////////////////////////////
 
-#ifndef SRC_TINT_LANG_WGSL_BUILTIN_FN_H_
-#define SRC_TINT_LANG_WGSL_BUILTIN_FN_H_
+#ifndef SRC_TINT_LANG_WGSL_ENUMS_H_
+#define SRC_TINT_LANG_WGSL_ENUMS_H_
 
 #include <cstdint>
 #include <string>
+#include <variant>
 
+#include "src/tint/utils/containers/hashmap.h"
+#include "src/tint/utils/containers/unique_vector.h"
+#include "src/tint/utils/diagnostic/diagnostic.h"
 #include "src/tint/utils/rtti/traits.h"
 
-// \cond DO_NOT_DOCUMENT
 namespace tint::wgsl {
 
+/// WGSL core diagnostic rules.
+enum class CoreDiagnosticRule : uint8_t {
+    kUndefined,
+    kDerivativeUniformity,
+    kSubgroupUniformity,
+};
+
+/// @param value the enum value
+/// @returns the string for the given enum value
+std::string_view ToString(CoreDiagnosticRule value);
+
+/// @param out the stream to write to
+/// @param value the CoreDiagnosticRule
+/// @returns @p out so calls can be chained
+template <typename STREAM>
+    requires(traits::IsOStream<STREAM>)
+auto& operator<<(STREAM& out, CoreDiagnosticRule value) {
+    return out << ToString(value);
+}
+
+/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
+CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str);
+
+constexpr std::string_view kCoreDiagnosticRuleStrings[] = {
+    "derivative_uniformity",
+    "subgroup_uniformity",
+};
+
+/// Chromium-specific diagnostic rules.
+enum class ChromiumDiagnosticRule : uint8_t {
+    kUndefined,
+    kSubgroupMatrixUniformity,
+    kUnreachableCode,
+};
+
+/// @param value the enum value
+/// @returns the string for the given enum value
+std::string_view ToString(ChromiumDiagnosticRule value);
+
+/// @param out the stream to write to
+/// @param value the ChromiumDiagnosticRule
+/// @returns @p out so calls can be chained
+template <typename STREAM>
+    requires(traits::IsOStream<STREAM>)
+auto& operator<<(STREAM& out, ChromiumDiagnosticRule value) {
+    return out << ToString(value);
+}
+
+/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be
+/// parsed.
+ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str);
+
+constexpr std::string_view kChromiumDiagnosticRuleStrings[] = {
+    "subgroup_matrix_uniformity",
+    "unreachable_code",
+};
+
+/// An enumerator of WGSL extensions
+/// @see src/tint/lang/wgsl/intrinsics.def for extension descriptions
+enum class Extension : uint8_t {
+    kUndefined,
+    kChromiumDisableUniformityAnalysis,
+    kChromiumExperimentalFramebufferFetch,
+    kChromiumExperimentalImmediate,
+    kChromiumExperimentalPixelLocal,
+    kChromiumExperimentalSubgroupMatrix,
+    kChromiumInternalGraphite,
+    kChromiumInternalInputAttachments,
+    kClipDistances,
+    kDualSourceBlending,
+    kF16,
+    kSubgroups,
+};
+
+/// @param value the enum value
+/// @returns the string for the given enum value
+std::string_view ToString(Extension value);
+
+/// @param out the stream to write to
+/// @param value the Extension
+/// @returns @p out so calls can be chained
+template <typename STREAM>
+    requires(traits::IsOStream<STREAM>)
+auto& operator<<(STREAM& out, Extension value) {
+    return out << ToString(value);
+}
+
+/// ParseExtension parses a Extension from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or Extension::kUndefined if the string could not be parsed.
+Extension ParseExtension(std::string_view str);
+
+constexpr std::string_view kExtensionStrings[] = {
+    "chromium_disable_uniformity_analysis",
+    "chromium_experimental_framebuffer_fetch",
+    "chromium_experimental_immediate",
+    "chromium_experimental_pixel_local",
+    "chromium_experimental_subgroup_matrix",
+    "chromium_internal_graphite",
+    "chromium_internal_input_attachments",
+    "clip_distances",
+    "dual_source_blending",
+    "f16",
+    "subgroups",
+};
+
+/// All extensions
+static constexpr Extension kAllExtensions[] = {
+    Extension::kChromiumDisableUniformityAnalysis,
+    Extension::kChromiumExperimentalFramebufferFetch,
+    Extension::kChromiumExperimentalImmediate,
+    Extension::kChromiumExperimentalPixelLocal,
+    Extension::kChromiumExperimentalSubgroupMatrix,
+    Extension::kChromiumInternalGraphite,
+    Extension::kChromiumInternalInputAttachments,
+    Extension::kClipDistances,
+    Extension::kDualSourceBlending,
+    Extension::kF16,
+    Extension::kSubgroups,
+};
+
+/// An enumerator of WGSL language features
+/// @see src/tint/lang/wgsl/wgsl.def for language feature descriptions
+enum class LanguageFeature : uint8_t {
+    kUndefined,
+    kChromiumTestingExperimental,
+    kChromiumTestingShipped,
+    kChromiumTestingShippedWithKillswitch,
+    kChromiumTestingUnimplemented,
+    kChromiumTestingUnsafeExperimental,
+    kPacked4X8IntegerDotProduct,
+    kPointerCompositeAccess,
+    kReadonlyAndReadwriteStorageTextures,
+    kSizedBindingArray,
+    kTexelBuffers,
+    kUnrestrictedPointerParameters,
+};
+
+/// @param value the enum value
+/// @returns the string for the given enum value
+std::string_view ToString(LanguageFeature value);
+
+/// ParseLanguageFeature parses a LanguageFeature from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or LanguageFeature::kUndefined if the string could not be parsed.
+LanguageFeature ParseLanguageFeature(std::string_view str);
+
+constexpr std::string_view kLanguageFeatureStrings[] = {
+    "chromium_testing_experimental",
+    "chromium_testing_shipped",
+    "chromium_testing_shipped_with_killswitch",
+    "chromium_testing_unimplemented",
+    "chromium_testing_unsafe_experimental",
+    "packed_4x8_integer_dot_product",
+    "pointer_composite_access",
+    "readonly_and_readwrite_storage_textures",
+    "sized_binding_array",
+    "texel_buffers",
+    "unrestricted_pointer_parameters",
+};
+
+/// All features
+static constexpr LanguageFeature kAllLanguageFeatures[] = {
+    LanguageFeature::kChromiumTestingExperimental,
+    LanguageFeature::kChromiumTestingShipped,
+    LanguageFeature::kChromiumTestingShippedWithKillswitch,
+    LanguageFeature::kChromiumTestingUnimplemented,
+    LanguageFeature::kChromiumTestingUnsafeExperimental,
+    LanguageFeature::kPacked4X8IntegerDotProduct,
+    LanguageFeature::kPointerCompositeAccess,
+    LanguageFeature::kReadonlyAndReadwriteStorageTextures,
+    LanguageFeature::kSizedBindingArray,
+    LanguageFeature::kTexelBuffers,
+    LanguageFeature::kUnrestrictedPointerParameters,
+};
+
+/// A unique vector of extensions
+using Extensions = UniqueVector<Extension, 4>;
+
+/// All diagnostic rules understood by Tint.
+using DiagnosticRule = std::variant<CoreDiagnosticRule, ChromiumDiagnosticRule>;
+
+/// The diagnostic severity control.
+enum class DiagnosticSeverity : uint8_t {
+    kUndefined,
+    kError,
+    kInfo,
+    kOff,
+    kWarning,
+};
+
+/// @param value the enum value
+/// @returns the string for the given enum value
+std::string_view ToString(DiagnosticSeverity value);
+
+/// @param out the stream to write to
+/// @param value the DiagnosticSeverity
+/// @returns @p out so calls can be chained
+template <typename STREAM>
+    requires(traits::IsOStream<STREAM>)
+auto& operator<<(STREAM& out, DiagnosticSeverity value) {
+    return out << ToString(value);
+}
+
+/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or DiagnosticSeverity::kUndefined if the string could not be parsed.
+DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str);
+
+constexpr std::string_view kDiagnosticSeverityStrings[] = {
+    "error",
+    "info",
+    "off",
+    "warning",
+};
+
+/// Convert a DiagnosticSeverity to the corresponding diag::Severity.
+diag::Severity ToSeverity(DiagnosticSeverity sc);
+
+/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity.
+using DiagnosticRuleSeverities = Hashmap<DiagnosticRule, DiagnosticSeverity, 1>;
+
 /// Enumerator of all builtin functions
 enum class BuiltinFn : uint8_t {
     kAbs,
@@ -604,6 +833,5 @@
 bool HasSideEffects(BuiltinFn f);
 
 }  // namespace tint::wgsl
-// \endcond
 
-#endif  // SRC_TINT_LANG_WGSL_BUILTIN_FN_H_
+#endif  // SRC_TINT_LANG_WGSL_ENUMS_H_
diff --git a/src/tint/lang/wgsl/builtin_fn.h.tmpl b/src/tint/lang/wgsl/enums.h.tmpl
similarity index 67%
rename from src/tint/lang/wgsl/builtin_fn.h.tmpl
rename to src/tint/lang/wgsl/enums.h.tmpl
index be29cf2..ba6596e 100644
--- a/src/tint/lang/wgsl/builtin_fn.h.tmpl
+++ b/src/tint/lang/wgsl/enums.h.tmpl
@@ -1,9 +1,6 @@
 {{- /*
 --------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate builtin_fn.h
-
-To update the generated file, run:
-    ./tools/run gen
+Template file for use with tools/src/cmd/gen to generate enums.h
 
 See:
 * tools/src/cmd/gen for structures used by this template
@@ -12,18 +9,68 @@
 */ -}}
 
 {{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
+{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
+{{- $extensions_enum := ($I.Sem.Enum "extension") -}}
+{{- $language_feature_enum := ($I.Sem.Enum "language_feature") -}}
 
-#ifndef SRC_TINT_LANG_WGSL_BUILTIN_FN_H_
-#define SRC_TINT_LANG_WGSL_BUILTIN_FN_H_
+#ifndef SRC_TINT_LANG_WGSL_ENUMS_H_
+#define SRC_TINT_LANG_WGSL_ENUMS_H_
 
 #include <cstdint>
 #include <string>
+#include <variant>
 
+#include "src/tint/utils/containers/hashmap.h"
+#include "src/tint/utils/containers/unique_vector.h"
+#include "src/tint/utils/diagnostic/diagnostic.h"
 #include "src/tint/utils/rtti/traits.h"
 
-// \cond DO_NOT_DOCUMENT
 namespace tint::wgsl {
 
+/// WGSL core diagnostic rules.
+{{ Eval "DeclareEnum" ($I.Sem.Enum "core_diagnostic_rule") }}
+
+/// Chromium-specific diagnostic rules.
+{{ Eval "DeclareEnum" ($I.Sem.Enum "chromium_diagnostic_rule") }}
+
+/// An enumerator of WGSL extensions
+/// @see src/tint/lang/wgsl/intrinsics.def for extension descriptions
+{{ Eval "DeclareEnum" $extensions_enum}}
+
+/// All extensions
+static constexpr Extension kAllExtensions[] = {
+{{-   range $entry := $extensions_enum.Entries }}
+    Extension::k{{PascalCase $entry.Name}},
+{{-   end }}
+};
+
+/// An enumerator of WGSL language features
+/// @see src/tint/lang/wgsl/wgsl.def for language feature descriptions
+{{ Eval "DeclareEnum" "Enum" $language_feature_enum "EmitOStream" false}}
+
+/// All features
+static constexpr LanguageFeature kAllLanguageFeatures[] = {
+{{-   range $entry := $language_feature_enum.Entries }}
+    LanguageFeature::k{{PascalCase $entry.Name}},
+{{-   end }}
+};
+
+/// A unique vector of extensions
+using Extensions = UniqueVector<Extension, 4>;
+
+/// All diagnostic rules understood by Tint.
+using DiagnosticRule = std::variant<CoreDiagnosticRule, ChromiumDiagnosticRule>;
+
+/// The diagnostic severity control.
+{{ Eval "DeclareEnum" ($I.Sem.Enum "diagnostic_severity") }}
+
+/// Convert a DiagnosticSeverity to the corresponding diag::Severity.
+diag::Severity ToSeverity(DiagnosticSeverity sc);
+
+/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity.
+using DiagnosticRuleSeverities = Hashmap<DiagnosticRule, DiagnosticSeverity, 1>;
+
+
 /// Enumerator of all builtin functions
 enum class BuiltinFn : uint8_t {
 {{- range $I.Sem.Builtins }}
@@ -136,6 +183,5 @@
 bool HasSideEffects(BuiltinFn f);
 
 }  // namespace tint::wgsl
-// \endcond
 
-#endif  // SRC_TINT_LANG_WGSL_BUILTIN_FN_H_
+#endif  // SRC_TINT_LANG_WGSL_ENUMS_H_
diff --git a/src/tint/lang/wgsl/enums_test.cc b/src/tint/lang/wgsl/enums_test.cc
new file mode 100644
index 0000000..a0f2533
--- /dev/null
+++ b/src/tint/lang/wgsl/enums_test.cc
@@ -0,0 +1,400 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by 'tools/src/cmd/gen' using the template:
+//   src/tint/lang/wgsl/enums_test.cc.tmpl
+//
+// To regenerate run: './tools/run gen'
+//
+//                       Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+#include "src/tint/lang/wgsl/enums.h"
+#include "src/tint/utils/text/string.h"
+
+namespace tint::wgsl {
+namespace {
+
+namespace core_diagnostic_rule_tests {
+namespace parse_print_tests {
+
+struct CoreDiagnosticRuleCase {
+    const char* string;
+    CoreDiagnosticRule value;
+};
+
+inline std::ostream& operator<<(std::ostream& out, CoreDiagnosticRuleCase c) {
+    return out << "'" << std::string(c.string) << "'";
+}
+
+static constexpr CoreDiagnosticRuleCase kValidCoreDiagnosticRuleCases[] = {
+    {"derivative_uniformity", CoreDiagnosticRule::kDerivativeUniformity},
+    {"subgroup_uniformity", CoreDiagnosticRule::kSubgroupUniformity},
+};
+
+static constexpr CoreDiagnosticRuleCase kInvalidCoreDiagnosticRuleCases[] = {
+    {"deriative_unccformity", CoreDiagnosticRule::kUndefined},
+    {"dlivative_3iformiy", CoreDiagnosticRule::kUndefined},
+    {"derivative_uniforVity", CoreDiagnosticRule::kUndefined},
+    {"s1bgroup_uniformity", CoreDiagnosticRule::kUndefined},
+    {"subgrouqq_unifJrmty", CoreDiagnosticRule::kUndefined},
+    {"sub77roup_ulliformity", CoreDiagnosticRule::kUndefined},
+};
+
+using CoreDiagnosticRuleParseTest = testing::TestWithParam<CoreDiagnosticRuleCase>;
+
+TEST_P(CoreDiagnosticRuleParseTest, Parse) {
+    const char* string = GetParam().string;
+    CoreDiagnosticRule expect = GetParam().value;
+    EXPECT_EQ(expect, ParseCoreDiagnosticRule(string));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidCoreDiagnosticRuleCases,
+                         CoreDiagnosticRuleParseTest,
+                         testing::ValuesIn(kValidCoreDiagnosticRuleCases));
+INSTANTIATE_TEST_SUITE_P(InvalidCoreDiagnosticRuleCases,
+                         CoreDiagnosticRuleParseTest,
+                         testing::ValuesIn(kInvalidCoreDiagnosticRuleCases));
+
+using CoreDiagnosticRulePrintTest = testing::TestWithParam<CoreDiagnosticRuleCase>;
+
+TEST_P(CoreDiagnosticRulePrintTest, Print) {
+    CoreDiagnosticRule value = GetParam().value;
+    const char* expect = GetParam().string;
+    EXPECT_EQ(expect, ToString(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidCoreDiagnosticRuleCases,
+                         CoreDiagnosticRulePrintTest,
+                         testing::ValuesIn(kValidCoreDiagnosticRuleCases));
+
+}  // namespace parse_print_tests
+}  // namespace core_diagnostic_rule_tests
+
+namespace chromium_diagnostic_rule_tests {
+namespace parse_print_tests {
+
+struct ChromiumDiagnosticRuleCase {
+    const char* string;
+    ChromiumDiagnosticRule value;
+};
+
+inline std::ostream& operator<<(std::ostream& out, ChromiumDiagnosticRuleCase c) {
+    return out << "'" << std::string(c.string) << "'";
+}
+
+static constexpr ChromiumDiagnosticRuleCase kValidChromiumDiagnosticRuleCases[] = {
+    {"subgroup_matrix_uniformity", ChromiumDiagnosticRule::kSubgroupMatrixUniformity},
+    {"unreachable_code", ChromiumDiagnosticRule::kUnreachableCode},
+};
+
+static constexpr ChromiumDiagnosticRuleCase kInvalidChromiumDiagnosticRuleCases[] = {
+    {"subgroppHp_matriqq_uiformity", ChromiumDiagnosticRule::kUndefined},
+    {"subroup_matrcx_niformit", ChromiumDiagnosticRule::kUndefined},
+    {"subroupGmatrbx_uniformity", ChromiumDiagnosticRule::kUndefined},
+    {"vnriiachable_code", ChromiumDiagnosticRule::kUndefined},
+    {"unreac8ablWW_code", ChromiumDiagnosticRule::kUndefined},
+    {"unreMchablxxcode", ChromiumDiagnosticRule::kUndefined},
+};
+
+using ChromiumDiagnosticRuleParseTest = testing::TestWithParam<ChromiumDiagnosticRuleCase>;
+
+TEST_P(ChromiumDiagnosticRuleParseTest, Parse) {
+    const char* string = GetParam().string;
+    ChromiumDiagnosticRule expect = GetParam().value;
+    EXPECT_EQ(expect, ParseChromiumDiagnosticRule(string));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidChromiumDiagnosticRuleCases,
+                         ChromiumDiagnosticRuleParseTest,
+                         testing::ValuesIn(kValidChromiumDiagnosticRuleCases));
+INSTANTIATE_TEST_SUITE_P(InvalidChromiumDiagnosticRuleCases,
+                         ChromiumDiagnosticRuleParseTest,
+                         testing::ValuesIn(kInvalidChromiumDiagnosticRuleCases));
+
+using ChromiumDiagnosticRulePrintTest = testing::TestWithParam<ChromiumDiagnosticRuleCase>;
+
+TEST_P(ChromiumDiagnosticRulePrintTest, Print) {
+    ChromiumDiagnosticRule value = GetParam().value;
+    const char* expect = GetParam().string;
+    EXPECT_EQ(expect, ToString(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidChromiumDiagnosticRuleCases,
+                         ChromiumDiagnosticRulePrintTest,
+                         testing::ValuesIn(kValidChromiumDiagnosticRuleCases));
+
+}  // namespace parse_print_tests
+}  // namespace chromium_diagnostic_rule_tests
+
+namespace diagnostic_severity_tests {
+namespace parse_print_tests {
+
+struct DiagnosticSeverityCase {
+    const char* string;
+    DiagnosticSeverity value;
+};
+
+inline std::ostream& operator<<(std::ostream& out, DiagnosticSeverityCase c) {
+    return out << "'" << std::string(c.string) << "'";
+}
+
+static constexpr DiagnosticSeverityCase kValidDiagnosticSeverityCases[] = {
+    {"error", DiagnosticSeverity::kError},
+    {"info", DiagnosticSeverity::kInfo},
+    {"off", DiagnosticSeverity::kOff},
+    {"warning", DiagnosticSeverity::kWarning},
+};
+
+static constexpr DiagnosticSeverityCase kInvalidDiagnosticSeverityCases[] = {
+    {"eggor", DiagnosticSeverity::kUndefined},  {"VoX", DiagnosticSeverity::kUndefined},
+    {"erro3", DiagnosticSeverity::kUndefined},  {"infE", DiagnosticSeverity::kUndefined},
+    {"TTPfo", DiagnosticSeverity::kUndefined},  {"xxnfo", DiagnosticSeverity::kUndefined},
+    {"44ff", DiagnosticSeverity::kUndefined},   {"oSVVf", DiagnosticSeverity::kUndefined},
+    {"RR2", DiagnosticSeverity::kUndefined},    {"wFni9g", DiagnosticSeverity::kUndefined},
+    {"waring", DiagnosticSeverity::kUndefined}, {"VOORRHng", DiagnosticSeverity::kUndefined},
+};
+
+using DiagnosticSeverityParseTest = testing::TestWithParam<DiagnosticSeverityCase>;
+
+TEST_P(DiagnosticSeverityParseTest, Parse) {
+    const char* string = GetParam().string;
+    DiagnosticSeverity expect = GetParam().value;
+    EXPECT_EQ(expect, ParseDiagnosticSeverity(string));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidDiagnosticSeverityCases,
+                         DiagnosticSeverityParseTest,
+                         testing::ValuesIn(kValidDiagnosticSeverityCases));
+INSTANTIATE_TEST_SUITE_P(InvalidDiagnosticSeverityCases,
+                         DiagnosticSeverityParseTest,
+                         testing::ValuesIn(kInvalidDiagnosticSeverityCases));
+
+using DiagnosticSeverityPrintTest = testing::TestWithParam<DiagnosticSeverityCase>;
+
+TEST_P(DiagnosticSeverityPrintTest, Print) {
+    DiagnosticSeverity value = GetParam().value;
+    const char* expect = GetParam().string;
+    EXPECT_EQ(expect, ToString(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidDiagnosticSeverityCases,
+                         DiagnosticSeverityPrintTest,
+                         testing::ValuesIn(kValidDiagnosticSeverityCases));
+
+}  // namespace parse_print_tests
+}  // namespace diagnostic_severity_tests
+
+namespace parse_print_tests {
+
+struct ExtensionCase {
+    const char* string;
+    Extension value;
+};
+
+inline std::ostream& operator<<(std::ostream& out, ExtensionCase c) {
+    return out << "'" << std::string(c.string) << "'";
+}
+
+static constexpr ExtensionCase kValidExtensionCases[] = {
+    {"chromium_disable_uniformity_analysis", Extension::kChromiumDisableUniformityAnalysis},
+    {"chromium_experimental_framebuffer_fetch", Extension::kChromiumExperimentalFramebufferFetch},
+    {"chromium_experimental_immediate", Extension::kChromiumExperimentalImmediate},
+    {"chromium_experimental_pixel_local", Extension::kChromiumExperimentalPixelLocal},
+    {"chromium_experimental_subgroup_matrix", Extension::kChromiumExperimentalSubgroupMatrix},
+    {"chromium_internal_graphite", Extension::kChromiumInternalGraphite},
+    {"chromium_internal_input_attachments", Extension::kChromiumInternalInputAttachments},
+    {"clip_distances", Extension::kClipDistances},
+    {"dual_source_blending", Extension::kDualSourceBlending},
+    {"f16", Extension::kF16},
+    {"subgroups", Extension::kSubgroups},
+};
+
+static constexpr ExtensionCase kInvalidExtensionCases[] = {
+    {"chromium_disable_ynifority_analysis", Extension::kUndefined},
+    {"c77nromium_disable_rrniformity_analysGll", Extension::kUndefined},
+    {"chromium_disable_uniform00ty_4nalysis", Extension::kUndefined},
+    {"chomium_experiooetal_fraebuffer_fetch", Extension::kUndefined},
+    {"chromium_experimentl_framebufzzr_fetch", Extension::kUndefined},
+    {"chromium_expperimental1framebuffer_fetci", Extension::kUndefined},
+    {"chromium_experimental_immediXXte", Extension::kUndefined},
+    {"chromium55eIIperimental_immenni99te", Extension::kUndefined},
+    {"chraamiuSS_experimentaHHr_immediaYe", Extension::kUndefined},
+    {"homHumkkeperimental_pixel_local", Extension::kUndefined},
+    {"chromim_egperimental_pRRjel_loal", Extension::kUndefined},
+    {"cromiumbexperimental_pixellocal", Extension::kUndefined},
+    {"chrjmium_experimental_subgroup_matrix", Extension::kUndefined},
+    {"chromium_experimental_subgrop_matrix", Extension::kUndefined},
+    {"chromqumexpermental_subgroup_matrix", Extension::kUndefined},
+    {"chromium_intenalNNgraphite", Extension::kUndefined},
+    {"chromiuminternal_gvaphite", Extension::kUndefined},
+    {"chromium_internal_grphitQQ", Extension::kUndefined},
+    {"chromirm_ffnternalinpt_attachments", Extension::kUndefined},
+    {"chromium_internal_input_attachmenjs", Extension::kUndefined},
+    {"chwwomiu2_interNNal_inpu_att8chments", Extension::kUndefined},
+    {"cli_distances", Extension::kUndefined},
+    {"clip_disrrances", Extension::kUndefined},
+    {"clip_diGtances", Extension::kUndefined},
+    {"dual_source_blendFFng", Extension::kUndefined},
+    {"dEl_surce_bending", Extension::kUndefined},
+    {"drra_source_blending", Extension::kUndefined},
+    {"1", Extension::kUndefined},
+    {"DJ1", Extension::kUndefined},
+    {"", Extension::kUndefined},
+    {"ubgrk1p", Extension::kUndefined},
+    {"subroups", Extension::kUndefined},
+    {"Jubgrups", Extension::kUndefined},
+};
+
+using ExtensionParseTest = testing::TestWithParam<ExtensionCase>;
+
+TEST_P(ExtensionParseTest, Parse) {
+    const char* string = GetParam().string;
+    Extension expect = GetParam().value;
+    EXPECT_EQ(expect, ParseExtension(string));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidExtensionCases,
+                         ExtensionParseTest,
+                         testing::ValuesIn(kValidExtensionCases));
+INSTANTIATE_TEST_SUITE_P(InvalidExtensionCases,
+                         ExtensionParseTest,
+                         testing::ValuesIn(kInvalidExtensionCases));
+
+using ExtensionPrintTest = testing::TestWithParam<ExtensionCase>;
+
+TEST_P(ExtensionPrintTest, Print) {
+    Extension value = GetParam().value;
+    const char* expect = GetParam().string;
+    EXPECT_EQ(expect, ToString(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidExtensionCases,
+                         ExtensionPrintTest,
+                         testing::ValuesIn(kValidExtensionCases));
+
+}  // namespace parse_print_tests
+
+namespace parse_print_tests {
+
+struct LanguageFeatureCase {
+    const char* string;
+    LanguageFeature value;
+};
+
+inline std::ostream& operator<<(std::ostream& out, LanguageFeatureCase c) {
+    return out << "'" << std::string(c.string) << "'";
+}
+
+static constexpr LanguageFeatureCase kValidLanguageFeatureCases[] = {
+    {"chromium_testing_experimental", LanguageFeature::kChromiumTestingExperimental},
+    {"chromium_testing_shipped", LanguageFeature::kChromiumTestingShipped},
+    {"chromium_testing_shipped_with_killswitch",
+     LanguageFeature::kChromiumTestingShippedWithKillswitch},
+    {"chromium_testing_unimplemented", LanguageFeature::kChromiumTestingUnimplemented},
+    {"chromium_testing_unsafe_experimental", LanguageFeature::kChromiumTestingUnsafeExperimental},
+    {"packed_4x8_integer_dot_product", LanguageFeature::kPacked4X8IntegerDotProduct},
+    {"pointer_composite_access", LanguageFeature::kPointerCompositeAccess},
+    {"readonly_and_readwrite_storage_textures",
+     LanguageFeature::kReadonlyAndReadwriteStorageTextures},
+    {"sized_binding_array", LanguageFeature::kSizedBindingArray},
+    {"texel_buffers", LanguageFeature::kTexelBuffers},
+    {"unrestricted_pointer_parameters", LanguageFeature::kUnrestrictedPointerParameters},
+};
+
+static constexpr LanguageFeatureCase kInvalidLanguageFeatureCases[] = {
+    {"chcomium_testing_experimental", LanguageFeature::kUndefined},
+    {"chromium_testing_experimentaO", LanguageFeature::kUndefined},
+    {"chrovvium_testing_ettperi__entaKK", LanguageFeature::kUndefined},
+    {"chromi5m_xxestig_shippe8", LanguageFeature::kUndefined},
+    {"qqhromuF___estin_shipped", LanguageFeature::kUndefined},
+    {"chromium_tetiqqg_shipped", LanguageFeature::kUndefined},
+    {"ch33omiu66_testing_shipped_with_iOlswitch", LanguageFeature::kUndefined},
+    {"chromium_testing_ship9ed_ttooth_kQQl6switch", LanguageFeature::kUndefined},
+    {"chromium_te66ing_shipped_with_killswitch", LanguageFeature::kUndefined},
+    {"chromium_txstinOz_66nimlemented", LanguageFeature::kUndefined},
+    {"cyyromium_testing_unimplemented", LanguageFeature::kUndefined},
+    {"chromiHHm_ZestZng_uimlemented", LanguageFeature::kUndefined},
+    {"cWWomium_44qsting_unsafe_experimental", LanguageFeature::kUndefined},
+    {"chromium_tOOstng_unsafe_experimental", LanguageFeature::kUndefined},
+    {"cromioomtesting_unsafe_hxpYrimental", LanguageFeature::kUndefined},
+    {"paked_48_integer_dot_roduct", LanguageFeature::kUndefined},
+    {"paked_4x8_integer_dFt_product", LanguageFeature::kUndefined},
+    {"paced_4x8_integer_dot_prodwct", LanguageFeature::kUndefined},
+    {"pointer_omposiGKaccesff", LanguageFeature::kUndefined},
+    {"poiqKter_composite_access", LanguageFeature::kUndefined},
+    {"pFinter_compo3ite_ammcess", LanguageFeature::kUndefined},
+    {"readonly_nd_readwrite_storage_textures", LanguageFeature::kUndefined},
+    {"readonly_nd_readwrite_storage_textureq", LanguageFeature::kUndefined},
+    {"readonby_and_readwritebbstorae_textures", LanguageFeature::kUndefined},
+    {"sizd_binding_array", LanguageFeature::kUndefined},
+    {"siqd_biOOding_array", LanguageFeature::kUndefined},
+    {"siTTed_binding_avvray", LanguageFeature::kUndefined},
+    {"texel_bufFFers", LanguageFeature::kUndefined},
+    {"exel_PffQ0ers", LanguageFeature::kUndefined},
+    {"texel_buffPrs", LanguageFeature::kUndefined},
+    {"unrestricted_77sointer_parameter", LanguageFeature::kUndefined},
+    {"unrbbstricted_pointCr_paramRRters", LanguageFeature::kUndefined},
+    {"unrestrictXXd_pointer_parameters", LanguageFeature::kUndefined},
+};
+
+using LanguageFeatureParseTest = testing::TestWithParam<LanguageFeatureCase>;
+
+TEST_P(LanguageFeatureParseTest, Parse) {
+    const char* string = GetParam().string;
+    LanguageFeature expect = GetParam().value;
+    EXPECT_EQ(expect, ParseLanguageFeature(string));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidLanguageFeatureCases,
+                         LanguageFeatureParseTest,
+                         testing::ValuesIn(kValidLanguageFeatureCases));
+INSTANTIATE_TEST_SUITE_P(InvalidLanguageFeatureCases,
+                         LanguageFeatureParseTest,
+                         testing::ValuesIn(kInvalidLanguageFeatureCases));
+
+using LanguageFeaturePrintTest = testing::TestWithParam<LanguageFeatureCase>;
+
+TEST_P(LanguageFeaturePrintTest, Print) {
+    LanguageFeature value = GetParam().value;
+    const char* expect = GetParam().string;
+    EXPECT_EQ(expect, ToString(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidLanguageFeatureCases,
+                         LanguageFeaturePrintTest,
+                         testing::ValuesIn(kValidLanguageFeatureCases));
+
+}  // namespace parse_print_tests
+
+}  // namespace
+}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_rule_test.cc.tmpl b/src/tint/lang/wgsl/enums_test.cc.tmpl
similarity index 65%
rename from src/tint/lang/wgsl/diagnostic_rule_test.cc.tmpl
rename to src/tint/lang/wgsl/enums_test.cc.tmpl
index 47793d1..c34f2ac 100644
--- a/src/tint/lang/wgsl/diagnostic_rule_test.cc.tmpl
+++ b/src/tint/lang/wgsl/enums_test.cc.tmpl
@@ -1,6 +1,6 @@
 {{- /*
 --------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate diagnostic_control_test.cc
+Template file for use with tools/src/cmd/gen to generate enums_test.cc
 
 See:
 * tools/src/cmd/gen for structures used by this template
@@ -10,28 +10,34 @@
 
 {{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
 {{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
+{{- $extensions_enum := ($I.Sem.Enum "extension") -}}
+{{- $language_feature_enum := ($I.Sem.Enum "language_feature") -}}
 
 #include <string>
 
 #include "gtest/gtest.h"
 
-#include "src/tint/lang/wgsl/diagnostic_rule.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/text/string.h"
 
 namespace tint::wgsl {
 namespace {
 
 namespace core_diagnostic_rule_tests {
-
 {{ Eval "TestParsePrintEnum" ($I.Sem.Enum "core_diagnostic_rule")}}
-
 }  // namespace core_diagnostic_rule_tests
 
 namespace chromium_diagnostic_rule_tests {
-
 {{ Eval "TestParsePrintEnum" ($I.Sem.Enum "chromium_diagnostic_rule")}}
-
 }  // namespace chromium_diagnostic_rule_tests
 
+namespace diagnostic_severity_tests {
+{{ Eval "TestParsePrintEnum" ($I.Sem.Enum "diagnostic_severity")}}
+}  // namespace diagnostic_severity_tests
+
+{{ Eval "TestParsePrintEnum" $extensions_enum}}
+
+{{ Eval "TestParsePrintEnum" $language_feature_enum}}
+
 }  // namespace
 }  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/extension.cc b/src/tint/lang/wgsl/extension.cc
deleted file mode 100644
index 8f8ba4e..0000000
--- a/src/tint/lang/wgsl/extension.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/extension.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/extension.h"
-
-namespace tint::wgsl {
-
-/// ParseExtension parses a Extension from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or Extension::kUndefined if the string could not be parsed.
-Extension ParseExtension(std::string_view str) {
-    if (str == "chromium_disable_uniformity_analysis") {
-        return Extension::kChromiumDisableUniformityAnalysis;
-    }
-    if (str == "chromium_experimental_framebuffer_fetch") {
-        return Extension::kChromiumExperimentalFramebufferFetch;
-    }
-    if (str == "chromium_experimental_immediate") {
-        return Extension::kChromiumExperimentalImmediate;
-    }
-    if (str == "chromium_experimental_pixel_local") {
-        return Extension::kChromiumExperimentalPixelLocal;
-    }
-    if (str == "chromium_experimental_subgroup_matrix") {
-        return Extension::kChromiumExperimentalSubgroupMatrix;
-    }
-    if (str == "chromium_internal_graphite") {
-        return Extension::kChromiumInternalGraphite;
-    }
-    if (str == "chromium_internal_input_attachments") {
-        return Extension::kChromiumInternalInputAttachments;
-    }
-    if (str == "clip_distances") {
-        return Extension::kClipDistances;
-    }
-    if (str == "dual_source_blending") {
-        return Extension::kDualSourceBlending;
-    }
-    if (str == "f16") {
-        return Extension::kF16;
-    }
-    if (str == "subgroups") {
-        return Extension::kSubgroups;
-    }
-    return Extension::kUndefined;
-}
-
-std::string_view ToString(Extension value) {
-    switch (value) {
-        case Extension::kUndefined:
-            return "undefined";
-        case Extension::kChromiumDisableUniformityAnalysis:
-            return "chromium_disable_uniformity_analysis";
-        case Extension::kChromiumExperimentalFramebufferFetch:
-            return "chromium_experimental_framebuffer_fetch";
-        case Extension::kChromiumExperimentalImmediate:
-            return "chromium_experimental_immediate";
-        case Extension::kChromiumExperimentalPixelLocal:
-            return "chromium_experimental_pixel_local";
-        case Extension::kChromiumExperimentalSubgroupMatrix:
-            return "chromium_experimental_subgroup_matrix";
-        case Extension::kChromiumInternalGraphite:
-            return "chromium_internal_graphite";
-        case Extension::kChromiumInternalInputAttachments:
-            return "chromium_internal_input_attachments";
-        case Extension::kClipDistances:
-            return "clip_distances";
-        case Extension::kDualSourceBlending:
-            return "dual_source_blending";
-        case Extension::kF16:
-            return "f16";
-        case Extension::kSubgroups:
-            return "subgroups";
-    }
-    return "<unknown>";
-}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/extension.cc.tmpl b/src/tint/lang/wgsl/extension.cc.tmpl
deleted file mode 100644
index cbe975b..0000000
--- a/src/tint/lang/wgsl/extension.cc.tmpl
+++ /dev/null
@@ -1,23 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate extension.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "extension") -}}
-
-#include "src/tint/lang/wgsl/extension.h"
-
-namespace tint::wgsl {
-
-{{ Eval "ParseEnum" $enum}}
-
-{{ Eval "EnumOStream" $enum}}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/extension.h b/src/tint/lang/wgsl/extension.h
deleted file mode 100644
index 525e0cc..0000000
--- a/src/tint/lang/wgsl/extension.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/extension.h.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef SRC_TINT_LANG_WGSL_EXTENSION_H_
-#define SRC_TINT_LANG_WGSL_EXTENSION_H_
-
-#include "src/tint/utils/containers/unique_vector.h"
-#include "src/tint/utils/rtti/traits.h"
-
-namespace tint::wgsl {
-
-/// An enumerator of WGSL extensions
-/// @see src/tint/lang/wgsl/intrinsics.def for extension descriptions
-enum class Extension : uint8_t {
-    kUndefined,
-    kChromiumDisableUniformityAnalysis,
-    kChromiumExperimentalFramebufferFetch,
-    kChromiumExperimentalImmediate,
-    kChromiumExperimentalPixelLocal,
-    kChromiumExperimentalSubgroupMatrix,
-    kChromiumInternalGraphite,
-    kChromiumInternalInputAttachments,
-    kClipDistances,
-    kDualSourceBlending,
-    kF16,
-    kSubgroups,
-};
-
-/// @param value the enum value
-/// @returns the string for the given enum value
-std::string_view ToString(Extension value);
-
-/// @param out the stream to write to
-/// @param value the Extension
-/// @returns @p out so calls can be chained
-template <typename STREAM>
-    requires(traits::IsOStream<STREAM>)
-auto& operator<<(STREAM& out, Extension value) {
-    return out << ToString(value);
-}
-
-/// ParseExtension parses a Extension from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or Extension::kUndefined if the string could not be parsed.
-Extension ParseExtension(std::string_view str);
-
-constexpr std::string_view kExtensionStrings[] = {
-    "chromium_disable_uniformity_analysis",
-    "chromium_experimental_framebuffer_fetch",
-    "chromium_experimental_immediate",
-    "chromium_experimental_pixel_local",
-    "chromium_experimental_subgroup_matrix",
-    "chromium_internal_graphite",
-    "chromium_internal_input_attachments",
-    "clip_distances",
-    "dual_source_blending",
-    "f16",
-    "subgroups",
-};
-
-/// All extensions
-static constexpr Extension kAllExtensions[] = {
-    Extension::kChromiumDisableUniformityAnalysis,
-    Extension::kChromiumExperimentalFramebufferFetch,
-    Extension::kChromiumExperimentalImmediate,
-    Extension::kChromiumExperimentalPixelLocal,
-    Extension::kChromiumExperimentalSubgroupMatrix,
-    Extension::kChromiumInternalGraphite,
-    Extension::kChromiumInternalInputAttachments,
-    Extension::kClipDistances,
-    Extension::kDualSourceBlending,
-    Extension::kF16,
-    Extension::kSubgroups,
-};
-
-/// A unique vector of extensions
-using Extensions = UniqueVector<Extension, 4>;
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_EXTENSION_H_
diff --git a/src/tint/lang/wgsl/extension.h.tmpl b/src/tint/lang/wgsl/extension.h.tmpl
deleted file mode 100644
index db42585..0000000
--- a/src/tint/lang/wgsl/extension.h.tmpl
+++ /dev/null
@@ -1,39 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate extension.h
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "extension") -}}
-
-#ifndef SRC_TINT_LANG_WGSL_EXTENSION_H_
-#define SRC_TINT_LANG_WGSL_EXTENSION_H_
-
-#include "src/tint/utils/rtti/traits.h"
-#include "src/tint/utils/containers/unique_vector.h"
-
-namespace tint::wgsl {
-
-/// An enumerator of WGSL extensions
-/// @see src/tint/lang/wgsl/intrinsics.def for extension descriptions
-{{ Eval "DeclareEnum" $enum}}
-
-/// All extensions
-static constexpr Extension kAllExtensions[] = {
-{{-   range $entry := $enum.Entries }}
-    Extension::k{{PascalCase $entry.Name}},
-{{-   end }}
-};
-
-/// A unique vector of extensions
-using Extensions = UniqueVector<Extension, 4>;
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_EXTENSION_H_
diff --git a/src/tint/lang/wgsl/extension_test.cc b/src/tint/lang/wgsl/extension_test.cc
deleted file mode 100644
index 942f1fc..0000000
--- a/src/tint/lang/wgsl/extension_test.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2021 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/extension_test.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/extension.h"
-
-#include <gtest/gtest.h>
-
-#include <string>
-
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-namespace parse_print_tests {
-
-struct ExtensionCase {
-    const char* string;
-    Extension value;
-};
-
-inline std::ostream& operator<<(std::ostream& out, ExtensionCase c) {
-    return out << "'" << std::string(c.string) << "'";
-}
-
-static constexpr ExtensionCase kValidExtensionCases[] = {
-    {"chromium_disable_uniformity_analysis", Extension::kChromiumDisableUniformityAnalysis},
-    {"chromium_experimental_framebuffer_fetch", Extension::kChromiumExperimentalFramebufferFetch},
-    {"chromium_experimental_immediate", Extension::kChromiumExperimentalImmediate},
-    {"chromium_experimental_pixel_local", Extension::kChromiumExperimentalPixelLocal},
-    {"chromium_experimental_subgroup_matrix", Extension::kChromiumExperimentalSubgroupMatrix},
-    {"chromium_internal_graphite", Extension::kChromiumInternalGraphite},
-    {"chromium_internal_input_attachments", Extension::kChromiumInternalInputAttachments},
-    {"clip_distances", Extension::kClipDistances},
-    {"dual_source_blending", Extension::kDualSourceBlending},
-    {"f16", Extension::kF16},
-    {"subgroups", Extension::kSubgroups},
-};
-
-static constexpr ExtensionCase kInvalidExtensionCases[] = {
-    {"chromium_disableuniformiccy_analysis", Extension::kUndefined},
-    {"chromil3_disable_unifority_analss", Extension::kUndefined},
-    {"chromium_disable_Vniformity_analysis", Extension::kUndefined},
-    {"chromium_experimental_framebuf1er_fetch", Extension::kUndefined},
-    {"chromium_experiqqntal_framebuffer_fetch", Extension::kUndefined},
-    {"chromium_experimental_framebuffll77_fetch", Extension::kUndefined},
-    {"chromium_experiHHepptal_immedqqae", Extension::kUndefined},
-    {"chroium_xpervmentl_immediate", Extension::kUndefined},
-    {"chbomium_exerimental_iGmediate", Extension::kUndefined},
-    {"vhromium_experimental_pixel_liical", Extension::kUndefined},
-    {"chromium_experiment8l_pixel_lWWcal", Extension::kUndefined},
-    {"chromium_expeimentMl_xxixel_local", Extension::kUndefined},
-    {"cXromium_experimeggtal_subgrup_matrix", Extension::kUndefined},
-    {"chrXmiuu_expeimVtal_subgroup_matrix", Extension::kUndefined},
-    {"chromium_e3perimental_subgroup_matrix", Extension::kUndefined},
-    {"chromium_internal_graphitE", Extension::kUndefined},
-    {"chromium_nternal_gTTPaphite", Extension::kUndefined},
-    {"chxxdomium_interal_graphite", Extension::kUndefined},
-    {"c44romium_internal_input_attachments", Extension::kUndefined},
-    {"chromium_internal_inputSSaVVtachments", Extension::kUndefined},
-    {"chrom22Rm_internal_input_atRchments", Extension::kUndefined},
-    {"clFp_disanc9s", Extension::kUndefined},
-    {"cli_distances", Extension::kUndefined},
-    {"clRR_diVtOOHces", Extension::kUndefined},
-    {"dual_souyce_bleding", Extension::kUndefined},
-    {"dualrrllnource_blendiG77", Extension::kUndefined},
-    {"dual00source_ble4ding", Extension::kUndefined},
-    {"5", Extension::kUndefined},
-    {"u16", Extension::kUndefined},
-    {"f", Extension::kUndefined},
-    {"skkkgroups", Extension::kUndefined},
-    {"siibgrop", Extension::kUndefined},
-    {"subgroupXX", Extension::kUndefined},
-};
-
-using ExtensionParseTest = testing::TestWithParam<ExtensionCase>;
-
-TEST_P(ExtensionParseTest, Parse) {
-    const char* string = GetParam().string;
-    Extension expect = GetParam().value;
-    EXPECT_EQ(expect, ParseExtension(string));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidExtensionCases,
-                         ExtensionParseTest,
-                         testing::ValuesIn(kValidExtensionCases));
-INSTANTIATE_TEST_SUITE_P(InvalidExtensionCases,
-                         ExtensionParseTest,
-                         testing::ValuesIn(kInvalidExtensionCases));
-
-using ExtensionPrintTest = testing::TestWithParam<ExtensionCase>;
-
-TEST_P(ExtensionPrintTest, Print) {
-    Extension value = GetParam().value;
-    const char* expect = GetParam().string;
-    EXPECT_EQ(expect, ToString(value));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidExtensionCases,
-                         ExtensionPrintTest,
-                         testing::ValuesIn(kValidExtensionCases));
-
-}  // namespace parse_print_tests
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/extension_test.cc.tmpl b/src/tint/lang/wgsl/extension_test.cc.tmpl
deleted file mode 100644
index 0e6d498..0000000
--- a/src/tint/lang/wgsl/extension_test.cc.tmpl
+++ /dev/null
@@ -1,29 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate extension_test.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "extension") -}}
-
-#include "src/tint/lang/wgsl/extension.h"
-
-#include <gtest/gtest.h>
-
-#include <string>
-
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-{{ Eval "TestParsePrintEnum" $enum}}
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/feature_status.cc b/src/tint/lang/wgsl/feature_status.cc
index 888ddd9..199e9bb 100644
--- a/src/tint/lang/wgsl/feature_status.cc
+++ b/src/tint/lang/wgsl/feature_status.cc
@@ -27,7 +27,7 @@
 
 #include "src/tint/lang/wgsl/feature_status.h"
 
-#include "src/tint/lang/wgsl/language_feature.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 namespace tint::wgsl {
 
diff --git a/src/tint/lang/wgsl/intrinsic/dialect.h b/src/tint/lang/wgsl/intrinsic/dialect.h
index b3e36c6..35d5218 100644
--- a/src/tint/lang/wgsl/intrinsic/dialect.h
+++ b/src/tint/lang/wgsl/intrinsic/dialect.h
@@ -29,7 +29,7 @@
 #define SRC_TINT_LANG_WGSL_INTRINSIC_DIALECT_H_
 
 #include "src/tint/lang/core/intrinsic/table_data.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/intrinsic/ctor_conv.h"
 
 namespace tint::wgsl::intrinsic {
diff --git a/src/tint/lang/wgsl/ir/builtin_call.h b/src/tint/lang/wgsl/ir/builtin_call.h
index 7711081..3a5d91f 100644
--- a/src/tint/lang/wgsl/ir/builtin_call.h
+++ b/src/tint/lang/wgsl/ir/builtin_call.h
@@ -32,7 +32,7 @@
 
 #include "src/tint/lang/core/intrinsic/table_data.h"
 #include "src/tint/lang/core/ir/builtin_call.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/intrinsic/dialect.h"
 #include "src/tint/utils/rtti/castable.h"
 
diff --git a/src/tint/lang/wgsl/language_feature.cc b/src/tint/lang/wgsl/language_feature.cc
deleted file mode 100644
index 5c3fb12..0000000
--- a/src/tint/lang/wgsl/language_feature.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/language_feature.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/language_feature.h"
-
-namespace tint::wgsl {
-
-/// ParseLanguageFeature parses a LanguageFeature from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or LanguageFeature::kUndefined if the string could not be parsed.
-LanguageFeature ParseLanguageFeature(std::string_view str) {
-    if (str == "chromium_testing_experimental") {
-        return LanguageFeature::kChromiumTestingExperimental;
-    }
-    if (str == "chromium_testing_shipped") {
-        return LanguageFeature::kChromiumTestingShipped;
-    }
-    if (str == "chromium_testing_shipped_with_killswitch") {
-        return LanguageFeature::kChromiumTestingShippedWithKillswitch;
-    }
-    if (str == "chromium_testing_unimplemented") {
-        return LanguageFeature::kChromiumTestingUnimplemented;
-    }
-    if (str == "chromium_testing_unsafe_experimental") {
-        return LanguageFeature::kChromiumTestingUnsafeExperimental;
-    }
-    if (str == "packed_4x8_integer_dot_product") {
-        return LanguageFeature::kPacked4X8IntegerDotProduct;
-    }
-    if (str == "pointer_composite_access") {
-        return LanguageFeature::kPointerCompositeAccess;
-    }
-    if (str == "readonly_and_readwrite_storage_textures") {
-        return LanguageFeature::kReadonlyAndReadwriteStorageTextures;
-    }
-    if (str == "sized_binding_array") {
-        return LanguageFeature::kSizedBindingArray;
-    }
-    if (str == "texel_buffers") {
-        return LanguageFeature::kTexelBuffers;
-    }
-    if (str == "unrestricted_pointer_parameters") {
-        return LanguageFeature::kUnrestrictedPointerParameters;
-    }
-    return LanguageFeature::kUndefined;
-}
-
-std::string_view ToString(LanguageFeature value) {
-    switch (value) {
-        case LanguageFeature::kUndefined:
-            return "undefined";
-        case LanguageFeature::kChromiumTestingExperimental:
-            return "chromium_testing_experimental";
-        case LanguageFeature::kChromiumTestingShipped:
-            return "chromium_testing_shipped";
-        case LanguageFeature::kChromiumTestingShippedWithKillswitch:
-            return "chromium_testing_shipped_with_killswitch";
-        case LanguageFeature::kChromiumTestingUnimplemented:
-            return "chromium_testing_unimplemented";
-        case LanguageFeature::kChromiumTestingUnsafeExperimental:
-            return "chromium_testing_unsafe_experimental";
-        case LanguageFeature::kPacked4X8IntegerDotProduct:
-            return "packed_4x8_integer_dot_product";
-        case LanguageFeature::kPointerCompositeAccess:
-            return "pointer_composite_access";
-        case LanguageFeature::kReadonlyAndReadwriteStorageTextures:
-            return "readonly_and_readwrite_storage_textures";
-        case LanguageFeature::kSizedBindingArray:
-            return "sized_binding_array";
-        case LanguageFeature::kTexelBuffers:
-            return "texel_buffers";
-        case LanguageFeature::kUnrestrictedPointerParameters:
-            return "unrestricted_pointer_parameters";
-    }
-    return "<unknown>";
-}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/language_feature.cc.tmpl b/src/tint/lang/wgsl/language_feature.cc.tmpl
deleted file mode 100644
index 782b515..0000000
--- a/src/tint/lang/wgsl/language_feature.cc.tmpl
+++ /dev/null
@@ -1,23 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate language_feature.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "language_feature") -}}
-
-#include "src/tint/lang/wgsl/language_feature.h"
-
-namespace tint::wgsl {
-
-{{ Eval "ParseEnum" $enum}}
-
-{{ Eval "EnumOStream" $enum}}
-
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/language_feature.h b/src/tint/lang/wgsl/language_feature.h
deleted file mode 100644
index e5020a6..0000000
--- a/src/tint/lang/wgsl/language_feature.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/language_feature.h.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
-#define SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
-
-#include <cstdint>
-#include <string>
-
-namespace tint::wgsl {
-
-/// An enumerator of WGSL language features
-/// @see src/tint/lang/wgsl/wgsl.def for language feature descriptions
-enum class LanguageFeature : uint8_t {
-    kUndefined,
-    kChromiumTestingExperimental,
-    kChromiumTestingShipped,
-    kChromiumTestingShippedWithKillswitch,
-    kChromiumTestingUnimplemented,
-    kChromiumTestingUnsafeExperimental,
-    kPacked4X8IntegerDotProduct,
-    kPointerCompositeAccess,
-    kReadonlyAndReadwriteStorageTextures,
-    kSizedBindingArray,
-    kTexelBuffers,
-    kUnrestrictedPointerParameters,
-};
-
-/// @param value the enum value
-/// @returns the string for the given enum value
-std::string_view ToString(LanguageFeature value);
-
-/// ParseLanguageFeature parses a LanguageFeature from a string.
-/// @param str the string to parse
-/// @returns the parsed enum, or LanguageFeature::kUndefined if the string could not be parsed.
-LanguageFeature ParseLanguageFeature(std::string_view str);
-
-constexpr std::string_view kLanguageFeatureStrings[] = {
-    "chromium_testing_experimental",
-    "chromium_testing_shipped",
-    "chromium_testing_shipped_with_killswitch",
-    "chromium_testing_unimplemented",
-    "chromium_testing_unsafe_experimental",
-    "packed_4x8_integer_dot_product",
-    "pointer_composite_access",
-    "readonly_and_readwrite_storage_textures",
-    "sized_binding_array",
-    "texel_buffers",
-    "unrestricted_pointer_parameters",
-};
-
-/// All features
-static constexpr LanguageFeature kAllLanguageFeatures[] = {
-    LanguageFeature::kChromiumTestingExperimental,
-    LanguageFeature::kChromiumTestingShipped,
-    LanguageFeature::kChromiumTestingShippedWithKillswitch,
-    LanguageFeature::kChromiumTestingUnimplemented,
-    LanguageFeature::kChromiumTestingUnsafeExperimental,
-    LanguageFeature::kPacked4X8IntegerDotProduct,
-    LanguageFeature::kPointerCompositeAccess,
-    LanguageFeature::kReadonlyAndReadwriteStorageTextures,
-    LanguageFeature::kSizedBindingArray,
-    LanguageFeature::kTexelBuffers,
-    LanguageFeature::kUnrestrictedPointerParameters,
-};
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
diff --git a/src/tint/lang/wgsl/language_feature.h.tmpl b/src/tint/lang/wgsl/language_feature.h.tmpl
deleted file mode 100644
index 6690fa5..0000000
--- a/src/tint/lang/wgsl/language_feature.h.tmpl
+++ /dev/null
@@ -1,36 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate language_feature.h
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "language_feature") -}}
-
-#ifndef SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
-#define SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
-
-#include <cstdint>
-#include <string>
-
-namespace tint::wgsl {
-
-/// An enumerator of WGSL language features
-/// @see src/tint/lang/wgsl/wgsl.def for language feature descriptions
-{{ Eval "DeclareEnum" "Enum" $enum "EmitOStream" false}}
-
-/// All features
-static constexpr LanguageFeature kAllLanguageFeatures[] = {
-{{-   range $entry := $enum.Entries }}
-    LanguageFeature::k{{PascalCase $entry.Name}},
-{{-   end }}
-};
-
-}  // namespace tint::wgsl
-
-#endif  // SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
diff --git a/src/tint/lang/wgsl/language_feature_status_test.cc b/src/tint/lang/wgsl/language_feature_status_test.cc
index 41f9512..b5a5306 100644
--- a/src/tint/lang/wgsl/language_feature_status_test.cc
+++ b/src/tint/lang/wgsl/language_feature_status_test.cc
@@ -27,8 +27,8 @@
 
 #include <gtest/gtest.h>
 
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/feature_status.h"
-#include "src/tint/lang/wgsl/language_feature.h"
 
 namespace tint::wgsl {
 namespace {
diff --git a/src/tint/lang/wgsl/language_feature_test.cc b/src/tint/lang/wgsl/language_feature_test.cc
deleted file mode 100644
index 4fbc210..0000000
--- a/src/tint/lang/wgsl/language_feature_test.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by 'tools/src/cmd/gen' using the template:
-//   src/tint/lang/wgsl/language_feature_test.cc.tmpl
-//
-// To regenerate run: './tools/run gen'
-//
-//                       Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/lang/wgsl/language_feature.h"
-
-#include <gtest/gtest.h>
-
-#include <string>
-
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-namespace parse_print_tests {
-
-struct LanguageFeatureCase {
-    const char* string;
-    LanguageFeature value;
-};
-
-inline std::ostream& operator<<(std::ostream& out, LanguageFeatureCase c) {
-    return out << "'" << std::string(c.string) << "'";
-}
-
-static constexpr LanguageFeatureCase kValidLanguageFeatureCases[] = {
-    {"chromium_testing_experimental", LanguageFeature::kChromiumTestingExperimental},
-    {"chromium_testing_shipped", LanguageFeature::kChromiumTestingShipped},
-    {"chromium_testing_shipped_with_killswitch",
-     LanguageFeature::kChromiumTestingShippedWithKillswitch},
-    {"chromium_testing_unimplemented", LanguageFeature::kChromiumTestingUnimplemented},
-    {"chromium_testing_unsafe_experimental", LanguageFeature::kChromiumTestingUnsafeExperimental},
-    {"packed_4x8_integer_dot_product", LanguageFeature::kPacked4X8IntegerDotProduct},
-    {"pointer_composite_access", LanguageFeature::kPointerCompositeAccess},
-    {"readonly_and_readwrite_storage_textures",
-     LanguageFeature::kReadonlyAndReadwriteStorageTextures},
-    {"sized_binding_array", LanguageFeature::kSizedBindingArray},
-    {"texel_buffers", LanguageFeature::kTexelBuffers},
-    {"unrestricted_pointer_parameters", LanguageFeature::kUnrestrictedPointerParameters},
-};
-
-static constexpr LanguageFeatureCase kInvalidLanguageFeatureCases[] = {
-    {"chccomium_esting_experimental", LanguageFeature::kUndefined},
-    {"cr3mium_testlg_experimentl", LanguageFeature::kUndefined},
-    {"cVromium_testing_experimental", LanguageFeature::kUndefined},
-    {"1hromium_testing_shipped", LanguageFeature::kUndefined},
-    {"chromium_testing_hJpqqed", LanguageFeature::kUndefined},
-    {"cllromium_te77ting_shipped", LanguageFeature::kUndefined},
-    {"chromippm_testing_sHHipped_with_kqqlswitch", LanguageFeature::kUndefined},
-    {"chromicm_esting_shippvd_with_kilsitch", LanguageFeature::kUndefined},
-    {"chrbmium_testing_shGpped_wih_killswitch", LanguageFeature::kUndefined},
-    {"chromium_testing_iinimplemevted", LanguageFeature::kUndefined},
-    {"chromiumWWtesting_unimp8emented", LanguageFeature::kUndefined},
-    {"chxxoium_tMsting_unimplemented", LanguageFeature::kUndefined},
-    {"chXggmium_testing_unsafe_expermental", LanguageFeature::kUndefined},
-    {"Xhomiuu_testng_unsafe_experimental", LanguageFeature::kUndefined},
-    {"chromium_3esting_unsafe_experimental", LanguageFeature::kUndefined},
-    {"packed_4x8_integer_Eot_product", LanguageFeature::kUndefined},
-    {"paked_4x8_integePP_dTTt_product", LanguageFeature::kUndefined},
-    {"packed_4x8_integxxrdot_pddoduct", LanguageFeature::kUndefined},
-    {"44ointer_composite_access", LanguageFeature::kUndefined},
-    {"VVSSinter_composite_access", LanguageFeature::kUndefined},
-    {"poinR2er_compRsite_acess", LanguageFeature::kUndefined},
-    {"readonlF_and_readwrite_st9rage_textues", LanguageFeature::kUndefined},
-    {"readonly_and_radwrite_storage_textures", LanguageFeature::kUndefined},
-    {"readonly_and_readwrite_sOOrage_tVxRRures", LanguageFeature::kUndefined},
-    {"sized_indiyg_array", LanguageFeature::kUndefined},
-    {"llGznnd_bin77ing_rrrray", LanguageFeature::kUndefined},
-    {"sized_bindin4_00rray", LanguageFeature::kUndefined},
-    {"teool_bffer", LanguageFeature::kUndefined},
-    {"exezz_uffers", LanguageFeature::kUndefined},
-    {"texel_bii11eps", LanguageFeature::kUndefined},
-    {"unrestricted_pointer_parametXXrs", LanguageFeature::kUndefined},
-    {"unrestri55tIId_pointer_paramnnt99rs", LanguageFeature::kUndefined},
-    {"unraastrSScted_pointerHHrparameteYs", LanguageFeature::kUndefined},
-};
-
-using LanguageFeatureParseTest = testing::TestWithParam<LanguageFeatureCase>;
-
-TEST_P(LanguageFeatureParseTest, Parse) {
-    const char* string = GetParam().string;
-    LanguageFeature expect = GetParam().value;
-    EXPECT_EQ(expect, ParseLanguageFeature(string));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidLanguageFeatureCases,
-                         LanguageFeatureParseTest,
-                         testing::ValuesIn(kValidLanguageFeatureCases));
-INSTANTIATE_TEST_SUITE_P(InvalidLanguageFeatureCases,
-                         LanguageFeatureParseTest,
-                         testing::ValuesIn(kInvalidLanguageFeatureCases));
-
-using LanguageFeaturePrintTest = testing::TestWithParam<LanguageFeatureCase>;
-
-TEST_P(LanguageFeaturePrintTest, Print) {
-    LanguageFeature value = GetParam().value;
-    const char* expect = GetParam().string;
-    EXPECT_EQ(expect, ToString(value));
-}
-
-INSTANTIATE_TEST_SUITE_P(ValidLanguageFeatureCases,
-                         LanguageFeaturePrintTest,
-                         testing::ValuesIn(kValidLanguageFeatureCases));
-
-}  // namespace parse_print_tests
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/language_feature_test.cc.tmpl b/src/tint/lang/wgsl/language_feature_test.cc.tmpl
deleted file mode 100644
index fe98798..0000000
--- a/src/tint/lang/wgsl/language_feature_test.cc.tmpl
+++ /dev/null
@@ -1,29 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate language_feature_test.cc
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-{{- $I := LoadIntrinsics "src/tint/lang/wgsl/wgsl.def" -}}
-{{- Import "src/tint/utils/templates/enums.tmpl.inc" -}}
-{{- $enum := ($I.Sem.Enum "language_feature") -}}
-
-#include "src/tint/lang/wgsl/language_feature.h"
-
-#include <gtest/gtest.h>
-
-#include <string>
-
-#include "src/tint/utils/text/string.h"
-
-namespace tint::wgsl {
-namespace {
-
-{{ Eval "TestParsePrintEnum" $enum}}
-
-}  // namespace
-}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/ls/completions.cc b/src/tint/lang/wgsl/ls/completions.cc
index 8102fd1..53d1821 100644
--- a/src/tint/lang/wgsl/ls/completions.cc
+++ b/src/tint/lang/wgsl/ls/completions.cc
@@ -30,7 +30,7 @@
 #include "src/tint/lang/wgsl/ast/identifier.h"
 #include "src/tint/lang/wgsl/ast/module.h"
 #include "src/tint/lang/wgsl/ast/type_decl.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/ls/utils.h"
 #include "src/tint/lang/wgsl/sem/block_statement.h"
 #include "src/tint/lang/wgsl/sem/function.h"
diff --git a/src/tint/lang/wgsl/ls/sem_tokens.cc b/src/tint/lang/wgsl/ls/sem_tokens.cc
index 7b045eb..3285b4a 100644
--- a/src/tint/lang/wgsl/ls/sem_tokens.cc
+++ b/src/tint/lang/wgsl/ls/sem_tokens.cc
@@ -35,7 +35,7 @@
 #include "src/tint/lang/wgsl/ast/struct.h"
 #include "src/tint/lang/wgsl/ast/struct_member.h"
 #include "src/tint/lang/wgsl/ast/type.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/ls/sem_token.h"
 #include "src/tint/lang/wgsl/ls/server.h"
 #include "src/tint/lang/wgsl/ls/utils.h"
diff --git a/src/tint/lang/wgsl/ls/signature_help.cc b/src/tint/lang/wgsl/ls/signature_help.cc
index d0f1850..96ad781 100644
--- a/src/tint/lang/wgsl/ls/signature_help.cc
+++ b/src/tint/lang/wgsl/ls/signature_help.cc
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <sstream>
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/ls/server.h"
 
 #include "langsvr/lsp/comparators.h"
diff --git a/src/tint/lang/wgsl/program/program_builder.h b/src/tint/lang/wgsl/program/program_builder.h
index d732b4e..b36497f 100644
--- a/src/tint/lang/wgsl/program/program_builder.h
+++ b/src/tint/lang/wgsl/program/program_builder.h
@@ -56,7 +56,7 @@
 #include "src/tint/lang/core/type/vector.h"
 #include "src/tint/lang/core/type/void.h"
 #include "src/tint/lang/wgsl/ast/builder.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/program/program.h"
 #include "src/tint/lang/wgsl/sem/array_count.h"
 #include "src/tint/lang/wgsl/sem/struct.h"
diff --git a/src/tint/lang/wgsl/reader/BUILD.bazel b/src/tint/lang/wgsl/reader/BUILD.bazel
index b88e902..81a3c8a 100644
--- a/src/tint/lang/wgsl/reader/BUILD.bazel
+++ b/src/tint/lang/wgsl/reader/BUILD.bazel
@@ -88,11 +88,13 @@
     "//src/tint/lang/wgsl",
     "//src/tint/utils",
     "//src/tint/utils/containers",
+    "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
     "//src/tint/utils/macros",
     "//src/tint/utils/math",
     "//src/tint/utils/memory",
     "//src/tint/utils/rtti",
+    "//src/tint/utils/text",
     "@gtest",
     "//src/utils",
   ] + select({
diff --git a/src/tint/lang/wgsl/reader/BUILD.cmake b/src/tint/lang/wgsl/reader/BUILD.cmake
index f839f23..552660d 100644
--- a/src/tint/lang/wgsl/reader/BUILD.cmake
+++ b/src/tint/lang/wgsl/reader/BUILD.cmake
@@ -100,11 +100,13 @@
   tint_lang_wgsl
   tint_utils
   tint_utils_containers
+  tint_utils_diagnostic
   tint_utils_ice
   tint_utils_macros
   tint_utils_math
   tint_utils_memory
   tint_utils_rtti
+  tint_utils_text
 )
 
 tint_target_add_external_dependencies(tint_lang_wgsl_reader_test test
diff --git a/src/tint/lang/wgsl/reader/BUILD.gn b/src/tint/lang/wgsl/reader/BUILD.gn
index 228ecf6..e958382 100644
--- a/src/tint/lang/wgsl/reader/BUILD.gn
+++ b/src/tint/lang/wgsl/reader/BUILD.gn
@@ -92,11 +92,13 @@
         "${tint_src_dir}/lang/wgsl",
         "${tint_src_dir}/utils",
         "${tint_src_dir}/utils/containers",
+        "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
         "${tint_src_dir}/utils/macros",
         "${tint_src_dir}/utils/math",
         "${tint_src_dir}/utils/memory",
         "${tint_src_dir}/utils/rtti",
+        "${tint_src_dir}/utils/text",
       ]
 
       if (tint_build_wgsl_reader) {
diff --git a/src/tint/lang/wgsl/reader/lower/lower.cc b/src/tint/lang/wgsl/reader/lower/lower.cc
index 7c3d562..9e65ff5 100644
--- a/src/tint/lang/wgsl/reader/lower/lower.cc
+++ b/src/tint/lang/wgsl/reader/lower/lower.cc
@@ -33,7 +33,7 @@
 #include "src/tint/lang/core/ir/builder.h"
 #include "src/tint/lang/core/ir/core_builtin_call.h"
 #include "src/tint/lang/core/ir/validator.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/ir/builtin_call.h"
 #include "src/tint/utils/ice/ice.h"
 
diff --git a/src/tint/lang/wgsl/reader/lower/lower_test.cc b/src/tint/lang/wgsl/reader/lower/lower_test.cc
index 1da5e74..0ee3f2d 100644
--- a/src/tint/lang/wgsl/reader/lower/lower_test.cc
+++ b/src/tint/lang/wgsl/reader/lower/lower_test.cc
@@ -29,7 +29,7 @@
 
 #include "src/tint/lang/core/ir/transform/helper_test.h"
 #include "src/tint/lang/core/type/struct.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/ir/builtin_call.h"
 #include "src/tint/lang/wgsl/reader/lower/lower.h"
 
diff --git a/src/tint/lang/wgsl/resolver/builtins_validation_test.cc b/src/tint/lang/wgsl/resolver/builtins_validation_test.cc
index 0e64144..2c512b2 100644
--- a/src/tint/lang/wgsl/resolver/builtins_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtins_validation_test.cc
@@ -28,7 +28,7 @@
 #include <functional>
 #include "src/tint/lang/core/enums.h"
 #include "src/tint/lang/wgsl/ast/call_statement.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
 #include "src/tint/utils/text/string_stream.h"
 
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.h b/src/tint/lang/wgsl/resolver/dependency_graph.h
index eb02497..fb92203 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.h
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.h
@@ -33,7 +33,7 @@
 
 #include "src/tint/lang/core/enums.h"
 #include "src/tint/lang/wgsl/ast/module.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/containers/hashmap.h"
 #include "src/tint/utils/diagnostic/diagnostic.h"
 
diff --git a/src/tint/lang/wgsl/resolver/eval_binary_op_test.cc b/src/tint/lang/wgsl/resolver/eval_binary_op_test.cc
index e05676c..ae883df 100644
--- a/src/tint/lang/wgsl/resolver/eval_binary_op_test.cc
+++ b/src/tint/lang/wgsl/resolver/eval_binary_op_test.cc
@@ -27,7 +27,7 @@
 
 #include "src/tint/lang/wgsl/resolver/eval_test.h"
 
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/utils/result.h"
 
 #if TINT_BUILD_WGSL_READER
diff --git a/src/tint/lang/wgsl/resolver/input_attachments_extension_test.cc b/src/tint/lang/wgsl/resolver/input_attachments_extension_test.cc
index 5387d09..44e2bdf 100644
--- a/src/tint/lang/wgsl/resolver/input_attachments_extension_test.cc
+++ b/src/tint/lang/wgsl/resolver/input_attachments_extension_test.cc
@@ -27,7 +27,7 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/number.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/resolver/resolver.h"
 #include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
 
diff --git a/src/tint/lang/wgsl/resolver/side_effects_test.cc b/src/tint/lang/wgsl/resolver/side_effects_test.cc
index aded8fa..1b518f9 100644
--- a/src/tint/lang/wgsl/resolver/side_effects_test.cc
+++ b/src/tint/lang/wgsl/resolver/side_effects_test.cc
@@ -31,7 +31,7 @@
 #include "src/tint/lang/core/enums.h"
 #include "src/tint/lang/core/fluent_types.h"
 #include "src/tint/lang/core/type/texture_dimension.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
 #include "src/tint/lang/wgsl/sem/index_accessor_expression.h"
 #include "src/tint/lang/wgsl/sem/member_accessor_expression.h"
diff --git a/src/tint/lang/wgsl/sem/builtin_enum_expression.cc b/src/tint/lang/wgsl/sem/builtin_enum_expression.cc
index 240935f..0975b51 100644
--- a/src/tint/lang/wgsl/sem/builtin_enum_expression.cc
+++ b/src/tint/lang/wgsl/sem/builtin_enum_expression.cc
@@ -28,7 +28,7 @@
 #include "src/tint/lang/wgsl/sem/builtin_enum_expression.h"
 
 #include "src/tint/lang/core/enums.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpressionBase);
 
diff --git a/src/tint/lang/wgsl/sem/builtin_fn.h b/src/tint/lang/wgsl/sem/builtin_fn.h
index 4652914..f88e137 100644
--- a/src/tint/lang/wgsl/sem/builtin_fn.h
+++ b/src/tint/lang/wgsl/sem/builtin_fn.h
@@ -31,9 +31,7 @@
 #include <string>
 #include <vector>
 
-#include "src/tint/lang/wgsl/builtin_fn.h"
-#include "src/tint/lang/wgsl/extension.h"
-#include "src/tint/lang/wgsl/language_feature.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/sem/call_target.h"
 #include "src/tint/lang/wgsl/sem/pipeline_stage_set.h"
 #include "src/tint/utils/math/hash.h"
diff --git a/src/tint/lang/wgsl/sem/function.h b/src/tint/lang/wgsl/sem/function.h
index eda36c0..3621a31 100644
--- a/src/tint/lang/wgsl/sem/function.h
+++ b/src/tint/lang/wgsl/sem/function.h
@@ -32,7 +32,7 @@
 #include <optional>
 #include <utility>
 
-#include "src/tint/lang/wgsl/diagnostic_severity.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/sem/call.h"
 #include "src/tint/utils/containers/unique_vector.h"
 #include "src/tint/utils/containers/vector.h"
diff --git a/src/tint/lang/wgsl/sem/module.h b/src/tint/lang/wgsl/sem/module.h
index 98c1022..c32236a 100644
--- a/src/tint/lang/wgsl/sem/module.h
+++ b/src/tint/lang/wgsl/sem/module.h
@@ -29,7 +29,7 @@
 #define SRC_TINT_LANG_WGSL_SEM_MODULE_H_
 
 #include "src/tint/lang/wgsl/ast/diagnostic_control.h"
-#include "src/tint/lang/wgsl/extension.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/sem/node.h"
 #include "src/tint/utils/containers/vector.h"
 
diff --git a/src/tint/lang/wgsl/writer/raise/raise.cc b/src/tint/lang/wgsl/writer/raise/raise.cc
index 8d45a4b..1955fbd 100644
--- a/src/tint/lang/wgsl/writer/raise/raise.cc
+++ b/src/tint/lang/wgsl/writer/raise/raise.cc
@@ -35,7 +35,7 @@
 #include "src/tint/lang/core/ir/load.h"
 #include "src/tint/lang/core/ir/transform/rename_conflicts.h"
 #include "src/tint/lang/core/type/pointer.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
+#include "src/tint/lang/wgsl/enums.h"
 #include "src/tint/lang/wgsl/ir/builtin_call.h"
 #include "src/tint/lang/wgsl/writer/raise/ptr_to_ref.h"
 #include "src/tint/lang/wgsl/writer/raise/value_to_let.h"