[tint][ir] Rename names going from IR to Program.
When converting from IR to Program, re-write any name which may conflict
with a WGSL keyword, reserved word, type name or enum name.
Bug: 42250952
Change-Id: I4c9c925ef25d506e697b7e3e61261f5ab3662c05
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/232894
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/wgsl/common/BUILD.bazel b/src/tint/lang/wgsl/common/BUILD.bazel
index 192bd28..2cea2a8 100644
--- a/src/tint/lang/wgsl/common/BUILD.bazel
+++ b/src/tint/lang/wgsl/common/BUILD.bazel
@@ -40,9 +40,11 @@
name = "common",
srcs = [
"common.cc",
+ "reserved_words.cc",
],
hdrs = [
"allowed_features.h",
+ "reserved_words.h",
],
deps = [
"//src/tint/lang/wgsl",
diff --git a/src/tint/lang/wgsl/common/BUILD.cmake b/src/tint/lang/wgsl/common/BUILD.cmake
index bc0e4cf..2a2784c 100644
--- a/src/tint/lang/wgsl/common/BUILD.cmake
+++ b/src/tint/lang/wgsl/common/BUILD.cmake
@@ -41,6 +41,8 @@
tint_add_target(tint_lang_wgsl_common lib
lang/wgsl/common/allowed_features.h
lang/wgsl/common/common.cc
+ lang/wgsl/common/reserved_words.cc
+ lang/wgsl/common/reserved_words.h
)
tint_target_add_dependencies(tint_lang_wgsl_common lib
diff --git a/src/tint/lang/wgsl/common/BUILD.gn b/src/tint/lang/wgsl/common/BUILD.gn
index 3981b0b..f2fb1d9 100644
--- a/src/tint/lang/wgsl/common/BUILD.gn
+++ b/src/tint/lang/wgsl/common/BUILD.gn
@@ -47,6 +47,8 @@
sources = [
"allowed_features.h",
"common.cc",
+ "reserved_words.cc",
+ "reserved_words.h",
]
deps = [
"${dawn_root}/src/utils:utils",
diff --git a/src/tint/lang/wgsl/common/reserved_words.cc b/src/tint/lang/wgsl/common/reserved_words.cc
new file mode 100644
index 0000000..d41c757
--- /dev/null
+++ b/src/tint/lang/wgsl/common/reserved_words.cc
@@ -0,0 +1,67 @@
+// 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.
+
+#include "src/tint/lang/wgsl/common/reserved_words.h"
+
+namespace tint::wgsl {
+
+bool IsReserved(std::string_view s) {
+ return s == "NULL" || s == "Self" || s == "abstract" || s == "active" || s == "alignas" ||
+ s == "alignof" || s == "as" || s == "asm" || s == "asm_fragment" || s == "async" ||
+ s == "attribute" || s == "auto" || s == "await" || s == "become" || s == "cast" ||
+ s == "catch" || s == "class" || s == "co_await" || s == "co_return" || s == "co_yield" ||
+ s == "coherent" || s == "column_major" || s == "common" || s == "compile" ||
+ s == "compile_fragment" || s == "concept" || s == "const_cast" || s == "consteval" ||
+ s == "constexpr" || s == "constinit" || s == "crate" || s == "debugger" ||
+ s == "decltype" || s == "delete" || s == "demote" || s == "demote_to_helper" ||
+ s == "do" || s == "dynamic_cast" || s == "enum" || s == "explicit" || s == "export" ||
+ s == "extends" || s == "extern" || s == "external" || s == "fallthrough" ||
+ s == "filter" || s == "final" || s == "finally" || s == "friend" || s == "from" ||
+ s == "fxgroup" || s == "get" || s == "goto" || s == "groupshared" || s == "highp" ||
+ s == "impl" || s == "implements" || s == "import" || s == "inline" ||
+ s == "instanceof" || s == "interface" || s == "layout" || s == "lowp" || s == "macro" ||
+ s == "macro_rules" || s == "match" || s == "mediump" || s == "meta" || s == "mod" ||
+ s == "module" || s == "move" || s == "mut" || s == "mutable" || s == "namespace" ||
+ s == "new" || s == "nil" || s == "noexcept" || s == "noinline" ||
+ s == "nointerpolation" || s == "non_coherent" || s == "noncoherent" ||
+ s == "noperspective" || s == "null" || s == "nullptr" || s == "of" || s == "operator" ||
+ s == "package" || s == "packoffset" || s == "partition" || s == "pass" || s == "patch" ||
+ s == "pixelfragment" || s == "precise" || s == "precision" || s == "premerge" ||
+ s == "priv" || s == "protected" || s == "pub" || s == "public" || s == "readonly" ||
+ s == "ref" || s == "regardless" || s == "register" || s == "reinterpret_cast" ||
+ s == "require" || s == "resource" || s == "restrict" || s == "self" || s == "set" ||
+ s == "shared" || s == "sizeof" || s == "smooth" || s == "snorm" || s == "static" ||
+ s == "static_assert" || s == "static_cast" || s == "std" || s == "subroutine" ||
+ s == "super" || s == "target" || s == "template" || s == "this" || s == "thread_local" ||
+ s == "throw" || s == "trait" || s == "try" || s == "type" || s == "typedef" ||
+ s == "typeid" || s == "typename" || s == "typeof" || s == "union" || s == "unless" ||
+ s == "unorm" || s == "unsafe" || s == "unsized" || s == "use" || s == "using" ||
+ s == "varying" || s == "virtual" || s == "volatile" || s == "wgsl" || s == "where" ||
+ s == "with" || s == "writeonly" || s == "yield";
+}
+
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/common/reserved_words.h b/src/tint/lang/wgsl/common/reserved_words.h
new file mode 100644
index 0000000..900dbf4
--- /dev/null
+++ b/src/tint/lang/wgsl/common/reserved_words.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef SRC_TINT_LANG_WGSL_COMMON_RESERVED_WORDS_H_
+#define SRC_TINT_LANG_WGSL_COMMON_RESERVED_WORDS_H_
+
+#include <string_view>
+
+namespace tint::wgsl {
+
+// https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords
+bool IsReserved(std::string_view s);
+
+} // namespace tint::wgsl
+
+#endif // SRC_TINT_LANG_WGSL_COMMON_RESERVED_WORDS_H_
diff --git a/src/tint/lang/wgsl/reader/parser/parser.cc b/src/tint/lang/wgsl/reader/parser/parser.cc
index 1b56eb1..a6bed34 100644
--- a/src/tint/lang/wgsl/reader/parser/parser.cc
+++ b/src/tint/lang/wgsl/reader/parser/parser.cc
@@ -55,6 +55,7 @@
#include "src/tint/lang/wgsl/ast/var.h"
#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
#include "src/tint/lang/wgsl/ast/workgroup_attribute.h"
+#include "src/tint/lang/wgsl/common/reserved_words.h"
#include "src/tint/lang/wgsl/reader/parser/classify_template_args.h"
#include "src/tint/lang/wgsl/reader/parser/lexer.h"
#include "src/tint/utils/containers/reverse.h"
@@ -86,45 +87,6 @@
/// parser on error.
constexpr size_t const kMaxResynchronizeLookahead = 32;
-// https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords
-//
-// Must be called with an identifier token.
-bool is_reserved(const Token& t) {
- auto s = t.to_str_view();
- return s == "NULL" || s == "Self" || s == "abstract" || s == "active" || s == "alignas" ||
- s == "alignof" || s == "as" || s == "asm" || s == "asm_fragment" || s == "async" ||
- s == "attribute" || s == "auto" || s == "await" || s == "become" || s == "cast" ||
- s == "catch" || s == "class" || s == "co_await" || s == "co_return" || s == "co_yield" ||
- s == "coherent" || s == "column_major" || s == "common" || s == "compile" ||
- s == "compile_fragment" || s == "concept" || s == "const_cast" || s == "consteval" ||
- s == "constexpr" || s == "constinit" || s == "crate" || s == "debugger" ||
- s == "decltype" || s == "delete" || s == "demote" || s == "demote_to_helper" ||
- s == "do" || s == "dynamic_cast" || s == "enum" || s == "explicit" || s == "export" ||
- s == "extends" || s == "extern" || s == "external" || s == "filter" || s == "final" ||
- s == "finally" || s == "friend" || s == "from" || s == "fxgroup" || s == "get" ||
- s == "goto" || s == "groupshared" || s == "highp" || s == "impl" || s == "implements" ||
- s == "import" || s == "inline" || s == "instanceof" || s == "interface" ||
- s == "layout" || s == "lowp" || s == "macro" || s == "macro_rules" || s == "match" ||
- s == "mediump" || s == "meta" || s == "mod" || s == "module" || s == "move" ||
- s == "mut" || s == "mutable" || s == "namespace" || s == "new" || s == "nil" ||
- s == "noexcept" || s == "noinline" || s == "nointerpolation" || s == "non_coherent" ||
- s == "noncoherent" || s == "noperspective" || s == "null" || s == "nullptr" ||
- s == "of" || s == "operator" || s == "package" || s == "packoffset" ||
- s == "partition" || s == "pass" || s == "patch" || s == "pixelfragment" ||
- s == "precise" || s == "precision" || s == "premerge" || s == "priv" ||
- s == "protected" || s == "pub" || s == "public" || s == "readonly" || s == "ref" ||
- s == "regardless" || s == "register" || s == "reinterpret_cast" || s == "require" ||
- s == "resource" || s == "restrict" || s == "self" || s == "set" || s == "shared" ||
- s == "sizeof" || s == "smooth" || s == "snorm" || s == "static" ||
- s == "static_assert" || s == "static_cast" || s == "std" || s == "subroutine" ||
- s == "super" || s == "target" || s == "template" || s == "this" || s == "thread_local" ||
- s == "throw" || s == "trait" || s == "try" || s == "type" || s == "typedef" ||
- s == "typeid" || s == "typename" || s == "typeof" || s == "union" || s == "unless" ||
- s == "unorm" || s == "unsafe" || s == "unsized" || s == "use" || s == "using" ||
- s == "varying" || s == "virtual" || s == "volatile" || s == "wgsl" || s == "where" ||
- s == "with" || s == "writeonly" || s == "yield";
-}
-
/// Enter-exit counters for block token types.
/// Used by sync_to() to skip over closing block tokens that were opened during
/// the forward scan.
@@ -3408,7 +3370,7 @@
synchronized_ = true;
next();
- if (is_reserved(t)) {
+ if (IsReserved(t.to_str_view())) {
return AddError(t.source(), "'" + t.to_str() + "' is a reserved keyword");
}
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 50ebb10..7baddd0 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -83,6 +83,7 @@
#include "src/tint/lang/core/type/texture.h"
#include "src/tint/lang/core/type/type.h"
#include "src/tint/lang/wgsl/ast/type.h"
+#include "src/tint/lang/wgsl/common/reserved_words.h"
#include "src/tint/lang/wgsl/ir/builtin_call.h"
#include "src/tint/lang/wgsl/ir/unary.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
@@ -1158,15 +1159,63 @@
// Bindings
////////////////////////////////////////////////////////////////////////////////////////////////
+ bool IsKeyword(std::string_view s) {
+ return s == "alias" || s == "break" || s == "case" || s == "const" || s == "const_assert" ||
+ s == "continue" || s == "continuing" || s == "default" || s == "diagnostic" ||
+ s == "discard" || s == "else" || s == "enable" || s == "false" || s == "fn" ||
+ s == "for" || s == "if" || s == "let" || s == "loop" || s == "override" ||
+ s == "requires" || s == "return" || s == "struct" || s == "switch" || s == "true" ||
+ s == "var" || s == "while";
+ }
+
+ bool IsEnumName(std::string_view s) {
+ return s == "read" || s == "write" || s == "read_write" || s == "function" ||
+ s == "private" || s == "workgroup" || s == "uniform" || s == "storage" ||
+ s == "rgba8unorm" || s == "rgba8snorm" || s == "rgba8uint" || s == "rgba8sint" ||
+ s == "rgba16uint" || s == "rgba16sint" || s == "rgba16float" || s == "r32uint" ||
+ s == "r32sint" || s == "r32float" || s == "rg32uint" || s == "rg32sint" ||
+ s == "rg32float" || s == "rgba32uint" || s == "rgba32sint" || s == "rgba32float" ||
+ s == "bgra8unorm";
+ }
+
+ bool IsTypeName(std::string_view s) {
+ return s == "bool" || s == "void" || s == "i32" || s == "u32" || s == "f32" || s == "f16" ||
+ s == "vec" || s == "vec2" || s == "vec3" || s == "vec4" || s == "vec2f" ||
+ s == "vec3f" || s == "vec4f" || s == "vec2h" || s == "vec3h" || s == "vec4h" ||
+ s == "vec2i" || s == "vec3i" || s == "vec4i" || s == "vec2u" || s == "vec3u" ||
+ s == "vec4u" || s == "mat2x2" || s == "mat2x3" || s == "mat2x4" || s == "mat3x2" ||
+ s == "mat3x3" || s == "mat3x4" || s == "mat4x2" || s == "mat4x3" || s == "mat4x4" ||
+ s == "mat2x2f" || s == "mat2x3f" || s == "mat2x4f" || s == "mat3x2f" ||
+ s == "mat3x3f" || s == "mat3x4f" || s == "mat4x2f" || s == "mat4x3f" ||
+ s == "mat4x4f" || s == "mat2x2h" || s == "mat2x3h" || s == "mat2x4h" ||
+ s == "mat3x2h" || s == "mat3x3h" || s == "mat3x4h" || s == "mat4x2h" ||
+ s == "mat4x3h" || s == "mat4x4h" || s == "atomic" || s == "array" || s == "ptr" ||
+ s == "texture_1d" || s == "texture_2d" || s == "texture_2d_array" ||
+ s == "texture_3d" || s == "texture_cube" || s == "texture_cube_array" ||
+ s == "texture_multisampled_2d" || s == "texture_depth_multisampled_2d" ||
+ s == "texture_external" || s == "texture_storage_1d" || s == "texture_storage_2d" ||
+ s == "texture_storage_2d_array" || s == "texture_storage_3d" ||
+ s == "texture_depth_2d" || s == "texture_depth_2d_array" ||
+ s == "texture_depth_cube" || s == "texture_depth_cube_array" || s == "sampler" ||
+ s == "sampler_comparison";
+ }
+
+ bool IsWGSLSafe(std::string_view name) {
+ return !IsReserved(name) && !IsKeyword(name) && !IsEnumName(name) && !IsTypeName(name);
+ }
+
/// @returns the AST name for the given value, creating and returning a new name on the first
/// call.
Symbol NameFor(const core::ir::Value* value, std::string_view suggested = {}) {
return names_.GetOrAdd(value, [&] {
if (!suggested.empty()) {
- return b.Symbols().Register(suggested);
- }
- if (auto sym = mod.NameOf(value)) {
- return b.Symbols().Register(sym.NameView());
+ if (IsWGSLSafe(suggested)) {
+ return b.Symbols().Register(suggested);
+ }
+ } else if (auto sym = mod.NameOf(value)) {
+ if (IsWGSLSafe(sym.NameView())) {
+ return b.Symbols().Register(sym.NameView());
+ }
}
return b.Symbols().New("v");
});
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index abb5f31..9227f10 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -319,6 +319,598 @@
)");
}
+TEST_F(IRToProgramTest, EnumWords) {
+ auto* fn = b.Function("f", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+
+ b.Append(fn->Block(), [&] {
+ Var("read", true);
+ Var("write", true);
+ Var("read_write", true);
+ Var("function", true);
+ Var("private", true);
+ Var("workgroup", true);
+ Var("uniform", true);
+ Var("storage", true);
+ Var("rgba8unorm", true);
+ Var("rgba8snorm", true);
+ Var("rgba8uint", true);
+ Var("rgba8sint", true);
+ Var("rgba16uint", true);
+ Var("rgba16sint", true);
+ Var("rgba16float", true);
+ Var("r32uint", true);
+ Var("r32sint", true);
+ Var("r32float", true);
+ Var("rg32uint", true);
+ Var("rg32sint", true);
+ Var("rg32float", true);
+ Var("rgba32uint", true);
+ Var("rgba32sint", true);
+ Var("rgba32float", true);
+ Var("bgra8unorm", true);
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+@fragment
+fn f() {
+ var v : bool = true;
+ var v_1 : bool = true;
+ var v_2 : bool = true;
+ var v_3 : bool = true;
+ var v_4 : bool = true;
+ var v_5 : bool = true;
+ var v_6 : bool = true;
+ var v_7 : bool = true;
+ var v_8 : bool = true;
+ var v_9 : bool = true;
+ var v_10 : bool = true;
+ var v_11 : bool = true;
+ var v_12 : bool = true;
+ var v_13 : bool = true;
+ var v_14 : bool = true;
+ var v_15 : bool = true;
+ var v_16 : bool = true;
+ var v_17 : bool = true;
+ var v_18 : bool = true;
+ var v_19 : bool = true;
+ var v_20 : bool = true;
+ var v_21 : bool = true;
+ var v_22 : bool = true;
+ var v_23 : bool = true;
+ var v_24 : bool = true;
+}
+)");
+}
+
+TEST_F(IRToProgramTest, TypeWords) {
+ auto* fn = b.Function("f", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+
+ b.Append(fn->Block(), [&] {
+ Var("bool", true);
+ Var("void", true);
+ Var("i32", true);
+ Var("u32", true);
+ Var("f32", true);
+ Var("f16", true);
+ Var("vec", true);
+ Var("vec2", true);
+ Var("vec3", true);
+ Var("vec4", true);
+ Var("vec2f", true);
+ Var("vec3f", true);
+ Var("vec4f", true);
+ Var("vec2h", true);
+ Var("vec3h", true);
+ Var("vec4h", true);
+ Var("vec2i", true);
+ Var("vec3i", true);
+ Var("vec4i", true);
+ Var("vec2u", true);
+ Var("vec3u", true);
+ Var("vec4u", true);
+ Var("mat2x2", true);
+ Var("mat2x3", true);
+ Var("mat2x4", true);
+ Var("mat3x2", true);
+ Var("mat3x3", true);
+ Var("mat3x4", true);
+ Var("mat4x2", true);
+ Var("mat4x3", true);
+ Var("mat4x4", true);
+ Var("mat2x2f", true);
+ Var("mat2x3f", true);
+ Var("mat2x4f", true);
+ Var("mat3x2f", true);
+ Var("mat3x3f", true);
+ Var("mat3x4f", true);
+ Var("mat4x2f", true);
+ Var("mat4x3f", true);
+ Var("mat4x4f", true);
+ Var("mat2x2h", true);
+ Var("mat2x3h", true);
+ Var("mat2x4h", true);
+ Var("mat3x2h", true);
+ Var("mat3x3h", true);
+ Var("mat3x4h", true);
+ Var("mat4x2h", true);
+ Var("mat4x3h", true);
+ Var("mat4x4h", true);
+ Var("atomic", true);
+ Var("array", true);
+ Var("ptr", true);
+ Var("texture_1d", true);
+ Var("texture_2d", true);
+ Var("texture_2d_array", true);
+ Var("texture_3d", true);
+ Var("texture_cube", true);
+ Var("texture_cube_array", true);
+ Var("texture_multisampled_2d", true);
+ Var("texture_depth_multisampled_2d", true);
+ Var("texture_external", true);
+ Var("texture_storage_1d", true);
+ Var("texture_storage_2d", true);
+ Var("texture_storage_2d_array", true);
+ Var("texture_storage_3d", true);
+ Var("texture_depth_2d", true);
+ Var("texture_depth_2d_array", true);
+ Var("texture_depth_cube", true);
+ Var("texture_depth_cube_array", true);
+ Var("sampler", true);
+ Var("sampler_comparison", true);
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+@fragment
+fn f() {
+ var v : bool = true;
+ var v_1 : bool = true;
+ var v_2 : bool = true;
+ var v_3 : bool = true;
+ var v_4 : bool = true;
+ var v_5 : bool = true;
+ var v_6 : bool = true;
+ var v_7 : bool = true;
+ var v_8 : bool = true;
+ var v_9 : bool = true;
+ var v_10 : bool = true;
+ var v_11 : bool = true;
+ var v_12 : bool = true;
+ var v_13 : bool = true;
+ var v_14 : bool = true;
+ var v_15 : bool = true;
+ var v_16 : bool = true;
+ var v_17 : bool = true;
+ var v_18 : bool = true;
+ var v_19 : bool = true;
+ var v_20 : bool = true;
+ var v_21 : bool = true;
+ var v_22 : bool = true;
+ var v_23 : bool = true;
+ var v_24 : bool = true;
+ var v_25 : bool = true;
+ var v_26 : bool = true;
+ var v_27 : bool = true;
+ var v_28 : bool = true;
+ var v_29 : bool = true;
+ var v_30 : bool = true;
+ var v_31 : bool = true;
+ var v_32 : bool = true;
+ var v_33 : bool = true;
+ var v_34 : bool = true;
+ var v_35 : bool = true;
+ var v_36 : bool = true;
+ var v_37 : bool = true;
+ var v_38 : bool = true;
+ var v_39 : bool = true;
+ var v_40 : bool = true;
+ var v_41 : bool = true;
+ var v_42 : bool = true;
+ var v_43 : bool = true;
+ var v_44 : bool = true;
+ var v_45 : bool = true;
+ var v_46 : bool = true;
+ var v_47 : bool = true;
+ var v_48 : bool = true;
+ var v_49 : bool = true;
+ var v_50 : bool = true;
+ var v_51 : bool = true;
+ var v_52 : bool = true;
+ var v_53 : bool = true;
+ var v_54 : bool = true;
+ var v_55 : bool = true;
+ var v_56 : bool = true;
+ var v_57 : bool = true;
+ var v_58 : bool = true;
+ var v_59 : bool = true;
+ var v_60 : bool = true;
+ var v_61 : bool = true;
+ var v_62 : bool = true;
+ var v_63 : bool = true;
+ var v_64 : bool = true;
+ var v_65 : bool = true;
+ var v_66 : bool = true;
+ var v_67 : bool = true;
+ var v_68 : bool = true;
+ var v_69 : bool = true;
+ var v_70 : bool = true;
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Keywords) {
+ auto* fn = b.Function("f", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+
+ b.Append(fn->Block(), [&] {
+ Var("alias", true);
+ Var("break", true);
+ Var("case", true);
+ Var("const", true);
+ Var("const_assert", true);
+ Var("continue", true);
+ Var("continuing", true);
+ Var("default", true);
+ Var("diagnostic", true);
+ Var("discard", true);
+ Var("else", true);
+ Var("enable", true);
+ Var("false", true);
+ Var("fn", true);
+ Var("for", true);
+ Var("if", true);
+ Var("let", true);
+ Var("loop", true);
+ Var("override", true);
+ Var("requires", true);
+ Var("return", true);
+ Var("struct", true);
+ Var("switch", true);
+ Var("true", true);
+ Var("var", true);
+ Var("while", true);
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+@fragment
+fn f() {
+ var v : bool = true;
+ var v_1 : bool = true;
+ var v_2 : bool = true;
+ var v_3 : bool = true;
+ var v_4 : bool = true;
+ var v_5 : bool = true;
+ var v_6 : bool = true;
+ var v_7 : bool = true;
+ var v_8 : bool = true;
+ var v_9 : bool = true;
+ var v_10 : bool = true;
+ var v_11 : bool = true;
+ var v_12 : bool = true;
+ var v_13 : bool = true;
+ var v_14 : bool = true;
+ var v_15 : bool = true;
+ var v_16 : bool = true;
+ var v_17 : bool = true;
+ var v_18 : bool = true;
+ var v_19 : bool = true;
+ var v_20 : bool = true;
+ var v_21 : bool = true;
+ var v_22 : bool = true;
+ var v_23 : bool = true;
+ var v_24 : bool = true;
+ var v_25 : bool = true;
+}
+)");
+}
+
+TEST_F(IRToProgramTest, ReservedWords) {
+ auto* fn = b.Function("f", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+
+ b.Append(fn->Block(), [&] {
+ Var("NULL", true);
+ Var("Self", true);
+ Var("abstract", true);
+ Var("active", true);
+ Var("alignas", true);
+ Var("alignof", true);
+ Var("as", true);
+ Var("asm", true);
+ Var("asm_fragment", true);
+ Var("async", true);
+ Var("attribute", true);
+ Var("auto", true);
+ Var("await", true);
+ Var("become", true);
+ Var("cast", true);
+ Var("catch", true);
+ Var("class", true);
+ Var("co_await", true);
+ Var("co_return", true);
+ Var("co_yield", true);
+ Var("coherent", true);
+ Var("column_major", true);
+ Var("common", true);
+ Var("compile", true);
+ Var("compile_fragment", true);
+ Var("concept", true);
+ Var("const_cast", true);
+ Var("consteval", true);
+ Var("constexpr", true);
+ Var("constinit", true);
+ Var("crate", true);
+ Var("debugger", true);
+ Var("decltype", true);
+ Var("delete", true);
+ Var("demote", true);
+ Var("demote_to_helper", true);
+ Var("do", true);
+ Var("dynamic_cast", true);
+ Var("enum", true);
+ Var("explicit", true);
+ Var("export", true);
+ Var("extends", true);
+ Var("extern", true);
+ Var("external", true);
+ Var("fallthrough", true);
+ Var("filter", true);
+ Var("final", true);
+ Var("finally", true);
+ Var("friend", true);
+ Var("from", true);
+ Var("fxgroup", true);
+ Var("get", true);
+ Var("goto", true);
+ Var("groupshared", true);
+ Var("highp", true);
+ Var("impl", true);
+ Var("implements", true);
+ Var("import", true);
+ Var("inline", true);
+ Var("instanceof", true);
+ Var("interface", true);
+ Var("layout", true);
+ Var("lowp", true);
+ Var("macro", true);
+ Var("macro_rules", true);
+ Var("match", true);
+ Var("mediump", true);
+ Var("meta", true);
+ Var("mod", true);
+ Var("module", true);
+ Var("move", true);
+ Var("mut", true);
+ Var("mutable", true);
+ Var("namespace", true);
+ Var("new", true);
+ Var("nil", true);
+ Var("noexcept", true);
+ Var("noinline", true);
+ Var("nointerpolation", true);
+ Var("non_coherent", true);
+ Var("noncoherent", true);
+ Var("noperspective", true);
+ Var("null", true);
+ Var("nullptr", true);
+ Var("of", true);
+ Var("operator", true);
+ Var("package", true);
+ Var("packoffset", true);
+ Var("partition", true);
+ Var("pass", true);
+ Var("patch", true);
+ Var("pixelfragment", true);
+ Var("precise", true);
+ Var("precision", true);
+ Var("premerge", true);
+ Var("priv", true);
+ Var("protected", true);
+ Var("pub", true);
+ Var("public", true);
+ Var("readonly", true);
+ Var("ref", true);
+ Var("regardless", true);
+ Var("register", true);
+ Var("reinterpret_cast", true);
+ Var("require", true);
+ Var("resource", true);
+ Var("restrict", true);
+ Var("self", true);
+ Var("set", true);
+ Var("shared", true);
+ Var("sizeof", true);
+ Var("smooth", true);
+ Var("snorm", true);
+ Var("static", true);
+ Var("static_assert", true);
+ Var("static_cast", true);
+ Var("std", true);
+ Var("subroutine", true);
+ Var("super", true);
+ Var("target", true);
+ Var("template", true);
+ Var("this", true);
+ Var("thread_local", true);
+ Var("throw", true);
+ Var("trait", true);
+ Var("try", true);
+ Var("type", true);
+ Var("typedef", true);
+ Var("typeid", true);
+ Var("typename", true);
+ Var("typeof", true);
+ Var("union", true);
+ Var("unless", true);
+ Var("unorm", true);
+ Var("unsafe", true);
+ Var("unsized", true);
+ Var("use", true);
+ Var("using", true);
+ Var("varying", true);
+ Var("virtual", true);
+ Var("volatile", true);
+ Var("wgsl", true);
+ Var("where", true);
+ Var("with", true);
+ Var("writeonly", true);
+ Var("yield", true);
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+@fragment
+fn f() {
+ var v : bool = true;
+ var v_1 : bool = true;
+ var v_2 : bool = true;
+ var v_3 : bool = true;
+ var v_4 : bool = true;
+ var v_5 : bool = true;
+ var v_6 : bool = true;
+ var v_7 : bool = true;
+ var v_8 : bool = true;
+ var v_9 : bool = true;
+ var v_10 : bool = true;
+ var v_11 : bool = true;
+ var v_12 : bool = true;
+ var v_13 : bool = true;
+ var v_14 : bool = true;
+ var v_15 : bool = true;
+ var v_16 : bool = true;
+ var v_17 : bool = true;
+ var v_18 : bool = true;
+ var v_19 : bool = true;
+ var v_20 : bool = true;
+ var v_21 : bool = true;
+ var v_22 : bool = true;
+ var v_23 : bool = true;
+ var v_24 : bool = true;
+ var v_25 : bool = true;
+ var v_26 : bool = true;
+ var v_27 : bool = true;
+ var v_28 : bool = true;
+ var v_29 : bool = true;
+ var v_30 : bool = true;
+ var v_31 : bool = true;
+ var v_32 : bool = true;
+ var v_33 : bool = true;
+ var v_34 : bool = true;
+ var v_35 : bool = true;
+ var v_36 : bool = true;
+ var v_37 : bool = true;
+ var v_38 : bool = true;
+ var v_39 : bool = true;
+ var v_40 : bool = true;
+ var v_41 : bool = true;
+ var v_42 : bool = true;
+ var v_43 : bool = true;
+ var v_44 : bool = true;
+ var v_45 : bool = true;
+ var v_46 : bool = true;
+ var v_47 : bool = true;
+ var v_48 : bool = true;
+ var v_49 : bool = true;
+ var v_50 : bool = true;
+ var v_51 : bool = true;
+ var v_52 : bool = true;
+ var v_53 : bool = true;
+ var v_54 : bool = true;
+ var v_55 : bool = true;
+ var v_56 : bool = true;
+ var v_57 : bool = true;
+ var v_58 : bool = true;
+ var v_59 : bool = true;
+ var v_60 : bool = true;
+ var v_61 : bool = true;
+ var v_62 : bool = true;
+ var v_63 : bool = true;
+ var v_64 : bool = true;
+ var v_65 : bool = true;
+ var v_66 : bool = true;
+ var v_67 : bool = true;
+ var v_68 : bool = true;
+ var v_69 : bool = true;
+ var v_70 : bool = true;
+ var v_71 : bool = true;
+ var v_72 : bool = true;
+ var v_73 : bool = true;
+ var v_74 : bool = true;
+ var v_75 : bool = true;
+ var v_76 : bool = true;
+ var v_77 : bool = true;
+ var v_78 : bool = true;
+ var v_79 : bool = true;
+ var v_80 : bool = true;
+ var v_81 : bool = true;
+ var v_82 : bool = true;
+ var v_83 : bool = true;
+ var v_84 : bool = true;
+ var v_85 : bool = true;
+ var v_86 : bool = true;
+ var v_87 : bool = true;
+ var v_88 : bool = true;
+ var v_89 : bool = true;
+ var v_90 : bool = true;
+ var v_91 : bool = true;
+ var v_92 : bool = true;
+ var v_93 : bool = true;
+ var v_94 : bool = true;
+ var v_95 : bool = true;
+ var v_96 : bool = true;
+ var v_97 : bool = true;
+ var v_98 : bool = true;
+ var v_99 : bool = true;
+ var v_100 : bool = true;
+ var v_101 : bool = true;
+ var v_102 : bool = true;
+ var v_103 : bool = true;
+ var v_104 : bool = true;
+ var v_105 : bool = true;
+ var v_106 : bool = true;
+ var v_107 : bool = true;
+ var v_108 : bool = true;
+ var v_109 : bool = true;
+ var v_110 : bool = true;
+ var v_111 : bool = true;
+ var v_112 : bool = true;
+ var v_113 : bool = true;
+ var v_114 : bool = true;
+ var v_115 : bool = true;
+ var v_116 : bool = true;
+ var v_117 : bool = true;
+ var v_118 : bool = true;
+ var v_119 : bool = true;
+ var v_120 : bool = true;
+ var v_121 : bool = true;
+ var v_122 : bool = true;
+ var v_123 : bool = true;
+ var v_124 : bool = true;
+ var v_125 : bool = true;
+ var v_126 : bool = true;
+ var v_127 : bool = true;
+ var v_128 : bool = true;
+ var v_129 : bool = true;
+ var v_130 : bool = true;
+ var v_131 : bool = true;
+ var v_132 : bool = true;
+ var v_133 : bool = true;
+ var v_134 : bool = true;
+ var v_135 : bool = true;
+ var v_136 : bool = true;
+ var v_137 : bool = true;
+ var v_138 : bool = true;
+ var v_139 : bool = true;
+ var v_140 : bool = true;
+ var v_141 : bool = true;
+ var v_142 : bool = true;
+ var v_143 : bool = true;
+ var v_144 : bool = true;
+ var v_145 : bool = true;
+}
+)");
+}
+
////////////////////////////////////////////////////////////////////////////////
// Unary ops
////////////////////////////////////////////////////////////////////////////////