[tint] Add LanguageFeature enum

Includes the readonly_and_readwrite_storage_textures feature.

Bug: tint:2088
Change-Id: Idabed901bd3c3ee449dcd1ac49deb86399050827
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/158624
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/wgsl/BUILD.bazel b/src/tint/lang/wgsl/BUILD.bazel
index 9b7655d..0dd8726 100644
--- a/src/tint/lang/wgsl/BUILD.bazel
+++ b/src/tint/lang/wgsl/BUILD.bazel
@@ -43,12 +43,14 @@
     "diagnostic_rule.cc",
     "diagnostic_severity.cc",
     "extension.cc",
+    "language_feature.cc",
   ],
   hdrs = [
     "builtin_fn.h",
     "diagnostic_rule.h",
     "diagnostic_severity.h",
     "extension.h",
+    "language_feature.h",
   ],
   deps = [
     "//src/tint/utils/containers",
@@ -71,6 +73,7 @@
     "diagnostic_rule_test.cc",
     "diagnostic_severity_test.cc",
     "extension_test.cc",
+    "language_feature_test.cc",
     "wgsl_test.cc",
   ] + select({
     "//conditions:default": [],
diff --git a/src/tint/lang/wgsl/BUILD.cmake b/src/tint/lang/wgsl/BUILD.cmake
index cea7aa0..7a1599d 100644
--- a/src/tint/lang/wgsl/BUILD.cmake
+++ b/src/tint/lang/wgsl/BUILD.cmake
@@ -58,6 +58,8 @@
   lang/wgsl/diagnostic_severity.h
   lang/wgsl/extension.cc
   lang/wgsl/extension.h
+  lang/wgsl/language_feature.cc
+  lang/wgsl/language_feature.h
 )
 
 tint_target_add_dependencies(tint_lang_wgsl lib
@@ -80,6 +82,7 @@
   lang/wgsl/diagnostic_rule_test.cc
   lang/wgsl/diagnostic_severity_test.cc
   lang/wgsl/extension_test.cc
+  lang/wgsl/language_feature_test.cc
   lang/wgsl/wgsl_test.cc
 )
 
diff --git a/src/tint/lang/wgsl/BUILD.gn b/src/tint/lang/wgsl/BUILD.gn
index 10d334a..619e1f8 100644
--- a/src/tint/lang/wgsl/BUILD.gn
+++ b/src/tint/lang/wgsl/BUILD.gn
@@ -52,6 +52,8 @@
     "diagnostic_severity.h",
     "extension.cc",
     "extension.h",
+    "language_feature.cc",
+    "language_feature.h",
   ]
   deps = [
     "${tint_src_dir}/utils/containers",
@@ -71,6 +73,7 @@
       "diagnostic_rule_test.cc",
       "diagnostic_severity_test.cc",
       "extension_test.cc",
+      "language_feature_test.cc",
       "wgsl_test.cc",
     ]
     deps = [
diff --git a/src/tint/lang/wgsl/language_feature.cc b/src/tint/lang/wgsl/language_feature.cc
new file mode 100644
index 0000000..a5e0430
--- /dev/null
+++ b/src/tint/lang/wgsl/language_feature.cc
@@ -0,0 +1,61 @@
+// 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 == "readonly_and_readwrite_storage_textures") {
+        return LanguageFeature::kReadonlyAndReadwriteStorageTextures;
+    }
+    return LanguageFeature::kUndefined;
+}
+
+std::string_view ToString(LanguageFeature value) {
+    switch (value) {
+        case LanguageFeature::kUndefined:
+            return "undefined";
+        case LanguageFeature::kReadonlyAndReadwriteStorageTextures:
+            return "readonly_and_readwrite_storage_textures";
+    }
+    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
new file mode 100644
index 0000000..782b515
--- /dev/null
+++ b/src/tint/lang/wgsl/language_feature.cc.tmpl
@@ -0,0 +1,23 @@
+{{- /*
+--------------------------------------------------------------------------------
+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
new file mode 100644
index 0000000..0a5573a
--- /dev/null
+++ b/src/tint/lang/wgsl/language_feature.h
@@ -0,0 +1,78 @@
+// 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 "src/tint/utils/containers/unique_vector.h"
+#include "src/tint/utils/traits/traits.h"
+
+namespace tint::wgsl {
+
+/// An enumerator of WGSL language features
+/// @see src/tint/lang/wgsl/intrinsics.def for language feature descriptions
+enum class LanguageFeature : uint8_t {
+    kUndefined,
+    kReadonlyAndReadwriteStorageTextures,
+};
+
+/// @param value the enum value
+/// @returns the string for the given enum value
+std::string_view ToString(LanguageFeature value);
+
+/// @param out the stream to write to
+/// @param value the LanguageFeature
+/// @returns @p out so calls can be chained
+template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
+auto& operator<<(STREAM& out, LanguageFeature value) {
+    return out << ToString(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 const char* kLanguageFeatureStrings[] = {
+    "readonly_and_readwrite_storage_textures",
+};
+
+// A unique vector of language features
+using LanguageFeatures = UniqueVector<LanguageFeature, 4>;
+
+}  // 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
new file mode 100644
index 0000000..cbe9f78
--- /dev/null
+++ b/src/tint/lang/wgsl/language_feature.h.tmpl
@@ -0,0 +1,32 @@
+{{- /*
+--------------------------------------------------------------------------------
+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 "src/tint/utils/traits/traits.h"
+#include "src/tint/utils/containers/unique_vector.h"
+
+namespace tint::wgsl {
+
+/// An enumerator of WGSL language features
+/// @see src/tint/lang/wgsl/intrinsics.def for language feature descriptions
+{{ Eval "DeclareEnum" $enum}}
+
+// A unique vector of language features
+using LanguageFeatures = UniqueVector<LanguageFeature, 4>;
+
+}  // namespace tint::wgsl
+
+#endif  // SRC_TINT_LANG_WGSL_LANGUAGE_FEATURE_H_
diff --git a/src/tint/lang/wgsl/language_feature_test.cc b/src/tint/lang/wgsl/language_feature_test.cc
new file mode 100644
index 0000000..4597ce9
--- /dev/null
+++ b/src/tint/lang/wgsl/language_feature_test.cc
@@ -0,0 +1,94 @@
+// 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 Case {
+    const char* string;
+    LanguageFeature value;
+};
+
+inline std::ostream& operator<<(std::ostream& out, Case c) {
+    return out << "'" << std::string(c.string) << "'";
+}
+
+static constexpr Case kValidCases[] = {
+    {"readonly_and_readwrite_storage_textures",
+     LanguageFeature::kReadonlyAndReadwriteStorageTextures},
+};
+
+static constexpr Case kInvalidCases[] = {
+    {"eadonly_and_readwrite_stccrage_textures", LanguageFeature::kUndefined},
+    {"rladonly_a3readrite_storage_textures", LanguageFeature::kUndefined},
+    {"readonly_and_readwriVe_storage_textures", LanguageFeature::kUndefined},
+};
+
+using LanguageFeatureParseTest = testing::TestWithParam<Case>;
+
+TEST_P(LanguageFeatureParseTest, Parse) {
+    const char* string = GetParam().string;
+    LanguageFeature expect = GetParam().value;
+    EXPECT_EQ(expect, ParseLanguageFeature(string));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidCases, LanguageFeatureParseTest, testing::ValuesIn(kValidCases));
+INSTANTIATE_TEST_SUITE_P(InvalidCases, LanguageFeatureParseTest, testing::ValuesIn(kInvalidCases));
+
+using LanguageFeaturePrintTest = testing::TestWithParam<Case>;
+
+TEST_P(LanguageFeaturePrintTest, Print) {
+    LanguageFeature value = GetParam().value;
+    const char* expect = GetParam().string;
+    EXPECT_EQ(expect, tint::ToString(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidCases, LanguageFeaturePrintTest, testing::ValuesIn(kValidCases));
+
+}  // 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
new file mode 100644
index 0000000..fe98798
--- /dev/null
+++ b/src/tint/lang/wgsl/language_feature_test.cc.tmpl
@@ -0,0 +1,29 @@
+{{- /*
+--------------------------------------------------------------------------------
+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/wgsl.def b/src/tint/lang/wgsl/wgsl.def
index 06039b2..a66c2ba 100644
--- a/src/tint/lang/wgsl/wgsl.def
+++ b/src/tint/lang/wgsl/wgsl.def
@@ -90,6 +90,11 @@
   chromium_experimental_pixel_local
 }
 
+// https://gpuweb.github.io/gpuweb/wgsl/#language-extensions-sec
+enum language_feature {
+  readonly_and_readwrite_storage_textures
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WGSL primitive types                                                       //
 // Types may be decorated with @precedence(N) to prioritize which type        //