Import Tint changes from Dawn
Changes:
- 8f80d999c4738aef4f8d6664468e411c6b96df26 tint: Support multiple extensions per 'enable' by Ben Clayton <bclayton@google.com>
- ed28de3c53937fd6c0824f534b66cdcea7c437a7 tint: Support @diagnostic on for loops by James Price <jrprice@google.com>
- 9536ced0148a1c645f595326201200bb1fbe6975 tint: Support @diagnostic on while statements by James Price <jrprice@google.com>
- d0ed63eb64f7761eaf9414fbbbe2a0e1f13e3f7a tint: Support @diagnostic on switch statements by James Price <jrprice@google.com>
- 0607796ef8e26124299df34abf5f5a5a8803425e tint: Support @diagnostic on if statements by James Price <jrprice@google.com>
- a370186824298735bac70a710815ae32f00a213f tint: Fix compilation on latest MSVC by Antonio Maiorano <amaiorano@google.com>
- 1f6ce67ed28881b9a4a42713474120224eb6871d Move `clamp_frag_depth` transformer to backend. by dan sinclair <dsinclair@chromium.org>
- 6521a357f5a54e1ed6296170beb1d8a90a015111 Convert generators over to use external texture options. by dan sinclair <dsinclair@chromium.org>
- 97382d96f5b21e17be317ca048b69dfc11be33ce tint: Validate no template args with functions / builtin ... by Ben Clayton <bclayton@google.com>
- 6784a5276639cda54003d15656de5c10b103030d Sync keyword/reserved word list. by dan sinclair <dsinclair@chromium.org>
- 7bca4d72938a96abd493438e8ca0e1423ea5f20b tint: Remove constant::Value::AllEqual() by James Price <jrprice@google.com>
- 69253ee8a527594ffc64732b608abbddb6075273 tint/uniformity: Move recently added tests by James Price <jrprice@google.com>
- 8cb5ed8c2c48ec856b7c83f06ea5f9b077dc8230 tint/uniformity: Fix compound assignment LHS eval by James Price <jrprice@google.com>
- 79d0f2b78435ab8e1b2e393d1e22274c249a5e24 [ir] Add `ir::Builtin` by dan sinclair <dsinclair@chromium.org>
- cd097f40a3bf40b32324ba58913066dc5be95c18 tint: Improve module scope var diagnostic by Ben Clayton <bclayton@google.com>
- e95b59c34dcabb38db618f25e2e9137ca77306ed Add ExternalTextureOptions by dan sinclair <dsinclair@chromium.org>
- a36fa42dd73ce65491030331d4961a7af9de14f9 tint/cmd: Use correct preprocessor guard for libspriv.hpp by Ben Clayton <bclayton@google.com>
- 574b4b19964714444836fa5c391a265266dcfdcb tint: Fix constant::Splat conversion of struct types by Ben Clayton <bclayton@google.com>
- 7972a10aa8f3686c9b9d7f69fc9b18d9db53d3e7 tint: Add missing include by Ben Clayton <bclayton@google.com>
- cc3f851ad8f2e15f917a04f8543310a6c06af2c7 tint/transform: Polyfill f32 conversion to i32 or u32 by Ben Clayton <bclayton@google.com>
- f1f56b2d3ca8201ec7e9c2cbcabb565655a5ba15 tint/writer/glsl: Set default precision to highp by Ben Clayton <bclayton@google.com>
- 4fea9d0fbbcd1a88cf59e8b39ff7064a16e46a19 tint: Implement Switch() without recursion by Ben Clayton <bclayton@google.com>
- 23946b36060b87a622a93e0331777c171b95d643 tint: Move Switch() to own header by Ben Clayton <bclayton@google.com>
- 9543f74739118a853dd5e5a46297f5442c3352f8 Move sem::BuiltinType to builtin::Function. by dan sinclair <dsinclair@chromium.org>
- 03ee23ea9efa2c4d053cb2c23152fc23553a3eaf [ir] Convert materialized nodes to constants by dan sinclair <dsinclair@chromium.org>
- 2657b923c91b7e8a6259d80895dbae1d9f6c58d8 tint/writer/glsl: Fix vector `select` by Ben Clayton <bclayton@google.com>
- da353b4b391e1ed4527ca43f9e36ab2b3c463f1d tint: Flip evaluation order of assignment statements by Ben Clayton <bclayton@google.com>
- 43c5efa7e813dab3b7991cdbc901dce4c639b64f [ir] Add error helper to ir builder. by dan sinclair <dsinclair@chromium.org>
- 724a70f7a19862250bef6355203b024dbd431e35 [ir] Add user functions, value constructors and value con... by dan sinclair <dsinclair@chromium.org>
- 51be3420b89f36ce3a9e27306dc0743915e2153b tint/writer/glsl: Fix emission of lowest i32 value by Ben Clayton <bclayton@google.com>
- ce2578bc993371e473fe6f9801a2c287a5f8ad64 tint/transform: Refactor BuiltinPolyfill transform by Ben Clayton <bclayton@google.com>
- eebbdef81a2a112126c6eb66e21be9dd3c5d5b1e Split `BindingPoint` out of MultiplanarExternalTexture. by dan sinclair <dsinclair@chromium.org>
- 068eb3ebdaf66b47264392bfbc708f871d0b45ee tint: Fix HLSL texture queries and re-add textureNumLayer... by Ben Clayton <bclayton@google.com>
- 0917fbb1472a7ffcbf614b63b1ee8dca1758ffa5 Reland "Add writer to emit the AST." by dan sinclair <dsinclair@chromium.org>
- 2fe7f19026088e7cd0d1510f44fbcd4aef925c21 Use `absl::from_chars` instead of `strtod` by dan sinclair <dsinclair@chromium.org>
- 64196ad60adfc7f831485ac7b592b8cd5f865a55 Add array length options header to `tint.h`. by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: 8f80d999c4738aef4f8d6664468e411c6b96df26
Change-Id: I05826385293df952c7c1bbc5b8703614ea5a7cdd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/123080
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/.gitignore b/.gitignore
index 70384df..b6cec0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.DS_Store
.gclient
.gclient_entries
+.gclient_previous_sync_commits
.vs
.vscode/*
!.vscode/tasks.json
@@ -10,10 +11,12 @@
default.profraw
lcov.info
-/buildtools
+/build/
+/buildtools/
/cmake-build-*/
/out
/testing
+/third_party/abseil-cpp
/third_party/benchmark
/third_party/binutils
/third_party/catapult
@@ -28,5 +31,4 @@
/tools/clang
/tools/bin
-/build*/
/test.wgsl
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 615a71b..a2130e3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -77,6 +77,7 @@
option_if_not_defined(TINT_BUILD_MSL_WRITER "Build the MSL output writer" ON)
option_if_not_defined(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option_if_not_defined(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
+option_if_not_defined(TINT_BUILD_SYNTAX_TREE_WRITER "Build the syntax tree writer" OFF)
option_if_not_defined(TINT_BUILD_IR "Build the IR" ON)
@@ -113,6 +114,7 @@
message(STATUS "Tint build MSL writer: ${TINT_BUILD_MSL_WRITER}")
message(STATUS "Tint build SPIR-V writer: ${TINT_BUILD_SPV_WRITER}")
message(STATUS "Tint build WGSL writer: ${TINT_BUILD_WGSL_WRITER}")
+message(STATUS "Tint build Syntax Tree writer: ${TINT_BUILD_SYNTAX_TREE_WRITER}")
message(STATUS "Tint build IR: ${TINT_BUILD_IR}")
message(STATUS "Tint build fuzzers: ${TINT_BUILD_FUZZERS}")
message(STATUS "Tint build SPIRV-Tools fuzzer: ${TINT_BUILD_SPIRV_TOOLS_FUZZER}")
@@ -284,6 +286,7 @@
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_MSL_WRITER=$<BOOL:${TINT_BUILD_MSL_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_SPV_WRITER=$<BOOL:${TINT_BUILD_SPV_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_WGSL_WRITER=$<BOOL:${TINT_BUILD_WGSL_WRITER}>)
+ target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_SYNTAX_TREE_WRITER=$<BOOL:${TINT_BUILD_SYNTAX_TREE_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_IR=$<BOOL:${TINT_BUILD_IR}>)
if (COMPILER_IS_LIKE_GNU)
diff --git a/DEPS b/DEPS
index 007996b..3c1a058 100644
--- a/DEPS
+++ b/DEPS
@@ -85,6 +85,10 @@
'dep_type': 'cipd',
},
+ 'third_party/abseil-cpp': {
+ 'url': '{chromium_git}/chromium/src/third_party/abseil-cpp@bc3ab29356a081d0b5dd4ac55e30f4b45d8794cc',
+ },
+
# Dependencies required for testing
'testing': {
'url': '{chromium_git}/chromium/src/testing@d5ea1bf4b64781cfe38f207f56f264eb080d06b2',
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni
new file mode 100644
index 0000000..6440625
--- /dev/null
+++ b/build_overrides/dawn.gni
@@ -0,0 +1,43 @@
+# Copyright 2018 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# These are variables that are overridable by projects that include Dawn.
+# The values in this file are the defaults for when we are building from
+# Dawn's repository.
+
+# Whether we are building from Dawn's repository.
+# MUST be unset in other projects (will default to false).
+dawn_standalone = true
+
+# True if Dawn can access build/, testing/ and other Chrome folders.
+dawn_has_build = true
+
+# Defaults for these are set again in dawn_overrides_with_defaults.gni so that
+# users of Dawn don't have to set dirs if they happen to use the same as Dawn.
+
+# The paths to Dawn's dependencies
+dawn_abseil_dir = "//third_party/abseil-cpp"
+dawn_angle_dir = "//third_party/angle"
+dawn_jinja2_dir = "//third_party/jinja2"
+dawn_glfw_dir = "//third_party/glfw"
+dawn_googletest_dir = "//third_party/googletest"
+dawn_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src"
+dawn_swiftshader_dir = "//third_party/swiftshader"
+dawn_vulkan_loader_dir = "//third_party/vulkan-deps/vulkan-loader/src"
+dawn_vulkan_validation_layers_dir =
+ "//third_party/vulkan-deps/vulkan-validation-layers/src"
+
+# Optional path to a one-liner version file. Default is empty path indicating
+# that git should be used to figure out the version.
+dawn_version_file = ""
diff --git a/include/tint/tint.h b/include/tint/tint.h
index 758e62a..0a0c027 100644
--- a/include/tint/tint.h
+++ b/include/tint/tint.h
@@ -27,7 +27,6 @@
#include "src/tint/reader/reader.h"
#include "src/tint/text/unicode.h"
#include "src/tint/transform/binding_remapper.h"
-#include "src/tint/transform/clamp_frag_depth.h"
#include "src/tint/transform/first_index_offset.h"
#include "src/tint/transform/manager.h"
#include "src/tint/transform/multiplanar_external_texture.h"
@@ -36,6 +35,8 @@
#include "src/tint/transform/substitute_override.h"
#include "src/tint/transform/vertex_pulling.h"
#include "src/tint/type/manager.h"
+#include "src/tint/writer/array_length_from_uniform_options.h"
+#include "src/tint/writer/binding_point.h"
#include "src/tint/writer/flatten_bindings.h"
#include "src/tint/writer/writer.h"
diff --git a/scripts/dawn_overrides_with_defaults.gni b/scripts/dawn_overrides_with_defaults.gni
new file mode 100644
index 0000000..bbe79e1
--- /dev/null
+++ b/scripts/dawn_overrides_with_defaults.gni
@@ -0,0 +1,91 @@
+# Copyright 2018 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This files imports the overrides for Dawn but sets the defaults so that
+# projects including Dawn don't have to set dirs if they happen to use the
+# same.
+# It takes advantage of GN's variable scoping rules to define global variables
+# inside if constructs.
+
+import("//build_overrides/dawn.gni")
+
+if (!defined(dawn_standalone)) {
+ dawn_standalone = false
+}
+
+if (!defined(dawn_has_build)) {
+ dawn_has_build = true
+}
+
+if (!defined(dawn_root)) {
+ dawn_root = get_path_info("..", "abspath")
+}
+dawn_gen_root = get_path_info("${dawn_root}", "gen_dir")
+
+if (!defined(dawn_jinja2_dir)) {
+ dawn_jinja2_dir = "//third_party/jinja2"
+}
+
+if (!defined(dawn_glfw_dir)) {
+ dawn_glfw_dir = "//third_party/glfw"
+}
+
+if (!defined(dawn_googletest_dir)) {
+ dawn_googletest_dir = "//third_party/googletest"
+}
+
+if (!defined(dawn_spirv_tools_dir)) {
+ dawn_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src"
+}
+
+if (!defined(dawn_swiftshader_dir)) {
+ # Default to swiftshader not being available.
+ dawn_swiftshader_dir = ""
+}
+
+if (!defined(dawn_vulkan_deps_dir)) {
+ dawn_vulkan_deps_dir = "//third_party/vulkan-deps"
+ if (dawn_standalone) {
+ dawn_vulkan_deps_dir = "${dawn_root}/third_party/vulkan-deps"
+ }
+}
+
+if (!defined(dawn_vulkan_headers_dir)) {
+ dawn_vulkan_headers_dir = "${dawn_vulkan_deps_dir}/vulkan-headers/src"
+}
+
+if (!defined(dawn_vulkan_loader_dir)) {
+ # Default to the Vulkan loader not being available except in standalone.
+ dawn_vulkan_loader_dir = ""
+ if (dawn_standalone) {
+ dawn_vulkan_loader_dir = "//third_party/vulkan-deps/vulkan-loader/src"
+ }
+}
+
+if (!defined(dawn_vulkan_tools_dir)) {
+ dawn_vulkan_tools_dir = "${dawn_vulkan_deps_dir}/vulkan-tools/src"
+}
+
+if (!defined(dawn_vulkan_validation_layers_dir)) {
+ # Default to VVLs not being available.
+ dawn_vulkan_validation_layers_dir = ""
+}
+
+if (!defined(dawn_abseil_dir)) {
+ dawn_abseil_dir = "//third_party/abseil-cpp"
+}
+
+if (!defined(dawn_version_file)) {
+ dawn_version_file = ""
+}
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 89eb6ee..11d98bd 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -14,6 +14,7 @@
import("//build_overrides/build.gni")
+import("../../scripts/dawn_overrides_with_defaults.gni")
import("../../tint_overrides_with_defaults.gni")
if (tint_build_unittests) {
@@ -78,6 +79,12 @@
defines += [ "TINT_BUILD_GLSL_WRITER=0" ]
}
+ if (tint_build_syntax_tree_writer) {
+ defines += [ "TINT_BUILD_SYNTAX_TREE_WRITER=1" ]
+ } else {
+ defines += [ "TINT_BUILD_SYNTAX_TREE_WRITER=0" ]
+ }
+
include_dirs = [
"${tint_root_dir}/",
"${tint_root_dir}/include/",
@@ -92,6 +99,17 @@
}
}
+group("abseil") {
+ # When build_with_chromium=true we need to include "//third_party/abseil-cpp:absl" while
+ # it's beneficial to be more specific with standalone Dawn, especially when it comes to
+ # including it as a dependency in other projects (such as Skia).
+ if (build_with_chromium) {
+ public_deps = [ "$dawn_abseil_dir:absl" ]
+ } else {
+ public_deps = [ "${dawn_root}/third_party/gn/abseil-cpp:strings" ]
+ }
+}
+
###############################################################################
# Helper library for IO operations
# Only to be used by tests and sample executable
@@ -195,6 +213,7 @@
"scope_stack.h",
"source.cc",
"source.h",
+ "switch.h",
"symbol.cc",
"symbol.h",
"symbol_table.cc",
@@ -476,6 +495,7 @@
"ast/discard_statement.h",
"ast/enable.h",
"ast/expression.h",
+ "ast/extension.h",
"ast/float_literal_expression.h",
"ast/for_loop_statement.h",
"ast/function.h",
@@ -562,6 +582,7 @@
"ast/discard_statement.cc",
"ast/enable.cc",
"ast/expression.cc",
+ "ast/extension.cc",
"ast/float_literal_expression.cc",
"ast/for_loop_statement.cc",
"ast/function.cc",
@@ -633,8 +654,6 @@
"sem/builtin.h",
"sem/builtin_enum_expression.cc",
"sem/builtin_enum_expression.h",
- "sem/builtin_type.cc",
- "sem/builtin_type.h",
"sem/call.cc",
"sem/call.h",
"sem/call_target.cc",
@@ -642,6 +661,7 @@
"sem/evaluation_stage.h",
"sem/expression.cc",
"sem/expression.h",
+ "sem/external_texture.h",
"sem/for_loop_statement.cc",
"sem/for_loop_statement.h",
"sem/function.cc",
@@ -718,6 +738,8 @@
"builtin/diagnostic_severity.h",
"builtin/extension.cc",
"builtin/extension.h",
+ "builtin/function.cc",
+ "builtin/function.h",
"builtin/interpolation_sampling.cc",
"builtin/interpolation_sampling.h",
"builtin/interpolation_type.cc",
@@ -877,14 +899,15 @@
"writer/append_vector.h",
"writer/array_length_from_uniform_options.cc",
"writer/array_length_from_uniform_options.h",
+ "writer/binding_point.h",
"writer/check_supported_extensions.cc",
"writer/check_supported_extensions.h",
+ "writer/external_texture_options.cc",
+ "writer/external_texture_options.h",
"writer/flatten_bindings.cc",
"writer/flatten_bindings.h",
"writer/float_to_string.cc",
"writer/float_to_string.h",
- "writer/generate_external_texture_bindings.cc",
- "writer/generate_external_texture_bindings.h",
"writer/text.cc",
"writer/text.h",
"writer/text_generator.cc",
@@ -953,6 +976,7 @@
]
deps = [
+ ":abseil",
":libtint_ast_src",
":libtint_base_src",
":libtint_builtins_src",
@@ -1045,6 +1069,25 @@
]
}
+libtint_source_set("libtint_syntax_tree_writer_src") {
+ sources = [
+ "writer/syntax_tree/generator.cc",
+ "writer/syntax_tree/generator.h",
+ "writer/syntax_tree/generator_impl.cc",
+ "writer/syntax_tree/generator_impl.h",
+ ]
+
+ deps = [
+ ":libtint_ast_src",
+ ":libtint_base_src",
+ ":libtint_builtins_src",
+ ":libtint_program_src",
+ ":libtint_sem_src",
+ ":libtint_type_src",
+ ":libtint_writer_src",
+ ]
+}
+
source_set("libtint") {
public_deps = [
":libtint_ast_src",
@@ -1089,6 +1132,10 @@
public_deps += [ ":libtint_glsl_writer_src" ]
}
+ if (tint_build_syntax_tree_writer) {
+ public_deps += [ ":libtint_syntax_tree_writer_src" ]
+ }
+
configs += [ ":tint_common_config" ]
public_configs = [ ":tint_public_config" ]
@@ -1580,7 +1627,6 @@
"writer/check_supported_extensions_test.cc",
"writer/flatten_bindings_test.cc",
"writer/float_to_string_test.cc",
- "writer/generate_external_texture_bindings_test.cc",
"writer/text_generator_test.cc",
]
deps = [
@@ -1590,6 +1636,16 @@
]
}
+ # Note, this includes the source files along with the test as otherwise the cmd helpers wouldn't
+ # be included in the binary.
+ tint_unittests_source_set("tint_unittests_cmd_src") {
+ sources = [
+ "cmd/generate_external_texture_bindings.cc",
+ "cmd/generate_external_texture_bindings.h",
+ "cmd/generate_external_texture_bindings_test.cc",
+ ]
+ }
+
tint_unittests_source_set("tint_unittests_spv_reader_src") {
sources = [
"reader/spirv/enum_converter_test.cc",
@@ -1939,6 +1995,7 @@
"reflection_test.cc",
"scope_stack_test.cc",
"source_test.cc",
+ "switch_test.cc",
"symbol_table_test.cc",
"symbol_test.cc",
"traits_test.cc",
@@ -1985,6 +2042,7 @@
":tint_unittests_ast_src",
":tint_unittests_base_src",
":tint_unittests_builtins_src",
+ ":tint_unittests_cmd_src",
":tint_unittests_constant_src",
":tint_unittests_core_src",
":tint_unittests_demangler_src",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 1d31896..07f7aa8 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -134,6 +134,8 @@
ast/enable.h
ast/expression.cc
ast/expression.h
+ ast/extension.cc
+ ast/extension.h
ast/float_literal_expression.cc
ast/float_literal_expression.h
ast/for_loop_statement.cc
@@ -280,6 +282,7 @@
resolver/validator.cc
resolver/validator.h
scope_stack.h
+ switch.h
sem/array_count.cc
sem/array_count.h
sem/behavior.cc
@@ -300,6 +303,7 @@
sem/evaluation_stage.h
sem/expression.cc
sem/expression.h
+ sem/external_texture.h
sem/for_loop_statement.cc
sem/for_loop_statement.h
sem/function_expression.cc
@@ -539,14 +543,15 @@
writer/append_vector.h
writer/array_length_from_uniform_options.cc
writer/array_length_from_uniform_options.h
+ writer/binding_point.h
writer/check_supported_extensions.cc
writer/check_supported_extensions.h
+ writer/external_texture_options.cc
+ writer/external_texture_options.h
writer/flatten_bindings.cc
writer/flatten_bindings.h
writer/float_to_string.cc
writer/float_to_string.h
- writer/generate_external_texture_bindings.cc
- writer/generate_external_texture_bindings.h
writer/text_generator.cc
writer/text_generator.h
writer/text.cc
@@ -563,12 +568,12 @@
tint_generated(builtin/diagnostic_rule BENCH TEST)
tint_generated(builtin/diagnostic_severity BENCH TEST)
tint_generated(builtin/extension BENCH TEST)
+tint_generated(builtin/function)
tint_generated(builtin/interpolation_sampling BENCH TEST)
tint_generated(builtin/interpolation_type BENCH TEST)
tint_generated(builtin/texel_format BENCH TEST)
tint_generated(resolver/ctor_conv_intrinsic)
-tint_generated(sem/builtin_type)
tint_generated(sem/parameter_usage)
if(UNIX)
@@ -677,6 +682,15 @@
)
endif()
+if(${TINT_BUILD_SYNTAX_TREE_WRITER})
+ list(APPEND TINT_LIB_SRCS
+ writer/syntax_tree/generator.cc
+ writer/syntax_tree/generator.h
+ writer/syntax_tree/generator_impl.cc
+ writer/syntax_tree/generator_impl.h
+ )
+endif()
+
if(${TINT_BUILD_IR})
list(APPEND TINT_LIB_SRCS
ir/binary.cc
@@ -689,8 +703,16 @@
ir/builder.h
ir/builder_impl.cc
ir/builder_impl.h
+ ir/builtin.cc
+ ir/builtin.h
+ ir/call.cc
+ ir/call.h
ir/constant.cc
ir/constant.h
+ ir/construct.cc
+ ir/construct.h
+ ir/convert.cc
+ ir/convert.h
ir/debug.cc
ir/debug.h
ir/disassembler.cc
@@ -713,6 +735,8 @@
ir/temp.h
ir/terminator.cc
ir/terminator.h
+ ir/user_call.cc
+ ir/user_call.h
ir/value.cc
ir/value.h
)
@@ -760,7 +784,7 @@
## Tint library
add_library(libtint ${TINT_LIB_SRCS})
tint_default_compile_options(libtint)
-target_link_libraries(libtint tint_diagnostic_utils)
+target_link_libraries(libtint tint_diagnostic_utils absl_strings)
if (${TINT_SYMBOL_STORE_DEBUG_NAME})
target_compile_definitions(libtint PUBLIC "TINT_SYMBOL_STORE_DEBUG_NAME=1")
endif()
@@ -770,7 +794,7 @@
# Tint library with fuzzer instrumentation
add_library(libtint-fuzz ${TINT_LIB_SRCS})
tint_default_compile_options(libtint-fuzz)
- target_link_libraries(libtint-fuzz tint_diagnostic_utils)
+ target_link_libraries(libtint-fuzz tint_diagnostic_utils absl_strings)
if (${COMPILER_IS_LIKE_GNU})
target_compile_options(libtint-fuzz PRIVATE -fvisibility=hidden)
endif()
@@ -942,6 +966,7 @@
sem/struct_test.cc
sem/value_expression_test.cc
source_test.cc
+ switch_test.cc
symbol_table_test.cc
symbol_test.cc
test_main.cc
@@ -997,10 +1022,17 @@
writer/check_supported_extensions_test.cc
writer/flatten_bindings_test.cc
writer/float_to_string_test.cc
- writer/generate_external_texture_bindings_test.cc
writer/text_generator_test.cc
)
+ # Noet, the source files are included here otherwise the cmd sources would not be included in the
+ # test binary.
+ list(APPEND TINT_TEST_SRCS
+ cmd/generate_external_texture_bindings.cc
+ cmd/generate_external_texture_bindings.h
+ cmd/generate_external_texture_bindings_test.cc
+ )
+
# Uniformity analysis tests depend on WGSL reader
if(${TINT_BUILD_WGSL_READER})
list(APPEND TINT_TEST_SRCS
@@ -1437,7 +1469,7 @@
endif()
list(APPEND TINT_BENCHMARK_SRCS
- "castable_bench.cc"
+ "switch_bench.cc"
"bench/benchmark.cc"
"reader/wgsl/parser_bench.cc"
)
diff --git a/src/tint/ast/builtin_texture_helper_test.cc b/src/tint/ast/builtin_texture_helper_test.cc
index 6d6aa69..658b650 100644
--- a/src/tint/ast/builtin_texture_helper_test.cc
+++ b/src/tint/ast/builtin_texture_helper_test.cc
@@ -852,6 +852,17 @@
/* returns value */ true,
},
{
+ ValidTextureOverload::kNumLayersCubeArray,
+ "textureNumLayers(t : texture_cube_array<f32>) -> u32",
+ TextureKind::kRegular,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](ProgramBuilder* b) { return b->ExprList(kTextureName); },
+ /* returns value */ true,
+ },
+ {
ValidTextureOverload::kNumLayersDepth2dArray,
"textureNumLayers(t : texture_depth_2d_array) -> u32",
TextureKind::kDepth,
@@ -863,6 +874,17 @@
/* returns value */ true,
},
{
+ ValidTextureOverload::kNumLayersDepthCubeArray,
+ "textureNumLayers(t : texture_depth_cube_array) -> u32",
+ TextureKind::kDepth,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](ProgramBuilder* b) { return b->ExprList(kTextureName); },
+ /* returns value */ true,
+ },
+ {
ValidTextureOverload::kNumLayersStorageWO2dArray,
"textureNumLayers(t : texture_storage_2d_array<rgba32float>) -> u32",
tint::builtin::Access::kWrite,
diff --git a/src/tint/ast/builtin_texture_helper_test.h b/src/tint/ast/builtin_texture_helper_test.h
index 4e1e46f..738db0c 100644
--- a/src/tint/ast/builtin_texture_helper_test.h
+++ b/src/tint/ast/builtin_texture_helper_test.h
@@ -83,7 +83,9 @@
kGatherCompareDepthCubeF32,
kGatherCompareDepthCubeArrayF32,
kNumLayers2dArray,
+ kNumLayersCubeArray,
kNumLayersDepth2dArray,
+ kNumLayersDepthCubeArray,
kNumLayersStorageWO2dArray,
kNumLevels2d,
kNumLevels2dArray,
diff --git a/src/tint/ast/enable.cc b/src/tint/ast/enable.cc
index 6087a3e..bb2b3b6 100644
--- a/src/tint/ast/enable.cc
+++ b/src/tint/ast/enable.cc
@@ -20,15 +20,29 @@
namespace tint::ast {
-Enable::Enable(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext)
- : Base(pid, nid, src), extension(ext) {}
+Enable::Enable(ProgramID pid,
+ NodeID nid,
+ const Source& src,
+ utils::VectorRef<const Extension*> exts)
+ : Base(pid, nid, src), extensions(std::move(exts)) {}
Enable::Enable(Enable&&) = default;
Enable::~Enable() = default;
+bool Enable::HasExtension(builtin::Extension ext) const {
+ for (auto* e : extensions) {
+ if (e->name == ext) {
+ return true;
+ }
+ }
+ return false;
+}
+
const Enable* Enable::Clone(CloneContext* ctx) const {
auto src = ctx->Clone(source);
- return ctx->dst->create<Enable>(src, extension);
+ auto exts = ctx->Clone(extensions);
+ return ctx->dst->create<Enable>(src, std::move(exts));
}
+
} // namespace tint::ast
diff --git a/src/tint/ast/enable.h b/src/tint/ast/enable.h
index 0c64df9..d87d12f 100644
--- a/src/tint/ast/enable.h
+++ b/src/tint/ast/enable.h
@@ -19,8 +19,7 @@
#include <utility>
#include <vector>
-#include "src/tint/ast/node.h"
-#include "src/tint/builtin/extension.h"
+#include "src/tint/ast/extension.h"
namespace tint::ast {
@@ -35,21 +34,24 @@
/// @param pid the identifier of the program that owns this node
/// @param nid the unique node identifier
/// @param src the source of this node
- /// @param ext the extension
- Enable(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext);
+ /// @param exts the extensions being enabled by this directive
+ Enable(ProgramID pid, NodeID nid, const Source& src, utils::VectorRef<const Extension*> exts);
/// Move constructor
Enable(Enable&&);
~Enable() override;
- /// Clones this node and all transitive child nodes using the `CloneContext`
- /// `ctx`.
+ /// @param ext the extension to search for
+ /// @returns true if this Enable lists the given extension
+ bool HasExtension(builtin::Extension ext) const;
+
+ /// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const Enable* Clone(CloneContext* ctx) const override;
- /// The extension name
- const builtin::Extension extension;
+ /// The extensions being enabled by this directive
+ const utils::Vector<const Extension*, 4> extensions;
};
} // namespace tint::ast
diff --git a/src/tint/ast/enable_test.cc b/src/tint/ast/enable_test.cc
index 5622207..20105bc 100644
--- a/src/tint/ast/enable_test.cc
+++ b/src/tint/ast/enable_test.cc
@@ -27,7 +27,14 @@
EXPECT_EQ(ext->source.range.begin.column, 2u);
EXPECT_EQ(ext->source.range.end.line, 20u);
EXPECT_EQ(ext->source.range.end.column, 5u);
- EXPECT_EQ(ext->extension, builtin::Extension::kF16);
+ ASSERT_EQ(ext->extensions.Length(), 1u);
+ EXPECT_EQ(ext->extensions[0]->name, builtin::Extension::kF16);
+}
+
+TEST_F(EnableTest, HasExtension) {
+ auto* ext = Enable(Source{{{20, 2}, {20, 5}}}, builtin::Extension::kF16);
+ EXPECT_TRUE(ext->HasExtension(builtin::Extension::kF16));
+ EXPECT_FALSE(ext->HasExtension(builtin::Extension::kChromiumDisableUniformityAnalysis));
}
} // namespace
diff --git a/src/tint/ast/extension.cc b/src/tint/ast/extension.cc
new file mode 100644
index 0000000..a45c704
--- /dev/null
+++ b/src/tint/ast/extension.cc
@@ -0,0 +1,40 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ast/extension.h"
+
+#include "src/tint/program_builder.h"
+
+//! @cond Doxygen_Suppress
+// Doxygen gets confused with tint::ast::Extension and tint::builtin::Extension
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::Extension);
+
+namespace tint::ast {
+
+Extension::Extension(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext)
+ : Base(pid, nid, src), name(ext) {}
+
+Extension::Extension(Extension&&) = default;
+
+Extension::~Extension() = default;
+
+const Extension* Extension::Clone(CloneContext* ctx) const {
+ auto src = ctx->Clone(source);
+ return ctx->dst->create<Extension>(src, name);
+}
+
+} // namespace tint::ast
+
+//! @endcond
diff --git a/src/tint/ast/extension.h b/src/tint/ast/extension.h
new file mode 100644
index 0000000..93f3baa
--- /dev/null
+++ b/src/tint/ast/extension.h
@@ -0,0 +1,52 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_AST_EXTENSION_H_
+#define SRC_TINT_AST_EXTENSION_H_
+
+#include "src/tint/ast/node.h"
+#include "src/tint/builtin/extension.h"
+
+namespace tint::ast {
+
+/// An extension used in an "enable" directive. Example:
+/// ```
+/// enable f16;
+/// ```
+class Extension final : public Castable<Extension, Node> {
+ public:
+ /// Create a extension
+ /// @param pid the identifier of the program that owns this node
+ /// @param nid the unique node identifier
+ /// @param src the source of this node
+ /// @param ext the extension
+ Extension(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext);
+ /// Move constructor
+ Extension(Extension&&);
+
+ ~Extension() override;
+
+ /// Clones this node and all transitive child nodes using the `CloneContext`
+ /// `ctx`.
+ /// @param ctx the clone context
+ /// @return the newly cloned node
+ const Extension* Clone(CloneContext* ctx) const override;
+
+ /// The extension name
+ const builtin::Extension name;
+};
+
+} // namespace tint::ast
+
+#endif // SRC_TINT_AST_EXTENSION_H_
diff --git a/src/tint/ast/for_loop_statement.cc b/src/tint/ast/for_loop_statement.cc
index aba956d..b2a5470 100644
--- a/src/tint/ast/for_loop_statement.cc
+++ b/src/tint/ast/for_loop_statement.cc
@@ -14,6 +14,8 @@
#include "src/tint/ast/for_loop_statement.h"
+#include <utility>
+
#include "src/tint/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::ForLoopStatement);
@@ -26,14 +28,24 @@
const Statement* init,
const Expression* cond,
const Statement* cont,
- const BlockStatement* b)
- : Base(pid, nid, src), initializer(init), condition(cond), continuing(cont), body(b) {
+ const BlockStatement* b,
+ utils::VectorRef<const ast::Attribute*> attrs)
+ : Base(pid, nid, src),
+ initializer(init),
+ condition(cond),
+ continuing(cont),
+ body(b),
+ attributes(std::move(attrs)) {
TINT_ASSERT(AST, body);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, initializer, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
+ for (auto* attr : attributes) {
+ TINT_ASSERT(AST, attr);
+ TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
+ }
}
ForLoopStatement::ForLoopStatement(ForLoopStatement&&) = default;
@@ -48,7 +60,8 @@
auto* cond = ctx->Clone(condition);
auto* cont = ctx->Clone(continuing);
auto* b = ctx->Clone(body);
- return ctx->dst->create<ForLoopStatement>(src, init, cond, cont, b);
+ auto attrs = ctx->Clone(attributes);
+ return ctx->dst->create<ForLoopStatement>(src, init, cond, cont, b, std::move(attrs));
}
} // namespace tint::ast
diff --git a/src/tint/ast/for_loop_statement.h b/src/tint/ast/for_loop_statement.h
index 59e0587..6063dda 100644
--- a/src/tint/ast/for_loop_statement.h
+++ b/src/tint/ast/for_loop_statement.h
@@ -32,13 +32,15 @@
/// @param condition the optional loop condition expression
/// @param continuing the optional continuing statement
/// @param body the loop body
+ /// @param attributes the while statement attributes
ForLoopStatement(ProgramID pid,
NodeID nid,
const Source& source,
const Statement* initializer,
const Expression* condition,
const Statement* continuing,
- const BlockStatement* body);
+ const BlockStatement* body,
+ utils::VectorRef<const ast::Attribute*> attributes);
/// Move constructor
ForLoopStatement(ForLoopStatement&&);
~ForLoopStatement() override;
@@ -60,6 +62,9 @@
/// The loop body block
const BlockStatement* const body;
+
+ /// The attribute list
+ const utils::Vector<const Attribute*, 1> attributes;
};
} // namespace tint::ast
diff --git a/src/tint/ast/for_loop_statement_test.cc b/src/tint/ast/for_loop_statement_test.cc
index 5e2a000..ad9050e 100644
--- a/src/tint/ast/for_loop_statement_test.cc
+++ b/src/tint/ast/for_loop_statement_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "gmock/gmock.h"
#include "gtest/gtest-spi.h"
#include "src/tint/ast/binary_expression.h"
#include "src/tint/ast/test_helper.h"
@@ -50,6 +51,15 @@
EXPECT_EQ(l->body, body);
}
+TEST_F(ForLoopStatementTest, Creation_WithAttributes) {
+ auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "foo");
+ auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "bar");
+ auto* body = Block(Return());
+ auto* l = For(nullptr, nullptr, nullptr, body, utils::Vector{attr1, attr2});
+
+ EXPECT_THAT(l->attributes, testing::ElementsAre(attr1, attr2));
+}
+
TEST_F(ForLoopStatementTest, Assert_Null_Body) {
EXPECT_FATAL_FAILURE(
{
diff --git a/src/tint/ast/if_statement.cc b/src/tint/ast/if_statement.cc
index fdea1da..6878c9f 100644
--- a/src/tint/ast/if_statement.cc
+++ b/src/tint/ast/if_statement.cc
@@ -25,8 +25,13 @@
const Source& src,
const Expression* cond,
const BlockStatement* b,
- const Statement* else_stmt)
- : Base(pid, nid, src), condition(cond), body(b), else_statement(else_stmt) {
+ const Statement* else_stmt,
+ utils::VectorRef<const Attribute*> attrs)
+ : Base(pid, nid, src),
+ condition(cond),
+ body(b),
+ else_statement(else_stmt),
+ attributes(std::move(attrs)) {
TINT_ASSERT(AST, condition);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
TINT_ASSERT(AST, body);
@@ -35,6 +40,10 @@
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, else_statement, program_id);
TINT_ASSERT(AST, (else_statement->IsAnyOf<IfStatement, BlockStatement>()));
}
+ for (auto* attr : attributes) {
+ TINT_ASSERT(AST, attr);
+ TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
+ }
}
IfStatement::IfStatement(IfStatement&&) = default;
@@ -47,7 +56,8 @@
auto* cond = ctx->Clone(condition);
auto* b = ctx->Clone(body);
auto* el = ctx->Clone(else_statement);
- return ctx->dst->create<IfStatement>(src, cond, b, el);
+ auto attrs = ctx->Clone(attributes);
+ return ctx->dst->create<IfStatement>(src, cond, b, el, std::move(attrs));
}
} // namespace tint::ast
diff --git a/src/tint/ast/if_statement.h b/src/tint/ast/if_statement.h
index 1c1abc3..8f291a8 100644
--- a/src/tint/ast/if_statement.h
+++ b/src/tint/ast/if_statement.h
@@ -32,12 +32,14 @@
/// @param condition the if condition
/// @param body the if body
/// @param else_stmt the else statement, or nullptr
+ /// @param attributes the if statement attributes
IfStatement(ProgramID pid,
NodeID nid,
const Source& src,
const Expression* condition,
const BlockStatement* body,
- const Statement* else_stmt);
+ const Statement* else_stmt,
+ utils::VectorRef<const Attribute*> attributes);
/// Move constructor
IfStatement(IfStatement&&);
~IfStatement() override;
@@ -56,6 +58,9 @@
/// The optional else statement, or nullptr
const Statement* const else_statement;
+
+ /// The attribute list
+ const utils::Vector<const Attribute*, 1> attributes;
};
} // namespace tint::ast
diff --git a/src/tint/ast/if_statement_test.cc b/src/tint/ast/if_statement_test.cc
index 9115cb7..b5b85fe 100644
--- a/src/tint/ast/if_statement_test.cc
+++ b/src/tint/ast/if_statement_test.cc
@@ -14,6 +14,7 @@
#include "src/tint/ast/if_statement.h"
+#include "gmock/gmock.h"
#include "gtest/gtest-spi.h"
#include "src/tint/ast/discard_statement.h"
#include "src/tint/ast/test_helper.h"
@@ -31,6 +32,15 @@
EXPECT_EQ(src.range.begin.column, 2u);
}
+TEST_F(IfStatementTest, Creation_WithAttributes) {
+ auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "foo");
+ auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "bar");
+ auto* cond = Expr("cond");
+ auto* stmt = If(cond, Block(), ElseStmt(), utils::Vector{attr1, attr2});
+
+ EXPECT_THAT(stmt->attributes, testing::ElementsAre(attr1, attr2));
+}
+
TEST_F(IfStatementTest, IsIf) {
auto* stmt = If(Expr(true), Block());
EXPECT_TRUE(stmt->Is<IfStatement>());
diff --git a/src/tint/ast/module.cc b/src/tint/ast/module.cc
index 32dafe8..fa652de 100644
--- a/src/tint/ast/module.cc
+++ b/src/tint/ast/module.cc
@@ -18,6 +18,7 @@
#include "src/tint/ast/type_decl.h"
#include "src/tint/program_builder.h"
+#include "src/tint/switch.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::Module);
diff --git a/src/tint/ast/switch_statement.cc b/src/tint/ast/switch_statement.cc
index 1cdf8a4..0445e48 100644
--- a/src/tint/ast/switch_statement.cc
+++ b/src/tint/ast/switch_statement.cc
@@ -26,14 +26,19 @@
NodeID nid,
const Source& src,
const Expression* cond,
- utils::VectorRef<const CaseStatement*> b)
- : Base(pid, nid, src), condition(cond), body(std::move(b)) {
+ utils::VectorRef<const CaseStatement*> b,
+ utils::VectorRef<const Attribute*> attrs)
+ : Base(pid, nid, src), condition(cond), body(std::move(b)), attributes(std::move(attrs)) {
TINT_ASSERT(AST, condition);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
for (auto* stmt : body) {
TINT_ASSERT(AST, stmt);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
}
+ for (auto* attr : attributes) {
+ TINT_ASSERT(AST, attr);
+ TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
+ }
}
SwitchStatement::SwitchStatement(SwitchStatement&&) = default;
@@ -45,7 +50,8 @@
auto src = ctx->Clone(source);
auto* cond = ctx->Clone(condition);
auto b = ctx->Clone(body);
- return ctx->dst->create<SwitchStatement>(src, cond, std::move(b));
+ auto attrs = ctx->Clone(attributes);
+ return ctx->dst->create<SwitchStatement>(src, cond, std::move(b), std::move(attrs));
}
} // namespace tint::ast
diff --git a/src/tint/ast/switch_statement.h b/src/tint/ast/switch_statement.h
index eb083f0..e918535 100644
--- a/src/tint/ast/switch_statement.h
+++ b/src/tint/ast/switch_statement.h
@@ -29,11 +29,13 @@
/// @param src the source of this node
/// @param condition the switch condition
/// @param body the switch body
+ /// @param attributes the switch statement attributes
SwitchStatement(ProgramID pid,
NodeID nid,
const Source& src,
const Expression* condition,
- utils::VectorRef<const CaseStatement*> body);
+ utils::VectorRef<const CaseStatement*> body,
+ utils::VectorRef<const Attribute*> attributes);
/// Move constructor
SwitchStatement(SwitchStatement&&);
~SwitchStatement() override;
@@ -50,6 +52,9 @@
/// The Switch body
const utils::Vector<const CaseStatement*, 4> body;
SwitchStatement(const SwitchStatement&) = delete;
+
+ /// The attribute list
+ const utils::Vector<const Attribute*, 1> attributes;
};
} // namespace tint::ast
diff --git a/src/tint/ast/switch_statement_test.cc b/src/tint/ast/switch_statement_test.cc
index e6101c8..aab2604 100644
--- a/src/tint/ast/switch_statement_test.cc
+++ b/src/tint/ast/switch_statement_test.cc
@@ -14,6 +14,7 @@
#include "src/tint/ast/switch_statement.h"
+#include "gmock/gmock.h"
#include "gtest/gtest-spi.h"
#include "src/tint/ast/test_helper.h"
@@ -29,7 +30,7 @@
auto* ident = Expr("ident");
utils::Vector body{case_stmt};
- auto* stmt = create<SwitchStatement>(ident, body);
+ auto* stmt = create<SwitchStatement>(ident, body, utils::Empty);
EXPECT_EQ(stmt->condition, ident);
ASSERT_EQ(stmt->body.Length(), 1u);
EXPECT_EQ(stmt->body[0], case_stmt);
@@ -37,18 +38,28 @@
TEST_F(SwitchStatementTest, Creation_WithSource) {
auto* ident = Expr("ident");
- auto* stmt = create<SwitchStatement>(Source{Source::Location{20, 2}}, ident, utils::Empty);
+ auto* stmt =
+ create<SwitchStatement>(Source{Source::Location{20, 2}}, ident, utils::Empty, utils::Empty);
auto src = stmt->source;
EXPECT_EQ(src.range.begin.line, 20u);
EXPECT_EQ(src.range.begin.column, 2u);
}
+TEST_F(SwitchStatementTest, Creation_WithAttributes) {
+ auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "foo");
+ auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "bar");
+ auto* ident = Expr("ident");
+ auto* stmt = create<SwitchStatement>(ident, utils::Empty, utils::Vector{attr1, attr2});
+
+ EXPECT_THAT(stmt->attributes, testing::ElementsAre(attr1, attr2));
+}
+
TEST_F(SwitchStatementTest, IsSwitch) {
utils::Vector lit{CaseSelector(2_i)};
auto* ident = Expr("ident");
utils::Vector body{create<CaseStatement>(lit, Block())};
- auto* stmt = create<SwitchStatement>(ident, body);
+ auto* stmt = create<SwitchStatement>(ident, body, utils::Empty);
EXPECT_TRUE(stmt->Is<SwitchStatement>());
}
@@ -60,7 +71,7 @@
CaseStatementList cases;
cases.Push(
b.create<CaseStatement>(utils::Vector{b.CaseSelector(b.Expr(1_i))}, b.Block()));
- b.create<SwitchStatement>(nullptr, cases);
+ b.create<SwitchStatement>(nullptr, cases, utils::Empty);
},
"internal compiler error");
}
@@ -70,7 +81,7 @@
EXPECT_FATAL_FAILURE(
{
ProgramBuilder b;
- b.create<SwitchStatement>(b.Expr(true), CaseStatementList{nullptr});
+ b.create<SwitchStatement>(b.Expr(true), CaseStatementList{nullptr}, utils::Empty);
},
"internal compiler error");
}
@@ -80,13 +91,15 @@
{
ProgramBuilder b1;
ProgramBuilder b2;
- b1.create<SwitchStatement>(b2.Expr(true), utils::Vector{
- b1.create<CaseStatement>(
- utils::Vector{
- b1.CaseSelector(b1.Expr(1_i)),
- },
- b1.Block()),
- });
+ b1.create<SwitchStatement>(b2.Expr(true),
+ utils::Vector{
+ b1.create<CaseStatement>(
+ utils::Vector{
+ b1.CaseSelector(b1.Expr(1_i)),
+ },
+ b1.Block()),
+ },
+ utils::Empty);
},
"internal compiler error");
}
@@ -96,13 +109,15 @@
{
ProgramBuilder b1;
ProgramBuilder b2;
- b1.create<SwitchStatement>(b1.Expr(true), utils::Vector{
- b2.create<CaseStatement>(
- utils::Vector{
- b2.CaseSelector(b2.Expr(1_i)),
- },
- b2.Block()),
- });
+ b1.create<SwitchStatement>(b1.Expr(true),
+ utils::Vector{
+ b2.create<CaseStatement>(
+ utils::Vector{
+ b2.CaseSelector(b2.Expr(1_i)),
+ },
+ b2.Block()),
+ },
+ utils::Empty);
},
"internal compiler error");
}
diff --git a/src/tint/ast/traverse_expressions.h b/src/tint/ast/traverse_expressions.h
index fb8aad1..84a10c3 100644
--- a/src/tint/ast/traverse_expressions.h
+++ b/src/tint/ast/traverse_expressions.h
@@ -25,6 +25,7 @@
#include "src/tint/ast/member_accessor_expression.h"
#include "src/tint/ast/phony_expression.h"
#include "src/tint/ast/unary_op_expression.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/reverse.h"
#include "src/tint/utils/vector.h"
diff --git a/src/tint/ast/while_statement.cc b/src/tint/ast/while_statement.cc
index 160af4b..47cf2bb 100644
--- a/src/tint/ast/while_statement.cc
+++ b/src/tint/ast/while_statement.cc
@@ -14,6 +14,8 @@
#include "src/tint/ast/while_statement.h"
+#include <utility>
+
#include "src/tint/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::WhileStatement);
@@ -24,13 +26,18 @@
NodeID nid,
const Source& src,
const Expression* cond,
- const BlockStatement* b)
- : Base(pid, nid, src), condition(cond), body(b) {
+ const BlockStatement* b,
+ utils::VectorRef<const ast::Attribute*> attrs)
+ : Base(pid, nid, src), condition(cond), body(b), attributes(std::move(attrs)) {
TINT_ASSERT(AST, cond);
TINT_ASSERT(AST, body);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
+ for (auto* attr : attributes) {
+ TINT_ASSERT(AST, attr);
+ TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
+ }
}
WhileStatement::WhileStatement(WhileStatement&&) = default;
@@ -43,7 +50,8 @@
auto* cond = ctx->Clone(condition);
auto* b = ctx->Clone(body);
- return ctx->dst->create<WhileStatement>(src, cond, b);
+ auto attrs = ctx->Clone(attributes);
+ return ctx->dst->create<WhileStatement>(src, cond, b, std::move(attrs));
}
} // namespace tint::ast
diff --git a/src/tint/ast/while_statement.h b/src/tint/ast/while_statement.h
index 4e8dd7e..b2b91dc 100644
--- a/src/tint/ast/while_statement.h
+++ b/src/tint/ast/while_statement.h
@@ -30,11 +30,13 @@
/// @param source the for loop statement source
/// @param condition the optional loop condition expression
/// @param body the loop body
+ /// @param attributes the while statement attributes
WhileStatement(ProgramID pid,
NodeID nid,
const Source& source,
const Expression* condition,
- const BlockStatement* body);
+ const BlockStatement* body,
+ utils::VectorRef<const ast::Attribute*> attributes);
/// Move constructor
WhileStatement(WhileStatement&&);
~WhileStatement() override;
@@ -50,6 +52,9 @@
/// The loop body block
const BlockStatement* const body;
+
+ /// The attribute list
+ const utils::Vector<const Attribute*, 1> attributes;
};
} // namespace tint::ast
diff --git a/src/tint/ast/while_statement_test.cc b/src/tint/ast/while_statement_test.cc
index 73c9e56..ef287fc 100644
--- a/src/tint/ast/while_statement_test.cc
+++ b/src/tint/ast/while_statement_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "gmock/gmock.h"
#include "gtest/gtest-spi.h"
#include "src/tint/ast/binary_expression.h"
#include "src/tint/ast/test_helper.h"
@@ -41,6 +42,16 @@
EXPECT_EQ(src.range.begin.column, 2u);
}
+TEST_F(WhileStatementTest, Creation_WithAttributes) {
+ auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "foo");
+ auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "bar");
+ auto* cond = create<BinaryExpression>(BinaryOp::kLessThan, Expr("i"), Expr(5_u));
+ auto* body = Block(Return());
+ auto* l = While(cond, body, utils::Vector{attr1, attr2});
+
+ EXPECT_THAT(l->attributes, testing::ElementsAre(attr1, attr2));
+}
+
TEST_F(WhileStatementTest, Assert_Null_Cond) {
EXPECT_FATAL_FAILURE(
{
diff --git a/src/tint/builtin/function.cc b/src/tint/builtin/function.cc
new file mode 100644
index 0000000..88e86b6
--- /dev/null
+++ b/src/tint/builtin/function.cc
@@ -0,0 +1,614 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+// src/tint/builtin/function.cc.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+#include "src/tint/builtin/function.h"
+
+namespace tint::builtin {
+
+Function ParseFunction(const std::string& name) {
+ if (name == "abs") {
+ return Function::kAbs;
+ }
+ if (name == "acos") {
+ return Function::kAcos;
+ }
+ if (name == "acosh") {
+ return Function::kAcosh;
+ }
+ if (name == "all") {
+ return Function::kAll;
+ }
+ if (name == "any") {
+ return Function::kAny;
+ }
+ if (name == "arrayLength") {
+ return Function::kArrayLength;
+ }
+ if (name == "asin") {
+ return Function::kAsin;
+ }
+ if (name == "asinh") {
+ return Function::kAsinh;
+ }
+ if (name == "atan") {
+ return Function::kAtan;
+ }
+ if (name == "atan2") {
+ return Function::kAtan2;
+ }
+ if (name == "atanh") {
+ return Function::kAtanh;
+ }
+ if (name == "ceil") {
+ return Function::kCeil;
+ }
+ if (name == "clamp") {
+ return Function::kClamp;
+ }
+ if (name == "cos") {
+ return Function::kCos;
+ }
+ if (name == "cosh") {
+ return Function::kCosh;
+ }
+ if (name == "countLeadingZeros") {
+ return Function::kCountLeadingZeros;
+ }
+ if (name == "countOneBits") {
+ return Function::kCountOneBits;
+ }
+ if (name == "countTrailingZeros") {
+ return Function::kCountTrailingZeros;
+ }
+ if (name == "cross") {
+ return Function::kCross;
+ }
+ if (name == "degrees") {
+ return Function::kDegrees;
+ }
+ if (name == "determinant") {
+ return Function::kDeterminant;
+ }
+ if (name == "distance") {
+ return Function::kDistance;
+ }
+ if (name == "dot") {
+ return Function::kDot;
+ }
+ if (name == "dot4I8Packed") {
+ return Function::kDot4I8Packed;
+ }
+ if (name == "dot4U8Packed") {
+ return Function::kDot4U8Packed;
+ }
+ if (name == "dpdx") {
+ return Function::kDpdx;
+ }
+ if (name == "dpdxCoarse") {
+ return Function::kDpdxCoarse;
+ }
+ if (name == "dpdxFine") {
+ return Function::kDpdxFine;
+ }
+ if (name == "dpdy") {
+ return Function::kDpdy;
+ }
+ if (name == "dpdyCoarse") {
+ return Function::kDpdyCoarse;
+ }
+ if (name == "dpdyFine") {
+ return Function::kDpdyFine;
+ }
+ if (name == "exp") {
+ return Function::kExp;
+ }
+ if (name == "exp2") {
+ return Function::kExp2;
+ }
+ if (name == "extractBits") {
+ return Function::kExtractBits;
+ }
+ if (name == "faceForward") {
+ return Function::kFaceForward;
+ }
+ if (name == "firstLeadingBit") {
+ return Function::kFirstLeadingBit;
+ }
+ if (name == "firstTrailingBit") {
+ return Function::kFirstTrailingBit;
+ }
+ if (name == "floor") {
+ return Function::kFloor;
+ }
+ if (name == "fma") {
+ return Function::kFma;
+ }
+ if (name == "fract") {
+ return Function::kFract;
+ }
+ if (name == "frexp") {
+ return Function::kFrexp;
+ }
+ if (name == "fwidth") {
+ return Function::kFwidth;
+ }
+ if (name == "fwidthCoarse") {
+ return Function::kFwidthCoarse;
+ }
+ if (name == "fwidthFine") {
+ return Function::kFwidthFine;
+ }
+ if (name == "insertBits") {
+ return Function::kInsertBits;
+ }
+ if (name == "inverseSqrt") {
+ return Function::kInverseSqrt;
+ }
+ if (name == "ldexp") {
+ return Function::kLdexp;
+ }
+ if (name == "length") {
+ return Function::kLength;
+ }
+ if (name == "log") {
+ return Function::kLog;
+ }
+ if (name == "log2") {
+ return Function::kLog2;
+ }
+ if (name == "max") {
+ return Function::kMax;
+ }
+ if (name == "min") {
+ return Function::kMin;
+ }
+ if (name == "mix") {
+ return Function::kMix;
+ }
+ if (name == "modf") {
+ return Function::kModf;
+ }
+ if (name == "normalize") {
+ return Function::kNormalize;
+ }
+ if (name == "pack2x16float") {
+ return Function::kPack2X16Float;
+ }
+ if (name == "pack2x16snorm") {
+ return Function::kPack2X16Snorm;
+ }
+ if (name == "pack2x16unorm") {
+ return Function::kPack2X16Unorm;
+ }
+ if (name == "pack4x8snorm") {
+ return Function::kPack4X8Snorm;
+ }
+ if (name == "pack4x8unorm") {
+ return Function::kPack4X8Unorm;
+ }
+ if (name == "pow") {
+ return Function::kPow;
+ }
+ if (name == "quantizeToF16") {
+ return Function::kQuantizeToF16;
+ }
+ if (name == "radians") {
+ return Function::kRadians;
+ }
+ if (name == "reflect") {
+ return Function::kReflect;
+ }
+ if (name == "refract") {
+ return Function::kRefract;
+ }
+ if (name == "reverseBits") {
+ return Function::kReverseBits;
+ }
+ if (name == "round") {
+ return Function::kRound;
+ }
+ if (name == "saturate") {
+ return Function::kSaturate;
+ }
+ if (name == "select") {
+ return Function::kSelect;
+ }
+ if (name == "sign") {
+ return Function::kSign;
+ }
+ if (name == "sin") {
+ return Function::kSin;
+ }
+ if (name == "sinh") {
+ return Function::kSinh;
+ }
+ if (name == "smoothstep") {
+ return Function::kSmoothstep;
+ }
+ if (name == "sqrt") {
+ return Function::kSqrt;
+ }
+ if (name == "step") {
+ return Function::kStep;
+ }
+ if (name == "storageBarrier") {
+ return Function::kStorageBarrier;
+ }
+ if (name == "tan") {
+ return Function::kTan;
+ }
+ if (name == "tanh") {
+ return Function::kTanh;
+ }
+ if (name == "transpose") {
+ return Function::kTranspose;
+ }
+ if (name == "trunc") {
+ return Function::kTrunc;
+ }
+ if (name == "unpack2x16float") {
+ return Function::kUnpack2X16Float;
+ }
+ if (name == "unpack2x16snorm") {
+ return Function::kUnpack2X16Snorm;
+ }
+ if (name == "unpack2x16unorm") {
+ return Function::kUnpack2X16Unorm;
+ }
+ if (name == "unpack4x8snorm") {
+ return Function::kUnpack4X8Snorm;
+ }
+ if (name == "unpack4x8unorm") {
+ return Function::kUnpack4X8Unorm;
+ }
+ if (name == "workgroupBarrier") {
+ return Function::kWorkgroupBarrier;
+ }
+ if (name == "workgroupUniformLoad") {
+ return Function::kWorkgroupUniformLoad;
+ }
+ if (name == "textureDimensions") {
+ return Function::kTextureDimensions;
+ }
+ if (name == "textureGather") {
+ return Function::kTextureGather;
+ }
+ if (name == "textureGatherCompare") {
+ return Function::kTextureGatherCompare;
+ }
+ if (name == "textureNumLayers") {
+ return Function::kTextureNumLayers;
+ }
+ if (name == "textureNumLevels") {
+ return Function::kTextureNumLevels;
+ }
+ if (name == "textureNumSamples") {
+ return Function::kTextureNumSamples;
+ }
+ if (name == "textureSample") {
+ return Function::kTextureSample;
+ }
+ if (name == "textureSampleBias") {
+ return Function::kTextureSampleBias;
+ }
+ if (name == "textureSampleCompare") {
+ return Function::kTextureSampleCompare;
+ }
+ if (name == "textureSampleCompareLevel") {
+ return Function::kTextureSampleCompareLevel;
+ }
+ if (name == "textureSampleGrad") {
+ return Function::kTextureSampleGrad;
+ }
+ if (name == "textureSampleLevel") {
+ return Function::kTextureSampleLevel;
+ }
+ if (name == "textureSampleBaseClampToEdge") {
+ return Function::kTextureSampleBaseClampToEdge;
+ }
+ if (name == "textureStore") {
+ return Function::kTextureStore;
+ }
+ if (name == "textureLoad") {
+ return Function::kTextureLoad;
+ }
+ if (name == "atomicLoad") {
+ return Function::kAtomicLoad;
+ }
+ if (name == "atomicStore") {
+ return Function::kAtomicStore;
+ }
+ if (name == "atomicAdd") {
+ return Function::kAtomicAdd;
+ }
+ if (name == "atomicSub") {
+ return Function::kAtomicSub;
+ }
+ if (name == "atomicMax") {
+ return Function::kAtomicMax;
+ }
+ if (name == "atomicMin") {
+ return Function::kAtomicMin;
+ }
+ if (name == "atomicAnd") {
+ return Function::kAtomicAnd;
+ }
+ if (name == "atomicOr") {
+ return Function::kAtomicOr;
+ }
+ if (name == "atomicXor") {
+ return Function::kAtomicXor;
+ }
+ if (name == "atomicExchange") {
+ return Function::kAtomicExchange;
+ }
+ if (name == "atomicCompareExchangeWeak") {
+ return Function::kAtomicCompareExchangeWeak;
+ }
+ if (name == "_tint_materialize") {
+ return Function::kTintMaterialize;
+ }
+ return Function::kNone;
+}
+
+const char* str(Function i) {
+ switch (i) {
+ case Function::kNone:
+ return "<none>";
+ case Function::kAbs:
+ return "abs";
+ case Function::kAcos:
+ return "acos";
+ case Function::kAcosh:
+ return "acosh";
+ case Function::kAll:
+ return "all";
+ case Function::kAny:
+ return "any";
+ case Function::kArrayLength:
+ return "arrayLength";
+ case Function::kAsin:
+ return "asin";
+ case Function::kAsinh:
+ return "asinh";
+ case Function::kAtan:
+ return "atan";
+ case Function::kAtan2:
+ return "atan2";
+ case Function::kAtanh:
+ return "atanh";
+ case Function::kCeil:
+ return "ceil";
+ case Function::kClamp:
+ return "clamp";
+ case Function::kCos:
+ return "cos";
+ case Function::kCosh:
+ return "cosh";
+ case Function::kCountLeadingZeros:
+ return "countLeadingZeros";
+ case Function::kCountOneBits:
+ return "countOneBits";
+ case Function::kCountTrailingZeros:
+ return "countTrailingZeros";
+ case Function::kCross:
+ return "cross";
+ case Function::kDegrees:
+ return "degrees";
+ case Function::kDeterminant:
+ return "determinant";
+ case Function::kDistance:
+ return "distance";
+ case Function::kDot:
+ return "dot";
+ case Function::kDot4I8Packed:
+ return "dot4I8Packed";
+ case Function::kDot4U8Packed:
+ return "dot4U8Packed";
+ case Function::kDpdx:
+ return "dpdx";
+ case Function::kDpdxCoarse:
+ return "dpdxCoarse";
+ case Function::kDpdxFine:
+ return "dpdxFine";
+ case Function::kDpdy:
+ return "dpdy";
+ case Function::kDpdyCoarse:
+ return "dpdyCoarse";
+ case Function::kDpdyFine:
+ return "dpdyFine";
+ case Function::kExp:
+ return "exp";
+ case Function::kExp2:
+ return "exp2";
+ case Function::kExtractBits:
+ return "extractBits";
+ case Function::kFaceForward:
+ return "faceForward";
+ case Function::kFirstLeadingBit:
+ return "firstLeadingBit";
+ case Function::kFirstTrailingBit:
+ return "firstTrailingBit";
+ case Function::kFloor:
+ return "floor";
+ case Function::kFma:
+ return "fma";
+ case Function::kFract:
+ return "fract";
+ case Function::kFrexp:
+ return "frexp";
+ case Function::kFwidth:
+ return "fwidth";
+ case Function::kFwidthCoarse:
+ return "fwidthCoarse";
+ case Function::kFwidthFine:
+ return "fwidthFine";
+ case Function::kInsertBits:
+ return "insertBits";
+ case Function::kInverseSqrt:
+ return "inverseSqrt";
+ case Function::kLdexp:
+ return "ldexp";
+ case Function::kLength:
+ return "length";
+ case Function::kLog:
+ return "log";
+ case Function::kLog2:
+ return "log2";
+ case Function::kMax:
+ return "max";
+ case Function::kMin:
+ return "min";
+ case Function::kMix:
+ return "mix";
+ case Function::kModf:
+ return "modf";
+ case Function::kNormalize:
+ return "normalize";
+ case Function::kPack2X16Float:
+ return "pack2x16float";
+ case Function::kPack2X16Snorm:
+ return "pack2x16snorm";
+ case Function::kPack2X16Unorm:
+ return "pack2x16unorm";
+ case Function::kPack4X8Snorm:
+ return "pack4x8snorm";
+ case Function::kPack4X8Unorm:
+ return "pack4x8unorm";
+ case Function::kPow:
+ return "pow";
+ case Function::kQuantizeToF16:
+ return "quantizeToF16";
+ case Function::kRadians:
+ return "radians";
+ case Function::kReflect:
+ return "reflect";
+ case Function::kRefract:
+ return "refract";
+ case Function::kReverseBits:
+ return "reverseBits";
+ case Function::kRound:
+ return "round";
+ case Function::kSaturate:
+ return "saturate";
+ case Function::kSelect:
+ return "select";
+ case Function::kSign:
+ return "sign";
+ case Function::kSin:
+ return "sin";
+ case Function::kSinh:
+ return "sinh";
+ case Function::kSmoothstep:
+ return "smoothstep";
+ case Function::kSqrt:
+ return "sqrt";
+ case Function::kStep:
+ return "step";
+ case Function::kStorageBarrier:
+ return "storageBarrier";
+ case Function::kTan:
+ return "tan";
+ case Function::kTanh:
+ return "tanh";
+ case Function::kTranspose:
+ return "transpose";
+ case Function::kTrunc:
+ return "trunc";
+ case Function::kUnpack2X16Float:
+ return "unpack2x16float";
+ case Function::kUnpack2X16Snorm:
+ return "unpack2x16snorm";
+ case Function::kUnpack2X16Unorm:
+ return "unpack2x16unorm";
+ case Function::kUnpack4X8Snorm:
+ return "unpack4x8snorm";
+ case Function::kUnpack4X8Unorm:
+ return "unpack4x8unorm";
+ case Function::kWorkgroupBarrier:
+ return "workgroupBarrier";
+ case Function::kWorkgroupUniformLoad:
+ return "workgroupUniformLoad";
+ case Function::kTextureDimensions:
+ return "textureDimensions";
+ case Function::kTextureGather:
+ return "textureGather";
+ case Function::kTextureGatherCompare:
+ return "textureGatherCompare";
+ case Function::kTextureNumLayers:
+ return "textureNumLayers";
+ case Function::kTextureNumLevels:
+ return "textureNumLevels";
+ case Function::kTextureNumSamples:
+ return "textureNumSamples";
+ case Function::kTextureSample:
+ return "textureSample";
+ case Function::kTextureSampleBias:
+ return "textureSampleBias";
+ case Function::kTextureSampleCompare:
+ return "textureSampleCompare";
+ case Function::kTextureSampleCompareLevel:
+ return "textureSampleCompareLevel";
+ case Function::kTextureSampleGrad:
+ return "textureSampleGrad";
+ case Function::kTextureSampleLevel:
+ return "textureSampleLevel";
+ case Function::kTextureSampleBaseClampToEdge:
+ return "textureSampleBaseClampToEdge";
+ case Function::kTextureStore:
+ return "textureStore";
+ case Function::kTextureLoad:
+ return "textureLoad";
+ case Function::kAtomicLoad:
+ return "atomicLoad";
+ case Function::kAtomicStore:
+ return "atomicStore";
+ case Function::kAtomicAdd:
+ return "atomicAdd";
+ case Function::kAtomicSub:
+ return "atomicSub";
+ case Function::kAtomicMax:
+ return "atomicMax";
+ case Function::kAtomicMin:
+ return "atomicMin";
+ case Function::kAtomicAnd:
+ return "atomicAnd";
+ case Function::kAtomicOr:
+ return "atomicOr";
+ case Function::kAtomicXor:
+ return "atomicXor";
+ case Function::kAtomicExchange:
+ return "atomicExchange";
+ case Function::kAtomicCompareExchangeWeak:
+ return "atomicCompareExchangeWeak";
+ case Function::kTintMaterialize:
+ return "_tint_materialize";
+ }
+ return "<unknown>";
+}
+
+utils::StringStream& operator<<(utils::StringStream& out, Function i) {
+ out << str(i);
+ return out;
+}
+
+} // namespace tint::builtin
diff --git a/src/tint/builtin/function.cc.tmpl b/src/tint/builtin/function.cc.tmpl
new file mode 100644
index 0000000..e2729dc
--- /dev/null
+++ b/src/tint/builtin/function.cc.tmpl
@@ -0,0 +1,44 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/src/cmd/gen to generate function.cc
+
+To update the generated file, run:
+ ./tools/run gen
+
+See:
+* tools/src/cmd/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+#include "src/tint/builtin/function.h"
+
+namespace tint::builtin {
+
+Function ParseFunction(const std::string& name) {
+{{- range Sem.Builtins }}
+ if (name == "{{.Name}}") {
+ return Function::k{{PascalCase .Name}};
+ }
+{{- end }}
+ return Function::kNone;
+}
+
+const char* str(Function i) {
+ switch (i) {
+ case Function::kNone:
+ return "<none>";
+{{- range Sem.Builtins }}
+ case Function::k{{PascalCase .Name}}:
+ return "{{.Name}}";
+{{- end }}
+ }
+ return "<unknown>";
+}
+
+utils::StringStream& operator<<(utils::StringStream& out, Function i) {
+ out << str(i);
+ return out;
+}
+
+} // namespace tint::builtin
diff --git a/src/tint/builtin/function.h b/src/tint/builtin/function.h
new file mode 100644
index 0000000..3ccb341
--- /dev/null
+++ b/src/tint/builtin/function.h
@@ -0,0 +1,405 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+// src/tint/builtin/function.h.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SRC_TINT_BUILTIN_FUNCTION_H_
+#define SRC_TINT_BUILTIN_FUNCTION_H_
+
+#include <string>
+
+#include "src/tint/utils/string_stream.h"
+
+// \cond DO_NOT_DOCUMENT
+namespace tint::builtin {
+
+/// Enumerator of all builtin functions
+enum class Function {
+ kNone = -1,
+ kAbs,
+ kAcos,
+ kAcosh,
+ kAll,
+ kAny,
+ kArrayLength,
+ kAsin,
+ kAsinh,
+ kAtan,
+ kAtan2,
+ kAtanh,
+ kCeil,
+ kClamp,
+ kCos,
+ kCosh,
+ kCountLeadingZeros,
+ kCountOneBits,
+ kCountTrailingZeros,
+ kCross,
+ kDegrees,
+ kDeterminant,
+ kDistance,
+ kDot,
+ kDot4I8Packed,
+ kDot4U8Packed,
+ kDpdx,
+ kDpdxCoarse,
+ kDpdxFine,
+ kDpdy,
+ kDpdyCoarse,
+ kDpdyFine,
+ kExp,
+ kExp2,
+ kExtractBits,
+ kFaceForward,
+ kFirstLeadingBit,
+ kFirstTrailingBit,
+ kFloor,
+ kFma,
+ kFract,
+ kFrexp,
+ kFwidth,
+ kFwidthCoarse,
+ kFwidthFine,
+ kInsertBits,
+ kInverseSqrt,
+ kLdexp,
+ kLength,
+ kLog,
+ kLog2,
+ kMax,
+ kMin,
+ kMix,
+ kModf,
+ kNormalize,
+ kPack2X16Float,
+ kPack2X16Snorm,
+ kPack2X16Unorm,
+ kPack4X8Snorm,
+ kPack4X8Unorm,
+ kPow,
+ kQuantizeToF16,
+ kRadians,
+ kReflect,
+ kRefract,
+ kReverseBits,
+ kRound,
+ kSaturate,
+ kSelect,
+ kSign,
+ kSin,
+ kSinh,
+ kSmoothstep,
+ kSqrt,
+ kStep,
+ kStorageBarrier,
+ kTan,
+ kTanh,
+ kTranspose,
+ kTrunc,
+ kUnpack2X16Float,
+ kUnpack2X16Snorm,
+ kUnpack2X16Unorm,
+ kUnpack4X8Snorm,
+ kUnpack4X8Unorm,
+ kWorkgroupBarrier,
+ kWorkgroupUniformLoad,
+ kTextureDimensions,
+ kTextureGather,
+ kTextureGatherCompare,
+ kTextureNumLayers,
+ kTextureNumLevels,
+ kTextureNumSamples,
+ kTextureSample,
+ kTextureSampleBias,
+ kTextureSampleCompare,
+ kTextureSampleCompareLevel,
+ kTextureSampleGrad,
+ kTextureSampleLevel,
+ kTextureSampleBaseClampToEdge,
+ kTextureStore,
+ kTextureLoad,
+ kAtomicLoad,
+ kAtomicStore,
+ kAtomicAdd,
+ kAtomicSub,
+ kAtomicMax,
+ kAtomicMin,
+ kAtomicAnd,
+ kAtomicOr,
+ kAtomicXor,
+ kAtomicExchange,
+ kAtomicCompareExchangeWeak,
+ kTintMaterialize,
+};
+
+/// Matches the Function by name
+/// @param name the builtin name to parse
+/// @returns the parsed Function, or Function::kNone if `name` did not
+/// match any builtin function.
+Function ParseFunction(const std::string& name);
+
+/// @returns the name of the builtin function type. The spelling, including
+/// case, matches the name in the WGSL spec.
+const char* str(Function i);
+
+/// Emits the name of the builtin function type. The spelling, including case,
+/// matches the name in the WGSL spec.
+utils::StringStream& operator<<(utils::StringStream& out, Function i);
+
+/// All builtin functions
+constexpr Function kFunctions[] = {
+ Function::kAbs,
+ Function::kAcos,
+ Function::kAcosh,
+ Function::kAll,
+ Function::kAny,
+ Function::kArrayLength,
+ Function::kAsin,
+ Function::kAsinh,
+ Function::kAtan,
+ Function::kAtan2,
+ Function::kAtanh,
+ Function::kCeil,
+ Function::kClamp,
+ Function::kCos,
+ Function::kCosh,
+ Function::kCountLeadingZeros,
+ Function::kCountOneBits,
+ Function::kCountTrailingZeros,
+ Function::kCross,
+ Function::kDegrees,
+ Function::kDeterminant,
+ Function::kDistance,
+ Function::kDot,
+ Function::kDot4I8Packed,
+ Function::kDot4U8Packed,
+ Function::kDpdx,
+ Function::kDpdxCoarse,
+ Function::kDpdxFine,
+ Function::kDpdy,
+ Function::kDpdyCoarse,
+ Function::kDpdyFine,
+ Function::kExp,
+ Function::kExp2,
+ Function::kExtractBits,
+ Function::kFaceForward,
+ Function::kFirstLeadingBit,
+ Function::kFirstTrailingBit,
+ Function::kFloor,
+ Function::kFma,
+ Function::kFract,
+ Function::kFrexp,
+ Function::kFwidth,
+ Function::kFwidthCoarse,
+ Function::kFwidthFine,
+ Function::kInsertBits,
+ Function::kInverseSqrt,
+ Function::kLdexp,
+ Function::kLength,
+ Function::kLog,
+ Function::kLog2,
+ Function::kMax,
+ Function::kMin,
+ Function::kMix,
+ Function::kModf,
+ Function::kNormalize,
+ Function::kPack2X16Float,
+ Function::kPack2X16Snorm,
+ Function::kPack2X16Unorm,
+ Function::kPack4X8Snorm,
+ Function::kPack4X8Unorm,
+ Function::kPow,
+ Function::kQuantizeToF16,
+ Function::kRadians,
+ Function::kReflect,
+ Function::kRefract,
+ Function::kReverseBits,
+ Function::kRound,
+ Function::kSaturate,
+ Function::kSelect,
+ Function::kSign,
+ Function::kSin,
+ Function::kSinh,
+ Function::kSmoothstep,
+ Function::kSqrt,
+ Function::kStep,
+ Function::kStorageBarrier,
+ Function::kTan,
+ Function::kTanh,
+ Function::kTranspose,
+ Function::kTrunc,
+ Function::kUnpack2X16Float,
+ Function::kUnpack2X16Snorm,
+ Function::kUnpack2X16Unorm,
+ Function::kUnpack4X8Snorm,
+ Function::kUnpack4X8Unorm,
+ Function::kWorkgroupBarrier,
+ Function::kWorkgroupUniformLoad,
+ Function::kTextureDimensions,
+ Function::kTextureGather,
+ Function::kTextureGatherCompare,
+ Function::kTextureNumLayers,
+ Function::kTextureNumLevels,
+ Function::kTextureNumSamples,
+ Function::kTextureSample,
+ Function::kTextureSampleBias,
+ Function::kTextureSampleCompare,
+ Function::kTextureSampleCompareLevel,
+ Function::kTextureSampleGrad,
+ Function::kTextureSampleLevel,
+ Function::kTextureSampleBaseClampToEdge,
+ Function::kTextureStore,
+ Function::kTextureLoad,
+ Function::kAtomicLoad,
+ Function::kAtomicStore,
+ Function::kAtomicAdd,
+ Function::kAtomicSub,
+ Function::kAtomicMax,
+ Function::kAtomicMin,
+ Function::kAtomicAnd,
+ Function::kAtomicOr,
+ Function::kAtomicXor,
+ Function::kAtomicExchange,
+ Function::kAtomicCompareExchangeWeak,
+ Function::kTintMaterialize,
+};
+
+/// All builtin function names
+constexpr const char* kFunctionStrings[] = {
+ "abs",
+ "acos",
+ "acosh",
+ "all",
+ "any",
+ "arrayLength",
+ "asin",
+ "asinh",
+ "atan",
+ "atan2",
+ "atanh",
+ "ceil",
+ "clamp",
+ "cos",
+ "cosh",
+ "countLeadingZeros",
+ "countOneBits",
+ "countTrailingZeros",
+ "cross",
+ "degrees",
+ "determinant",
+ "distance",
+ "dot",
+ "dot4I8Packed",
+ "dot4U8Packed",
+ "dpdx",
+ "dpdxCoarse",
+ "dpdxFine",
+ "dpdy",
+ "dpdyCoarse",
+ "dpdyFine",
+ "exp",
+ "exp2",
+ "extractBits",
+ "faceForward",
+ "firstLeadingBit",
+ "firstTrailingBit",
+ "floor",
+ "fma",
+ "fract",
+ "frexp",
+ "fwidth",
+ "fwidthCoarse",
+ "fwidthFine",
+ "insertBits",
+ "inverseSqrt",
+ "ldexp",
+ "length",
+ "log",
+ "log2",
+ "max",
+ "min",
+ "mix",
+ "modf",
+ "normalize",
+ "pack2x16float",
+ "pack2x16snorm",
+ "pack2x16unorm",
+ "pack4x8snorm",
+ "pack4x8unorm",
+ "pow",
+ "quantizeToF16",
+ "radians",
+ "reflect",
+ "refract",
+ "reverseBits",
+ "round",
+ "saturate",
+ "select",
+ "sign",
+ "sin",
+ "sinh",
+ "smoothstep",
+ "sqrt",
+ "step",
+ "storageBarrier",
+ "tan",
+ "tanh",
+ "transpose",
+ "trunc",
+ "unpack2x16float",
+ "unpack2x16snorm",
+ "unpack2x16unorm",
+ "unpack4x8snorm",
+ "unpack4x8unorm",
+ "workgroupBarrier",
+ "workgroupUniformLoad",
+ "textureDimensions",
+ "textureGather",
+ "textureGatherCompare",
+ "textureNumLayers",
+ "textureNumLevels",
+ "textureNumSamples",
+ "textureSample",
+ "textureSampleBias",
+ "textureSampleCompare",
+ "textureSampleCompareLevel",
+ "textureSampleGrad",
+ "textureSampleLevel",
+ "textureSampleBaseClampToEdge",
+ "textureStore",
+ "textureLoad",
+ "atomicLoad",
+ "atomicStore",
+ "atomicAdd",
+ "atomicSub",
+ "atomicMax",
+ "atomicMin",
+ "atomicAnd",
+ "atomicOr",
+ "atomicXor",
+ "atomicExchange",
+ "atomicCompareExchangeWeak",
+ "_tint_materialize",
+};
+
+} // namespace tint::builtin
+// \endcond
+
+#endif // SRC_TINT_BUILTIN_FUNCTION_H_
diff --git a/src/tint/builtin/function.h.tmpl b/src/tint/builtin/function.h.tmpl
new file mode 100644
index 0000000..d9109bf
--- /dev/null
+++ b/src/tint/builtin/function.h.tmpl
@@ -0,0 +1,63 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/src/cmd/gen to generate function.h
+
+To update the generated file, run:
+ ./tools/run gen
+
+See:
+* tools/src/cmd/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+#ifndef SRC_TINT_BUILTIN_FUNCTION_H_
+#define SRC_TINT_BUILTIN_FUNCTION_H_
+
+#include <string>
+
+#include "src/tint/utils/string_stream.h"
+
+// \cond DO_NOT_DOCUMENT
+namespace tint::builtin {
+
+/// Enumerator of all builtin functions
+enum class Function {
+ kNone = -1,
+{{- range Sem.Builtins }}
+ k{{PascalCase .Name}},
+{{- end }}
+};
+
+/// Matches the Function by name
+/// @param name the builtin name to parse
+/// @returns the parsed Function, or Function::kNone if `name` did not
+/// match any builtin function.
+Function ParseFunction(const std::string& name);
+
+/// @returns the name of the builtin function type. The spelling, including
+/// case, matches the name in the WGSL spec.
+const char* str(Function i);
+
+/// Emits the name of the builtin function type. The spelling, including case,
+/// matches the name in the WGSL spec.
+utils::StringStream& operator<<(utils::StringStream& out, Function i);
+
+/// All builtin functions
+constexpr Function kFunctions[] = {
+{{- range Sem.Builtins }}
+ Function::k{{PascalCase .Name}},
+{{- end }}
+};
+
+/// All builtin function names
+constexpr const char* kFunctionStrings[] = {
+{{- range Sem.Builtins }}
+ "{{.Name}}",
+{{- end }}
+};
+
+} // namespace tint::builtin
+// \endcond
+
+#endif // SRC_TINT_BUILTIN_FUNCTION_H_
diff --git a/src/tint/castable.h b/src/tint/castable.h
index d6597fc..71e3ab8 100644
--- a/src/tint/castable.h
+++ b/src/tint/castable.h
@@ -21,9 +21,7 @@
#include <utility>
#include "src/tint/traits.h"
-#include "src/tint/utils/bitcast.h"
#include "src/tint/utils/crc32.h"
-#include "src/tint/utils/defer.h"
#if defined(__clang__)
/// Temporarily disable certain warnings when using Castable API
@@ -532,280 +530,6 @@
template <typename... TYPES>
using CastableCommonBase = detail::CastableCommonBase<TYPES...>;
-/// Default can be used as the default case for a Switch(), when all previous cases failed to match.
-///
-/// Example:
-/// ```
-/// Switch(object,
-/// [&](TypeA*) { /* ... */ },
-/// [&](TypeB*) { /* ... */ },
-/// [&](Default) { /* If not TypeA or TypeB */ });
-/// ```
-struct Default {};
-
-namespace detail {
-
-/// Evaluates to the Switch case type being matched by the switch case function `FN`.
-/// @note does not handle the Default case
-/// @see Switch().
-template <typename FN>
-using SwitchCaseType = std::remove_pointer_t<traits::ParameterType<std::remove_reference_t<FN>, 0>>;
-
-/// Evaluates to true if the function `FN` has the signature of a Default case in a Switch().
-/// @see Switch().
-template <typename FN>
-inline constexpr bool IsDefaultCase =
- std::is_same_v<traits::ParameterType<std::remove_reference_t<FN>, 0>, Default>;
-
-/// Searches the list of Switch cases for a Default case, returning the index of the Default case.
-/// If the a Default case is not found in the tuple, then -1 is returned.
-template <typename TUPLE, std::size_t START_IDX = 0>
-constexpr int IndexOfDefaultCase() {
- if constexpr (START_IDX < std::tuple_size_v<TUPLE>) {
- return IsDefaultCase<std::tuple_element_t<START_IDX, TUPLE>>
- ? static_cast<int>(START_IDX)
- : IndexOfDefaultCase<TUPLE, START_IDX + 1>();
- } else {
- return -1;
- }
-}
-
-/// The implementation of Switch() for non-Default cases.
-/// Switch splits the cases into two a low and high block of cases, and quickly rules out blocks
-/// that cannot match by comparing the HashCode of the object and the cases in the block. If a block
-/// of cases may match the given object's type, then that block is split into two, and the process
-/// recurses. When NonDefaultCases() is called with a single case, then As<> will be used to
-/// dynamically cast to the case type and if the cast succeeds, then the case handler is called.
-/// @returns true if a case handler was found, otherwise false.
-template <typename T, typename RETURN_TYPE, typename... CASES>
-inline bool NonDefaultCases([[maybe_unused]] T* object,
- const TypeInfo* type,
- [[maybe_unused]] RETURN_TYPE* result,
- std::tuple<CASES...>&& cases) {
- using Cases = std::tuple<CASES...>;
-
- static constexpr bool kHasReturnType = !std::is_same_v<RETURN_TYPE, void>;
- static constexpr size_t kNumCases = sizeof...(CASES);
-
- if constexpr (kNumCases == 0) {
- // No cases. Nothing to do.
- return false;
- } else if constexpr (kNumCases == 1) { // NOLINT: cpplint doesn't understand
- // `else if constexpr`
- // Single case.
- using CaseFunc = std::tuple_element_t<0, Cases>;
- static_assert(!IsDefaultCase<CaseFunc>, "NonDefaultCases called with a Default case");
- // Attempt to dynamically cast the object to the handler type. If that succeeds, call the
- // case handler with the cast object.
- using CaseType = SwitchCaseType<CaseFunc>;
- if (type->Is<CaseType>()) {
- auto* ptr = static_cast<CaseType*>(object);
- if constexpr (kHasReturnType) {
- new (result) RETURN_TYPE(static_cast<RETURN_TYPE>(std::get<0>(cases)(ptr)));
- } else {
- std::get<0>(cases)(ptr);
- }
- return true;
- }
- return false;
- } else {
- // Multiple cases.
- // Check the hashcode bits to see if there's any possibility of a case matching in these
- // cases. If there isn't, we can skip all these cases.
- if (MaybeAnyOf(TypeInfo::CombinedHashCodeOf<SwitchCaseType<CASES>...>(),
- type->full_hashcode)) {
- // Split the cases into two, and recurse.
- constexpr size_t kMid = kNumCases / 2;
- return NonDefaultCases(object, type, result, traits::Slice<0, kMid>(cases)) ||
- NonDefaultCases(object, type, result,
- traits::Slice<kMid, kNumCases - kMid>(cases));
- } else {
- return false;
- }
- }
-}
-
-/// The implementation of Switch() for all cases.
-/// @see NonDefaultCases
-template <typename T, typename RETURN_TYPE, typename... CASES>
-inline void SwitchCases(T* object, RETURN_TYPE* result, std::tuple<CASES...>&& cases) {
- using Cases = std::tuple<CASES...>;
-
- static constexpr int kDefaultIndex = detail::IndexOfDefaultCase<Cases>();
- static constexpr bool kHasDefaultCase = kDefaultIndex >= 0;
- static constexpr bool kHasReturnType = !std::is_same_v<RETURN_TYPE, void>;
-
- // Static assertions
- static constexpr bool kDefaultIsOK =
- kDefaultIndex == -1 || kDefaultIndex == static_cast<int>(std::tuple_size_v<Cases> - 1);
- static constexpr bool kReturnIsOK =
- kHasDefaultCase || !kHasReturnType || std::is_constructible_v<RETURN_TYPE>;
- static_assert(kDefaultIsOK, "Default case must be last in Switch()");
- static_assert(kReturnIsOK,
- "Switch() requires either a Default case or a return type that is either void or "
- "default-constructable");
-
- // If the static asserts have fired, don't bother spewing more errors below
- static constexpr bool kAllOK = kDefaultIsOK && kReturnIsOK;
- if constexpr (kAllOK) {
- if (object) {
- auto* type = &object->TypeInfo();
- if constexpr (kHasDefaultCase) {
- // Evaluate non-default cases.
- if (!detail::NonDefaultCases<T>(object, type, result,
- traits::Slice<0, kDefaultIndex>(cases))) {
- // Nothing matched. Evaluate default case.
- if constexpr (kHasReturnType) {
- new (result) RETURN_TYPE(
- static_cast<RETURN_TYPE>(std::get<kDefaultIndex>(cases)({})));
- } else {
- std::get<kDefaultIndex>(cases)({});
- }
- }
- } else {
- if (!detail::NonDefaultCases<T>(object, type, result, std::move(cases))) {
- // Nothing matched. No default case.
- if constexpr (kHasReturnType) {
- new (result) RETURN_TYPE();
- }
- }
- }
- } else {
- // Object is nullptr, so no cases can match
- if constexpr (kHasDefaultCase) {
- // Evaluate default case.
- if constexpr (kHasReturnType) {
- new (result)
- RETURN_TYPE(static_cast<RETURN_TYPE>(std::get<kDefaultIndex>(cases)({})));
- } else {
- std::get<kDefaultIndex>(cases)({});
- }
- } else {
- // No default case, no case can match.
- if constexpr (kHasReturnType) {
- new (result) RETURN_TYPE();
- }
- }
- }
- }
-}
-
-/// Resolves to T if T is not nullptr_t, otherwise resolves to Ignore.
-template <typename T>
-using NullptrToIgnore = std::conditional_t<std::is_same_v<T, std::nullptr_t>, Ignore, T>;
-
-/// Resolves to `const TYPE` if any of `CASE_RETURN_TYPES` are const or pointer-to-const, otherwise
-/// resolves to TYPE.
-template <typename TYPE, typename... CASE_RETURN_TYPES>
-using PropagateReturnConst = std::conditional_t<
- // Are any of the pointer-stripped types const?
- (std::is_const_v<std::remove_pointer_t<CASE_RETURN_TYPES>> || ...),
- const TYPE, // Yes: Apply const to TYPE
- TYPE>; // No: Passthrough
-
-/// SwitchReturnTypeImpl is the implementation of SwitchReturnType
-template <bool IS_CASTABLE, typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
-struct SwitchReturnTypeImpl;
-
-/// SwitchReturnTypeImpl specialization for non-castable case types and an explicitly specified
-/// return type.
-template <typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
-struct SwitchReturnTypeImpl</*IS_CASTABLE*/ false, REQUESTED_TYPE, CASE_RETURN_TYPES...> {
- /// Resolves to `REQUESTED_TYPE`
- using type = REQUESTED_TYPE;
-};
-
-/// SwitchReturnTypeImpl specialization for non-castable case types and an inferred return type.
-template <typename... CASE_RETURN_TYPES>
-struct SwitchReturnTypeImpl</*IS_CASTABLE*/ false, Infer, CASE_RETURN_TYPES...> {
- /// Resolves to the common type for all the cases return types.
- using type = std::common_type_t<CASE_RETURN_TYPES...>;
-};
-
-/// SwitchReturnTypeImpl specialization for castable case types and an explicitly specified return
-/// type.
-template <typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
-struct SwitchReturnTypeImpl</*IS_CASTABLE*/ true, REQUESTED_TYPE, CASE_RETURN_TYPES...> {
- public:
- /// Resolves to `const REQUESTED_TYPE*` or `REQUESTED_TYPE*`
- using type = PropagateReturnConst<std::remove_pointer_t<REQUESTED_TYPE>, CASE_RETURN_TYPES...>*;
-};
-
-/// SwitchReturnTypeImpl specialization for castable case types and an inferred return type.
-template <typename... CASE_RETURN_TYPES>
-struct SwitchReturnTypeImpl</*IS_CASTABLE*/ true, Infer, CASE_RETURN_TYPES...> {
- private:
- using InferredType =
- CastableCommonBase<detail::NullptrToIgnore<std::remove_pointer_t<CASE_RETURN_TYPES>>...>;
-
- public:
- /// `const T*` or `T*`, where T is the common base type for all the castable case types.
- using type = PropagateReturnConst<InferredType, CASE_RETURN_TYPES...>*;
-};
-
-/// Resolves to the return type for a Switch() with the requested return type `REQUESTED_TYPE` and
-/// case statement return types. If `REQUESTED_TYPE` is Infer then the return type will be inferred
-/// from the case return types.
-template <typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
-using SwitchReturnType = typename SwitchReturnTypeImpl<
- IsCastable<NullptrToIgnore<std::remove_pointer_t<CASE_RETURN_TYPES>>...>,
- REQUESTED_TYPE,
- CASE_RETURN_TYPES...>::type;
-
-} // namespace detail
-
-/// Switch is used to dispatch one of the provided callback case handler functions based on the type
-/// of `object` and the parameter type of the case handlers. Switch will sequentially check the type
-/// of `object` against each of the switch case handler functions, and will invoke the first case
-/// handler function which has a parameter type that matches the object type. When a case handler is
-/// matched, it will be called with the single argument of `object` cast to the case handler's
-/// parameter type. Switch will invoke at most one case handler. Each of the case functions must
-/// have the signature `R(T*)` or `R(const T*)`, where `T` is the type matched by that case and `R`
-/// is the return type, consistent across all case handlers.
-///
-/// An optional default case function with the signature `R(Default)` can be used as the last case.
-/// This default case will be called if all previous cases failed to match.
-///
-/// If `object` is nullptr and a default case is provided, then the default case will be called. If
-/// `object` is nullptr and no default case is provided, then no cases will be called.
-///
-/// Example:
-/// ```
-/// Switch(object,
-/// [&](TypeA*) { /* ... */ },
-/// [&](TypeB*) { /* ... */ });
-///
-/// Switch(object,
-/// [&](TypeA*) { /* ... */ },
-/// [&](TypeB*) { /* ... */ },
-/// [&](Default) { /* Called if object is not TypeA or TypeB */ });
-/// ```
-///
-/// @param object the object who's type is used to
-/// @param cases the switch cases
-/// @return the value returned by the called case. If no cases matched, then the zero value for the
-/// consistent case type.
-template <typename RETURN_TYPE = detail::Infer, typename T = CastableBase, typename... CASES>
-inline auto Switch(T* object, CASES&&... cases) {
- using ReturnType = detail::SwitchReturnType<RETURN_TYPE, traits::ReturnType<CASES>...>;
- static constexpr bool kHasReturnType = !std::is_same_v<ReturnType, void>;
-
- if constexpr (kHasReturnType) {
- // Replacement for std::aligned_storage as this is broken on earlier versions of MSVC.
- struct alignas(alignof(ReturnType)) ReturnStorage {
- uint8_t data[sizeof(ReturnType)];
- };
- ReturnStorage storage;
- auto* res = utils::Bitcast<ReturnType*>(&storage);
- TINT_DEFER(res->~ReturnType());
- detail::SwitchCases(object, res, std::forward_as_tuple(std::forward<CASES>(cases)...));
- return *res;
- } else {
- detail::SwitchCases<T, void>(object, nullptr,
- std::forward_as_tuple(std::forward<CASES>(cases)...));
- }
-}
-
} // namespace tint
TINT_CASTABLE_POP_DISABLE_WARNINGS();
diff --git a/src/tint/castable_test.cc b/src/tint/castable_test.cc
index c452c9b..57bd904 100644
--- a/src/tint/castable_test.cc
+++ b/src/tint/castable_test.cc
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
namespace tint {
+namespace {
struct Animal : public tint::Castable<Animal> {};
struct Amphibian : public tint::Castable<Amphibian, Animal> {};
@@ -31,8 +32,6 @@
struct Gecko : public tint::Castable<Gecko, Lizard> {};
struct Iguana : public tint::Castable<Iguana, Lizard> {};
-namespace {
-
TEST(CastableBase, Is) {
std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
std::unique_ptr<CastableBase> bear = std::make_unique<Bear>();
@@ -230,512 +229,6 @@
ASSERT_EQ(gecko->As<Reptile>(), static_cast<Reptile*>(gecko.get()));
}
-TEST(Castable, SwitchNoDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- bool frog_matched_amphibian = false;
- Switch(
- frog.get(), //
- [&](Reptile*) { FAIL() << "frog is not reptile"; },
- [&](Mammal*) { FAIL() << "frog is not mammal"; },
- [&](Amphibian* amphibian) {
- EXPECT_EQ(amphibian, frog.get());
- frog_matched_amphibian = true;
- });
- EXPECT_TRUE(frog_matched_amphibian);
- }
- {
- bool bear_matched_mammal = false;
- Switch(
- bear.get(), //
- [&](Reptile*) { FAIL() << "bear is not reptile"; },
- [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
- [&](Mammal* mammal) {
- EXPECT_EQ(mammal, bear.get());
- bear_matched_mammal = true;
- });
- EXPECT_TRUE(bear_matched_mammal);
- }
- {
- bool gecko_matched_reptile = false;
- Switch(
- gecko.get(), //
- [&](Mammal*) { FAIL() << "gecko is not mammal"; },
- [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
- [&](Reptile* reptile) {
- EXPECT_EQ(reptile, gecko.get());
- gecko_matched_reptile = true;
- });
- EXPECT_TRUE(gecko_matched_reptile);
- }
-}
-
-TEST(Castable, SwitchWithUnusedDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- bool frog_matched_amphibian = false;
- Switch(
- frog.get(), //
- [&](Reptile*) { FAIL() << "frog is not reptile"; },
- [&](Mammal*) { FAIL() << "frog is not mammal"; },
- [&](Amphibian* amphibian) {
- EXPECT_EQ(amphibian, frog.get());
- frog_matched_amphibian = true;
- },
- [&](Default) { FAIL() << "default should not have been selected"; });
- EXPECT_TRUE(frog_matched_amphibian);
- }
- {
- bool bear_matched_mammal = false;
- Switch(
- bear.get(), //
- [&](Reptile*) { FAIL() << "bear is not reptile"; },
- [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
- [&](Mammal* mammal) {
- EXPECT_EQ(mammal, bear.get());
- bear_matched_mammal = true;
- },
- [&](Default) { FAIL() << "default should not have been selected"; });
- EXPECT_TRUE(bear_matched_mammal);
- }
- {
- bool gecko_matched_reptile = false;
- Switch(
- gecko.get(), //
- [&](Mammal*) { FAIL() << "gecko is not mammal"; },
- [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
- [&](Reptile* reptile) {
- EXPECT_EQ(reptile, gecko.get());
- gecko_matched_reptile = true;
- },
- [&](Default) { FAIL() << "default should not have been selected"; });
- EXPECT_TRUE(gecko_matched_reptile);
- }
-}
-
-TEST(Castable, SwitchDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- bool frog_matched_default = false;
- Switch(
- frog.get(), //
- [&](Reptile*) { FAIL() << "frog is not reptile"; },
- [&](Mammal*) { FAIL() << "frog is not mammal"; },
- [&](Default) { frog_matched_default = true; });
- EXPECT_TRUE(frog_matched_default);
- }
- {
- bool bear_matched_default = false;
- Switch(
- bear.get(), //
- [&](Reptile*) { FAIL() << "bear is not reptile"; },
- [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
- [&](Default) { bear_matched_default = true; });
- EXPECT_TRUE(bear_matched_default);
- }
- {
- bool gecko_matched_default = false;
- Switch(
- gecko.get(), //
- [&](Mammal*) { FAIL() << "gecko is not mammal"; },
- [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
- [&](Default) { gecko_matched_default = true; });
- EXPECT_TRUE(gecko_matched_default);
- }
-}
-
-TEST(Castable, SwitchMatchFirst) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- {
- bool frog_matched_animal = false;
- Switch(
- frog.get(),
- [&](Animal* animal) {
- EXPECT_EQ(animal, frog.get());
- frog_matched_animal = true;
- },
- [&](Amphibian*) { FAIL() << "animal should have been matched first"; });
- EXPECT_TRUE(frog_matched_animal);
- }
- {
- bool frog_matched_amphibian = false;
- Switch(
- frog.get(),
- [&](Amphibian* amphibain) {
- EXPECT_EQ(amphibain, frog.get());
- frog_matched_amphibian = true;
- },
- [&](Animal*) { FAIL() << "amphibian should have been matched first"; });
- EXPECT_TRUE(frog_matched_amphibian);
- }
-}
-
-TEST(Castable, SwitchReturnValueWithDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- const char* result = Switch(
- frog.get(), //
- [](Mammal*) { return "mammal"; }, //
- [](Amphibian*) { return "amphibian"; }, //
- [](Default) { return "unknown"; });
- static_assert(std::is_same_v<decltype(result), const char*>);
- EXPECT_EQ(std::string(result), "amphibian");
- }
- {
- const char* result = Switch(
- bear.get(), //
- [](Mammal*) { return "mammal"; }, //
- [](Amphibian*) { return "amphibian"; }, //
- [](Default) { return "unknown"; });
- static_assert(std::is_same_v<decltype(result), const char*>);
- EXPECT_EQ(std::string(result), "mammal");
- }
- {
- const char* result = Switch(
- gecko.get(), //
- [](Mammal*) { return "mammal"; }, //
- [](Amphibian*) { return "amphibian"; }, //
- [](Default) { return "unknown"; });
- static_assert(std::is_same_v<decltype(result), const char*>);
- EXPECT_EQ(std::string(result), "unknown");
- }
-}
-
-TEST(Castable, SwitchReturnValueWithoutDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- const char* result = Switch(
- frog.get(), //
- [](Mammal*) { return "mammal"; }, //
- [](Amphibian*) { return "amphibian"; });
- static_assert(std::is_same_v<decltype(result), const char*>);
- EXPECT_EQ(std::string(result), "amphibian");
- }
- {
- const char* result = Switch(
- bear.get(), //
- [](Mammal*) { return "mammal"; }, //
- [](Amphibian*) { return "amphibian"; });
- static_assert(std::is_same_v<decltype(result), const char*>);
- EXPECT_EQ(std::string(result), "mammal");
- }
- {
- auto* result = Switch(
- gecko.get(), //
- [](Mammal*) { return "mammal"; }, //
- [](Amphibian*) { return "amphibian"; });
- static_assert(std::is_same_v<decltype(result), const char*>);
- EXPECT_EQ(result, nullptr);
- }
-}
-
-TEST(Castable, SwitchInferPODReturnTypeWithDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto result = Switch(
- frog.get(), //
- [](Mammal*) { return 1; }, //
- [](Amphibian*) { return 2.0f; }, //
- [](Default) { return 3.0; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 2.0);
- }
- {
- auto result = Switch(
- bear.get(), //
- [](Mammal*) { return 1.0; }, //
- [](Amphibian*) { return 2.0f; }, //
- [](Default) { return 3; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 1.0);
- }
- {
- auto result = Switch(
- gecko.get(), //
- [](Mammal*) { return 1.0f; }, //
- [](Amphibian*) { return 2; }, //
- [](Default) { return 3.0; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 3.0);
- }
-}
-
-TEST(Castable, SwitchInferPODReturnTypeWithoutDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto result = Switch(
- frog.get(), //
- [](Mammal*) { return 1; }, //
- [](Amphibian*) { return 2.0f; });
- static_assert(std::is_same_v<decltype(result), float>);
- EXPECT_EQ(result, 2.0f);
- }
- {
- auto result = Switch(
- bear.get(), //
- [](Mammal*) { return 1.0f; }, //
- [](Amphibian*) { return 2; });
- static_assert(std::is_same_v<decltype(result), float>);
- EXPECT_EQ(result, 1.0f);
- }
- {
- auto result = Switch(
- gecko.get(), //
- [](Mammal*) { return 1.0; }, //
- [](Amphibian*) { return 2.0f; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 0.0);
- }
-}
-
-TEST(Castable, SwitchInferCastableReturnTypeWithDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto* result = Switch(
- frog.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian*) { return nullptr; }, //
- [](Default) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), Mammal*>);
- EXPECT_EQ(result, nullptr);
- }
- {
- auto* result = Switch(
- bear.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return const_cast<const Amphibian*>(p); },
- [](Default) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), const Animal*>);
- EXPECT_EQ(result, bear.get());
- }
- {
- auto* result = Switch(
- gecko.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return p; }, //
- [](Default) -> CastableBase* { return nullptr; });
- static_assert(std::is_same_v<decltype(result), CastableBase*>);
- EXPECT_EQ(result, nullptr);
- }
-}
-
-TEST(Castable, SwitchInferCastableReturnTypeWithoutDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto* result = Switch(
- frog.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian*) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), Mammal*>);
- EXPECT_EQ(result, nullptr);
- }
- {
- auto* result = Switch(
- bear.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return const_cast<const Amphibian*>(p); }); //
- static_assert(std::is_same_v<decltype(result), const Animal*>);
- EXPECT_EQ(result, bear.get());
- }
- {
- auto* result = Switch(
- gecko.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return p; });
- static_assert(std::is_same_v<decltype(result), Animal*>);
- EXPECT_EQ(result, nullptr);
- }
-}
-
-TEST(Castable, SwitchExplicitPODReturnTypeWithDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto result = Switch<double>(
- frog.get(), //
- [](Mammal*) { return 1; }, //
- [](Amphibian*) { return 2.0f; }, //
- [](Default) { return 3.0; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 2.0f);
- }
- {
- auto result = Switch<double>(
- bear.get(), //
- [](Mammal*) { return 1; }, //
- [](Amphibian*) { return 2; }, //
- [](Default) { return 3; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 1.0f);
- }
- {
- auto result = Switch<double>(
- gecko.get(), //
- [](Mammal*) { return 1.0f; }, //
- [](Amphibian*) { return 2.0f; }, //
- [](Default) { return 3.0f; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 3.0f);
- }
-}
-
-TEST(Castable, SwitchExplicitPODReturnTypeWithoutDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto result = Switch<double>(
- frog.get(), //
- [](Mammal*) { return 1; }, //
- [](Amphibian*) { return 2.0f; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 2.0f);
- }
- {
- auto result = Switch<double>(
- bear.get(), //
- [](Mammal*) { return 1.0f; }, //
- [](Amphibian*) { return 2; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 1.0f);
- }
- {
- auto result = Switch<double>(
- gecko.get(), //
- [](Mammal*) { return 1.0; }, //
- [](Amphibian*) { return 2.0f; });
- static_assert(std::is_same_v<decltype(result), double>);
- EXPECT_EQ(result, 0.0);
- }
-}
-
-TEST(Castable, SwitchExplicitCastableReturnTypeWithDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto* result = Switch<Animal>(
- frog.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian*) { return nullptr; }, //
- [](Default) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), Animal*>);
- EXPECT_EQ(result, nullptr);
- }
- {
- auto* result = Switch<CastableBase>(
- bear.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return const_cast<const Amphibian*>(p); },
- [](Default) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), const CastableBase*>);
- EXPECT_EQ(result, bear.get());
- }
- {
- auto* result = Switch<const Animal>(
- gecko.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return p; }, //
- [](Default) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), const Animal*>);
- EXPECT_EQ(result, nullptr);
- }
-}
-
-TEST(Castable, SwitchExplicitCastableReturnTypeWithoutDefault) {
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- std::unique_ptr<Animal> bear = std::make_unique<Bear>();
- std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
- {
- auto* result = Switch<Animal>(
- frog.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian*) { return nullptr; });
- static_assert(std::is_same_v<decltype(result), Animal*>);
- EXPECT_EQ(result, nullptr);
- }
- {
- auto* result = Switch<CastableBase>(
- bear.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return const_cast<const Amphibian*>(p); }); //
- static_assert(std::is_same_v<decltype(result), const CastableBase*>);
- EXPECT_EQ(result, bear.get());
- }
- {
- auto* result = Switch<const Animal*>(
- gecko.get(), //
- [](Mammal* p) { return p; }, //
- [](Amphibian* p) { return p; });
- static_assert(std::is_same_v<decltype(result), const Animal*>);
- EXPECT_EQ(result, nullptr);
- }
-}
-
-TEST(Castable, SwitchNull) {
- Animal* null = nullptr;
- Switch(
- null, //
- [&](Amphibian*) { FAIL() << "should not be called"; },
- [&](Animal*) { FAIL() << "should not be called"; });
-}
-
-TEST(Castable, SwitchNullNoDefault) {
- Animal* null = nullptr;
- bool default_called = false;
- Switch(
- null, //
- [&](Amphibian*) { FAIL() << "should not be called"; },
- [&](Animal*) { FAIL() << "should not be called"; },
- [&](Default) { default_called = true; });
- EXPECT_TRUE(default_called);
-}
-
-TEST(Castable, SwitchReturnNoDefaultInitializer) {
- struct Object {
- explicit Object(int v) : value(v) {}
- int value;
- };
-
- std::unique_ptr<Animal> frog = std::make_unique<Frog>();
- {
- auto result = Switch(
- frog.get(), //
- [](Mammal*) { return Object(1); }, //
- [](Amphibian*) { return Object(2); }, //
- [](Default) { return Object(3); });
- static_assert(std::is_same_v<decltype(result), Object>);
- EXPECT_EQ(result.value, 2);
- }
- {
- auto result = Switch(
- frog.get(), //
- [](Mammal*) { return Object(1); }, //
- [](Default) { return Object(3); });
- static_assert(std::is_same_v<decltype(result), Object>);
- EXPECT_EQ(result.value, 3);
- }
-}
-
// IsCastable static tests
static_assert(IsCastable<CastableBase>);
static_assert(IsCastable<Animal>);
diff --git a/src/tint/cmd/BUILD.gn b/src/tint/cmd/BUILD.gn
index b4ff6d5..946bd36 100644
--- a/src/tint/cmd/BUILD.gn
+++ b/src/tint/cmd/BUILD.gn
@@ -17,6 +17,8 @@
source_set("tint_cmd_helper") {
sources = [
+ "generate_external_texture_bindings.cc",
+ "generate_external_texture_bindings.h",
"helper.cc",
"helper.h",
]
diff --git a/src/tint/cmd/CMakeLists.txt b/src/tint/cmd/CMakeLists.txt
index 6da9701..142595b 100644
--- a/src/tint/cmd/CMakeLists.txt
+++ b/src/tint/cmd/CMakeLists.txt
@@ -15,6 +15,8 @@
## Tint executable
add_executable(tint "")
target_sources(tint PRIVATE
+ "generate_external_texture_bindings.cc"
+ "generate_external_texture_bindings.h"
"helper.cc"
"helper.h"
"main.cc"
diff --git a/src/tint/writer/generate_external_texture_bindings.cc b/src/tint/cmd/generate_external_texture_bindings.cc
similarity index 82%
rename from src/tint/writer/generate_external_texture_bindings.cc
rename to src/tint/cmd/generate_external_texture_bindings.cc
index 6e5daf0..1b6ca74 100644
--- a/src/tint/writer/generate_external_texture_bindings.cc
+++ b/src/tint/cmd/generate_external_texture_bindings.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/tint/writer/generate_external_texture_bindings.h"
+#include "src/tint/cmd/generate_external_texture_bindings.h"
#include <algorithm>
#include <unordered_map>
@@ -20,12 +20,13 @@
#include "src/tint/ast/module.h"
#include "src/tint/program.h"
+#include "src/tint/sem/binding_point.h"
#include "src/tint/sem/variable.h"
#include "src/tint/type/external_texture.h"
-namespace tint::writer {
+namespace tint::cmd {
-transform::MultiplanarExternalTexture::BindingsMap GenerateExternalTextureBindings(
+writer::ExternalTextureOptions::BindingsMap GenerateExternalTextureBindings(
const Program* program) {
// TODO(tint:1491): Use Inspector once we can get binding info for all
// variables, not just those referenced by entry points.
@@ -45,15 +46,17 @@
}
}
- transform::MultiplanarExternalTexture::BindingsMap new_bindings_map;
+ writer::ExternalTextureOptions::BindingsMap new_bindings_map;
for (auto bp : ext_tex_bps) {
uint32_t g = bp.group;
uint32_t& next_num = group_to_next_binding_number[g];
auto new_bps =
- transform::MultiplanarExternalTexture::BindingPoints{{g, next_num++}, {g, next_num++}};
+ writer::ExternalTextureOptions::BindingPoints{{g, next_num++}, {g, next_num++}};
+
new_bindings_map[bp] = new_bps;
}
+
return new_bindings_map;
}
-} // namespace tint::writer
+} // namespace tint::cmd
diff --git a/src/tint/cmd/generate_external_texture_bindings.h b/src/tint/cmd/generate_external_texture_bindings.h
new file mode 100644
index 0000000..c6a842d
--- /dev/null
+++ b/src/tint/cmd/generate_external_texture_bindings.h
@@ -0,0 +1,26 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_CMD_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
+#define SRC_TINT_CMD_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
+
+#include "tint/tint.h"
+
+namespace tint::cmd {
+
+writer::ExternalTextureOptions::BindingsMap GenerateExternalTextureBindings(const Program* program);
+
+} // namespace tint::cmd
+
+#endif // SRC_TINT_CMD_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
diff --git a/src/tint/writer/generate_external_texture_bindings_test.cc b/src/tint/cmd/generate_external_texture_bindings_test.cc
similarity index 88%
rename from src/tint/writer/generate_external_texture_bindings_test.cc
rename to src/tint/cmd/generate_external_texture_bindings_test.cc
index d6b22ac..2c19675 100644
--- a/src/tint/writer/generate_external_texture_bindings_test.cc
+++ b/src/tint/cmd/generate_external_texture_bindings_test.cc
@@ -15,10 +15,11 @@
#include <utility>
#include "gtest/gtest.h"
+#include "src/tint/cmd/generate_external_texture_bindings.h"
#include "src/tint/program_builder.h"
-#include "src/tint/writer/generate_external_texture_bindings.h"
+#include "src/tint/writer/binding_point.h"
-namespace tint::writer {
+namespace tint::cmd {
namespace {
using namespace tint::number_suffixes; // NOLINT
@@ -45,7 +46,7 @@
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 1u);
- auto to = bindings[transform::BindingPoint{0, 0}];
+ auto to = bindings[writer::BindingPoint{0, 0}];
ASSERT_EQ(to.plane_1.group, 0u);
ASSERT_EQ(to.params.group, 0u);
ASSERT_EQ(to.plane_1.binding, 1u);
@@ -62,13 +63,13 @@
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 2u);
- auto to0 = bindings[transform::BindingPoint{0, 0}];
+ auto to0 = bindings[writer::BindingPoint{0, 0}];
ASSERT_EQ(to0.plane_1.group, 0u);
ASSERT_EQ(to0.params.group, 0u);
ASSERT_EQ(to0.plane_1.binding, 2u);
ASSERT_EQ(to0.params.binding, 3u);
- auto to1 = bindings[transform::BindingPoint{0, 1}];
+ auto to1 = bindings[writer::BindingPoint{0, 1}];
ASSERT_EQ(to1.plane_1.group, 0u);
ASSERT_EQ(to1.params.group, 0u);
ASSERT_EQ(to1.plane_1.binding, 4u);
@@ -85,13 +86,13 @@
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 2u);
- auto to0 = bindings[transform::BindingPoint{0, 0}];
+ auto to0 = bindings[writer::BindingPoint{0, 0}];
ASSERT_EQ(to0.plane_1.group, 0u);
ASSERT_EQ(to0.params.group, 0u);
ASSERT_EQ(to0.plane_1.binding, 1u);
ASSERT_EQ(to0.params.binding, 2u);
- auto to1 = bindings[transform::BindingPoint{1, 0}];
+ auto to1 = bindings[writer::BindingPoint{1, 0}];
ASSERT_EQ(to1.plane_1.group, 1u);
ASSERT_EQ(to1.params.group, 1u);
ASSERT_EQ(to1.plane_1.binding, 1u);
@@ -111,13 +112,13 @@
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 2u);
- auto to0 = bindings[transform::BindingPoint{0, 1}];
+ auto to0 = bindings[writer::BindingPoint{0, 1}];
ASSERT_EQ(to0.plane_1.group, 0u);
ASSERT_EQ(to0.params.group, 0u);
ASSERT_EQ(to0.plane_1.binding, 5u);
ASSERT_EQ(to0.params.binding, 6u);
- auto to1 = bindings[transform::BindingPoint{0, 3}];
+ auto to1 = bindings[writer::BindingPoint{0, 3}];
ASSERT_EQ(to1.plane_1.group, 0u);
ASSERT_EQ(to1.params.group, 0u);
ASSERT_EQ(to1.plane_1.binding, 7u);
@@ -125,4 +126,4 @@
}
} // namespace
-} // namespace tint::writer
+} // namespace tint::cmd
diff --git a/src/tint/cmd/helper.cc b/src/tint/cmd/helper.cc
index 53013fe..49b970a 100644
--- a/src/tint/cmd/helper.cc
+++ b/src/tint/cmd/helper.cc
@@ -18,7 +18,7 @@
#include <utility>
#include <vector>
-#if TINT_BUILD_SPV_WRITER
+#if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp"
#endif
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index 0b2aad2..898f0ac 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -29,11 +29,17 @@
#include "glslang/Public/ShaderLang.h"
#endif // TINT_BUILD_GLSL_WRITER
+#if TINT_BUILD_SYNTAX_TREE_WRITER
+#include "src/tint/writer/syntax_tree/generator.h" // nogncheck
+
+#endif // TINT_BUILD_SYNTAX_TREE_WRITER
+
#if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER
#include "src/tint/ast/module.h"
+#include "src/tint/cmd/generate_external_texture_bindings.h"
#include "src/tint/cmd/helper.h"
#include "src/tint/utils/io/command.h"
#include "src/tint/utils/string.h"
@@ -106,6 +112,10 @@
bool dump_ir = false;
bool dump_ir_graph = false;
#endif // TINT_BUILD_IR
+
+#if TINT_BUILD_SYNTAX_TREE_WRITER
+ bool dump_syntax_tree = false;
+#endif // TINB_BUILD_SYNTAX_TREE_WRITER
};
const char kUsage[] = R"(Usage: tint [options] <input-file>
@@ -383,6 +393,10 @@
} else if (arg == "--dump-ir-graph") {
opts->dump_ir_graph = true;
#endif // TINT_BUILD_IR
+#if TINT_BUILD_SYNTAX_TREE_WRITER
+ } else if (arg == "--dump-ast") {
+ opts->dump_syntax_tree = true;
+#endif // TINT_BUILD_SYNTAX_TREE_WRITER
} else if (arg == "--xcrun") {
++i;
if (i >= args.size()) {
@@ -536,7 +550,8 @@
tint::writer::spirv::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
- gen_options.generate_external_texture_bindings = true;
+ gen_options.external_texture_options.bindings_map =
+ tint::cmd::GenerateExternalTextureBindings(program);
auto result = tint::writer::spirv::Generate(program, gen_options);
if (!result.success) {
tint::cmd::PrintWGSL(std::cerr, *program);
@@ -643,7 +658,8 @@
tint::writer::msl::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
- gen_options.generate_external_texture_bindings = true;
+ gen_options.external_texture_options.bindings_map =
+ tint::cmd::GenerateExternalTextureBindings(input_program);
auto result = tint::writer::msl::Generate(input_program, gen_options);
if (!result.success) {
tint::cmd::PrintWGSL(std::cerr, *program);
@@ -704,7 +720,8 @@
tint::writer::hlsl::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
- gen_options.generate_external_texture_bindings = true;
+ gen_options.external_texture_options.bindings_map =
+ tint::cmd::GenerateExternalTextureBindings(program);
gen_options.root_constant_binding_point = options.hlsl_root_constant_binding_point;
auto result = tint::writer::hlsl::Generate(program, gen_options);
if (!result.success) {
@@ -738,8 +755,8 @@
auto enable_list = program->AST().Enables();
bool dxc_require_16bit_types = false;
- for (auto enable : enable_list) {
- if (enable->extension == tint::builtin::Extension::kF16) {
+ for (auto* enable : enable_list) {
+ if (enable->HasExtension(tint::builtin::Extension::kF16)) {
dxc_require_16bit_types = true;
break;
}
@@ -843,7 +860,8 @@
auto generate = [&](const tint::Program* prg, const std::string entry_point_name) -> bool {
tint::writer::glsl::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
- gen_options.generate_external_texture_bindings = true;
+ gen_options.external_texture_options.bindings_map =
+ tint::cmd::GenerateExternalTextureBindings(prg);
auto result = tint::writer::glsl::Generate(prg, gen_options, entry_point_name);
if (!result.success) {
tint::cmd::PrintWGSL(std::cerr, *prg);
@@ -990,55 +1008,6 @@
m.Add<tint::transform::SubstituteOverride>();
return true;
}},
- {"multiplaner_external_texture",
- [](tint::inspector::Inspector& inspector, tint::transform::Manager& m,
- tint::transform::DataMap& i) {
- using MET = tint::transform::MultiplanarExternalTexture;
-
- // Generate the MultiplanarExternalTexture::NewBindingPoints by finding two free
- // binding points. We may wish to expose these binding points via a command line flag
- // in the future.
-
- // Set of all the group-0 bindings in use.
- std::unordered_set<uint32_t> group0_bindings_in_use;
- auto allocate_binding = [&] {
- for (uint32_t idx = 0;; idx++) {
- auto binding = tint::transform::BindingPoint{0u, idx};
- if (group0_bindings_in_use.emplace(idx).second) {
- return binding;
- }
- }
- };
- // Populate group0_bindings_in_use with the existing bindings across all entry points.
- for (auto ep : inspector.GetEntryPoints()) {
- for (auto binding : inspector.GetResourceBindings(ep.name)) {
- if (binding.bind_group == 0) {
- group0_bindings_in_use.emplace(binding.binding);
- }
- }
- }
- // Allocate new binding points for the external texture's planes and parameters.
- MET::BindingsMap met_bindings;
- for (auto ep : inspector.GetEntryPoints()) {
- for (auto ext_tex : inspector.GetExternalTextureResourceBindings(ep.name)) {
- auto binding = tint::transform::BindingPoint{
- ext_tex.bind_group,
- ext_tex.binding,
- };
- if (met_bindings.count(binding)) {
- continue;
- }
- met_bindings.emplace(binding, MET::BindingPoints{
- /* plane_1 */ allocate_binding(),
- /* params */ allocate_binding(),
- });
- }
- }
-
- i.Add<MET::NewBindingPoints>(std::move(met_bindings));
- m.Add<MET>();
- return true;
- }},
};
auto transform_names = [&] {
tint::utils::StringStream names;
@@ -1055,6 +1024,9 @@
" --dump-ir -- Writes the IR to stdout\n"
" --dump-ir-graph -- Writes the IR graph to 'tint.dot' as a dot graph\n";
#endif // TINT_BUILD_IR
+#if TINT_BUILD_SYNTAX_TREE_WRITER
+ usage += " --dump-ast -- Writes the AST to stdout\n";
+#endif // TINT_BUILD_SYNTAX_TREE_WRITER
std::cout << usage << std::endl;
return 0;
@@ -1092,6 +1064,18 @@
return 1;
}
+#if TINT_BUILD_SYNTAX_TREE_WRITER
+ if (options.dump_syntax_tree) {
+ tint::writer::syntax_tree::Options gen_options;
+ auto result = tint::writer::syntax_tree::Generate(program.get(), gen_options);
+ if (!result.success) {
+ std::cerr << "Failed to dump AST: " << result.error << std::endl;
+ } else {
+ std::cout << result.ast << std::endl;
+ }
+ }
+#endif // TINT_BUILD_SYNTAX_TREE_WRITER
+
#if TINT_BUILD_IR
if (options.dump_ir || options.dump_ir_graph) {
auto result = tint::ir::Module::FromProgram(program.get());
diff --git a/src/tint/constant/composite.h b/src/tint/constant/composite.h
index 3bd4973..ef7233c 100644
--- a/src/tint/constant/composite.h
+++ b/src/tint/constant/composite.h
@@ -25,31 +25,37 @@
namespace tint::constant {
/// Composite holds a number of mixed child values.
-/// Composite may be of a vector, matrix or array type.
+/// Composite may be of a vector, matrix, array or structure type.
/// If each element is the same type and value, then a Splat would be a more efficient constant
/// implementation. Use CreateComposite() to create the appropriate type.
-class Composite : public Castable<Composite, constant::Value> {
+class Composite : public Castable<Composite, Value> {
public:
/// Constructor
/// @param t the compsite type
/// @param els the composite elements
/// @param all_0 true if all elements are 0
/// @param any_0 true if any element is 0
- Composite(const type::Type* t,
- utils::VectorRef<const constant::Value*> els,
- bool all_0,
- bool any_0);
+ Composite(const type::Type* t, utils::VectorRef<const Value*> els, bool all_0, bool any_0);
~Composite() override;
+ /// @copydoc Value::Type()
const type::Type* Type() const override { return type; }
- const constant::Value* Index(size_t i) const override {
+ /// @copydoc Value::Index()
+ const Value* Index(size_t i) const override {
return i < elements.Length() ? elements[i] : nullptr;
}
+ /// @copydoc Value::NumElements()
+ size_t NumElements() const override { return elements.Length(); }
+
+ /// @copydoc Value::AllZero()
bool AllZero() const override { return all_zero; }
+
+ /// @copydoc Value::AnyZero()
bool AnyZero() const override { return any_zero; }
- bool AllEqual() const override { return false; }
+
+ /// @copydoc Value::Hash()
size_t Hash() const override { return hash; }
/// Clones the constant into the provided context
@@ -60,7 +66,7 @@
/// The composite type
type::Type const* const type;
/// The composite elements
- const utils::Vector<const constant::Value*, 4> elements;
+ const utils::Vector<const Value*, 4> elements;
/// True if all elements are zero
const bool all_zero;
/// True if any element is zero
@@ -69,6 +75,7 @@
const size_t hash;
protected:
+ /// @copydoc Value::InternalValue()
std::variant<std::monostate, AInt, AFloat> InternalValue() const override { return {}; }
private:
diff --git a/src/tint/constant/composite_test.cc b/src/tint/constant/composite_test.cc
index 6fc532d..fd083db 100644
--- a/src/tint/constant/composite_test.cc
+++ b/src/tint/constant/composite_test.cc
@@ -56,20 +56,6 @@
EXPECT_FALSE(compositeNone->AnyZero());
}
-TEST_F(ConstantTest_Composite, AllEqual) {
- auto* f32 = create<type::F32>();
-
- auto* fPos0 = create<Scalar<tint::f32>>(f32, 0_f);
- auto* fNeg0 = create<Scalar<tint::f32>>(f32, -0_f);
- auto* fPos1 = create<Scalar<tint::f32>>(f32, 1_f);
-
- auto* compositeEq = create<Composite>(f32, utils::Vector{fPos0, fPos0});
- auto* compositeNe = create<Composite>(f32, utils::Vector{fNeg0, fPos1, fPos0});
-
- EXPECT_TRUE(compositeEq->AllEqual());
- EXPECT_FALSE(compositeNe->AllZero());
-}
-
TEST_F(ConstantTest_Composite, Index) {
auto* f32 = create<type::F32>();
diff --git a/src/tint/constant/scalar.h b/src/tint/constant/scalar.h
index a412d91..fc6aef0 100644
--- a/src/tint/constant/scalar.h
+++ b/src/tint/constant/scalar.h
@@ -25,7 +25,7 @@
/// Scalar holds a single scalar or abstract-numeric value.
template <typename T>
-class Scalar : public Castable<Scalar<T>, constant::Value> {
+class Scalar : public Castable<Scalar<T>, Value> {
public:
static_assert(!std::is_same_v<UnwrapNumber<T>, T> || std::is_same_v<T, bool>,
"T must be a Number or bool");
@@ -40,13 +40,22 @@
}
~Scalar() override = default;
+ /// @copydoc Value::Type()
const type::Type* Type() const override { return type; }
- const constant::Value* Index(size_t) const override { return nullptr; }
+ /// @return nullptr, as Scalar does not hold any elements.
+ const Value* Index(size_t) const override { return nullptr; }
+ /// @copydoc Value::NumElements()
+ size_t NumElements() const override { return 1; }
+
+ /// @copydoc Value::AllZero()
bool AllZero() const override { return IsPositiveZero(); }
+
+ /// @copydoc Value::AnyZero()
bool AnyZero() const override { return IsPositiveZero(); }
- bool AllEqual() const override { return true; }
+
+ /// @copydoc Value::Hash()
size_t Hash() const override { return utils::Hash(type, ValueOf()); }
/// Clones the constant into the provided context
@@ -79,6 +88,7 @@
const T value;
protected:
+ /// @copydoc Value::InternalValue()
std::variant<std::monostate, AInt, AFloat> InternalValue() const override {
if constexpr (IsFloatingPoint<UnwrapNumber<T>>) {
return static_cast<AFloat>(value);
diff --git a/src/tint/constant/scalar_test.cc b/src/tint/constant/scalar_test.cc
index e05cca0..6dedf75 100644
--- a/src/tint/constant/scalar_test.cc
+++ b/src/tint/constant/scalar_test.cc
@@ -155,72 +155,6 @@
EXPECT_FALSE(aiNeg1->AnyZero());
}
-TEST_F(ConstantTest_Scalar, AllEqual) {
- auto* i32 = create<type::I32>();
- auto* u32 = create<type::U32>();
- auto* f16 = create<type::F16>();
- auto* f32 = create<type::F32>();
- auto* bool_ = create<type::Bool>();
-
- auto* i0 = create<Scalar<tint::i32>>(i32, 0_i);
- auto* iPos1 = create<Scalar<tint::i32>>(i32, 1_i);
- auto* iNeg1 = create<Scalar<tint::i32>>(i32, -1_i);
-
- auto* u0 = create<Scalar<tint::u32>>(u32, 0_u);
- auto* u1 = create<Scalar<tint::u32>>(u32, 1_u);
-
- auto* fPos0 = create<Scalar<tint::f32>>(f32, 0_f);
- auto* fNeg0 = create<Scalar<tint::f32>>(f32, -0_f);
- auto* fPos1 = create<Scalar<tint::f32>>(f32, 1_f);
- auto* fNeg1 = create<Scalar<tint::f32>>(f32, -1_f);
-
- auto* f16Pos0 = create<Scalar<tint::f16>>(f16, 0_h);
- auto* f16Neg0 = create<Scalar<tint::f16>>(f16, -0_h);
- auto* f16Pos1 = create<Scalar<tint::f16>>(f16, 1_h);
- auto* f16Neg1 = create<Scalar<tint::f16>>(f16, -1_h);
-
- auto* bf = create<Scalar<bool>>(bool_, false);
- auto* bt = create<Scalar<bool>>(bool_, true);
-
- auto* afPos0 = create<Scalar<tint::AFloat>>(f32, 0.0_a);
- auto* afNeg0 = create<Scalar<tint::AFloat>>(f32, -0.0_a);
- auto* afPos1 = create<Scalar<tint::AFloat>>(f32, 1.0_a);
- auto* afNeg1 = create<Scalar<tint::AFloat>>(f32, -1.0_a);
-
- auto* ai0 = create<Scalar<tint::AInt>>(i32, 0_a);
- auto* aiPos1 = create<Scalar<tint::AInt>>(i32, 1_a);
- auto* aiNeg1 = create<Scalar<tint::AInt>>(i32, -1_a);
-
- EXPECT_TRUE(i0->AllEqual());
- EXPECT_TRUE(iPos1->AllEqual());
- EXPECT_TRUE(iNeg1->AllEqual());
-
- EXPECT_TRUE(u0->AllEqual());
- EXPECT_TRUE(u1->AllEqual());
-
- EXPECT_TRUE(fPos0->AllEqual());
- EXPECT_TRUE(fNeg0->AllEqual());
- EXPECT_TRUE(fPos1->AllEqual());
- EXPECT_TRUE(fNeg1->AllEqual());
-
- EXPECT_TRUE(f16Pos0->AllEqual());
- EXPECT_TRUE(f16Neg0->AllEqual());
- EXPECT_TRUE(f16Pos1->AllEqual());
- EXPECT_TRUE(f16Neg1->AllEqual());
-
- EXPECT_TRUE(bf->AllEqual());
- EXPECT_TRUE(bt->AllEqual());
-
- EXPECT_TRUE(afPos0->AllEqual());
- EXPECT_TRUE(afNeg0->AllEqual());
- EXPECT_TRUE(afPos1->AllEqual());
- EXPECT_TRUE(afNeg1->AllEqual());
-
- EXPECT_TRUE(ai0->AllEqual());
- EXPECT_TRUE(aiPos1->AllEqual());
- EXPECT_TRUE(aiNeg1->AllEqual());
-}
-
TEST_F(ConstantTest_Scalar, ValueOf) {
auto* i32 = create<type::I32>();
auto* u32 = create<type::U32>();
diff --git a/src/tint/constant/splat.h b/src/tint/constant/splat.h
index 5494c8f..a496235 100644
--- a/src/tint/constant/splat.h
+++ b/src/tint/constant/splat.h
@@ -25,14 +25,14 @@
/// Splat holds a single value, duplicated as all children.
///
/// Splat is used for zero-initializers, 'splat' initializers, or initializers where each element is
-/// identical. Splat may be of a vector, matrix or array type.
-class Splat : public Castable<Splat, constant::Value> {
+/// identical. Splat may be of a vector, matrix, array or structure type.
+class Splat : public Castable<Splat, Value> {
public:
/// Constructor
/// @param t the splat type
/// @param e the splat element
/// @param n the number of items in the splat
- Splat(const type::Type* t, const constant::Value* e, size_t n);
+ Splat(const type::Type* t, const Value* e, size_t n);
~Splat() override;
/// @returns the type of the splat
@@ -41,14 +41,15 @@
/// Retrieve item at index @p i
/// @param i the index to retrieve
/// @returns the element, or nullptr if out of bounds
- const constant::Value* Index(size_t i) const override { return i < count ? el : nullptr; }
+ const Value* Index(size_t i) const override { return i < count ? el : nullptr; }
+
+ /// @copydoc Value::NumElements()
+ size_t NumElements() const override { return count; }
/// @returns true if the element is zero
bool AllZero() const override { return el->AllZero(); }
/// @returns true if the element is zero
bool AnyZero() const override { return el->AnyZero(); }
- /// @returns true
- bool AllEqual() const override { return true; }
/// @returns the hash for the splat
size_t Hash() const override { return utils::Hash(type, el->Hash(), count); }
@@ -61,7 +62,7 @@
/// The type of the splat element
type::Type const* const type;
/// The element stored in the splat
- const constant::Value* el;
+ const Value* el;
/// The number of items in the splat
const size_t count;
diff --git a/src/tint/constant/splat_test.cc b/src/tint/constant/splat_test.cc
index 5c897cb..fe8aeda 100644
--- a/src/tint/constant/splat_test.cc
+++ b/src/tint/constant/splat_test.cc
@@ -56,22 +56,6 @@
EXPECT_FALSE(SpfPos1->AnyZero());
}
-TEST_F(ConstantTest_Splat, AllEqual) {
- auto* f32 = create<type::F32>();
-
- auto* fPos0 = create<Scalar<tint::f32>>(f32, 0_f);
- auto* fNeg0 = create<Scalar<tint::f32>>(f32, -0_f);
- auto* fPos1 = create<Scalar<tint::f32>>(f32, 1_f);
-
- auto* SpfPos0 = create<Splat>(f32, fPos0, 2);
- auto* SpfNeg0 = create<Splat>(f32, fNeg0, 2);
- auto* SpfPos1 = create<Splat>(f32, fPos1, 2);
-
- EXPECT_TRUE(SpfPos0->AllEqual());
- EXPECT_TRUE(SpfNeg0->AllEqual());
- EXPECT_TRUE(SpfPos1->AllEqual());
-}
-
TEST_F(ConstantTest_Splat, Index) {
auto* f32 = create<type::F32>();
diff --git a/src/tint/constant/value.cc b/src/tint/constant/value.cc
index c41ca34..7545731 100644
--- a/src/tint/constant/value.cc
+++ b/src/tint/constant/value.cc
@@ -14,6 +14,7 @@
#include "src/tint/constant/value.h"
+#include "src/tint/switch.h"
#include "src/tint/type/array.h"
#include "src/tint/type/matrix.h"
#include "src/tint/type/struct.h"
diff --git a/src/tint/constant/value.h b/src/tint/constant/value.h
index d5b9876..eb29998 100644
--- a/src/tint/constant/value.h
+++ b/src/tint/constant/value.h
@@ -37,6 +37,7 @@
/// @returns the type of the value
virtual const type::Type* Type() const = 0;
+ /// @param i the index of the element
/// @returns the child element with the given index, or nullptr if there are no children, or
/// the index is out of bounds.
///
@@ -44,7 +45,10 @@
/// For vectors, this returns the i'th element of the vector.
/// For matrices, this returns the i'th column vector of the matrix.
/// For structures, this returns the i'th member field of the structure.
- virtual const Value* Index(size_t) const = 0;
+ virtual const Value* Index(size_t i) const = 0;
+
+ /// @return the number of elements held by this Value
+ virtual size_t NumElements() const = 0;
/// @returns true if child elements are positive-zero valued.
virtual bool AllZero() const = 0;
@@ -52,9 +56,6 @@
/// @returns true if any child elements are positive-zero valued.
virtual bool AnyZero() const = 0;
- /// @returns true if all child elements have the same value and type.
- virtual bool AllEqual() const = 0;
-
/// @returns a hash of the value.
virtual size_t Hash() const = 0;
@@ -74,7 +75,7 @@
/// @param b the value to compare too
/// @returns true if this value is equal to @p b
- bool Equal(const constant::Value* b) const;
+ bool Equal(const Value* b) const;
/// Clones the constant into the provided context
/// @param ctx the clone context
diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc
index 6e96523..93e5c58 100644
--- a/src/tint/inspector/inspector.cc
+++ b/src/tint/inspector/inspector.cc
@@ -39,6 +39,7 @@
#include "src/tint/sem/statement.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/type/array.h"
#include "src/tint/type/bool.h"
#include "src/tint/type/depth_multisampled_texture.h"
@@ -570,8 +571,10 @@
// Ast nodes for enable directive are stored within global declarations list
auto global_decls = program_->AST().GlobalDeclarations();
for (auto* node : global_decls) {
- if (auto* ext = node->As<ast::Enable>()) {
- result.push_back({utils::ToString(ext->extension), ext->source});
+ if (auto* enable = node->As<ast::Enable>()) {
+ for (auto* ext : enable->extensions) {
+ result.push_back({utils::ToString(ext->name), ext->source});
+ }
}
}
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 316d224..fae4ee4 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -739,7 +739,9 @@
@must_use fn textureGatherCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> vec4<f32>
@must_use fn textureGatherCompare<A: iu32>(texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3<f32>, array_index: A, depth_ref: f32) -> vec4<f32>
@must_use fn textureNumLayers<T: fiu32>(texture: texture_2d_array<T>) -> u32
+@must_use fn textureNumLayers<T: fiu32>(texture: texture_cube_array<T>) -> u32
@must_use fn textureNumLayers(texture: texture_depth_2d_array) -> u32
+@must_use fn textureNumLayers(texture: texture_depth_cube_array) -> u32
@must_use fn textureNumLayers<F: texel_format, A: write>(texture: texture_storage_2d_array<F, A>) -> u32
@must_use fn textureNumLevels<T: fiu32>(texture: texture_1d<T>) -> u32
@must_use fn textureNumLevels<T: fiu32>(texture: texture_2d<T>) -> u32
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index 1452dc4..a3d2a31 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -177,4 +177,26 @@
return ir.instructions.Create<ir::Bitcast>(Temp(type), val);
}
+ir::UserCall* Builder::UserCall(const type::Type* type,
+ Symbol name,
+ utils::VectorRef<Value*> args) {
+ return ir.instructions.Create<ir::UserCall>(Temp(type), name, std::move(args));
+}
+
+ir::Convert* Builder::Convert(const type::Type* to,
+ const type::Type* from,
+ utils::VectorRef<Value*> args) {
+ return ir.instructions.Create<ir::Convert>(Temp(to), from, std::move(args));
+}
+
+ir::Construct* Builder::Construct(const type::Type* to, utils::VectorRef<Value*> args) {
+ return ir.instructions.Create<ir::Construct>(Temp(to), std::move(args));
+}
+
+ir::Builtin* Builder::Builtin(const type::Type* type,
+ builtin::Function func,
+ utils::VectorRef<Value*> args) {
+ return ir.instructions.Create<ir::Builtin>(Temp(type), func, args);
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index 147e4c4..5a39dbb 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -20,7 +20,10 @@
#include "src/tint/constant/scalar.h"
#include "src/tint/ir/binary.h"
#include "src/tint/ir/bitcast.h"
+#include "src/tint/ir/builtin.h"
#include "src/tint/ir/constant.h"
+#include "src/tint/ir/construct.h"
+#include "src/tint/ir/convert.h"
#include "src/tint/ir/function.h"
#include "src/tint/ir/if.h"
#include "src/tint/ir/loop.h"
@@ -28,6 +31,7 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/temp.h"
#include "src/tint/ir/terminator.h"
+#include "src/tint/ir/user_call.h"
#include "src/tint/ir/value.h"
#include "src/tint/type/bool.h"
#include "src/tint/type/f16.h"
@@ -279,6 +283,37 @@
/// @returns the instruction
ir::Bitcast* Bitcast(const type::Type* type, Value* val);
+ /// Creates a user function call instruction
+ /// @param type the return type of the call
+ /// @param name the name of the function being called
+ /// @param args the call arguments
+ /// @returns the instruction
+ ir::UserCall* UserCall(const type::Type* type, Symbol name, utils::VectorRef<Value*> args);
+
+ /// Creates a value conversion instruction
+ /// @param to the type converted to
+ /// @param from the type converted from
+ /// @param args the arguments to be converted
+ /// @returns the instruction
+ ir::Convert* Convert(const type::Type* to,
+ const type::Type* from,
+ utils::VectorRef<Value*> args);
+
+ /// Creates a value constructor instruction
+ /// @param to the type being converted
+ /// @param args the arguments to be converted
+ /// @returns the instruction
+ ir::Construct* Construct(const type::Type* to, utils::VectorRef<Value*> args);
+
+ /// Creates a builtin call instruction
+ /// @param type the return type
+ /// @param func the builtin function
+ /// @param args the arguments to be converted
+ /// @returns the instruction
+ ir::Builtin* Builtin(const type::Type* type,
+ builtin::Function func,
+ utils::VectorRef<Value*> args);
+
/// @returns a unique temp id
Temp::Id AllocateTempId();
diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc
index d3f8d53..ba63be6 100644
--- a/src/tint/ir/builder_impl.cc
+++ b/src/tint/ir/builder_impl.cc
@@ -14,6 +14,8 @@
#include "src/tint/ir/builder_impl.h"
+#include <iostream>
+
#include "src/tint/ast/alias.h"
#include "src/tint/ast/binary_expression.h"
#include "src/tint/ast/bitcast_expression.h"
@@ -21,6 +23,8 @@
#include "src/tint/ast/bool_literal_expression.h"
#include "src/tint/ast/break_if_statement.h"
#include "src/tint/ast/break_statement.h"
+#include "src/tint/ast/call_expression.h"
+#include "src/tint/ast/call_statement.h"
#include "src/tint/ast/const_assert.h"
#include "src/tint/ast/continue_statement.h"
#include "src/tint/ast/float_literal_expression.h"
@@ -28,6 +32,7 @@
#include "src/tint/ast/function.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/identifier.h"
+#include "src/tint/ast/identifier_expression.h"
#include "src/tint/ast/if_statement.h"
#include "src/tint/ast/int_literal_expression.h"
#include "src/tint/ast/literal_expression.h"
@@ -39,6 +44,7 @@
#include "src/tint/ast/struct_member_align_attribute.h"
#include "src/tint/ast/struct_member_size_attribute.h"
#include "src/tint/ast/switch_statement.h"
+#include "src/tint/ast/templated_identifier.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/ast/while_statement.h"
#include "src/tint/ir/function.h"
@@ -48,9 +54,15 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/terminator.h"
#include "src/tint/program.h"
+#include "src/tint/sem/builtin.h"
+#include "src/tint/sem/call.h"
+#include "src/tint/sem/materialize.h"
#include "src/tint/sem/module.h"
#include "src/tint/sem/switch_statement.h"
+#include "src/tint/sem/value_constructor.h"
+#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/value_expression.h"
+#include "src/tint/switch.h"
#include "src/tint/type/void.h"
namespace tint::ir {
@@ -99,6 +111,10 @@
BuilderImpl::~BuilderImpl() = default;
+void BuilderImpl::add_error(const Source& s, const std::string& err) {
+ diagnostics_.add_error(tint::diag::System::IR, err, s);
+}
+
void BuilderImpl::BranchTo(FlowNode* node, utils::VectorRef<Value*> args) {
TINT_ASSERT(IR, current_flow_block);
TINT_ASSERT(IR, !IsBranched(current_flow_block));
@@ -161,9 +177,7 @@
return true;
},
[&](Default) {
- diagnostics_.add_warning(tint::diag::System::IR,
- "unknown type: " + std::string(decl->TypeInfo().name),
- decl->source);
+ add_error(decl->source, "unknown type: " + std::string(decl->TypeInfo().name));
return true;
});
if (!ok) {
@@ -237,9 +251,7 @@
[&](const ast::BlockStatement* b) { return EmitBlock(b); },
[&](const ast::BreakStatement* b) { return EmitBreak(b); },
[&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); },
- // [&](const ast::CallStatement* c) {
- // TODO(dsinclair): Implement
- // },
+ [&](const ast::CallStatement* c) { return EmitCall(c); },
// [&](const ast::CompoundAssignmentStatement* c) {
// TODO(dsinclair): Implement
// },
@@ -258,9 +270,8 @@
return true; // Not emitted
},
[&](Default) {
- diagnostics_.add_warning(
- tint::diag::System::IR,
- "unknown statement type: " + std::string(stmt->TypeInfo().name), stmt->source);
+ add_error(stmt->source,
+ "unknown statement type: " + std::string(stmt->TypeInfo().name));
// TODO(dsinclair): This should return `false`, switch back when all
// the cases are handled.
return true;
@@ -593,9 +604,7 @@
// },
[&](const ast::BinaryExpression* b) { return EmitBinary(b); },
[&](const ast::BitcastExpression* b) { return EmitBitcast(b); },
- // [&](const ast::CallExpression* c) {
- // TODO(dsinclair): Implement
- // },
+ [&](const ast::CallExpression* c) { return EmitCall(c); },
// [&](const ast::IdentifierExpression* i) {
// TODO(dsinclair): Implement
// },
@@ -610,9 +619,8 @@
// TODO(dsinclair): Implement
// },
[&](Default) {
- diagnostics_.add_warning(
- tint::diag::System::IR,
- "unknown expression type: " + std::string(expr->TypeInfo().name), expr->source);
+ add_error(expr->source,
+ "unknown expression type: " + std::string(expr->TypeInfo().name));
// TODO(dsinclair): This should return utils::Failure; Switch back
// once all the above cases are handled.
auto* v = builder.ir.types.Get<type::Void>();
@@ -630,19 +638,16 @@
// TODO(dsinclair): Implement
// },
[&](const ast::Override*) {
- diagnostics_.add_warning(tint::diag::System::IR,
- "found an `Override` variable. The SubstituteOverrides "
- "transform must be run before converting to IR",
- var->source);
+ add_error(var->source,
+ "found an `Override` variable. The SubstituteOverrides "
+ "transform must be run before converting to IR");
return false;
},
// [&](const ast::Const* c) {
// TODO(dsinclair): Implement
// },
[&](Default) {
- diagnostics_.add_warning(tint::diag::System::IR,
- "unknown variable: " + std::string(var->TypeInfo().name),
- var->source);
+ add_error(var->source, "unknown variable: " + std::string(var->TypeInfo().name));
// TODO(dsinclair): This should return `false`, switch back when all
// the cases are handled.
@@ -743,22 +748,83 @@
return instr->Result();
}
+utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallStatement* stmt) {
+ return EmitCall(stmt->expr);
+}
+
+utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
+ // If this is a materialized semantic node, just use the constant value.
+ if (auto* mat = program_->Sem().Get(expr)) {
+ if (mat->ConstantValue()) {
+ auto* cv = mat->ConstantValue()->Clone(clone_ctx_);
+ if (!cv) {
+ add_error(expr->source, "failed to get constant value for call " +
+ std::string(expr->TypeInfo().name));
+ return utils::Failure;
+ }
+ return builder.Constant(cv);
+ }
+ }
+
+ utils::Vector<Value*, 8> args;
+ args.Reserve(expr->args.Length());
+
+ // Emit the arguments
+ for (const auto* arg : expr->args) {
+ auto value = EmitExpression(arg);
+ if (!value) {
+ add_error(arg->source, "failed to convert arguments");
+ return utils::Failure;
+ }
+ args.Push(value.Get());
+ }
+
+ auto* sem = program_->Sem().Get<sem::Call>(expr);
+ if (!sem) {
+ add_error(expr->source, "failed to get semantic information for call " +
+ std::string(expr->TypeInfo().name));
+ return utils::Failure;
+ }
+
+ auto* ty = sem->Target()->ReturnType()->Clone(clone_ctx_.type_ctx);
+
+ Instruction* instr = nullptr;
+
+ // If this is a builtin function, emit the specific builtin value
+ if (auto* b = sem->Target()->As<sem::Builtin>()) {
+ instr = builder.Builtin(ty, b->Type(), args);
+ } else if (sem->Target()->As<sem::ValueConstructor>()) {
+ instr = builder.Construct(ty, std::move(args));
+ } else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
+ auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
+ instr = builder.Convert(ty, from, std::move(args));
+ } else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
+ TINT_UNIMPLEMENTED(IR, diagnostics_) << "missing templated ident support";
+ return utils::Failure;
+ } else {
+ // Not a builtin and not a templated call, so this is a user function.
+ auto name = CloneSymbol(expr->target->identifier->symbol);
+ instr = builder.UserCall(ty, name, std::move(args));
+ }
+ if (instr == nullptr) {
+ return utils::Failure;
+ }
+ current_flow_block->instructions.Push(instr);
+ return instr->Result();
+}
+
utils::Result<Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
auto* sem = program_->Sem().Get(lit);
if (!sem) {
- diagnostics_.add_error(
- tint::diag::System::IR,
- "Failed to get semantic information for node " + std::string(lit->TypeInfo().name),
- lit->source);
+ add_error(lit->source, "failed to get semantic information for node " +
+ std::string(lit->TypeInfo().name));
return utils::Failure;
}
auto* cv = sem->ConstantValue()->Clone(clone_ctx_);
if (!cv) {
- diagnostics_.add_error(
- tint::diag::System::IR,
- "Failed to get constant value for node " + std::string(lit->TypeInfo().name),
- lit->source);
+ add_error(lit->source,
+ "failed to get constant value for node " + std::string(lit->TypeInfo().name));
return utils::Failure;
}
return builder.Constant(cv);
@@ -804,10 +870,9 @@
// TODO(dsinclair): Implement
// },
[&](const ast::IdAttribute*) {
- diagnostics_.add_warning(tint::diag::System::IR,
- "found an `Id` attribute. The SubstituteOverrides transform "
- "must be run before converting to IR",
- attr->source);
+ add_error(attr->source,
+ "found an `Id` attribute. The SubstituteOverrides transform "
+ "must be run before converting to IR");
return false;
},
[&](const ast::StructMemberSizeAttribute*) {
@@ -827,9 +892,7 @@
// TODO(dsinclair): Implement
// },
[&](Default) {
- diagnostics_.add_warning(tint::diag::System::IR,
- "unknown attribute: " + std::string(attr->TypeInfo().name),
- attr->source);
+ add_error(attr->source, "unknown attribute: " + std::string(attr->TypeInfo().name));
return false;
});
}
diff --git a/src/tint/ir/builder_impl.h b/src/tint/ir/builder_impl.h
index 034ab65..2e38ef7 100644
--- a/src/tint/ir/builder_impl.h
+++ b/src/tint/ir/builder_impl.h
@@ -39,6 +39,8 @@
class BlockStatement;
class BreakIfStatement;
class BreakStatement;
+class CallExpression;
+class CallStatement;
class ContinueStatement;
class Expression;
class ForLoopStatement;
@@ -61,6 +63,9 @@
class Switch;
class Terminator;
} // namespace tint::ir
+namespace tint::sem {
+class Builtin;
+} // namespace tint::sem
namespace tint::ir {
@@ -165,6 +170,16 @@
/// @returns the value storing the result if successful, utils::Failure otherwise
utils::Result<Value*> EmitBitcast(const ast::BitcastExpression* expr);
+ /// Emits a call expression
+ /// @param stmt the call statement
+ /// @returns the value storing the result if successful, utils::Failure otherwise
+ utils::Result<Value*> EmitCall(const ast::CallStatement* stmt);
+
+ /// Emits a call expression
+ /// @param expr the call expression
+ /// @returns the value storing the result if successful, utils::Failure otherwise
+ utils::Result<Value*> EmitCall(const ast::CallExpression* expr);
+
/// Emits a literal expression
/// @param lit the literal to emit
/// @returns true if successful, false otherwise
@@ -207,6 +222,8 @@
FlowNode* FindEnclosingControl(ControlFlags flags);
+ void add_error(const Source& s, const std::string& err);
+
const Program* program_ = nullptr;
Symbol CloneSymbol(Symbol sym) const;
diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc
index 9af481b..4e02875 100644
--- a/src/tint/ir/builder_impl_test.cc
+++ b/src/tint/ir/builder_impl_test.cc
@@ -1858,5 +1858,106 @@
)");
}
+TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) {
+ Func("my_func", utils::Vector{Param("p", ty.f32())}, ty.void_(), utils::Empty);
+
+ auto* stmt = CallStmt(Call("my_func", Mul(2_f, 3_f)));
+ WrapInFunction(stmt);
+
+ auto& b = CreateBuilder();
+ InjectFlowBlock();
+ auto r = b.EmitStatement(stmt);
+ ASSERT_TRUE(r) << b.error();
+
+ Disassembler d(b.builder.ir);
+ d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
+ EXPECT_EQ(d.AsString(), R"(%1 (f32) = 2.0 * 3.0
+%2 (void) = call(my_func, %1 (f32))
+)");
+}
+
+// TODO(dsinclair): This needs assignment in order to output correctly. The empty constructor ends
+// up materializing, so there is no expression to emit until there is a usage. When assigment is
+// implemented this can be enabled (and the output updated).
+TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_ConstructEmpty) {
+ auto* expr = vec3(ty.f32());
+ GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
+
+ auto& b = CreateBuilder();
+ InjectFlowBlock();
+ auto r = b.EmitExpression(expr);
+ ASSERT_TRUE(r) << b.error();
+
+ Disassembler d(b.builder.ir);
+ d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
+ EXPECT_EQ(d.AsString(), R"(%1 (vec3<f32>) = construct(vec3<f32>)
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Construct) {
+ auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
+ auto* expr = vec3(ty.f32(), 2_f, 3_f, i);
+ WrapInFunction(expr);
+
+ auto& b = CreateBuilder();
+ InjectFlowBlock();
+ auto r = b.EmitExpression(expr);
+ ASSERT_TRUE(r) << b.error();
+
+ Disassembler d(b.builder.ir);
+ d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
+ EXPECT_EQ(d.AsString(), R"(%2 (vec3<f32>) = construct(vec3<f32>, 2.0, 3.0, %1 (void))
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Convert) {
+ auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i));
+ auto* expr = Call(ty.f32(), i);
+ WrapInFunction(expr);
+
+ auto& b = CreateBuilder();
+ InjectFlowBlock();
+ auto r = b.EmitExpression(expr);
+ ASSERT_TRUE(r) << b.error();
+
+ Disassembler d(b.builder.ir);
+ d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
+ EXPECT_EQ(d.AsString(), R"(%2 (f32) = convert(f32, i32, %1 (void))
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_MaterializedCall) {
+ auto* expr = Return(Call("trunc", 2.5_f));
+
+ Func("test_function", {}, ty.f32(), expr, utils::Empty);
+
+ auto r = Build();
+ ASSERT_TRUE(r) << Error();
+ auto m = r.Move();
+
+ EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function
+ %bb1 = Block
+ Return (2.0)
+FunctionEnd
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Builtin) {
+ auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
+ auto* expr = Call("asin", i);
+ WrapInFunction(expr);
+
+ auto& b = CreateBuilder();
+ InjectFlowBlock();
+ auto r = b.EmitExpression(expr);
+ ASSERT_TRUE(r) << b.error();
+
+ Disassembler d(b.builder.ir);
+ d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
+ EXPECT_EQ(d.AsString(), R"(%2 (f32) = asin(%1 (void))
+)");
+}
+
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/builtin.cc b/src/tint/ir/builtin.cc
new file mode 100644
index 0000000..e9acf66
--- /dev/null
+++ b/src/tint/ir/builtin.cc
@@ -0,0 +1,37 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/builtin.h"
+#include "src/tint/debug.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::Builtin);
+
+// \cond DO_NOT_DOCUMENT
+namespace tint::ir {
+
+Builtin::Builtin(Value* result, builtin::Function func, utils::VectorRef<Value*> args)
+ : Base(result, args), func_(func) {}
+
+Builtin::~Builtin() = default;
+
+utils::StringStream& Builtin::ToString(utils::StringStream& out, const SymbolTable& st) const {
+ Result()->ToString(out, st);
+ out << " = " << builtin::str(func_) << "(";
+ EmitArgs(out, st);
+ out << ")";
+ return out;
+}
+
+} // namespace tint::ir
+// \endcond
diff --git a/src/tint/ir/builtin.h b/src/tint/ir/builtin.h
new file mode 100644
index 0000000..0385c6c
--- /dev/null
+++ b/src/tint/ir/builtin.h
@@ -0,0 +1,57 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_BUILTIN_H_
+#define SRC_TINT_IR_BUILTIN_H_
+
+#include "src/tint/builtin/function.h"
+#include "src/tint/castable.h"
+#include "src/tint/ir/call.h"
+#include "src/tint/symbol_table.h"
+#include "src/tint/type/type.h"
+#include "src/tint/utils/string_stream.h"
+
+namespace tint::ir {
+
+/// A value conversion instruction in the IR.
+class Builtin : public Castable<Builtin, Call> {
+ public:
+ /// Constructor
+ /// @param result the result value
+ /// @param func the builtin function
+ /// @param args the conversion arguments
+ Builtin(Value* result, builtin::Function func, utils::VectorRef<Value*> args);
+ Builtin(const Builtin& instr) = delete;
+ Builtin(Builtin&& instr) = delete;
+ ~Builtin() override;
+
+ Builtin& operator=(const Builtin& instr) = delete;
+ Builtin& operator=(Builtin&& instr) = delete;
+
+ /// @returns the builtin function
+ builtin::Function Func() const { return func_; }
+
+ /// Write the instruction to the given stream
+ /// @param out the stream to write to
+ /// @param st the symbol table
+ /// @returns the stream
+ utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override;
+
+ private:
+ const builtin::Function func_;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_BUILTIN_H_
diff --git a/src/tint/ir/call.cc b/src/tint/ir/call.cc
new file mode 100644
index 0000000..9dda1f9
--- /dev/null
+++ b/src/tint/ir/call.cc
@@ -0,0 +1,40 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/call.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::Call);
+
+namespace tint::ir {
+
+Call::Call(Value* result, utils::VectorRef<Value*> args) : Base(result), args_(args) {
+ for (auto* arg : args) {
+ arg->AddUsage(this);
+ }
+}
+
+Call::~Call() = default;
+
+void Call::EmitArgs(utils::StringStream& out, const SymbolTable& st) const {
+ bool first = true;
+ for (const auto* arg : args_) {
+ if (!first) {
+ out << ", ";
+ }
+ first = false;
+ arg->ToString(out, st);
+ }
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/call.h b/src/tint/ir/call.h
new file mode 100644
index 0000000..d6ced3f
--- /dev/null
+++ b/src/tint/ir/call.h
@@ -0,0 +1,54 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_CALL_H_
+#define SRC_TINT_IR_CALL_H_
+
+#include "src/tint/castable.h"
+#include "src/tint/ir/instruction.h"
+#include "src/tint/symbol_table.h"
+#include "src/tint/type/type.h"
+#include "src/tint/utils/string_stream.h"
+
+namespace tint::ir {
+
+/// A Call instruction in the IR.
+class Call : public Castable<Call, Instruction> {
+ public:
+ /// Constructor
+ /// @param result the result value
+ /// @param args the constructor arguments
+ Call(Value* result, utils::VectorRef<Value*> args);
+ Call(const Call& instr) = delete;
+ Call(Call&& instr) = delete;
+ ~Call() override;
+
+ Call& operator=(const Call& instr) = delete;
+ Call& operator=(Call&& instr) = delete;
+
+ /// @returns the constructor arguments
+ utils::VectorRef<Value*> Args() const { return args_; }
+
+ /// Writes the call arguments to the given stream.
+ /// @param out the output stream
+ /// @param st the symbol table
+ void EmitArgs(utils::StringStream& out, const SymbolTable& st) const;
+
+ private:
+ utils::Vector<Value*, 1> args_;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_CALL_H_
diff --git a/src/tint/ir/constant.cc b/src/tint/ir/constant.cc
index da4cb36..61610b0 100644
--- a/src/tint/ir/constant.cc
+++ b/src/tint/ir/constant.cc
@@ -19,6 +19,7 @@
#include "src/tint/constant/composite.h"
#include "src/tint/constant/scalar.h"
#include "src/tint/constant/splat.h"
+#include "src/tint/switch.h"
TINT_INSTANTIATE_TYPEINFO(tint::ir::Constant);
diff --git a/src/tint/ir/construct.cc b/src/tint/ir/construct.cc
new file mode 100644
index 0000000..27bb084
--- /dev/null
+++ b/src/tint/ir/construct.cc
@@ -0,0 +1,37 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/construct.h"
+#include "src/tint/debug.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::Construct);
+
+namespace tint::ir {
+
+Construct::Construct(Value* result, utils::VectorRef<Value*> args) : Base(result, args) {}
+
+Construct::~Construct() = default;
+
+utils::StringStream& Construct::ToString(utils::StringStream& out, const SymbolTable& st) const {
+ Result()->ToString(out, st);
+ out << " = construct(" << Result()->Type()->FriendlyName(st);
+ if (!Args().IsEmpty()) {
+ out << ", ";
+ EmitArgs(out, st);
+ }
+ out << ")";
+ return out;
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/construct.h b/src/tint/ir/construct.h
new file mode 100644
index 0000000..6f620d3
--- /dev/null
+++ b/src/tint/ir/construct.h
@@ -0,0 +1,49 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_CONSTRUCT_H_
+#define SRC_TINT_IR_CONSTRUCT_H_
+
+#include "src/tint/castable.h"
+#include "src/tint/ir/call.h"
+#include "src/tint/symbol_table.h"
+#include "src/tint/type/type.h"
+#include "src/tint/utils/string_stream.h"
+
+namespace tint::ir {
+
+/// A constructor instruction in the IR.
+class Construct : public Castable<Construct, Call> {
+ public:
+ /// Constructor
+ /// @param result the result value
+ /// @param args the constructor arguments
+ Construct(Value* result, utils::VectorRef<Value*> args);
+ Construct(const Construct& instr) = delete;
+ Construct(Construct&& instr) = delete;
+ ~Construct() override;
+
+ Construct& operator=(const Construct& instr) = delete;
+ Construct& operator=(Construct&& instr) = delete;
+
+ /// Write the instruction to the given stream
+ /// @param out the stream to write to
+ /// @param st the symbol table
+ /// @returns the stream
+ utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_CONSTRUCT_H_
diff --git a/src/tint/ir/convert.cc b/src/tint/ir/convert.cc
new file mode 100644
index 0000000..e845adb
--- /dev/null
+++ b/src/tint/ir/convert.cc
@@ -0,0 +1,36 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/convert.h"
+#include "src/tint/debug.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::Convert);
+
+namespace tint::ir {
+
+Convert::Convert(Value* result, const type::Type* from, utils::VectorRef<Value*> args)
+ : Base(result, args), from_(from) {}
+
+Convert::~Convert() = default;
+
+utils::StringStream& Convert::ToString(utils::StringStream& out, const SymbolTable& st) const {
+ Result()->ToString(out, st);
+ out << " = convert(" << Result()->Type()->FriendlyName(st) << ", " << from_->FriendlyName(st)
+ << ", ";
+ EmitArgs(out, st);
+ out << ")";
+ return out;
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/convert.h b/src/tint/ir/convert.h
new file mode 100644
index 0000000..5132248
--- /dev/null
+++ b/src/tint/ir/convert.h
@@ -0,0 +1,58 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_CONVERT_H_
+#define SRC_TINT_IR_CONVERT_H_
+
+#include "src/tint/castable.h"
+#include "src/tint/ir/call.h"
+#include "src/tint/symbol_table.h"
+#include "src/tint/type/type.h"
+#include "src/tint/utils/string_stream.h"
+
+namespace tint::ir {
+
+/// A value conversion instruction in the IR.
+class Convert : public Castable<Convert, Call> {
+ public:
+ /// Constructor
+ /// @param result the result value
+ /// @param from the type being converted from
+ /// @param args the conversion arguments
+ Convert(Value* result, const type::Type* from, utils::VectorRef<Value*> args);
+ Convert(const Convert& instr) = delete;
+ Convert(Convert&& instr) = delete;
+ ~Convert() override;
+
+ Convert& operator=(const Convert& instr) = delete;
+ Convert& operator=(Convert&& instr) = delete;
+
+ /// @returns the from type
+ const type::Type* From() const { return from_; }
+ /// @returns the to type
+ const type::Type* To() const { return Result()->Type(); }
+
+ /// Write the instruction to the given stream
+ /// @param out the stream to write to
+ /// @param st the symbol table
+ /// @returns the stream
+ utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override;
+
+ private:
+ const type::Type* from_ = nullptr;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_CONVERT_H_
diff --git a/src/tint/ir/debug.cc b/src/tint/ir/debug.cc
index 290aaeb8..eb7d40f 100644
--- a/src/tint/ir/debug.cc
+++ b/src/tint/ir/debug.cc
@@ -22,6 +22,7 @@
#include "src/tint/ir/loop.h"
#include "src/tint/ir/switch.h"
#include "src/tint/ir/terminator.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/string_stream.h"
namespace tint::ir {
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index 1bac411..041495d 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -19,6 +19,7 @@
#include "src/tint/ir/loop.h"
#include "src/tint/ir/switch.h"
#include "src/tint/ir/terminator.h"
+#include "src/tint/switch.h"
namespace tint::ir {
namespace {
diff --git a/src/tint/ir/test_helper.h b/src/tint/ir/test_helper.h
index 9fb54cc..6e36ed3 100644
--- a/src/tint/ir/test_helper.h
+++ b/src/tint/ir/test_helper.h
@@ -40,6 +40,8 @@
/// return the same builder without rebuilding.
/// @return the builder
BuilderImpl& CreateBuilder() {
+ SetResolveOnBuild(true);
+
if (gen_) {
return *gen_;
}
diff --git a/src/tint/ir/user_call.cc b/src/tint/ir/user_call.cc
new file mode 100644
index 0000000..cf672cf
--- /dev/null
+++ b/src/tint/ir/user_call.cc
@@ -0,0 +1,36 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/user_call.h"
+#include "src/tint/debug.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::UserCall);
+
+namespace tint::ir {
+
+UserCall::UserCall(Value* result, Symbol name, utils::VectorRef<Value*> args)
+ : Base(result, args), name_(name) {}
+
+UserCall::~UserCall() = default;
+
+utils::StringStream& UserCall::ToString(utils::StringStream& out, const SymbolTable& st) const {
+ Result()->ToString(out, st);
+ out << " = call(";
+ out << st.NameFor(name_) << ", ";
+ EmitArgs(out, st);
+ out << ")";
+ return out;
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/user_call.h b/src/tint/ir/user_call.h
new file mode 100644
index 0000000..2edeecb
--- /dev/null
+++ b/src/tint/ir/user_call.h
@@ -0,0 +1,56 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_USER_CALL_H_
+#define SRC_TINT_IR_USER_CALL_H_
+
+#include "src/tint/castable.h"
+#include "src/tint/ir/call.h"
+#include "src/tint/symbol_table.h"
+#include "src/tint/type/type.h"
+#include "src/tint/utils/string_stream.h"
+
+namespace tint::ir {
+
+/// A user call instruction in the IR.
+class UserCall : public Castable<UserCall, Call> {
+ public:
+ /// Constructor
+ /// @param result the result value
+ /// @param name the function name
+ /// @param args the function arguments
+ UserCall(Value* result, Symbol name, utils::VectorRef<Value*> args);
+ UserCall(const UserCall& instr) = delete;
+ UserCall(UserCall&& instr) = delete;
+ ~UserCall() override;
+
+ UserCall& operator=(const UserCall& instr) = delete;
+ UserCall& operator=(UserCall&& instr) = delete;
+
+ /// @returns the function name
+ Symbol Name() const { return name_; }
+
+ /// Write the instruction to the given stream
+ /// @param out the stream to write to
+ /// @param st the symbol table
+ /// @returns the stream
+ utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override;
+
+ private:
+ Symbol name_{};
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_USER_CALL_H_
diff --git a/src/tint/program.cc b/src/tint/program.cc
index 432758b..643999d 100644
--- a/src/tint/program.cc
+++ b/src/tint/program.cc
@@ -19,6 +19,7 @@
#include "src/tint/resolver/resolver.h"
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/value_expression.h"
+#include "src/tint/switch.h"
namespace tint {
namespace {
diff --git a/src/tint/program_builder.cc b/src/tint/program_builder.cc
index c0c2ef6..99fce9e 100644
--- a/src/tint/program_builder.cc
+++ b/src/tint/program_builder.cc
@@ -21,6 +21,7 @@
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/value_expression.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/compiler_macros.h"
using namespace tint::number_suffixes; // NOLINT
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index c84a6e0..31f566b 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -2048,20 +2048,22 @@
}
/// Adds the extension to the list of enable directives at the top of the module.
- /// @param ext the extension to enable
+ /// @param extension the extension to enable
/// @return an `ast::Enable` enabling the given extension.
- const ast::Enable* Enable(builtin::Extension ext) {
- auto* enable = create<ast::Enable>(ext);
+ const ast::Enable* Enable(builtin::Extension extension) {
+ auto* ext = create<ast::Extension>(extension);
+ auto* enable = create<ast::Enable>(utils::Vector{ext});
AST().AddEnable(enable);
return enable;
}
/// Adds the extension to the list of enable directives at the top of the module.
/// @param source the enable source
- /// @param ext the extension to enable
+ /// @param extension the extension to enable
/// @return an `ast::Enable` enabling the given extension.
- const ast::Enable* Enable(const Source& source, builtin::Extension ext) {
- auto* enable = create<ast::Enable>(source, ext);
+ const ast::Enable* Enable(const Source& source, builtin::Extension extension) {
+ auto* ext = create<ast::Extension>(source, extension);
+ auto* enable = create<ast::Enable>(source, utils::Vector{ext});
AST().AddEnable(enable);
return enable;
}
@@ -3130,14 +3132,16 @@
/// @param condition the if statement condition expression
/// @param body the if statement body
/// @param else_stmt optional else statement
+ /// @param attributes optional attributes
/// @returns the if statement pointer
template <typename CONDITION>
const ast::IfStatement* If(const Source& source,
CONDITION&& condition,
const ast::BlockStatement* body,
- const ElseStmt else_stmt = ElseStmt()) {
+ const ElseStmt else_stmt = ElseStmt(),
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return create<ast::IfStatement>(source, Expr(std::forward<CONDITION>(condition)), body,
- else_stmt.stmt);
+ else_stmt.stmt, std::move(attributes));
}
/// Creates a ast::IfStatement with input condition, body, and optional
@@ -3145,13 +3149,15 @@
/// @param condition the if statement condition expression
/// @param body the if statement body
/// @param else_stmt optional else statement
+ /// @param attributes optional attributes
/// @returns the if statement pointer
template <typename CONDITION>
const ast::IfStatement* If(CONDITION&& condition,
const ast::BlockStatement* body,
- const ElseStmt else_stmt = ElseStmt()) {
+ const ElseStmt else_stmt = ElseStmt(),
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return create<ast::IfStatement>(Expr(std::forward<CONDITION>(condition)), body,
- else_stmt.stmt);
+ else_stmt.stmt, std::move(attributes));
}
/// Creates an Else object.
@@ -3274,58 +3280,74 @@
return create<ast::LoopStatement>(body, continuing);
}
- /// Creates a ast::ForLoopStatement with input body and optional initializer,
- /// condition and continuing.
+ /// Creates a ast::ForLoopStatement with input body and optional initializer, condition,
+ /// continuing, and attributes.
/// @param source the source information
/// @param init the optional loop initializer
/// @param cond the optional loop condition
/// @param cont the optional loop continuing
/// @param body the loop body
+ /// @param attributes optional attributes
/// @returns the for loop statement pointer
template <typename COND>
- const ast::ForLoopStatement* For(const Source& source,
- const ast::Statement* init,
- COND&& cond,
- const ast::Statement* cont,
- const ast::BlockStatement* body) {
+ const ast::ForLoopStatement* For(
+ const Source& source,
+ const ast::Statement* init,
+ COND&& cond,
+ const ast::Statement* cont,
+ const ast::BlockStatement* body,
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return create<ast::ForLoopStatement>(source, init, Expr(std::forward<COND>(cond)), cont,
- body);
+ body, std::move(attributes));
}
- /// Creates a ast::ForLoopStatement with input body and optional initializer,
- /// condition and continuing.
+ /// Creates a ast::ForLoopStatement with input body and optional initializer, condition,
+ /// continuing, and attributes.
/// @param init the optional loop initializer
/// @param cond the optional loop condition
/// @param cont the optional loop continuing
/// @param body the loop body
+ /// @param attributes optional attributes
/// @returns the for loop statement pointer
template <typename COND>
- const ast::ForLoopStatement* For(const ast::Statement* init,
- COND&& cond,
- const ast::Statement* cont,
- const ast::BlockStatement* body) {
- return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body);
+ const ast::ForLoopStatement* For(
+ const ast::Statement* init,
+ COND&& cond,
+ const ast::Statement* cont,
+ const ast::BlockStatement* body,
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
+ return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body,
+ std::move(attributes));
}
- /// Creates a ast::WhileStatement with input body and condition.
+ /// Creates a ast::WhileStatement with input body, condition, and optional attributes.
/// @param source the source information
/// @param cond the loop condition
/// @param body the loop body
+ /// @param attributes optional attributes
/// @returns the while statement pointer
template <typename COND>
- const ast::WhileStatement* While(const Source& source,
- COND&& cond,
- const ast::BlockStatement* body) {
- return create<ast::WhileStatement>(source, Expr(std::forward<COND>(cond)), body);
+ const ast::WhileStatement* While(
+ const Source& source,
+ COND&& cond,
+ const ast::BlockStatement* body,
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
+ return create<ast::WhileStatement>(source, Expr(std::forward<COND>(cond)), body,
+ std::move(attributes));
}
- /// Creates a ast::WhileStatement with given condition and body.
+ /// Creates a ast::WhileStatement with input body, condition, and optional attributes.
/// @param cond the condition
/// @param body the loop body
+ /// @param attributes optional attributes
/// @returns the while loop statement pointer
template <typename COND>
- const ast::WhileStatement* While(COND&& cond, const ast::BlockStatement* body) {
- return create<ast::WhileStatement>(Expr(std::forward<COND>(cond)), body);
+ const ast::WhileStatement* While(
+ COND&& cond,
+ const ast::BlockStatement* body,
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
+ return create<ast::WhileStatement>(Expr(std::forward<COND>(cond)), body,
+ std::move(attributes));
}
/// Creates a ast::VariableDeclStatement for the input variable
@@ -3348,14 +3370,15 @@
/// @param condition the condition expression initializer
/// @param cases case statements
/// @returns the switch statement pointer
- template <typename ExpressionInit, typename... Cases>
+ template <typename ExpressionInit, typename... Cases, typename = DisableIfVectorLike<Cases...>>
const ast::SwitchStatement* Switch(const Source& source,
ExpressionInit&& condition,
Cases&&... cases) {
return create<ast::SwitchStatement>(
source, Expr(std::forward<ExpressionInit>(condition)),
utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
- std::forward<Cases>(cases)...});
+ std::forward<Cases>(cases)...},
+ utils::Empty);
}
/// Creates a ast::SwitchStatement with input expression and cases
@@ -3364,12 +3387,44 @@
/// @returns the switch statement pointer
template <typename ExpressionInit,
typename... Cases,
- typename = DisableIfSource<ExpressionInit>>
+ typename = DisableIfSource<ExpressionInit>,
+ typename = DisableIfVectorLike<Cases...>>
const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
return create<ast::SwitchStatement>(
Expr(std::forward<ExpressionInit>(condition)),
utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
- std::forward<Cases>(cases)...});
+ std::forward<Cases>(cases)...},
+ utils::Empty);
+ }
+
+ /// Creates a ast::SwitchStatement with input expression, cases, and optional attributes
+ /// @param source the source information
+ /// @param condition the condition expression initializer
+ /// @param cases case statements
+ /// @param attributes optional attributes
+ /// @returns the switch statement pointer
+ template <typename ExpressionInit>
+ const ast::SwitchStatement* Switch(
+ const Source& source,
+ ExpressionInit&& condition,
+ utils::VectorRef<const ast::CaseStatement*> cases,
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
+ return create<ast::SwitchStatement>(source, Expr(std::forward<ExpressionInit>(condition)),
+ cases, std::move(attributes));
+ }
+
+ /// Creates a ast::SwitchStatement with input expression, cases, and optional attributes
+ /// @param condition the condition expression initializer
+ /// @param cases case statements
+ /// @param attributes optional attributes
+ /// @returns the switch statement pointer
+ template <typename ExpressionInit, typename = DisableIfSource<ExpressionInit>>
+ const ast::SwitchStatement* Switch(
+ ExpressionInit&& condition,
+ utils::VectorRef<const ast::CaseStatement*> cases,
+ utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
+ return create<ast::SwitchStatement>(Expr(std::forward<ExpressionInit>(condition)), cases,
+ std::move(attributes));
}
/// Creates a ast::CaseStatement with input list of selectors, and body
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 49d4e83..7ec46e7 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -32,7 +32,8 @@
#include "src/tint/ast/unary_op_expression.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/builtin/builtin_value.h"
-#include "src/tint/sem/builtin_type.h"
+#include "src/tint/builtin/function.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/spirv_atomic.h"
#include "src/tint/type/depth_texture.h"
#include "src/tint/type/sampled_texture.h"
@@ -452,42 +453,42 @@
}
// Returns the WGSL standard library function builtin for the
-// given instruction, or sem::BuiltinType::kNone
-sem::BuiltinType GetBuiltin(spv::Op opcode) {
+// given instruction, or builtin::Function::kNone
+builtin::Function GetBuiltin(spv::Op opcode) {
switch (opcode) {
case spv::Op::OpBitCount:
- return sem::BuiltinType::kCountOneBits;
+ return builtin::Function::kCountOneBits;
case spv::Op::OpBitFieldInsert:
- return sem::BuiltinType::kInsertBits;
+ return builtin::Function::kInsertBits;
case spv::Op::OpBitFieldSExtract:
case spv::Op::OpBitFieldUExtract:
- return sem::BuiltinType::kExtractBits;
+ return builtin::Function::kExtractBits;
case spv::Op::OpBitReverse:
- return sem::BuiltinType::kReverseBits;
+ return builtin::Function::kReverseBits;
case spv::Op::OpDot:
- return sem::BuiltinType::kDot;
+ return builtin::Function::kDot;
case spv::Op::OpDPdx:
- return sem::BuiltinType::kDpdx;
+ return builtin::Function::kDpdx;
case spv::Op::OpDPdy:
- return sem::BuiltinType::kDpdy;
+ return builtin::Function::kDpdy;
case spv::Op::OpFwidth:
- return sem::BuiltinType::kFwidth;
+ return builtin::Function::kFwidth;
case spv::Op::OpDPdxFine:
- return sem::BuiltinType::kDpdxFine;
+ return builtin::Function::kDpdxFine;
case spv::Op::OpDPdyFine:
- return sem::BuiltinType::kDpdyFine;
+ return builtin::Function::kDpdyFine;
case spv::Op::OpFwidthFine:
- return sem::BuiltinType::kFwidthFine;
+ return builtin::Function::kFwidthFine;
case spv::Op::OpDPdxCoarse:
- return sem::BuiltinType::kDpdxCoarse;
+ return builtin::Function::kDpdxCoarse;
case spv::Op::OpDPdyCoarse:
- return sem::BuiltinType::kDpdyCoarse;
+ return builtin::Function::kDpdyCoarse;
case spv::Op::OpFwidthCoarse:
- return sem::BuiltinType::kFwidthCoarse;
+ return builtin::Function::kFwidthCoarse;
default:
break;
}
- return sem::BuiltinType::kNone;
+ return builtin::Function::kNone;
}
// @param opcode a SPIR-V opcode
@@ -705,8 +706,8 @@
auto reversed_cases = cases;
std::reverse(reversed_cases.begin(), reversed_cases.end());
- return builder->create<ast::SwitchStatement>(Source{}, condition,
- std::move(reversed_cases));
+ return builder->create<ast::SwitchStatement>(Source{}, condition, std::move(reversed_cases),
+ utils::Empty);
}
/// Switch statement condition
@@ -725,7 +726,7 @@
/// @param builder the program builder
/// @returns the built ast::IfStatement
const ast::IfStatement* Build(ProgramBuilder* builder) const override {
- return builder->create<ast::IfStatement>(Source{}, cond, body, else_stmt);
+ return builder->create<ast::IfStatement>(Source{}, cond, body, else_stmt, utils::Empty);
}
/// If-statement condition
@@ -3324,7 +3325,8 @@
else_block = create<ast::BlockStatement>(StatementList{else_stmt}, utils::Empty);
}
- auto* if_stmt = create<ast::IfStatement>(Source{}, condition, if_block, else_block);
+ auto* if_stmt =
+ create<ast::IfStatement>(Source{}, condition, if_block, else_block, utils::Empty);
return if_stmt;
}
@@ -3816,7 +3818,7 @@
}
const auto builtin = GetBuiltin(op);
- if (builtin != sem::BuiltinType::kNone) {
+ if (builtin != builtin::Function::kNone) {
return MakeBuiltinCall(inst);
}
@@ -5250,7 +5252,7 @@
TypedExpression FunctionEmitter::MakeBuiltinCall(const spvtools::opt::Instruction& inst) {
const auto builtin = GetBuiltin(opcode(inst));
- auto* name = sem::str(builtin);
+ auto* name = builtin::str(builtin);
auto* ident = create<ast::Identifier>(Source{}, builder_.Symbols().Register(name));
ExpressionList params;
@@ -5741,7 +5743,7 @@
}
bool FunctionEmitter::EmitAtomicOp(const spvtools::opt::Instruction& inst) {
- auto emit_atomic = [&](sem::BuiltinType builtin, std::initializer_list<TypedExpression> args) {
+ auto emit_atomic = [&](builtin::Function builtin, std::initializer_list<TypedExpression> args) {
// Split args into params and expressions
ParameterList params;
params.Reserve(args.size());
@@ -5763,7 +5765,7 @@
// Emit stub, will be removed by transform::SpirvAtomic
auto* stub = builder_.Func(
- Source{}, builder_.Symbols().New(std::string("stub_") + sem::str(builtin)),
+ Source{}, builder_.Symbols().New(std::string("stub_") + builtin::str(builtin)),
std::move(params), ret_type,
/* body */ nullptr,
utils::Vector{
@@ -5800,39 +5802,39 @@
switch (opcode(inst)) {
case spv::Op::OpAtomicLoad:
- return emit_atomic(sem::BuiltinType::kAtomicLoad, {oper(/*ptr*/ 0)});
+ return emit_atomic(builtin::Function::kAtomicLoad, {oper(/*ptr*/ 0)});
case spv::Op::OpAtomicStore:
- return emit_atomic(sem::BuiltinType::kAtomicStore,
+ return emit_atomic(builtin::Function::kAtomicStore,
{oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicExchange:
- return emit_atomic(sem::BuiltinType::kAtomicExchange,
+ return emit_atomic(builtin::Function::kAtomicExchange,
{oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicCompareExchange:
case spv::Op::OpAtomicCompareExchangeWeak:
- return emit_atomic(sem::BuiltinType::kAtomicCompareExchangeWeak,
+ return emit_atomic(builtin::Function::kAtomicCompareExchangeWeak,
{oper(/*ptr*/ 0), /*value*/ oper(5), /*comparator*/ oper(4)});
case spv::Op::OpAtomicIIncrement:
- return emit_atomic(sem::BuiltinType::kAtomicAdd, {oper(/*ptr*/ 0), lit(1)});
+ return emit_atomic(builtin::Function::kAtomicAdd, {oper(/*ptr*/ 0), lit(1)});
case spv::Op::OpAtomicIDecrement:
- return emit_atomic(sem::BuiltinType::kAtomicSub, {oper(/*ptr*/ 0), lit(1)});
+ return emit_atomic(builtin::Function::kAtomicSub, {oper(/*ptr*/ 0), lit(1)});
case spv::Op::OpAtomicIAdd:
- return emit_atomic(sem::BuiltinType::kAtomicAdd, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicAdd, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicISub:
- return emit_atomic(sem::BuiltinType::kAtomicSub, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicSub, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicSMin:
- return emit_atomic(sem::BuiltinType::kAtomicMin, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicMin, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicUMin:
- return emit_atomic(sem::BuiltinType::kAtomicMin, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicMin, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicSMax:
- return emit_atomic(sem::BuiltinType::kAtomicMax, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicMax, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicUMax:
- return emit_atomic(sem::BuiltinType::kAtomicMax, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicMax, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicAnd:
- return emit_atomic(sem::BuiltinType::kAtomicAnd, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicAnd, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicOr:
- return emit_atomic(sem::BuiltinType::kAtomicOr, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicOr, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicXor:
- return emit_atomic(sem::BuiltinType::kAtomicXor, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ return emit_atomic(builtin::Function::kAtomicXor, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
case spv::Op::OpAtomicFlagTestAndSet:
case spv::Op::OpAtomicFlagClear:
case spv::Op::OpAtomicFMinEXT:
diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc
index a1c9042..9f5afdb 100644
--- a/src/tint/reader/spirv/parser_impl.cc
+++ b/src/tint/reader/spirv/parser_impl.cc
@@ -26,6 +26,7 @@
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/unary_op_expression.h"
#include "src/tint/reader/spirv/function.h"
+#include "src/tint/switch.h"
#include "src/tint/type/depth_texture.h"
#include "src/tint/type/multisampled_texture.h"
#include "src/tint/type/sampled_texture.h"
diff --git a/src/tint/reader/spirv/parser_impl_barrier_test.cc b/src/tint/reader/spirv/parser_impl_barrier_test.cc
index a594098..ef8e5af 100644
--- a/src/tint/reader/spirv/parser_impl_barrier_test.cc
+++ b/src/tint/reader/spirv/parser_impl_barrier_test.cc
@@ -73,7 +73,7 @@
ASSERT_NE(sem_call, nullptr);
auto* builtin = sem_call->Target()->As<sem::Builtin>();
ASSERT_NE(builtin, nullptr);
- EXPECT_EQ(builtin->Type(), sem::BuiltinType::kWorkgroupBarrier);
+ EXPECT_EQ(builtin->Type(), builtin::Function::kWorkgroupBarrier);
}
TEST_F(SpvParserTest, StorageBarrier) {
@@ -106,7 +106,7 @@
ASSERT_NE(sem_call, nullptr);
auto* builtin = sem_call->Target()->As<sem::Builtin>();
ASSERT_NE(builtin, nullptr);
- EXPECT_EQ(builtin->Type(), sem::BuiltinType::kStorageBarrier);
+ EXPECT_EQ(builtin->Type(), builtin::Function::kStorageBarrier);
}
TEST_F(SpvParserTest, ErrBarrierInvalidExecution) {
diff --git a/src/tint/reader/spirv/parser_impl_test_helper.cc b/src/tint/reader/spirv/parser_impl_test_helper.cc
index 754922c..2a19c3d 100644
--- a/src/tint/reader/spirv/parser_impl_test_helper.cc
+++ b/src/tint/reader/spirv/parser_impl_test_helper.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include "src/tint/reader/spirv/parser_impl_test_helper.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/wgsl/generator_impl.h"
diff --git a/src/tint/reader/spirv/parser_type.cc b/src/tint/reader/spirv/parser_type.cc
index 71482ff..bc8bd93 100644
--- a/src/tint/reader/spirv/parser_type.cc
+++ b/src/tint/reader/spirv/parser_type.cc
@@ -19,6 +19,7 @@
#include <utility>
#include "src/tint/program_builder.h"
+#include "src/tint/switch.h"
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/hash.h"
#include "src/tint/utils/map.h"
diff --git a/src/tint/reader/wgsl/lexer.cc b/src/tint/reader/wgsl/lexer.cc
index 28fb135..91c2993 100644
--- a/src/tint/reader/wgsl/lexer.cc
+++ b/src/tint/reader/wgsl/lexer.cc
@@ -25,6 +25,7 @@
#include <type_traits>
#include <utility>
+#include "absl/strings/charconv.h"
#include "src/tint/debug.h"
#include "src/tint/number.h"
#include "src/tint/text/unicode.h"
@@ -352,9 +353,11 @@
// Parse the exponent if one exists
bool has_exponent = false;
+ bool negative_exponent = false;
if (end < length() && (matches(end, 'e') || matches(end, 'E'))) {
end++;
if (end < length() && (matches(end, '+') || matches(end, '-'))) {
+ negative_exponent = matches(end, '-');
end++;
}
@@ -374,10 +377,8 @@
bool has_f_suffix = false;
bool has_h_suffix = false;
if (end < length() && matches(end, 'f')) {
- end++;
has_f_suffix = true;
} else if (end < length() && matches(end, 'h')) {
- end++;
has_h_suffix = true;
}
@@ -386,29 +387,51 @@
return {};
}
- advance(end - start);
- end_source(source);
+ // Note, the `at` method will return a static `0` if the provided position is >= length. We
+ // actually need the end pointer to point to the correct memory location to use `from_chars`.
+ // So, handle the case where we point past the length specially.
+ auto* end_ptr = &at(end);
+ if (end >= length()) {
+ end_ptr = &at(length() - 1) + 1;
+ }
- double value = std::strtod(&at(start), nullptr);
+ double value = 0;
+ auto ret = absl::from_chars(&at(start), end_ptr, value);
+ bool overflow = ret.ec != std::errc();
+
+ // The provided value did not fit in a double and has a negative exponent, so treat it as a 0.
+ if (negative_exponent && ret.ec == std::errc::result_out_of_range) {
+ overflow = false;
+ value = 0.0;
+ }
+
+ TINT_ASSERT(Reader, end_ptr == ret.ptr);
+ advance(end - start);
if (has_f_suffix) {
- if (auto f = CheckedConvert<f32>(AFloat(value))) {
+ auto f = CheckedConvert<f32>(AFloat(value));
+ if (!overflow && f) {
+ advance(1);
+ end_source(source);
return {Token::Type::kFloatLiteral_F, source, static_cast<double>(f.Get())};
- } else {
- return {Token::Type::kError, source, "value cannot be represented as 'f32'"};
}
+ return {Token::Type::kError, source, "value cannot be represented as 'f32'"};
}
if (has_h_suffix) {
- if (auto f = CheckedConvert<f16>(AFloat(value))) {
+ auto f = CheckedConvert<f16>(AFloat(value));
+ if (!overflow && f) {
+ advance(1);
+ end_source(source);
return {Token::Type::kFloatLiteral_H, source, static_cast<double>(f.Get())};
- } else {
- return {Token::Type::kError, source, "value cannot be represented as 'f16'"};
}
+ return {Token::Type::kError, source, "value cannot be represented as 'f16'"};
}
+ end_source(source);
+
TINT_BEGIN_DISABLE_WARNING(FLOAT_EQUAL);
- if (value == HUGE_VAL || -value == HUGE_VAL) {
+ if (overflow || value == HUGE_VAL || -value == HUGE_VAL) {
return {Token::Type::kError, source, "value cannot be represented as 'abstract-float'"};
} else {
return {Token::Type::kFloatLiteral, source, value};
diff --git a/src/tint/reader/wgsl/lexer_test.cc b/src/tint/reader/wgsl/lexer_test.cc
index 95b43a7..a244273 100644
--- a/src/tint/reader/wgsl/lexer_test.cc
+++ b/src/tint/reader/wgsl/lexer_test.cc
@@ -397,7 +397,7 @@
Lexer l(&file);
auto list = l.Lex();
- ASSERT_EQ(2u, list.size());
+ ASSERT_EQ(2u, list.size()) << "Got: " << list[0].to_str();
{
auto& t = list[0];
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index e4eab29..6864084 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -42,6 +42,7 @@
#include "src/tint/type/multisampled_texture.h"
#include "src/tint/type/sampled_texture.h"
#include "src/tint/type/texture_dimension.h"
+#include "src/tint/utils/defer.h"
#include "src/tint/utils/reverse.h"
#include "src/tint/utils/string.h"
#include "src/tint/utils/string_stream.h"
@@ -72,21 +73,19 @@
// https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords
bool is_reserved(const Token& t) {
- return t == "CompileShader" || t == "ComputeShader" || t == "DomainShader" ||
- t == "GeometryShader" || t == "Hullshader" || t == "NULL" || t == "Self" ||
- t == "abstract" || t == "active" || t == "alignas" || t == "alignof" || t == "as" ||
- t == "asm" || t == "asm_fragment" || t == "async" || t == "attribute" || t == "auto" ||
- t == "await" || t == "become" || t == "binding_array" || t == "cast" || t == "catch" ||
- t == "class" || t == "co_await" || t == "co_return" || t == "co_yield" ||
- t == "coherent" || t == "column_major" || t == "common" || t == "compile" ||
- t == "compile_fragment" || t == "concept" || t == "const_cast" || t == "consteval" ||
- t == "constexpr" || t == "constinit" || t == "crate" || t == "debugger" ||
- t == "decltype" || t == "delete" || t == "demote" || t == "demote_to_helper" ||
- t == "do" || t == "dynamic_cast" || t == "enum" || t == "explicit" || t == "export" ||
- t == "extends" || t == "extern" || t == "external" || t == "filter" || t == "final" ||
- t == "finally" || t == "friend" || t == "from" || t == "fxgroup" || t == "get" ||
- t == "goto" || t == "groupshared" || t == "handle" || t == "highp" || t == "impl" ||
- t == "implements" || t == "import" || t == "inline" || t == "inout" ||
+ return t == "NULL" || t == "Self" || t == "abstract" || t == "active" || t == "alignas" ||
+ t == "alignof" || t == "as" || t == "asm" || t == "asm_fragment" || t == "async" ||
+ t == "attribute" || t == "auto" || t == "await" || t == "become" ||
+ t == "binding_array" || t == "cast" || t == "catch" || t == "class" || t == "co_await" ||
+ t == "co_return" || t == "co_yield" || t == "coherent" || t == "column_major" ||
+ t == "common" || t == "compile" || t == "compile_fragment" || t == "concept" ||
+ t == "const_cast" || t == "consteval" || t == "constexpr" || t == "constinit" ||
+ t == "crate" || t == "debugger" || t == "decltype" || t == "delete" || t == "demote" ||
+ t == "demote_to_helper" || t == "do" || t == "dynamic_cast" || t == "enum" ||
+ t == "explicit" || t == "export" || t == "extends" || t == "extern" || t == "external" ||
+ t == "filter" || t == "final" || t == "finally" || t == "friend" || t == "from" ||
+ t == "fxgroup" || t == "get" || t == "goto" || t == "groupshared" || t == "highp" ||
+ t == "impl" || t == "implements" || t == "import" || t == "inline" ||
t == "instanceof" || t == "interface" || t == "layout" || t == "lowp" || t == "macro" ||
t == "macro_rules" || t == "match" || t == "mediump" || t == "meta" || t == "mod" ||
t == "module" || t == "move" || t == "mut" || t == "mutable" || t == "namespace" ||
@@ -96,8 +95,8 @@
t == "partition" || t == "pass" || t == "patch" || t == "pixelfragment" ||
t == "precise" || t == "precision" || t == "premerge" || t == "priv" ||
t == "protected" || t == "pub" || t == "public" || t == "readonly" || t == "ref" ||
- t == "regardless" || t == "register" || t == "reinterpret_cast" || t == "resource" ||
- t == "restrict" || t == "self" || t == "set" || t == "shared" || t == "signed" ||
+ t == "regardless" || t == "register" || t == "reinterpret_cast" || t == "require" ||
+ t == "resource" || t == "restrict" || t == "self" || t == "set" || t == "shared" ||
t == "sizeof" || t == "smooth" || t == "snorm" || t == "static" ||
t == "static_assert" || t == "static_cast" || t == "std" || t == "subroutine" ||
t == "super" || t == "target" || t == "template" || t == "this" || t == "thread_local" ||
@@ -391,53 +390,52 @@
return decl;
}
-// enable_directive
-// : enable name SEMICLON
+// enable_directive :
+// | 'enable' identifier (COMMA identifier)* COMMA? SEMICOLON
Maybe<Void> ParserImpl::enable_directive() {
- auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
+ return sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
+ MultiTokenSource decl_source(this);
if (!match(Token::Type::kEnable)) {
return Failure::kNoMatch;
}
- // Match the extension name.
- auto& t = peek();
- if (handle_error(t)) {
- // The token might itself be an error.
- return Failure::kErrored;
- }
-
- if (t.Is(Token::Type::kParenLeft)) {
+ if (peek_is(Token::Type::kParenLeft)) {
// A common error case is writing `enable(foo);` instead of `enable foo;`.
synchronized_ = false;
- return add_error(t.source(), "enable directives don't take parenthesis");
+ return add_error(peek().source(), "enable directives don't take parenthesis");
}
- auto ext = expect_enum("extension", builtin::ParseExtension, builtin::kExtensionStrings);
- if (ext.errored) {
- return Failure::kErrored;
+ utils::Vector<const ast::Extension*, 4> extensions;
+ while (continue_parsing()) {
+ Source ext_src = peek().source();
+ auto ext =
+ expect_enum("extension", builtin::ParseExtension, builtin::kExtensionStrings);
+ if (ext.errored) {
+ return Failure::kErrored;
+ }
+ extensions.Push(create<ast::Extension>(ext_src, ext.value));
+
+ if (!match(Token::Type::kComma)) {
+ break;
+ }
+ if (peek_is(Token::Type::kSemicolon)) {
+ break;
+ }
}
if (!expect("enable directive", Token::Type::kSemicolon)) {
return Failure::kErrored;
}
- builder_.AST().AddEnable(create<ast::Enable>(t.source(), ext.value));
+
+ builder_.AST().AddEnable(create<ast::Enable>(decl_source.Source(), std::move(extensions)));
return kSuccess;
});
-
- if (decl.errored) {
- return Failure::kErrored;
- }
- if (decl.matched) {
- return kSuccess;
- }
-
- return Failure::kNoMatch;
}
// requires_directive
-// : require identifier (COMMA identifier)? SEMICLON
+// : require identifier (COMMA identifier)* COMMA? SEMICOLON
Maybe<Void> ParserImpl::requires_directive() {
- auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
+ return sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
if (!match(Token::Type::kRequires)) {
return Failure::kNoMatch;
}
@@ -484,15 +482,6 @@
// conditional.
return add_error(t.source(), "missing feature names in requires directive");
});
-
- if (decl.errored) {
- return Failure::kErrored;
- }
- if (decl.matched) {
- return kSuccess;
- }
-
- return Failure::kNoMatch;
}
// global_decl
@@ -1265,7 +1254,7 @@
return stmt;
}
- auto stmt_if = if_statement();
+ auto stmt_if = if_statement(attrs.value);
if (stmt_if.errored) {
return Failure::kErrored;
}
@@ -1273,7 +1262,7 @@
return stmt_if.value;
}
- auto sw = switch_statement();
+ auto sw = switch_statement(attrs.value);
if (sw.errored) {
return Failure::kErrored;
}
@@ -1289,7 +1278,7 @@
return loop.value;
}
- auto stmt_for = for_statement();
+ auto stmt_for = for_statement(attrs.value);
if (stmt_for.errored) {
return Failure::kErrored;
}
@@ -1297,7 +1286,7 @@
return stmt_for.value;
}
- auto stmt_while = while_statement();
+ auto stmt_while = while_statement(attrs.value);
if (stmt_while.errored) {
return Failure::kErrored;
}
@@ -1517,11 +1506,14 @@
}
// if_statement
-// : IF expression compound_stmt ( ELSE else_stmt ) ?
-// else_stmt
-// : compound_statement
-// | if_statement
-Maybe<const ast::IfStatement*> ParserImpl::if_statement() {
+// : attribute* if_clause else_if_clause* else_clause?
+// if_clause:
+// : IF expression compound_stmt
+// else_if_clause:
+// : ELSE IF expression compound_stmt
+// else_clause
+// : ELSE compound_statement
+Maybe<const ast::IfStatement*> ParserImpl::if_statement(AttributeList& attrs) {
// Parse if-else chains iteratively instead of recursively, to avoid
// stack-overflow for long chains of if-else statements.
@@ -1529,6 +1521,7 @@
Source source;
const ast::Expression* condition;
const ast::BlockStatement* body;
+ AttributeList attributes;
};
// Parse an if statement, capturing the source, condition, and body statement.
@@ -1551,7 +1544,8 @@
return Failure::kErrored;
}
- return IfInfo{source, condition.value, body.value};
+ TINT_DEFER(attrs.Clear());
+ return IfInfo{source, condition.value, body.value, std::move(attrs)};
};
std::vector<IfInfo> statements;
@@ -1592,15 +1586,16 @@
// Now walk back through the statements to create their AST nodes.
for (auto itr = statements.rbegin(); itr != statements.rend(); itr++) {
- last_stmt = create<ast::IfStatement>(itr->source, itr->condition, itr->body, last_stmt);
+ last_stmt = create<ast::IfStatement>(itr->source, itr->condition, itr->body, last_stmt,
+ std::move(itr->attributes));
}
return last_stmt->As<ast::IfStatement>();
}
// switch_statement
-// : SWITCH expression BRACKET_LEFT switch_body+ BRACKET_RIGHT
-Maybe<const ast::SwitchStatement*> ParserImpl::switch_statement() {
+// : attribute* SWITCH expression BRACKET_LEFT switch_body+ BRACKET_RIGHT
+Maybe<const ast::SwitchStatement*> ParserImpl::switch_statement(AttributeList& attrs) {
Source source;
if (!match(Token::Type::kSwitch, &source)) {
return Failure::kNoMatch;
@@ -1638,7 +1633,8 @@
return Failure::kErrored;
}
- return create<ast::SwitchStatement>(source, condition.value, body.value);
+ TINT_DEFER(attrs.Clear());
+ return create<ast::SwitchStatement>(source, condition.value, body.value, std::move(attrs));
}
// switch_body
@@ -1875,7 +1871,7 @@
// for_statement
// : FOR PAREN_LEFT for_header PAREN_RIGHT compound_statement
-Maybe<const ast::ForLoopStatement*> ParserImpl::for_statement() {
+Maybe<const ast::ForLoopStatement*> ParserImpl::for_statement(AttributeList& attrs) {
Source source;
if (!match(Token::Type::kFor, &source)) {
return Failure::kNoMatch;
@@ -1891,13 +1887,14 @@
return Failure::kErrored;
}
+ TINT_DEFER(attrs.Clear());
return create<ast::ForLoopStatement>(source, header->initializer, header->condition,
- header->continuing, body.value);
+ header->continuing, body.value, std::move(attrs));
}
// while_statement
-// : WHILE expression compound_statement
-Maybe<const ast::WhileStatement*> ParserImpl::while_statement() {
+// : attribute* WHILE expression compound_statement
+Maybe<const ast::WhileStatement*> ParserImpl::while_statement(AttributeList& attrs) {
Source source;
if (!match(Token::Type::kWhile, &source)) {
return Failure::kNoMatch;
@@ -1916,7 +1913,8 @@
return Failure::kErrored;
}
- return create<ast::WhileStatement>(source, condition.value, body.value);
+ TINT_DEFER(attrs.Clear());
+ return create<ast::WhileStatement>(source, condition.value, body.value, std::move(attrs));
}
// func_call_statement
diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h
index bfc2f9a..9693ea4 100644
--- a/src/tint/reader/wgsl/parser_impl.h
+++ b/src/tint/reader/wgsl/parser_impl.h
@@ -488,12 +488,14 @@
/// Parses a `variable_statement` grammar element
/// @returns the parsed variable or nullptr
Maybe<const ast::VariableDeclStatement*> variable_statement();
- /// Parses a `if_statement` grammar element
+ /// Parses a `if_statement` grammar element, with the attribute list provided as `attrs`.
+ /// @param attrs the list of attributes for the statement
/// @returns the parsed statement or nullptr
- Maybe<const ast::IfStatement*> if_statement();
+ Maybe<const ast::IfStatement*> if_statement(AttributeList& attrs);
/// Parses a `switch_statement` grammar element
+ /// @param attrs the list of attributes for the statement
/// @returns the parsed statement or nullptr
- Maybe<const ast::SwitchStatement*> switch_statement();
+ Maybe<const ast::SwitchStatement*> switch_statement(AttributeList& attrs);
/// Parses a `switch_body` grammar element
/// @returns the parsed statement or nullptr
Maybe<const ast::CaseStatement*> switch_body();
@@ -515,12 +517,14 @@
/// Parses a `for_header` grammar element, erroring on parse failure.
/// @returns the parsed for header or nullptr
Expect<std::unique_ptr<ForHeader>> expect_for_header();
- /// Parses a `for_statement` grammar element
+ /// Parses a `for_statement` grammar element, with the attribute list provided as `attrs`.
+ /// @param attrs the list of attributes for the statement
/// @returns the parsed for loop or nullptr
- Maybe<const ast::ForLoopStatement*> for_statement();
- /// Parses a `while_statement` grammar element
+ Maybe<const ast::ForLoopStatement*> for_statement(AttributeList& attrs);
+ /// Parses a `while_statement` grammar element, with the attribute list provided as `attrs`.
+ /// @param attrs the list of attributes for the statement
/// @returns the parsed while loop or nullptr
- Maybe<const ast::WhileStatement*> while_statement();
+ Maybe<const ast::WhileStatement*> while_statement(AttributeList& attrs);
/// Parses a `break_if_statement` grammar element
/// @returns the parsed statement or nullptr
Maybe<const ast::Statement*> break_if_statement();
diff --git a/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc b/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
index 7ad39c2..3c63a02 100644
--- a/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
@@ -22,7 +22,7 @@
using EnableDirectiveTest = ParserImplTest;
// Test a valid enable directive.
-TEST_F(EnableDirectiveTest, Valid) {
+TEST_F(EnableDirectiveTest, Single) {
auto p = parser("enable f16;");
p->enable_directive();
EXPECT_FALSE(p->has_error()) << p->error();
@@ -30,13 +30,105 @@
auto& ast = program.AST();
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
- EXPECT_EQ(enable->extension, builtin::Extension::kF16);
+ EXPECT_EQ(enable->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->source.range.begin.column, 1u);
+ EXPECT_EQ(enable->source.range.end.line, 1u);
+ EXPECT_EQ(enable->source.range.end.column, 12u);
+ ASSERT_EQ(enable->extensions.Length(), 1u);
+ EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
+ ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
+ EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
+}
+
+// Test a valid enable directive.
+TEST_F(EnableDirectiveTest, SingleTrailingComma) {
+ auto p = parser("enable f16, ;");
+ p->enable_directive();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ auto program = p->program();
+ auto& ast = program.AST();
+ ASSERT_EQ(ast.Enables().Length(), 1u);
+ auto* enable = ast.Enables()[0];
+ EXPECT_EQ(enable->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->source.range.begin.column, 1u);
+ EXPECT_EQ(enable->source.range.end.line, 1u);
+ EXPECT_EQ(enable->source.range.end.column, 14u);
+ ASSERT_EQ(enable->extensions.Length(), 1u);
+ EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
+ ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
+ EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
+}
+
+// Test a valid enable directive with multiple extensions.
+TEST_F(EnableDirectiveTest, Multiple) {
+ auto p =
+ parser("enable f16, chromium_disable_uniformity_analysis, chromium_experimental_dp4a;");
+ p->enable_directive();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ auto program = p->program();
+ auto& ast = program.AST();
+ ASSERT_EQ(ast.Enables().Length(), 1u);
+ auto* enable = ast.Enables()[0];
+ ASSERT_EQ(enable->extensions.Length(), 3u);
+ EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
+ EXPECT_EQ(enable->extensions[1]->name, builtin::Extension::kChromiumDisableUniformityAnalysis);
+ EXPECT_EQ(enable->extensions[1]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[1]->source.range.begin.column, 13u);
+ EXPECT_EQ(enable->extensions[1]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[1]->source.range.end.column, 49u);
+ EXPECT_EQ(enable->extensions[2]->name, builtin::Extension::kChromiumExperimentalDp4A);
+ EXPECT_EQ(enable->extensions[2]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[2]->source.range.begin.column, 51u);
+ EXPECT_EQ(enable->extensions[2]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[2]->source.range.end.column, 77u);
+ ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
+ EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
+}
+
+// Test a valid enable directive with multiple extensions.
+TEST_F(EnableDirectiveTest, MultipleTrailingComma) {
+ auto p =
+ parser("enable f16, chromium_disable_uniformity_analysis, chromium_experimental_dp4a,;");
+ p->enable_directive();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ auto program = p->program();
+ auto& ast = program.AST();
+ ASSERT_EQ(ast.Enables().Length(), 1u);
+ auto* enable = ast.Enables()[0];
+ ASSERT_EQ(enable->extensions.Length(), 3u);
+ EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
+ EXPECT_EQ(enable->extensions[1]->name, builtin::Extension::kChromiumDisableUniformityAnalysis);
+ EXPECT_EQ(enable->extensions[1]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[1]->source.range.begin.column, 13u);
+ EXPECT_EQ(enable->extensions[1]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[1]->source.range.end.column, 49u);
+ EXPECT_EQ(enable->extensions[2]->name, builtin::Extension::kChromiumExperimentalDp4A);
+ EXPECT_EQ(enable->extensions[2]->source.range.begin.line, 1u);
+ EXPECT_EQ(enable->extensions[2]->source.range.begin.column, 51u);
+ EXPECT_EQ(enable->extensions[2]->source.range.end.line, 1u);
+ EXPECT_EQ(enable->extensions[2]->source.range.end.column, 77u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}
// Test multiple enable directives for a same extension.
-TEST_F(EnableDirectiveTest, EnableMultipleTime) {
+TEST_F(EnableDirectiveTest, EnableSameLine) {
auto p = parser(R"(
enable f16;
enable f16;
@@ -48,8 +140,18 @@
ASSERT_EQ(ast.Enables().Length(), 2u);
auto* enable_a = ast.Enables()[0];
auto* enable_b = ast.Enables()[1];
- EXPECT_EQ(enable_a->extension, builtin::Extension::kF16);
- EXPECT_EQ(enable_b->extension, builtin::Extension::kF16);
+ ASSERT_EQ(enable_a->extensions.Length(), 1u);
+ EXPECT_EQ(enable_a->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable_a->extensions[0]->source.range.begin.line, 2u);
+ EXPECT_EQ(enable_a->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable_a->extensions[0]->source.range.end.line, 2u);
+ EXPECT_EQ(enable_a->extensions[0]->source.range.end.column, 11u);
+ ASSERT_EQ(enable_b->extensions.Length(), 1u);
+ EXPECT_EQ(enable_b->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable_b->extensions[0]->source.range.begin.line, 3u);
+ EXPECT_EQ(enable_b->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable_b->extensions[0]->source.range.end.line, 3u);
+ EXPECT_EQ(enable_b->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 2u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable_a);
EXPECT_EQ(ast.GlobalDeclarations()[1], enable_b);
@@ -169,7 +271,12 @@
// Accept the enable directive although it caused an error
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
- EXPECT_EQ(enable->extension, builtin::Extension::kF16);
+ ASSERT_EQ(enable->extensions.Length(), 1u);
+ EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 3u);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.line, 3u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 2u);
EXPECT_EQ(ast.GlobalDeclarations()[1], enable);
}
@@ -189,7 +296,12 @@
// Accept the enable directive although it cause an error
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
- EXPECT_EQ(enable->extension, builtin::Extension::kF16);
+ ASSERT_EQ(enable->extensions.Length(), 1u);
+ EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 3u);
+ EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.line, 3u);
+ EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}
diff --git a/src/tint/reader/wgsl/parser_impl_for_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_for_stmt_test.cc
index 5af8f22..528be9f 100644
--- a/src/tint/reader/wgsl/parser_impl_for_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_for_stmt_test.cc
@@ -24,7 +24,8 @@
// Test an empty for loop.
TEST_F(ForStmtTest, Empty) {
auto p = parser("for (;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -37,7 +38,8 @@
// Test a for loop with non-empty body.
TEST_F(ForStmtTest, Body) {
auto p = parser("for (;;) { discard; }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -51,7 +53,8 @@
// Test a for loop declaring a variable in the initializer statement.
TEST_F(ForStmtTest, InitializerStatementDecl) {
auto p = parser("for (var i: i32 ;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -68,7 +71,8 @@
// statement.
TEST_F(ForStmtTest, InitializerStatementDeclEqual) {
auto p = parser("for (var i: i32 = 0 ;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -84,7 +88,8 @@
// Test a for loop declaring a const variable in the initializer statement.
TEST_F(ForStmtTest, InitializerStatementConstDecl) {
auto p = parser("for (let i: i32 = 0 ;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -100,7 +105,8 @@
// Test a for loop assigning a variable in the initializer statement.
TEST_F(ForStmtTest, InitializerStatementAssignment) {
auto p = parser("for (i = 0 ;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -113,7 +119,8 @@
// Test a for loop incrementing a variable in the initializer statement.
TEST_F(ForStmtTest, InitializerStatementIncrement) {
auto p = parser("for (i++;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -126,7 +133,8 @@
// Test a for loop calling a function in the initializer statement.
TEST_F(ForStmtTest, InitializerStatementFuncCall) {
auto p = parser("for (a(b,c) ;;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -139,7 +147,8 @@
// Test a for loop with a break condition
TEST_F(ForStmtTest, BreakCondition) {
auto p = parser("for (; 0 == 1;) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -152,7 +161,8 @@
// Test a for loop assigning a variable in the continuing statement.
TEST_F(ForStmtTest, ContinuingAssignment) {
auto p = parser("for (;; x = 2) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -165,7 +175,8 @@
// Test a for loop with an increment statement as the continuing statement.
TEST_F(ForStmtTest, ContinuingIncrement) {
auto p = parser("for (;; x++) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -178,7 +189,8 @@
// Test a for loop calling a function in the continuing statement.
TEST_F(ForStmtTest, ContinuingFuncCall) {
auto p = parser("for (;; a(b,c)) { }");
- auto fl = p->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto fl = p->for_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(fl.errored);
ASSERT_TRUE(fl.matched);
@@ -188,11 +200,26 @@
EXPECT_TRUE(fl->body->Empty());
}
+// Test a for loop with attributes.
+TEST_F(ForStmtTest, WithAttributes) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) for (;;) { }");
+ auto attrs = p->attribute_list();
+ auto fl = p->for_statement(attrs.value);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(fl.errored);
+ ASSERT_TRUE(fl.matched);
+
+ EXPECT_TRUE(attrs->IsEmpty());
+ ASSERT_EQ(fl->attributes.Length(), 1u);
+ EXPECT_TRUE(fl->attributes[0]->Is<ast::DiagnosticAttribute>());
+}
+
class ForStmtErrorTest : public ParserImplTest {
public:
void TestForWithError(std::string for_str, std::string error_str) {
auto p_for = parser(for_str);
- auto e_for = p_for->for_statement();
+ ParserImpl::AttributeList attrs;
+ auto e_for = p_for->for_statement(attrs);
EXPECT_FALSE(e_for.matched);
EXPECT_TRUE(e_for.errored);
diff --git a/src/tint/reader/wgsl/parser_impl_if_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_if_stmt_test.cc
index 55effc7..2acb26c 100644
--- a/src/tint/reader/wgsl/parser_impl_if_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_if_stmt_test.cc
@@ -19,7 +19,8 @@
TEST_F(ParserImplTest, IfStmt) {
auto p = parser("if a == 4 { a = b; c = d; }");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -34,7 +35,8 @@
TEST_F(ParserImplTest, IfStmt_WithElse) {
auto p = parser("if a == 4 { a = b; c = d; } else if(c) { d = 2; } else {}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -57,7 +59,8 @@
TEST_F(ParserImplTest, IfStmt_WithElse_WithParens) {
auto p = parser("if(a==4) { a = b; c = d; } else if(c) { d = 2; } else {}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -78,9 +81,25 @@
EXPECT_EQ(el->statements.Length(), 0u);
}
+TEST_F(ParserImplTest, IfStmt_WithAttributes) {
+ auto p = parser(R"(@diagnostic(off, derivative_uniformity) if true { })");
+ auto a = p->attribute_list();
+ auto e = p->if_statement(a.value);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e->Is<ast::IfStatement>());
+
+ EXPECT_TRUE(a->IsEmpty());
+ ASSERT_EQ(e->attributes.Length(), 1u);
+ EXPECT_TRUE(e->attributes[0]->Is<ast::DiagnosticAttribute>());
+}
+
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
auto p = parser("if a = 3 {}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -90,7 +109,8 @@
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
auto p = parser("if {}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -100,7 +120,8 @@
TEST_F(ParserImplTest, IfStmt_InvalidBody) {
auto p = parser("if a { fn main() {}}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -110,7 +131,8 @@
TEST_F(ParserImplTest, IfStmt_MissingBody) {
auto p = parser("if a");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -120,7 +142,8 @@
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
auto p = parser("if a {} else if a { fn main() -> a{}}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -130,7 +153,8 @@
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
auto p = parser("if a {} else { fn main() -> a{}}");
- auto e = p->if_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->if_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
diff --git a/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc b/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
index 647bb44..50f43ea 100644
--- a/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
@@ -85,11 +85,7 @@
}
INSTANTIATE_TEST_SUITE_P(ParserImplReservedKeywordTest,
ParserImplReservedKeywordTest,
- testing::Values("ComputeShader",
- "DomainShader",
- "GeometryShader",
- "Hullshader",
- "NULL",
+ testing::Values("NULL",
"Self",
"abstract",
"active",
@@ -143,13 +139,11 @@
"get",
"goto",
"groupshared",
- "handle",
"highp",
"impl",
"implements",
"import",
"inline",
- "inout",
"instanceof",
"interface",
"layout",
@@ -198,7 +192,6 @@
"self",
"set",
"shared",
- "signed",
"sizeof",
"smooth",
"snorm",
diff --git a/src/tint/reader/wgsl/parser_impl_statement_test.cc b/src/tint/reader/wgsl/parser_impl_statement_test.cc
index 634bfb4..8c920a7 100644
--- a/src/tint/reader/wgsl/parser_impl_statement_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_statement_test.cc
@@ -314,6 +314,66 @@
EXPECT_EQ(sa->condition->source.range.end.column, 19u);
}
+TEST_F(ParserImplTest, Statement_ConsumedAttributes_Block) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) {}");
+ auto e = p->statement();
+ ASSERT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+
+ auto* s = As<ast::BlockStatement>(e.value);
+ ASSERT_NE(s, nullptr);
+ EXPECT_EQ(s->attributes.Length(), 1u);
+}
+
+TEST_F(ParserImplTest, Statement_ConsumedAttributes_For) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) for (;false;) {}");
+ auto e = p->statement();
+ ASSERT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+
+ auto* s = As<ast::ForLoopStatement>(e.value);
+ ASSERT_NE(s, nullptr);
+ EXPECT_EQ(s->attributes.Length(), 1u);
+}
+
+TEST_F(ParserImplTest, Statement_ConsumedAttributes_If) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) if true {}");
+ auto e = p->statement();
+ ASSERT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+
+ auto* s = As<ast::IfStatement>(e.value);
+ ASSERT_NE(s, nullptr);
+ EXPECT_EQ(s->attributes.Length(), 1u);
+}
+
+TEST_F(ParserImplTest, Statement_ConsumedAttributes_Switch) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) switch (0) { default{} }");
+ auto e = p->statement();
+ ASSERT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+
+ auto* s = As<ast::SwitchStatement>(e.value);
+ ASSERT_NE(s, nullptr);
+ EXPECT_EQ(s->attributes.Length(), 1u);
+}
+
+TEST_F(ParserImplTest, Statement_ConsumedAttributes_While) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) while (false) {}");
+ auto e = p->statement();
+ ASSERT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+
+ auto* s = As<ast::WhileStatement>(e.value);
+ ASSERT_NE(s, nullptr);
+ EXPECT_EQ(s->attributes.Length(), 1u);
+}
+
TEST_F(ParserImplTest, Statement_UnexpectedAttributes) {
auto p = parser("@diagnostic(off, derivative_uniformity) return;");
auto e = p->statement();
diff --git a/src/tint/reader/wgsl/parser_impl_switch_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_switch_stmt_test.cc
index a5e3dd3..ef0b1b4 100644
--- a/src/tint/reader/wgsl/parser_impl_switch_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_switch_stmt_test.cc
@@ -22,7 +22,8 @@
case 1: {}
case 2: {}
})");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -35,7 +36,8 @@
TEST_F(ParserImplTest, SwitchStmt_Empty) {
auto p = parser("switch a { }");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -50,7 +52,8 @@
default: {}
case 2: {}
})");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -67,7 +70,8 @@
auto p = parser(R"(switch a {
case 1, default, 2: {}
})");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -80,7 +84,8 @@
TEST_F(ParserImplTest, SwitchStmt_WithParens) {
auto p = parser("switch(a+b) { }");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -89,9 +94,25 @@
ASSERT_EQ(e->body.Length(), 0u);
}
+TEST_F(ParserImplTest, SwitchStmt_WithAttributes) {
+ auto p = parser(R"(@diagnostic(off, derivative_uniformity) switch a { default{} })");
+ auto a = p->attribute_list();
+ auto e = p->switch_statement(a.value);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e->Is<ast::SwitchStatement>());
+
+ EXPECT_TRUE(a->IsEmpty());
+ ASSERT_EQ(e->attributes.Length(), 1u);
+ EXPECT_TRUE(e->attributes[0]->Is<ast::DiagnosticAttribute>());
+}
+
TEST_F(ParserImplTest, SwitchStmt_InvalidExpression) {
auto p = parser("switch a=b {}");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -101,7 +122,8 @@
TEST_F(ParserImplTest, SwitchStmt_MissingExpression) {
auto p = parser("switch {}");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -111,7 +133,8 @@
TEST_F(ParserImplTest, SwitchStmt_MissingBracketLeft) {
auto p = parser("switch a }");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -121,7 +144,8 @@
TEST_F(ParserImplTest, SwitchStmt_MissingBracketRight) {
auto p = parser("switch a {");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -133,7 +157,8 @@
auto p = parser(R"(switch a {
case: {}
})");
- auto e = p->switch_statement();
+ ParserImpl::AttributeList attrs;
+ auto e = p->switch_statement(attrs);
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
diff --git a/src/tint/reader/wgsl/parser_impl_while_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_while_stmt_test.cc
index d61843e..dcbb59b 100644
--- a/src/tint/reader/wgsl/parser_impl_while_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_while_stmt_test.cc
@@ -24,7 +24,8 @@
// Test an empty while loop.
TEST_F(WhileStmtTest, Empty) {
auto p = parser("while true { }");
- auto wl = p->while_statement();
+ ParserImpl::AttributeList attrs;
+ auto wl = p->while_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(wl.errored);
ASSERT_TRUE(wl.matched);
@@ -35,7 +36,8 @@
// Test an empty while loop with parentheses.
TEST_F(WhileStmtTest, EmptyWithParentheses) {
auto p = parser("while (true) { }");
- auto wl = p->while_statement();
+ ParserImpl::AttributeList attrs;
+ auto wl = p->while_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(wl.errored);
ASSERT_TRUE(wl.matched);
@@ -46,7 +48,8 @@
// Test a while loop with non-empty body.
TEST_F(WhileStmtTest, Body) {
auto p = parser("while (true) { discard; }");
- auto wl = p->while_statement();
+ ParserImpl::AttributeList attrs;
+ auto wl = p->while_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(wl.errored);
ASSERT_TRUE(wl.matched);
@@ -58,7 +61,8 @@
// Test a while loop with complex condition.
TEST_F(WhileStmtTest, ComplexCondition) {
auto p = parser("while (a + 1 - 2) == 3 { }");
- auto wl = p->while_statement();
+ ParserImpl::AttributeList attrs;
+ auto wl = p->while_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(wl.errored);
ASSERT_TRUE(wl.matched);
@@ -69,7 +73,8 @@
// Test a while loop with complex condition, with parentheses.
TEST_F(WhileStmtTest, ComplexConditionWithParentheses) {
auto p = parser("while ((a + 1 - 2) == 3) { }");
- auto wl = p->while_statement();
+ ParserImpl::AttributeList attrs;
+ auto wl = p->while_statement(attrs);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_FALSE(wl.errored);
ASSERT_TRUE(wl.matched);
@@ -77,11 +82,26 @@
EXPECT_TRUE(wl->body->Empty());
}
+// Test a while loop with attributes.
+TEST_F(WhileStmtTest, WithAttributes) {
+ auto p = parser("@diagnostic(off, derivative_uniformity) while true { }");
+ auto attrs = p->attribute_list();
+ auto wl = p->while_statement(attrs.value);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(wl.errored);
+ ASSERT_TRUE(wl.matched);
+
+ EXPECT_TRUE(attrs->IsEmpty());
+ ASSERT_EQ(wl->attributes.Length(), 1u);
+ EXPECT_TRUE(wl->attributes[0]->Is<ast::DiagnosticAttribute>());
+}
+
class WhileStmtErrorTest : public ParserImplTest {
public:
void TestWhileWithError(std::string for_str, std::string error_str) {
auto p_for = parser(for_str);
- auto e_for = p_for->while_statement();
+ ParserImpl::AttributeList attrs;
+ auto e_for = p_for->while_statement(attrs);
EXPECT_FALSE(e_for.matched);
EXPECT_TRUE(e_for.errored);
diff --git a/src/tint/reader/wgsl/token.h b/src/tint/reader/wgsl/token.h
index 43f6831..19bdd40 100644
--- a/src/tint/reader/wgsl/token.h
+++ b/src/tint/reader/wgsl/token.h
@@ -165,17 +165,19 @@
kContinue,
/// A 'continuing'
kContinuing,
+ /// A 'default'
+ kDefault,
/// A 'diagnostic'
kDiagnostic,
/// A 'discard'
kDiscard,
- /// A 'default'
- kDefault,
/// A 'else'
kElse,
/// A 'enable'
kEnable,
/// A 'fallthrough'
+ // Note, this isn't a keyword, but a reserved word. We match it as a keyword in order to
+ // provide better diagnostics in case a `fallthrough` is added to a case body.
kFallthrough,
/// A 'false'
kFalse,
@@ -191,10 +193,10 @@
kLoop,
/// A 'override'
kOverride,
- /// A 'return'
- kReturn,
/// A 'requires'
kRequires,
+ /// A 'return'
+ kReturn,
/// A 'struct'
kStruct,
/// A 'switch'
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 5c09c2a..23f82a2 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -1045,6 +1045,138 @@
12:34 note: first attribute declared here)");
}
+using SwitchStatementAttributeTest = TestWithParams;
+TEST_P(SwitchStatementAttributeTest, IsValid) {
+ auto& params = GetParam();
+
+ WrapInFunction(Switch(Expr(0_a), utils::Vector{DefaultCase()},
+ createAttributes(Source{{12, 34}}, *this, params.kind)));
+
+ if (params.should_pass) {
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+ } else {
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: attribute is not valid for switch statements");
+ }
+}
+INSTANTIATE_TEST_SUITE_P(ResolverAttributeValidationTest,
+ SwitchStatementAttributeTest,
+ testing::Values(TestParams{AttributeKind::kAlign, false},
+ TestParams{AttributeKind::kBinding, false},
+ TestParams{AttributeKind::kBuiltin, false},
+ TestParams{AttributeKind::kDiagnostic, true},
+ TestParams{AttributeKind::kGroup, false},
+ TestParams{AttributeKind::kId, false},
+ TestParams{AttributeKind::kInterpolate, false},
+ TestParams{AttributeKind::kInvariant, false},
+ TestParams{AttributeKind::kLocation, false},
+ TestParams{AttributeKind::kMustUse, false},
+ TestParams{AttributeKind::kOffset, false},
+ TestParams{AttributeKind::kSize, false},
+ TestParams{AttributeKind::kStage, false},
+ TestParams{AttributeKind::kStride, false},
+ TestParams{AttributeKind::kWorkgroup, false},
+ TestParams{AttributeKind::kBindingAndGroup, false}));
+
+using IfStatementAttributeTest = TestWithParams;
+TEST_P(IfStatementAttributeTest, IsValid) {
+ auto& params = GetParam();
+
+ WrapInFunction(If(Expr(true), Block(), ElseStmt(),
+ createAttributes(Source{{12, 34}}, *this, params.kind)));
+
+ if (params.should_pass) {
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+ } else {
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: attribute is not valid for if statements");
+ }
+}
+INSTANTIATE_TEST_SUITE_P(ResolverAttributeValidationTest,
+ IfStatementAttributeTest,
+ testing::Values(TestParams{AttributeKind::kAlign, false},
+ TestParams{AttributeKind::kBinding, false},
+ TestParams{AttributeKind::kBuiltin, false},
+ TestParams{AttributeKind::kDiagnostic, true},
+ TestParams{AttributeKind::kGroup, false},
+ TestParams{AttributeKind::kId, false},
+ TestParams{AttributeKind::kInterpolate, false},
+ TestParams{AttributeKind::kInvariant, false},
+ TestParams{AttributeKind::kLocation, false},
+ TestParams{AttributeKind::kMustUse, false},
+ TestParams{AttributeKind::kOffset, false},
+ TestParams{AttributeKind::kSize, false},
+ TestParams{AttributeKind::kStage, false},
+ TestParams{AttributeKind::kStride, false},
+ TestParams{AttributeKind::kWorkgroup, false},
+ TestParams{AttributeKind::kBindingAndGroup, false}));
+
+using ForStatementAttributeTest = TestWithParams;
+TEST_P(ForStatementAttributeTest, IsValid) {
+ auto& params = GetParam();
+
+ WrapInFunction(For(nullptr, Expr(false), nullptr, Block(),
+ createAttributes(Source{{12, 34}}, *this, params.kind)));
+
+ if (params.should_pass) {
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+ } else {
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: attribute is not valid for for statements");
+ }
+}
+INSTANTIATE_TEST_SUITE_P(ResolverAttributeValidationTest,
+ ForStatementAttributeTest,
+ testing::Values(TestParams{AttributeKind::kAlign, false},
+ TestParams{AttributeKind::kBinding, false},
+ TestParams{AttributeKind::kBuiltin, false},
+ TestParams{AttributeKind::kDiagnostic, true},
+ TestParams{AttributeKind::kGroup, false},
+ TestParams{AttributeKind::kId, false},
+ TestParams{AttributeKind::kInterpolate, false},
+ TestParams{AttributeKind::kInvariant, false},
+ TestParams{AttributeKind::kLocation, false},
+ TestParams{AttributeKind::kMustUse, false},
+ TestParams{AttributeKind::kOffset, false},
+ TestParams{AttributeKind::kSize, false},
+ TestParams{AttributeKind::kStage, false},
+ TestParams{AttributeKind::kStride, false},
+ TestParams{AttributeKind::kWorkgroup, false},
+ TestParams{AttributeKind::kBindingAndGroup, false}));
+
+using WhileStatementAttributeTest = TestWithParams;
+TEST_P(WhileStatementAttributeTest, IsValid) {
+ auto& params = GetParam();
+
+ WrapInFunction(
+ While(Expr(false), Block(), createAttributes(Source{{12, 34}}, *this, params.kind)));
+
+ if (params.should_pass) {
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+ } else {
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: attribute is not valid for while statements");
+ }
+}
+INSTANTIATE_TEST_SUITE_P(ResolverAttributeValidationTest,
+ WhileStatementAttributeTest,
+ testing::Values(TestParams{AttributeKind::kAlign, false},
+ TestParams{AttributeKind::kBinding, false},
+ TestParams{AttributeKind::kBuiltin, false},
+ TestParams{AttributeKind::kDiagnostic, true},
+ TestParams{AttributeKind::kGroup, false},
+ TestParams{AttributeKind::kId, false},
+ TestParams{AttributeKind::kInterpolate, false},
+ TestParams{AttributeKind::kInvariant, false},
+ TestParams{AttributeKind::kLocation, false},
+ TestParams{AttributeKind::kMustUse, false},
+ TestParams{AttributeKind::kOffset, false},
+ TestParams{AttributeKind::kSize, false},
+ TestParams{AttributeKind::kStage, false},
+ TestParams{AttributeKind::kStride, false},
+ TestParams{AttributeKind::kWorkgroup, false},
+ TestParams{AttributeKind::kBindingAndGroup, false}));
+
namespace BlockStatementTests {
class BlockStatementTest : public TestWithParams {
protected:
diff --git a/src/tint/resolver/builtin_test.cc b/src/tint/resolver/builtin_test.cc
index 2bc024f..80df98f 100644
--- a/src/tint/resolver/builtin_test.cc
+++ b/src/tint/resolver/builtin_test.cc
@@ -50,13 +50,11 @@
using ExpressionList = utils::Vector<const ast::Expression*, 8>;
-using BuiltinType = sem::BuiltinType;
-
using ResolverBuiltinTest = ResolverTest;
struct BuiltinData {
const char* name;
- BuiltinType builtin;
+ builtin::Function builtin;
};
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
@@ -253,7 +251,7 @@
struct BuiltinDataWithParamNum {
uint32_t args_number;
const char* name;
- BuiltinType builtin;
+ builtin::Function builtin;
};
inline std::ostream& operator<<(std::ostream& out, BuiltinDataWithParamNum data) {
@@ -680,55 +678,55 @@
INSTANTIATE_TEST_SUITE_P(
ResolverTest,
ResolverBuiltinTest_FloatBuiltin_IdenticalType,
- testing::Values(BuiltinDataWithParamNum{1, "abs", BuiltinType::kAbs},
- BuiltinDataWithParamNum{1, "acos", BuiltinType::kAcos},
- BuiltinDataWithParamNum{1, "acosh", BuiltinType::kAcos},
- BuiltinDataWithParamNum{1, "asin", BuiltinType::kAsin},
- BuiltinDataWithParamNum{1, "asinh", BuiltinType::kAsin},
- BuiltinDataWithParamNum{1, "atan", BuiltinType::kAtan},
- BuiltinDataWithParamNum{1, "atanh", BuiltinType::kAtan},
- BuiltinDataWithParamNum{2, "atan2", BuiltinType::kAtan2},
- BuiltinDataWithParamNum{1, "ceil", BuiltinType::kCeil},
- BuiltinDataWithParamNum{3, "clamp", BuiltinType::kClamp},
- BuiltinDataWithParamNum{1, "cos", BuiltinType::kCos},
- BuiltinDataWithParamNum{1, "cosh", BuiltinType::kCosh},
+ testing::Values(BuiltinDataWithParamNum{1, "abs", builtin::Function::kAbs},
+ BuiltinDataWithParamNum{1, "acos", builtin::Function::kAcos},
+ BuiltinDataWithParamNum{1, "acosh", builtin::Function::kAcos},
+ BuiltinDataWithParamNum{1, "asin", builtin::Function::kAsin},
+ BuiltinDataWithParamNum{1, "asinh", builtin::Function::kAsin},
+ BuiltinDataWithParamNum{1, "atan", builtin::Function::kAtan},
+ BuiltinDataWithParamNum{1, "atanh", builtin::Function::kAtan},
+ BuiltinDataWithParamNum{2, "atan2", builtin::Function::kAtan2},
+ BuiltinDataWithParamNum{1, "ceil", builtin::Function::kCeil},
+ BuiltinDataWithParamNum{3, "clamp", builtin::Function::kClamp},
+ BuiltinDataWithParamNum{1, "cos", builtin::Function::kCos},
+ BuiltinDataWithParamNum{1, "cosh", builtin::Function::kCosh},
// cross: (vec3<T>, vec3<T>) -> vec3<T>
- BuiltinDataWithParamNum{1, "degrees", BuiltinType::kDegrees},
+ BuiltinDataWithParamNum{1, "degrees", builtin::Function::kDegrees},
// distance: (T, T) -> T, (vecN<T>, vecN<T>) -> T
- BuiltinDataWithParamNum{1, "exp", BuiltinType::kExp},
- BuiltinDataWithParamNum{1, "exp2", BuiltinType::kExp2},
+ BuiltinDataWithParamNum{1, "exp", builtin::Function::kExp},
+ BuiltinDataWithParamNum{1, "exp2", builtin::Function::kExp2},
// faceForward: (vecN<T>, vecN<T>, vecN<T>) -> vecN<T>
- BuiltinDataWithParamNum{1, "floor", BuiltinType::kFloor},
- BuiltinDataWithParamNum{3, "fma", BuiltinType::kFma},
- BuiltinDataWithParamNum{1, "fract", BuiltinType::kFract},
+ BuiltinDataWithParamNum{1, "floor", builtin::Function::kFloor},
+ BuiltinDataWithParamNum{3, "fma", builtin::Function::kFma},
+ BuiltinDataWithParamNum{1, "fract", builtin::Function::kFract},
// frexp
- BuiltinDataWithParamNum{1, "inverseSqrt", BuiltinType::kInverseSqrt},
+ BuiltinDataWithParamNum{1, "inverseSqrt", builtin::Function::kInverseSqrt},
// ldexp: (T, i32) -> T, (vecN<T>, vecN<i32>) -> vecN<T>
// length: (vecN<T>) -> T
- BuiltinDataWithParamNum{1, "log", BuiltinType::kLog},
- BuiltinDataWithParamNum{1, "log2", BuiltinType::kLog2},
- BuiltinDataWithParamNum{2, "max", BuiltinType::kMax},
- BuiltinDataWithParamNum{2, "min", BuiltinType::kMin},
+ BuiltinDataWithParamNum{1, "log", builtin::Function::kLog},
+ BuiltinDataWithParamNum{1, "log2", builtin::Function::kLog2},
+ BuiltinDataWithParamNum{2, "max", builtin::Function::kMax},
+ BuiltinDataWithParamNum{2, "min", builtin::Function::kMin},
// Note that `mix(vecN<f32>, vecN<f32>, f32) -> vecN<f32>` is not tested here.
- BuiltinDataWithParamNum{3, "mix", BuiltinType::kMix},
+ BuiltinDataWithParamNum{3, "mix", builtin::Function::kMix},
// modf
// normalize: (vecN<T>) -> vecN<T>
- BuiltinDataWithParamNum{2, "pow", BuiltinType::kPow},
+ BuiltinDataWithParamNum{2, "pow", builtin::Function::kPow},
// quantizeToF16 is not implemented yet.
- BuiltinDataWithParamNum{1, "radians", BuiltinType::kRadians},
+ BuiltinDataWithParamNum{1, "radians", builtin::Function::kRadians},
// reflect: (vecN<T>, vecN<T>) -> vecN<T>
// refract: (vecN<T>, vecN<T>, T) -> vecN<T>
- BuiltinDataWithParamNum{1, "round", BuiltinType::kRound},
+ BuiltinDataWithParamNum{1, "round", builtin::Function::kRound},
// saturate not implemented yet.
- BuiltinDataWithParamNum{1, "sign", BuiltinType::kSign},
- BuiltinDataWithParamNum{1, "sin", BuiltinType::kSin},
- BuiltinDataWithParamNum{1, "sinh", BuiltinType::kSinh},
- BuiltinDataWithParamNum{3, "smoothstep", BuiltinType::kSmoothstep},
- BuiltinDataWithParamNum{1, "sqrt", BuiltinType::kSqrt},
- BuiltinDataWithParamNum{2, "step", BuiltinType::kStep},
- BuiltinDataWithParamNum{1, "tan", BuiltinType::kTan},
- BuiltinDataWithParamNum{1, "tanh", BuiltinType::kTanh},
- BuiltinDataWithParamNum{1, "trunc", BuiltinType::kTrunc}));
+ BuiltinDataWithParamNum{1, "sign", builtin::Function::kSign},
+ BuiltinDataWithParamNum{1, "sin", builtin::Function::kSin},
+ BuiltinDataWithParamNum{1, "sinh", builtin::Function::kSinh},
+ BuiltinDataWithParamNum{3, "smoothstep", builtin::Function::kSmoothstep},
+ BuiltinDataWithParamNum{1, "sqrt", builtin::Function::kSqrt},
+ BuiltinDataWithParamNum{2, "step", builtin::Function::kStep},
+ BuiltinDataWithParamNum{1, "tan", builtin::Function::kTan},
+ BuiltinDataWithParamNum{1, "tanh", builtin::Function::kTanh},
+ BuiltinDataWithParamNum{1, "trunc", builtin::Function::kTrunc}));
using ResolverBuiltinFloatTest = ResolverTest;
@@ -1409,7 +1407,7 @@
struct BuiltinDataWithParamNum {
uint32_t args_number;
const char* name;
- BuiltinType builtin;
+ builtin::Function builtin;
};
inline std::ostream& operator<<(std::ostream& out, BuiltinDataWithParamNum data) {
@@ -1805,18 +1803,18 @@
ResolverTest,
ResolverBuiltinTest_IntegerBuiltin_IdenticalType,
testing::Values(
- BuiltinDataWithParamNum{1, "abs", BuiltinType::kAbs},
- BuiltinDataWithParamNum{3, "clamp", BuiltinType::kClamp},
- BuiltinDataWithParamNum{1, "countLeadingZeros", BuiltinType::kCountLeadingZeros},
- BuiltinDataWithParamNum{1, "countOneBits", BuiltinType::kCountOneBits},
- BuiltinDataWithParamNum{1, "countTrailingZeros", BuiltinType::kCountTrailingZeros},
+ BuiltinDataWithParamNum{1, "abs", builtin::Function::kAbs},
+ BuiltinDataWithParamNum{3, "clamp", builtin::Function::kClamp},
+ BuiltinDataWithParamNum{1, "countLeadingZeros", builtin::Function::kCountLeadingZeros},
+ BuiltinDataWithParamNum{1, "countOneBits", builtin::Function::kCountOneBits},
+ BuiltinDataWithParamNum{1, "countTrailingZeros", builtin::Function::kCountTrailingZeros},
// extractBits: (T, u32, u32) -> T
- BuiltinDataWithParamNum{1, "firstLeadingBit", BuiltinType::kFirstLeadingBit},
- BuiltinDataWithParamNum{1, "firstTrailingBit", BuiltinType::kFirstTrailingBit},
+ BuiltinDataWithParamNum{1, "firstLeadingBit", builtin::Function::kFirstLeadingBit},
+ BuiltinDataWithParamNum{1, "firstTrailingBit", builtin::Function::kFirstTrailingBit},
// insertBits: (T, T, u32, u32) -> T
- BuiltinDataWithParamNum{2, "max", BuiltinType::kMax},
- BuiltinDataWithParamNum{2, "min", BuiltinType::kMin},
- BuiltinDataWithParamNum{1, "reverseBits", BuiltinType::kReverseBits}));
+ BuiltinDataWithParamNum{2, "max", builtin::Function::kMax},
+ BuiltinDataWithParamNum{2, "min", builtin::Function::kMin},
+ BuiltinDataWithParamNum{1, "reverseBits", builtin::Function::kReverseBits}));
} // namespace integer_builtin_tests
@@ -2263,7 +2261,9 @@
case ValidTextureOverload::kGatherCompareDepthCubeArrayF32:
return R"(textureGatherCompare(texture, sampler, coords, array_index, depth_ref))";
case ValidTextureOverload::kNumLayers2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
case ValidTextureOverload::kNumLayersStorageWO2dArray:
return R"(textureNumLayers(texture))";
case ValidTextureOverload::kNumLevels2d:
@@ -2553,8 +2553,8 @@
TEST_P(ResolverBuiltinTest_DataPacking, InferType) {
auto param = GetParam();
- bool pack4 =
- param.builtin == BuiltinType::kPack4X8Snorm || param.builtin == BuiltinType::kPack4X8Unorm;
+ bool pack4 = param.builtin == builtin::Function::kPack4X8Snorm ||
+ param.builtin == builtin::Function::kPack4X8Unorm;
auto* call = pack4 ? Call(param.name, vec4<f32>(1_f, 2_f, 3_f, 4_f))
: Call(param.name, vec2<f32>(1_f, 2_f));
@@ -2568,8 +2568,8 @@
TEST_P(ResolverBuiltinTest_DataPacking, Error_IncorrectParamType) {
auto param = GetParam();
- bool pack4 =
- param.builtin == BuiltinType::kPack4X8Snorm || param.builtin == BuiltinType::kPack4X8Unorm;
+ bool pack4 = param.builtin == builtin::Function::kPack4X8Snorm ||
+ param.builtin == builtin::Function::kPack4X8Unorm;
auto* call = pack4 ? Call(param.name, vec4<i32>(1_i, 2_i, 3_i, 4_i))
: Call(param.name, vec2<i32>(1_i, 2_i));
@@ -2594,8 +2594,8 @@
TEST_P(ResolverBuiltinTest_DataPacking, Error_TooManyParams) {
auto param = GetParam();
- bool pack4 =
- param.builtin == BuiltinType::kPack4X8Snorm || param.builtin == BuiltinType::kPack4X8Unorm;
+ bool pack4 = param.builtin == builtin::Function::kPack4X8Snorm ||
+ param.builtin == builtin::Function::kPack4X8Unorm;
auto* call = pack4 ? Call(param.name, vec4<f32>(1_f, 2_f, 3_f, 4_f), 1_f)
: Call(param.name, vec2<f32>(1_f, 2_f), 1_f);
@@ -2606,14 +2606,14 @@
EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " + std::string(param.name)));
}
-INSTANTIATE_TEST_SUITE_P(ResolverTest,
- ResolverBuiltinTest_DataPacking,
- testing::Values(BuiltinData{"pack4x8snorm", BuiltinType::kPack4X8Snorm},
- BuiltinData{"pack4x8unorm", BuiltinType::kPack4X8Unorm},
- BuiltinData{"pack2x16snorm", BuiltinType::kPack2X16Snorm},
- BuiltinData{"pack2x16unorm", BuiltinType::kPack2X16Unorm},
- BuiltinData{"pack2x16float",
- BuiltinType::kPack2X16Float}));
+INSTANTIATE_TEST_SUITE_P(
+ ResolverTest,
+ ResolverBuiltinTest_DataPacking,
+ testing::Values(BuiltinData{"pack4x8snorm", builtin::Function::kPack4X8Snorm},
+ BuiltinData{"pack4x8unorm", builtin::Function::kPack4X8Unorm},
+ BuiltinData{"pack2x16snorm", builtin::Function::kPack2X16Snorm},
+ BuiltinData{"pack2x16unorm", builtin::Function::kPack2X16Unorm},
+ BuiltinData{"pack2x16float", builtin::Function::kPack2X16Float}));
} // namespace data_packing_builtin_tests
@@ -2624,8 +2624,8 @@
TEST_P(ResolverBuiltinTest_DataUnpacking, InferType) {
auto param = GetParam();
- bool pack4 = param.builtin == BuiltinType::kUnpack4X8Snorm ||
- param.builtin == BuiltinType::kUnpack4X8Unorm;
+ bool pack4 = param.builtin == builtin::Function::kUnpack4X8Snorm ||
+ param.builtin == builtin::Function::kUnpack4X8Unorm;
auto* call = Call(param.name, 1_u);
WrapInFunction(call);
@@ -2643,11 +2643,11 @@
INSTANTIATE_TEST_SUITE_P(
ResolverTest,
ResolverBuiltinTest_DataUnpacking,
- testing::Values(BuiltinData{"unpack4x8snorm", BuiltinType::kUnpack4X8Snorm},
- BuiltinData{"unpack4x8unorm", BuiltinType::kUnpack4X8Unorm},
- BuiltinData{"unpack2x16snorm", BuiltinType::kUnpack2X16Snorm},
- BuiltinData{"unpack2x16unorm", BuiltinType::kUnpack2X16Unorm},
- BuiltinData{"unpack2x16float", BuiltinType::kUnpack2X16Float}));
+ testing::Values(BuiltinData{"unpack4x8snorm", builtin::Function::kUnpack4X8Snorm},
+ BuiltinData{"unpack4x8unorm", builtin::Function::kUnpack4X8Unorm},
+ BuiltinData{"unpack2x16snorm", builtin::Function::kUnpack2X16Snorm},
+ BuiltinData{"unpack2x16unorm", builtin::Function::kUnpack2X16Unorm},
+ BuiltinData{"unpack2x16float", builtin::Function::kUnpack2X16Float}));
} // namespace data_unpacking_builtin_tests
@@ -2680,8 +2680,8 @@
INSTANTIATE_TEST_SUITE_P(
ResolverTest,
ResolverBuiltinTest_Barrier,
- testing::Values(BuiltinData{"storageBarrier", BuiltinType::kStorageBarrier},
- BuiltinData{"workgroupBarrier", BuiltinType::kWorkgroupBarrier}));
+ testing::Values(BuiltinData{"storageBarrier", builtin::Function::kStorageBarrier},
+ BuiltinData{"workgroupBarrier", builtin::Function::kWorkgroupBarrier}));
} // namespace synchronization_builtin_tests
diff --git a/src/tint/resolver/call_validation_test.cc b/src/tint/resolver/call_validation_test.cc
index b749df9..b00db68 100644
--- a/src/tint/resolver/call_validation_test.cc
+++ b/src/tint/resolver/call_validation_test.cc
@@ -478,5 +478,34 @@
EXPECT_EQ(r()->error(), "12:34 error: ignoring return value of builtin 'max'");
}
+TEST_F(ResolverCallValidationTest, UnexpectedFunctionTemplateArgs) {
+ // fn a() {}
+ // fn b() {
+ // a<i32>();
+ // }
+ Func(Source{{56, 78}}, "a", utils::Empty, ty.void_(), utils::Empty);
+ Func("b", utils::Empty, ty.void_(),
+ utils::Vector{
+ CallStmt(Call(Ident(Source{{12, 34}}, "a", "i32"))),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: function 'a' does not take template arguments
+56:78 note: function 'a' declared here)");
+}
+
+TEST_F(ResolverCallValidationTest, UnexpectedBuiltinTemplateArgs) {
+ // fn f() {
+ // min<i32>(1, 2);
+ // }
+ Func("f", utils::Empty, ty.void_(),
+ utils::Vector{
+ Decl(Var("v", Call(Ident(Source{{12, 34}}, "min", "i32"), 1_a, 2_a))),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: builtin 'min' does not take template arguments)");
+}
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index 325ccb0..b90ea00 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -30,6 +30,7 @@
#include "src/tint/program_builder.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/value_constructor.h"
+#include "src/tint/switch.h"
#include "src/tint/type/abstract_float.h"
#include "src/tint/type/abstract_int.h"
#include "src/tint/type/array.h"
@@ -325,35 +326,20 @@
const Source& source,
bool use_runtime_semantics);
-ConstEval::Result SplatConvert(const constant::Splat* splat,
- ProgramBuilder& builder,
- const type::Type* target_ty,
- const Source& source,
- bool use_runtime_semantics) {
- // Convert the single splatted element type.
- auto conv_el = ConvertInternal(splat->el, builder, type::Type::ElementOf(target_ty), source,
- use_runtime_semantics);
- if (!conv_el) {
- return utils::Failure;
- }
- if (!conv_el.Get()) {
- return nullptr;
- }
- return builder.create<constant::Splat>(target_ty, conv_el.Get(), splat->count);
-}
-
-ConstEval::Result CompositeConvert(const constant::Composite* composite,
+ConstEval::Result CompositeConvert(const constant::Value* value,
ProgramBuilder& builder,
const type::Type* target_ty,
const Source& source,
bool use_runtime_semantics) {
+ const size_t el_count = value->NumElements();
+
// Convert each of the composite element types.
utils::Vector<const constant::Value*, 4> conv_els;
- conv_els.Reserve(composite->elements.Length());
+ conv_els.Reserve(el_count);
std::function<const type::Type*(size_t idx)> target_el_ty;
if (auto* str = target_ty->As<type::Struct>()) {
- if (TINT_UNLIKELY(str->Members().Length() != composite->elements.Length())) {
+ if (TINT_UNLIKELY(str->Members().Length() != el_count)) {
TINT_ICE(Resolver, builder.Diagnostics())
<< "const-eval conversion of structure has mismatched element counts";
return utils::Failure;
@@ -364,7 +350,8 @@
target_el_ty = [el_ty](size_t) { return el_ty; };
}
- for (auto* el : composite->elements) {
+ for (size_t i = 0; i < el_count; i++) {
+ auto* el = value->Index(i);
auto conv_el = ConvertInternal(el, builder, target_el_ty(conv_els.Length()), source,
use_runtime_semantics);
if (!conv_el) {
@@ -378,6 +365,40 @@
return builder.create<constant::Composite>(target_ty, std::move(conv_els));
}
+ConstEval::Result SplatConvert(const constant::Splat* splat,
+ ProgramBuilder& builder,
+ const type::Type* target_ty,
+ const Source& source,
+ bool use_runtime_semantics) {
+ const type::Type* target_el_ty = nullptr;
+ if (auto* str = target_ty->As<type::Struct>()) {
+ // Structure conversion.
+ auto members = str->Members();
+ target_el_ty = members[0]->Type();
+
+ // Structures can only be converted during materialization. The user cannot declare the
+ // target structure type, so each member type must be the same default materialization type.
+ for (size_t i = 1; i < members.Length(); i++) {
+ if (members[i]->Type() != target_el_ty) {
+ TINT_ICE(Resolver, builder.Diagnostics())
+ << "inconsistent target struct member types for SplatConvert";
+ return utils::Failure;
+ }
+ }
+ } else {
+ target_el_ty = type::Type::ElementOf(target_ty);
+ }
+ // Convert the single splatted element type.
+ auto conv_el = ConvertInternal(splat->el, builder, target_el_ty, source, use_runtime_semantics);
+ if (!conv_el) {
+ return utils::Failure;
+ }
+ if (!conv_el.Get()) {
+ return nullptr;
+ }
+ return builder.create<constant::Splat>(target_ty, conv_el.Get(), splat->count);
+}
+
ConstEval::Result ConvertInternal(const constant::Value* c,
ProgramBuilder& builder,
const type::Type* target_ty,
diff --git a/src/tint/resolver/const_eval_builtin_test.cc b/src/tint/resolver/const_eval_builtin_test.cc
index bd32779..2cef1d1 100644
--- a/src/tint/resolver/const_eval_builtin_test.cc
+++ b/src/tint/resolver/const_eval_builtin_test.cc
@@ -139,7 +139,7 @@
return Case{std::move(args), std::move(err)};
}
-using ResolverConstEvalBuiltinTest = ResolverTestWithParam<std::tuple<sem::BuiltinType, Case>>;
+using ResolverConstEvalBuiltinTest = ResolverTestWithParam<std::tuple<builtin::Function, Case>>;
TEST_P(ResolverConstEvalBuiltinTest, Test) {
Enable(builtin::Extension::kF16);
@@ -152,7 +152,7 @@
args.Push(a.Expr(*this));
}
- auto* expr = Call(Source{{12, 34}}, sem::str(builtin), std::move(args));
+ auto* expr = Call(Source{{12, 34}}, builtin::str(builtin), std::move(args));
GlobalConst("C", expr);
if (c.expected) {
@@ -187,7 +187,7 @@
INSTANTIATE_TEST_SUITE_P( //
MixedAbstractArgs,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAtan2),
+ testing::Combine(testing::Values(builtin::Function::kAtan2),
testing::ValuesIn(std::vector{
C({0_a, -0.0_a}, kPi<AFloat>),
C({1.0_a, 0_a}, kPiOver2<AFloat>),
@@ -222,7 +222,7 @@
INSTANTIATE_TEST_SUITE_P( //
Abs,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAbs),
+ testing::Combine(testing::Values(builtin::Function::kAbs),
testing::ValuesIn(Concat(AbsCases<AInt>(), //
AbsCases<i32>(),
AbsCases<u32>(),
@@ -257,7 +257,7 @@
INSTANTIATE_TEST_SUITE_P( //
All,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAll), testing::ValuesIn(AllCases())));
+ testing::Combine(testing::Values(builtin::Function::kAll), testing::ValuesIn(AllCases())));
static std::vector<Case> AnyCases() {
return {
@@ -286,7 +286,7 @@
INSTANTIATE_TEST_SUITE_P( //
Any,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAny), testing::ValuesIn(AnyCases())));
+ testing::Combine(testing::Values(builtin::Function::kAny), testing::ValuesIn(AnyCases())));
template <typename T>
std::vector<Case> Atan2Cases() {
@@ -315,7 +315,7 @@
INSTANTIATE_TEST_SUITE_P( //
Atan2,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAtan2),
+ testing::Combine(testing::Values(builtin::Function::kAtan2),
testing::ValuesIn(Concat(Atan2Cases<AFloat>(), //
Atan2Cases<f32>(),
Atan2Cases<f16>()))));
@@ -336,7 +336,7 @@
INSTANTIATE_TEST_SUITE_P( //
Atan,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAtan),
+ testing::Combine(testing::Values(builtin::Function::kAtan),
testing::ValuesIn(Concat(AtanCases<AFloat>(), //
AtanCases<f32>(),
AtanCases<f16>()))));
@@ -361,7 +361,7 @@
INSTANTIATE_TEST_SUITE_P( //
Atanh,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAtanh),
+ testing::Combine(testing::Values(builtin::Function::kAtanh),
testing::ValuesIn(Concat(AtanhCases<AFloat>(), //
AtanhCases<f32>(),
AtanhCases<f16>()))));
@@ -387,7 +387,7 @@
INSTANTIATE_TEST_SUITE_P( //
Acos,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAcos),
+ testing::Combine(testing::Values(builtin::Function::kAcos),
testing::ValuesIn(Concat(AcosCases<AFloat>(), //
AcosCases<f32>(),
AcosCases<f16>()))));
@@ -409,7 +409,7 @@
INSTANTIATE_TEST_SUITE_P( //
Acosh,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAcosh),
+ testing::Combine(testing::Values(builtin::Function::kAcosh),
testing::ValuesIn(Concat(AcoshCases<AFloat>(), //
AcoshCases<f32>(),
AcoshCases<f16>()))));
@@ -436,7 +436,7 @@
INSTANTIATE_TEST_SUITE_P( //
Asin,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAsin),
+ testing::Combine(testing::Values(builtin::Function::kAsin),
testing::ValuesIn(Concat(AsinCases<AFloat>(), //
AsinCases<f32>(),
AsinCases<f16>()))));
@@ -460,7 +460,7 @@
INSTANTIATE_TEST_SUITE_P( //
Asinh,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kAsinh),
+ testing::Combine(testing::Values(builtin::Function::kAsinh),
testing::ValuesIn(Concat(AsinhCases<AFloat>(), //
AsinhCases<f32>(),
AsinhCases<f16>()))));
@@ -482,7 +482,7 @@
Ceil,
ResolverConstEvalBuiltinTest,
testing::Combine(
- testing::Values(sem::BuiltinType::kCeil),
+ testing::Values(builtin::Function::kCeil),
testing::ValuesIn(Concat(CeilCases<AFloat>(), CeilCases<f32>(), CeilCases<f16>()))));
template <typename T>
@@ -512,7 +512,7 @@
INSTANTIATE_TEST_SUITE_P( //
Clamp,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kClamp),
+ testing::Combine(testing::Values(builtin::Function::kClamp),
testing::ValuesIn(Concat(ClampCases<AInt>(), //
ClampCases<i32>(),
ClampCases<u32>(),
@@ -535,7 +535,7 @@
INSTANTIATE_TEST_SUITE_P( //
Cos,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kCos),
+ testing::Combine(testing::Values(builtin::Function::kCos),
testing::ValuesIn(Concat(CosCases<AFloat>(), //
CosCases<f32>(),
CosCases<f16>()))));
@@ -561,7 +561,7 @@
INSTANTIATE_TEST_SUITE_P( //
Cosh,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kCosh),
+ testing::Combine(testing::Values(builtin::Function::kCosh),
testing::ValuesIn(Concat(CoshCases<AFloat>(), //
CoshCases<f32>(),
CoshCases<f16>()))));
@@ -608,7 +608,7 @@
INSTANTIATE_TEST_SUITE_P( //
CountLeadingZeros,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kCountLeadingZeros),
+ testing::Combine(testing::Values(builtin::Function::kCountLeadingZeros),
testing::ValuesIn(Concat(CountLeadingZerosCases<i32>(), //
CountLeadingZerosCases<u32>()))));
@@ -654,7 +654,7 @@
INSTANTIATE_TEST_SUITE_P( //
CountTrailingZeros,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kCountTrailingZeros),
+ testing::Combine(testing::Values(builtin::Function::kCountTrailingZeros),
testing::ValuesIn(Concat(CountTrailingZerosCases<i32>(), //
CountTrailingZerosCases<u32>()))));
@@ -691,7 +691,7 @@
INSTANTIATE_TEST_SUITE_P( //
CountOneBits,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kCountOneBits),
+ testing::Combine(testing::Values(builtin::Function::kCountOneBits),
testing::ValuesIn(Concat(CountOneBitsCases<i32>(), //
CountOneBitsCases<u32>()))));
@@ -790,7 +790,7 @@
INSTANTIATE_TEST_SUITE_P( //
Cross,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kCross),
+ testing::Combine(testing::Values(builtin::Function::kCross),
testing::ValuesIn(Concat(CrossCases<AFloat>(), //
CrossCases<f32>(), //
CrossCases<f16>()))));
@@ -817,7 +817,7 @@
INSTANTIATE_TEST_SUITE_P( //
Distance,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kDistance),
+ testing::Combine(testing::Values(builtin::Function::kDistance),
testing::ValuesIn(Concat(DistanceCases<AFloat>(), //
DistanceCases<f32>(), //
DistanceCases<f16>()))));
@@ -865,7 +865,7 @@
INSTANTIATE_TEST_SUITE_P( //
Dot,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kDot),
+ testing::Combine(testing::Values(builtin::Function::kDot),
testing::ValuesIn(Concat(DotCases<AInt>(), //
DotCases<i32>(), //
DotCases<u32>(), //
@@ -945,7 +945,7 @@
INSTANTIATE_TEST_SUITE_P( //
Determinant,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kDeterminant),
+ testing::Combine(testing::Values(builtin::Function::kDeterminant),
testing::ValuesIn(Concat(DeterminantCases<AFloat>(), //
DeterminantCases<f32>(), //
DeterminantCases<f16>()))));
@@ -1027,7 +1027,7 @@
INSTANTIATE_TEST_SUITE_P( //
FaceForward,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFaceForward),
+ testing::Combine(testing::Values(builtin::Function::kFaceForward),
testing::ValuesIn(Concat(FaceForwardCases<AFloat>(), //
FaceForwardCases<f32>(), //
FaceForwardCases<f16>()))));
@@ -1090,7 +1090,7 @@
INSTANTIATE_TEST_SUITE_P( //
FirstLeadingBit,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFirstLeadingBit),
+ testing::Combine(testing::Values(builtin::Function::kFirstLeadingBit),
testing::ValuesIn(Concat(FirstLeadingBitCases<i32>(), //
FirstLeadingBitCases<u32>()))));
@@ -1123,7 +1123,7 @@
INSTANTIATE_TEST_SUITE_P( //
FirstTrailingBit,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFirstTrailingBit),
+ testing::Combine(testing::Values(builtin::Function::kFirstTrailingBit),
testing::ValuesIn(Concat(FirstTrailingBitCases<i32>(), //
FirstTrailingBitCases<u32>()))));
@@ -1143,7 +1143,7 @@
INSTANTIATE_TEST_SUITE_P( //
Floor,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFloor),
+ testing::Combine(testing::Values(builtin::Function::kFloor),
testing::ValuesIn(Concat(FloorCases<AFloat>(), //
FloorCases<f32>(),
FloorCases<f16>()))));
@@ -1167,7 +1167,7 @@
INSTANTIATE_TEST_SUITE_P( //
Fma,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFma),
+ testing::Combine(testing::Values(builtin::Function::kFma),
testing::ValuesIn(Concat(FmaCases<AFloat>(), //
FmaCases<f32>(),
FmaCases<f16>()))));
@@ -1199,7 +1199,7 @@
INSTANTIATE_TEST_SUITE_P( //
Fract,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFract),
+ testing::Combine(testing::Values(builtin::Function::kFract),
testing::ValuesIn(Concat(FractCases<AFloat>(), //
FractCases<f32>(),
FractCases<f16>()))));
@@ -1256,7 +1256,7 @@
INSTANTIATE_TEST_SUITE_P( //
Frexp,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kFrexp),
+ testing::Combine(testing::Values(builtin::Function::kFrexp),
testing::ValuesIn(Concat(FrexpCases<AFloat>(), //
FrexpCases<f32>(), //
FrexpCases<f16>()))));
@@ -1338,7 +1338,7 @@
INSTANTIATE_TEST_SUITE_P( //
InsertBits,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kInsertBits),
+ testing::Combine(testing::Values(builtin::Function::kInsertBits),
testing::ValuesIn(Concat(InsertBitsCases<i32>(), //
InsertBitsCases<u32>()))));
@@ -1358,7 +1358,7 @@
INSTANTIATE_TEST_SUITE_P( //
InverseSqrt,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kInverseSqrt),
+ testing::Combine(testing::Values(builtin::Function::kInverseSqrt),
testing::ValuesIn(Concat(InverseSqrtCases<AFloat>(), //
InverseSqrtCases<f32>(),
InverseSqrtCases<f16>()))));
@@ -1377,7 +1377,7 @@
INSTANTIATE_TEST_SUITE_P( //
DegreesAFloat,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kDegrees),
+ testing::Combine(testing::Values(builtin::Function::kDegrees),
testing::ValuesIn(DegreesAFloatCases<AFloat>())));
template <typename T>
@@ -1394,7 +1394,7 @@
INSTANTIATE_TEST_SUITE_P( //
DegreesF32,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kDegrees),
+ testing::Combine(testing::Values(builtin::Function::kDegrees),
testing::ValuesIn(DegreesF32Cases<f32>())));
template <typename T>
@@ -1411,7 +1411,7 @@
INSTANTIATE_TEST_SUITE_P( //
DegreesF16,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kDegrees),
+ testing::Combine(testing::Values(builtin::Function::kDegrees),
testing::ValuesIn(DegreesF16Cases<f16>())));
template <typename T>
@@ -1428,7 +1428,7 @@
INSTANTIATE_TEST_SUITE_P( //
Exp,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kExp),
+ testing::Combine(testing::Values(builtin::Function::kExp),
testing::ValuesIn(Concat(ExpCases<AFloat>(), //
ExpCases<f32>(),
ExpCases<f16>()))));
@@ -1449,7 +1449,7 @@
INSTANTIATE_TEST_SUITE_P( //
Exp2,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kExp2),
+ testing::Combine(testing::Values(builtin::Function::kExp2),
testing::ValuesIn(Concat(Exp2Cases<AFloat>(), //
Exp2Cases<f32>(),
Exp2Cases<f16>()))));
@@ -1546,7 +1546,7 @@
INSTANTIATE_TEST_SUITE_P( //
ExtractBits,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kExtractBits),
+ testing::Combine(testing::Values(builtin::Function::kExtractBits),
testing::ValuesIn(Concat(ExtractBitsCases<i32>(), //
ExtractBitsCases<u32>()))));
@@ -1610,7 +1610,7 @@
INSTANTIATE_TEST_SUITE_P( //
Ldexp,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLdexp),
+ testing::Combine(testing::Values(builtin::Function::kLdexp),
testing::ValuesIn(Concat(LdexpCases<AFloat>(), //
LdexpCases<f32>(),
LdexpCases<f16>()))));
@@ -1669,7 +1669,7 @@
INSTANTIATE_TEST_SUITE_P( //
Length,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLength),
+ testing::Combine(testing::Values(builtin::Function::kLength),
testing::ValuesIn(Concat(LengthCases<AFloat>(), //
LengthCases<f32>(),
LengthCases<f16>()))));
@@ -1685,7 +1685,7 @@
INSTANTIATE_TEST_SUITE_P( //
Log,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::Combine(testing::Values(builtin::Function::kLog),
testing::ValuesIn(Concat(LogCases<AFloat>(), //
LogCases<f32>(),
LogCases<f16>()))));
@@ -1698,7 +1698,7 @@
INSTANTIATE_TEST_SUITE_P( //
LogF16,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::Combine(testing::Values(builtin::Function::kLog),
testing::ValuesIn(LogF16Cases<f16>())));
template <typename T>
std::vector<Case> LogF32Cases() {
@@ -1709,7 +1709,7 @@
INSTANTIATE_TEST_SUITE_P( //
LogF32,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::Combine(testing::Values(builtin::Function::kLog),
testing::ValuesIn(LogF32Cases<f32>())));
template <typename T>
@@ -1721,7 +1721,7 @@
INSTANTIATE_TEST_SUITE_P( //
LogAbstract,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::Combine(testing::Values(builtin::Function::kLog),
testing::ValuesIn(LogAbstractCases<AFloat>())));
template <typename T>
@@ -1739,7 +1739,7 @@
INSTANTIATE_TEST_SUITE_P( //
Log2,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::Combine(testing::Values(builtin::Function::kLog2),
testing::ValuesIn(Concat(Log2Cases<AFloat>(), //
Log2Cases<f32>(),
Log2Cases<f16>()))));
@@ -1752,7 +1752,7 @@
INSTANTIATE_TEST_SUITE_P( //
Log2F16,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::Combine(testing::Values(builtin::Function::kLog2),
testing::ValuesIn(Log2F16Cases<f16>())));
template <typename T>
std::vector<Case> Log2F32Cases() {
@@ -1763,7 +1763,7 @@
INSTANTIATE_TEST_SUITE_P( //
Log2F32,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::Combine(testing::Values(builtin::Function::kLog2),
testing::ValuesIn(Log2F32Cases<f32>())));
template <typename T>
std::vector<Case> Log2AbstractCases() {
@@ -1774,7 +1774,7 @@
INSTANTIATE_TEST_SUITE_P( //
Log2Abstract,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::Combine(testing::Values(builtin::Function::kLog2),
testing::ValuesIn(Log2AbstractCases<AFloat>())));
template <typename T>
@@ -1797,7 +1797,7 @@
INSTANTIATE_TEST_SUITE_P( //
Max,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kMax),
+ testing::Combine(testing::Values(builtin::Function::kMax),
testing::ValuesIn(Concat(MaxCases<AInt>(), //
MaxCases<i32>(),
MaxCases<u32>(),
@@ -1823,7 +1823,7 @@
INSTANTIATE_TEST_SUITE_P( //
Min,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kMin),
+ testing::Combine(testing::Values(builtin::Function::kMin),
testing::ValuesIn(Concat(MinCases<AInt>(), //
MinCases<i32>(),
MinCases<u32>(),
@@ -1913,7 +1913,7 @@
INSTANTIATE_TEST_SUITE_P( //
Mix,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kMix),
+ testing::Combine(testing::Values(builtin::Function::kMix),
testing::ValuesIn(Concat(MixCases<AFloat>(), //
MixCases<f32>(), //
MixCases<f16>()))));
@@ -1947,7 +1947,7 @@
INSTANTIATE_TEST_SUITE_P( //
Modf,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kModf),
+ testing::Combine(testing::Values(builtin::Function::kModf),
testing::ValuesIn(Concat(ModfCases<AFloat>(), //
ModfCases<f32>(), //
ModfCases<f16>()))));
@@ -1977,7 +1977,7 @@
INSTANTIATE_TEST_SUITE_P( //
Normalize,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kNormalize),
+ testing::Combine(testing::Values(builtin::Function::kNormalize),
testing::ValuesIn(Concat(NormalizeCases<AFloat>(), //
NormalizeCases<f32>(), //
NormalizeCases<f16>()))));
@@ -1997,7 +1997,7 @@
INSTANTIATE_TEST_SUITE_P( //
Pack4x8snorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kPack4X8Snorm),
+ testing::Combine(testing::Values(builtin::Function::kPack4X8Snorm),
testing::ValuesIn(Pack4x8snormCases())));
std::vector<Case> Pack4x8unormCases() {
@@ -2014,7 +2014,7 @@
INSTANTIATE_TEST_SUITE_P( //
Pack4x8unorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kPack4X8Unorm),
+ testing::Combine(testing::Values(builtin::Function::kPack4X8Unorm),
testing::ValuesIn(Pack4x8unormCases())));
std::vector<Case> Pack2x16floatCases() {
@@ -2035,7 +2035,7 @@
INSTANTIATE_TEST_SUITE_P( //
Pack2x16float,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kPack2X16Float),
+ testing::Combine(testing::Values(builtin::Function::kPack2X16Float),
testing::ValuesIn(Pack2x16floatCases())));
std::vector<Case> Pack2x16snormCases() {
@@ -2053,7 +2053,7 @@
INSTANTIATE_TEST_SUITE_P( //
Pack2x16snorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kPack2X16Snorm),
+ testing::Combine(testing::Values(builtin::Function::kPack2X16Snorm),
testing::ValuesIn(Pack2x16snormCases())));
std::vector<Case> Pack2x16unormCases() {
@@ -2067,7 +2067,7 @@
INSTANTIATE_TEST_SUITE_P( //
Pack2x16unorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kPack2X16Unorm),
+ testing::Combine(testing::Values(builtin::Function::kPack2X16Unorm),
testing::ValuesIn(Pack2x16unormCases())));
template <typename T>
@@ -2113,7 +2113,7 @@
INSTANTIATE_TEST_SUITE_P( //
Pow,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kPow),
+ testing::Combine(testing::Values(builtin::Function::kPow),
testing::ValuesIn(Concat(PowCases<AFloat>(), //
PowCases<f32>(), //
PowCases<f16>()))));
@@ -2160,7 +2160,7 @@
INSTANTIATE_TEST_SUITE_P( //
ReverseBits,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kReverseBits),
+ testing::Combine(testing::Values(builtin::Function::kReverseBits),
testing::ValuesIn(Concat(ReverseBitsCases<i32>(), //
ReverseBitsCases<u32>()))));
@@ -2212,7 +2212,7 @@
INSTANTIATE_TEST_SUITE_P( //
Reflect,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kReflect),
+ testing::Combine(testing::Values(builtin::Function::kReflect),
testing::ValuesIn(Concat(ReflectCases<AFloat>(), //
ReflectCases<f32>(), //
ReflectCases<f16>()))));
@@ -2294,7 +2294,7 @@
INSTANTIATE_TEST_SUITE_P( //
Refract,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kRefract),
+ testing::Combine(testing::Values(builtin::Function::kRefract),
testing::ValuesIn(Concat(RefractCases<AFloat>(), //
RefractCases<f32>(), //
RefractCases<f16>()))));
@@ -2313,7 +2313,7 @@
INSTANTIATE_TEST_SUITE_P( //
Radians,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kRadians),
+ testing::Combine(testing::Values(builtin::Function::kRadians),
testing::ValuesIn(Concat(RadiansCases<AFloat>(), //
RadiansCases<f32>()))));
@@ -2331,7 +2331,7 @@
INSTANTIATE_TEST_SUITE_P( //
RadiansF16,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kRadians),
+ testing::Combine(testing::Values(builtin::Function::kRadians),
testing::ValuesIn(RadiansF16Cases<f16>())));
template <typename T>
@@ -2357,7 +2357,7 @@
INSTANTIATE_TEST_SUITE_P( //
Round,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kRound),
+ testing::Combine(testing::Values(builtin::Function::kRound),
testing::ValuesIn(Concat(RoundCases<AFloat>(), //
RoundCases<f32>(),
RoundCases<f16>()))));
@@ -2382,7 +2382,7 @@
INSTANTIATE_TEST_SUITE_P( //
Saturate,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSaturate),
+ testing::Combine(testing::Values(builtin::Function::kSaturate),
testing::ValuesIn(Concat(SaturateCases<AFloat>(), //
SaturateCases<f32>(),
SaturateCases<f16>()))));
@@ -2424,7 +2424,7 @@
INSTANTIATE_TEST_SUITE_P( //
Select,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSelect),
+ testing::Combine(testing::Values(builtin::Function::kSelect),
testing::ValuesIn(Concat(SelectCases<AInt>(), //
SelectCases<i32>(),
SelectCases<u32>(),
@@ -2465,7 +2465,7 @@
INSTANTIATE_TEST_SUITE_P( //
Sign,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSign),
+ testing::Combine(testing::Values(builtin::Function::kSign),
testing::ValuesIn(Concat(SignCases<AInt>(), //
SignCases<i32>(),
SignCases<AFloat>(),
@@ -2487,7 +2487,7 @@
INSTANTIATE_TEST_SUITE_P( //
Sin,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSin),
+ testing::Combine(testing::Values(builtin::Function::kSin),
testing::ValuesIn(Concat(SinCases<AFloat>(), //
SinCases<f32>(),
SinCases<f16>()))));
@@ -2512,7 +2512,7 @@
INSTANTIATE_TEST_SUITE_P( //
Sinh,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSinh),
+ testing::Combine(testing::Values(builtin::Function::kSinh),
testing::ValuesIn(Concat(SinhCases<AFloat>(), //
SinhCases<f32>(),
SinhCases<f16>()))));
@@ -2545,7 +2545,7 @@
INSTANTIATE_TEST_SUITE_P( //
Smoothstep,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSmoothstep),
+ testing::Combine(testing::Values(builtin::Function::kSmoothstep),
testing::ValuesIn(Concat(SmoothstepCases<AFloat>(), //
SmoothstepCases<f32>(),
SmoothstepCases<f16>()))));
@@ -2577,7 +2577,7 @@
INSTANTIATE_TEST_SUITE_P( //
Step,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kStep),
+ testing::Combine(testing::Values(builtin::Function::kStep),
testing::ValuesIn(Concat(StepCases<AFloat>(), //
StepCases<f32>(),
StepCases<f16>()))));
@@ -2598,7 +2598,7 @@
INSTANTIATE_TEST_SUITE_P( //
Sqrt,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kSqrt),
+ testing::Combine(testing::Values(builtin::Function::kSqrt),
testing::ValuesIn(Concat(SqrtCases<AFloat>(), //
SqrtCases<f32>(),
SqrtCases<f16>()))));
@@ -2617,7 +2617,7 @@
INSTANTIATE_TEST_SUITE_P( //
Tan,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kTan),
+ testing::Combine(testing::Values(builtin::Function::kTan),
testing::ValuesIn(Concat(TanCases<AFloat>(), //
TanCases<f32>(),
TanCases<f16>()))));
@@ -2637,7 +2637,7 @@
INSTANTIATE_TEST_SUITE_P( //
Tanh,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kTanh),
+ testing::Combine(testing::Values(builtin::Function::kTanh),
testing::ValuesIn(Concat(TanhCases<AFloat>(), //
TanhCases<f32>(),
TanhCases<f16>()))));
@@ -2703,7 +2703,7 @@
INSTANTIATE_TEST_SUITE_P( //
Transpose,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kTranspose),
+ testing::Combine(testing::Values(builtin::Function::kTranspose),
testing::ValuesIn(Concat(TransposeCases<AFloat>(), //
TransposeCases<f32>(),
TransposeCases<f16>()))));
@@ -2721,7 +2721,7 @@
INSTANTIATE_TEST_SUITE_P( //
Trunc,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kTrunc),
+ testing::Combine(testing::Values(builtin::Function::kTrunc),
testing::ValuesIn(Concat(TruncCases<AFloat>(), //
TruncCases<f32>(),
TruncCases<f16>()))));
@@ -2742,7 +2742,7 @@
INSTANTIATE_TEST_SUITE_P( //
Unpack4x8snorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kUnpack4X8Snorm),
+ testing::Combine(testing::Values(builtin::Function::kUnpack4X8Snorm),
testing::ValuesIn(Unpack4x8snormCases())));
std::vector<Case> Unpack4x8unormCases() {
@@ -2759,7 +2759,7 @@
INSTANTIATE_TEST_SUITE_P( //
Unpack4x8unorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kUnpack4X8Unorm),
+ testing::Combine(testing::Values(builtin::Function::kUnpack4X8Unorm),
testing::ValuesIn(Unpack4x8unormCases())));
std::vector<Case> Unpack2x16floatCases() {
@@ -2773,7 +2773,7 @@
INSTANTIATE_TEST_SUITE_P( //
Unpack2x16float,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kUnpack2X16Float),
+ testing::Combine(testing::Values(builtin::Function::kUnpack2X16Float),
testing::ValuesIn(Unpack2x16floatCases())));
std::vector<Case> Unpack2x16snormCases() {
@@ -2791,7 +2791,7 @@
INSTANTIATE_TEST_SUITE_P( //
Unpack2x16snorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kUnpack2X16Snorm),
+ testing::Combine(testing::Values(builtin::Function::kUnpack2X16Snorm),
testing::ValuesIn(Unpack2x16snormCases())));
std::vector<Case> Unpack2x16unormCases() {
@@ -2805,7 +2805,7 @@
INSTANTIATE_TEST_SUITE_P( //
Unpack2x16unorm,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kUnpack2X16Unorm),
+ testing::Combine(testing::Values(builtin::Function::kUnpack2X16Unorm),
testing::ValuesIn(Unpack2x16unormCases())));
std::vector<Case> QuantizeToF16Cases() {
@@ -2864,7 +2864,7 @@
INSTANTIATE_TEST_SUITE_P( //
QuantizeToF16,
ResolverConstEvalBuiltinTest,
- testing::Combine(testing::Values(sem::BuiltinType::kQuantizeToF16),
+ testing::Combine(testing::Values(builtin::Function::kQuantizeToF16),
testing::ValuesIn(QuantizeToF16Cases())));
} // namespace
diff --git a/src/tint/resolver/const_eval_construction_test.cc b/src/tint/resolver/const_eval_construction_test.cc
index 55c2cf5..e98d21f 100644
--- a/src/tint/resolver/const_eval_construction_test.cc
+++ b/src/tint/resolver/const_eval_construction_test.cc
@@ -30,7 +30,6 @@
ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::AbstractFloat>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<AFloat>(), 99.0f);
@@ -47,7 +46,6 @@
ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::AbstractInt>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<AInt>(), 99);
@@ -63,7 +61,6 @@
ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<AInt>(), 99);
@@ -79,7 +76,6 @@
ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::U32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<AInt>(), 99u);
@@ -95,7 +91,6 @@
ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::F32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<AFloat>().value, 9.9f);
@@ -113,7 +108,6 @@
EXPECT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::F16>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
// 9.9 is not exactly representable by f16, and should be quantized to 9.8984375
@@ -130,7 +124,6 @@
ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<type::Bool>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<bool>(), true);
@@ -158,7 +151,6 @@
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
@@ -167,18 +159,15 @@
EXPECT_EQ(sem->ConstantValue()->ValueAs<f32>(), 0.0f);
} else if (auto* vec = sem->Type()->As<type::Vector>()) {
for (size_t i = 0; i < vec->Width(); ++i) {
- EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(i)->ValueAs<f32>(), 0.0f);
}
} else if (auto* mat = sem->Type()->As<type::Matrix>()) {
for (size_t i = 0; i < mat->columns(); ++i) {
- EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllZero());
for (size_t j = 0; j < mat->rows(); ++j) {
- EXPECT_TRUE(sem->ConstantValue()->Index(i)->Index(j)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->Index(j)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->Index(j)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(i)->Index(j)->ValueAs<f32>(), 0.0f);
@@ -186,7 +175,6 @@
}
} else if (auto* arr = sem->Type()->As<type::Array>()) {
for (size_t i = 0; i < *(arr->ConstantCount()); ++i) {
- EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(i)->ValueAs<f32>(), 0.0f);
@@ -229,21 +217,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 0);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 0);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 0);
@@ -262,21 +246,17 @@
EXPECT_TRUE(vec->type()->Is<type::U32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 0u);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 0u);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 0u);
@@ -295,21 +275,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 0._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 0._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 0._a);
@@ -330,21 +306,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 0._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 0._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 0._a);
@@ -363,21 +335,17 @@
EXPECT_TRUE(vec->type()->Is<type::Bool>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<bool>(), false);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<bool>(), false);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<bool>(), false);
@@ -396,21 +364,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 99);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 99);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 99);
@@ -429,21 +393,17 @@
EXPECT_TRUE(vec->type()->Is<type::U32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 99u);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 99u);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 99u);
@@ -462,21 +422,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 9.9f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 9.9f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 9.9f);
@@ -497,22 +453,18 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
// 9.9 is not exactly representable by f16, and should be quantized to 9.8984375
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 9.8984375f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 9.8984375f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 9.8984375f);
@@ -531,21 +483,17 @@
EXPECT_TRUE(vec->type()->Is<type::Bool>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<bool>(), true);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<bool>(), true);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<bool>(), true);
@@ -565,21 +513,17 @@
EXPECT_TRUE(vec->type()->Is<type::AbstractInt>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3);
@@ -599,21 +543,17 @@
EXPECT_TRUE(vec->type()->Is<type::AbstractFloat>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 1.0f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 2.0f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 3.0f);
@@ -632,21 +572,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3);
@@ -665,21 +601,17 @@
EXPECT_TRUE(vec->type()->Is<type::U32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3);
@@ -698,21 +630,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 1.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 2.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 3.f);
@@ -733,21 +661,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 1.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 2.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 3.f);
@@ -766,21 +690,17 @@
EXPECT_TRUE(vec->type()->Is<type::Bool>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<bool>(), true);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<bool>(), false);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<bool>(), true);
@@ -799,21 +719,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3);
@@ -832,21 +748,17 @@
EXPECT_TRUE(vec->type()->Is<type::U32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3);
@@ -865,21 +777,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 1.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 2.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 3.f);
@@ -898,21 +806,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 10_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 10_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 10_f);
@@ -931,21 +835,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 0_f);
@@ -964,21 +864,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), -0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), -0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), -0_f);
@@ -997,21 +893,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), -0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 0_f);
@@ -1032,21 +924,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 1.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 2.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 3.f);
@@ -1067,21 +955,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f16>(), 10_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f16>(), 10_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f16>(), 10_h);
@@ -1102,21 +986,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f16>(), 0_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f16>(), 0_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f16>(), 0_h);
@@ -1137,21 +1017,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f16>(), -0_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f16>(), -0_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f16>(), -0_h);
@@ -1172,21 +1048,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f16>(), 0_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f16>(), -0_h);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f16>(), 0_h);
@@ -1205,21 +1077,17 @@
EXPECT_TRUE(vec->type()->Is<type::Bool>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<bool>(), true);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<bool>(), false);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<bool>(), true);
@@ -1238,21 +1106,17 @@
EXPECT_TRUE(vec->type()->Is<type::Bool>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<bool>(), true);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<bool>(), true);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<bool>(), true);
@@ -1271,21 +1135,17 @@
EXPECT_TRUE(vec->type()->Is<type::Bool>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<bool>(), false);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<bool>(), false);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<bool>(), false);
@@ -1305,36 +1165,29 @@
EXPECT_EQ(mat->columns(), 2u);
EXPECT_EQ(mat->rows(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<f32>(), 0._f);
@@ -1356,36 +1209,29 @@
EXPECT_EQ(mat->columns(), 2u);
EXPECT_EQ(mat->rows(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<f16>(), 0._h);
@@ -1405,36 +1251,29 @@
EXPECT_EQ(mat->columns(), 3u);
EXPECT_EQ(mat->rows(), 2u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<AFloat>(), 1._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<AFloat>(), 2._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<AFloat>(), 3._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<AFloat>(), 4._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(0)->ValueAs<AFloat>(), 5._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(1)->ValueAs<AFloat>(), 6._a);
@@ -1457,36 +1296,29 @@
EXPECT_EQ(mat->columns(), 3u);
EXPECT_EQ(mat->rows(), 2u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<AFloat>(), 1._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<AFloat>(), 2._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<AFloat>(), 3._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<AFloat>(), 4._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(0)->ValueAs<AFloat>(), 5._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(1)->ValueAs<AFloat>(), 6._a);
@@ -1504,26 +1336,21 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<i32>(), 0_i);
@@ -1541,26 +1368,21 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<type::F32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<f32>(), 0_f);
@@ -1578,36 +1400,29 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<type::Vector>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<f32>(), 0_f);
@@ -1629,26 +1444,21 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Struct>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<f32>(), 0_f);
@@ -1666,26 +1476,21 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<i32>(), 10_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<i32>(), 20_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<i32>(), 30_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<i32>(), 40_i);
@@ -1765,17 +1570,13 @@
EXPECT_TRUE(outer_arr->ElemType()->As<type::Array>()->ElemType()->Is<type::F32>());
auto* arr = sem->ConstantValue();
- EXPECT_FALSE(arr->AllEqual());
EXPECT_FALSE(arr->AnyZero());
EXPECT_FALSE(arr->AllZero());
- EXPECT_FALSE(arr->Index(0)->AllEqual());
EXPECT_FALSE(arr->Index(0)->AnyZero());
EXPECT_FALSE(arr->Index(0)->AllZero());
- EXPECT_FALSE(arr->Index(1)->AllEqual());
EXPECT_FALSE(arr->Index(1)->AnyZero());
EXPECT_FALSE(arr->Index(1)->AllZero());
- EXPECT_FALSE(arr->Index(2)->AllEqual());
EXPECT_FALSE(arr->Index(2)->AnyZero());
EXPECT_FALSE(arr->Index(2)->AllZero());
@@ -1799,26 +1600,21 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<type::F32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 10_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 20_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 30_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<f32>(), 40_f);
@@ -1837,7 +1633,6 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<type::Vector>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<f32>(), 1_f);
@@ -1866,26 +1661,21 @@
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Struct>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<f32>(), 1_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<f32>(), 2_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<f32>(), 3_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<f32>(), 4_f);
@@ -1914,7 +1704,6 @@
EXPECT_EQ(str->Members().Length(), 5u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
@@ -1930,7 +1719,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(4)->ValueAs<bool>(), false);
for (size_t i = 0; i < str->Members().Length(); ++i) {
- EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(i)->AllZero());
}
@@ -1962,12 +1750,10 @@
ASSERT_NE(str, nullptr);
EXPECT_EQ(str->Members().Length(), 1u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
auto* inner_struct = sem->ConstantValue()->Index(0);
- EXPECT_FALSE(inner_struct->AllEqual());
EXPECT_TRUE(inner_struct->AnyZero());
EXPECT_TRUE(inner_struct->AllZero());
@@ -1983,7 +1769,6 @@
EXPECT_EQ(inner_struct->Index(4)->ValueAs<bool>(), false);
for (size_t i = 0; i < str->Members().Length(); ++i) {
- EXPECT_TRUE(inner_struct->Index(i)->AllEqual());
EXPECT_TRUE(inner_struct->Index(i)->AnyZero());
EXPECT_TRUE(inner_struct->Index(i)->AllZero());
}
@@ -2004,23 +1789,19 @@
EXPECT_EQ(str->Members().Length(), 3u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::I32>());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::I32>());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->Type()->Is<type::I32>());
@@ -2049,35 +1830,29 @@
EXPECT_EQ(str->Members().Length(), 5u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::I32>());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::U32>());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<u32>(), 0_u);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->Type()->Is<type::F32>());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->Type()->Is<type::F16>());
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->Type()->Is<type::Bool>());
@@ -2102,11 +1877,9 @@
EXPECT_EQ(str->Members().Length(), 3u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::Vector>());
@@ -2116,7 +1889,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<f32>(), 0._f);
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::Vector>());
@@ -2126,7 +1898,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<f32>(), 0._f);
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->Type()->Is<type::Vector>());
@@ -2159,11 +1930,9 @@
EXPECT_EQ(str->Members().Length(), 5u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::Vector>());
@@ -2172,7 +1941,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<i32>(), 0_i);
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<i32>(), 0_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::Vector>());
@@ -2182,7 +1950,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<u32>(), 0_u);
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<u32>(), 0_u);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->Type()->Is<type::Vector>());
@@ -2193,7 +1960,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(2)->ValueAs<f32>(), 0._f);
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(3)->ValueAs<f32>(), 0._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->Type()->Is<type::Vector>());
@@ -2203,7 +1969,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(3)->Index(1)->ValueAs<f16>(), 0._h);
EXPECT_EQ(sem->ConstantValue()->Index(3)->Index(2)->ValueAs<f16>(), 0._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->Type()->Is<type::Vector>());
@@ -2236,11 +2001,9 @@
EXPECT_EQ(str->Members().Length(), 2u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->AllZero());
- EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<sem::Struct>());
@@ -2248,7 +2011,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<u32>(), 0_u);
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 0_f);
- EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<sem::Struct>());
@@ -2279,35 +2041,29 @@
EXPECT_EQ(str->Members().Length(), 5u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::I32>());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<i32>(), 1_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::U32>());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<u32>(), 2_u);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->Type()->Is<type::F32>());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 3._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->Type()->Is<type::F16>());
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<f16>(), 4._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->Type()->Is<type::Bool>());
@@ -2337,11 +2093,9 @@
EXPECT_EQ(str->Members().Length(), 5u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::Vector>());
@@ -2350,7 +2104,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<i32>(), 1_i);
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<i32>(), 1_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::Vector>());
@@ -2360,7 +2113,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<u32>(), 2_u);
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<u32>(), 2_u);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->Type()->Is<type::Vector>());
@@ -2371,7 +2123,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(2)->ValueAs<f32>(), 3._f);
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(3)->ValueAs<f32>(), 3._f);
- EXPECT_TRUE(sem->ConstantValue()->Index(3)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(3)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(3)->Type()->Is<type::Vector>());
@@ -2381,7 +2132,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(3)->Index(1)->ValueAs<f16>(), 4._h);
EXPECT_EQ(sem->ConstantValue()->Index(3)->Index(2)->ValueAs<f16>(), 4._h);
- EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(4)->Type()->Is<type::Vector>());
@@ -2415,11 +2165,9 @@
EXPECT_EQ(str->Members().Length(), 2u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<sem::Struct>());
@@ -2427,7 +2175,6 @@
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<u32>(), 2_u);
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 3_f);
- EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<sem::Struct>());
@@ -2454,18 +2201,15 @@
EXPECT_EQ(str->Members().Length(), 2u);
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::Array>());
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<i32>(), 1_i);
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<u32>(), 2_i);
- EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::Array>());
diff --git a/src/tint/resolver/const_eval_conversion_test.cc b/src/tint/resolver/const_eval_conversion_test.cc
index 92af2de..350afb2 100644
--- a/src/tint/resolver/const_eval_conversion_test.cc
+++ b/src/tint/resolver/const_eval_conversion_test.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include "src/tint/resolver/const_eval_test.h"
+#include "src/tint/sem/materialize.h"
using namespace tint::number_suffixes; // NOLINT
@@ -235,21 +236,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3);
@@ -268,21 +265,17 @@
EXPECT_TRUE(vec->type()->Is<type::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 10.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 20.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 30.f);
@@ -303,21 +296,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 1_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 2_i);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), 3_i);
@@ -338,21 +327,17 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 10.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 20.f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 30.f);
@@ -371,21 +356,17 @@
EXPECT_TRUE(vec->type()->Is<type::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), i32::Highest());
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), i32::Lowest());
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), i32::Highest());
@@ -404,21 +385,17 @@
EXPECT_TRUE(vec->type()->Is<type::U32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), u32::Highest());
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), u32::Lowest());
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AInt>(), u32::Highest());
@@ -449,28 +426,69 @@
EXPECT_TRUE(vec->type()->Is<type::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 0.0);
EXPECT_FALSE(std::signbit(sem->ConstantValue()->Index(0)->ValueAs<AFloat>().value));
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), -0.0);
EXPECT_TRUE(std::signbit(sem->ConstantValue()->Index(1)->ValueAs<AFloat>().value));
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<AFloat>(), 0.0);
EXPECT_FALSE(std::signbit(sem->ConstantValue()->Index(2)->ValueAs<AFloat>().value));
}
+TEST_F(ResolverConstEvalTest, StructAbstractSplat_to_StructDifferentTypes) {
+ // fn f() {
+ // const c = modf(4.0);
+ // var v = c;
+ // }
+ auto* expr_c = Call(builtin::Function::kModf, 0_a);
+ auto* materialized = Expr("c");
+ WrapInFunction(Decl(Const("c", expr_c)), Decl(Var("v", materialized)));
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* c = Sem().Get(expr_c);
+ ASSERT_NE(c, nullptr);
+ EXPECT_TRUE(c->ConstantValue()->Is<constant::Splat>());
+ EXPECT_TRUE(c->ConstantValue()->AnyZero());
+ EXPECT_TRUE(c->ConstantValue()->AllZero());
+
+ EXPECT_TRUE(c->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_TRUE(c->ConstantValue()->Index(0)->AllZero());
+ EXPECT_TRUE(c->ConstantValue()->Index(0)->Type()->Is<type::AbstractFloat>());
+ EXPECT_EQ(c->ConstantValue()->Index(0)->ValueAs<AFloat>(), 0_f);
+
+ EXPECT_TRUE(c->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_TRUE(c->ConstantValue()->Index(1)->AllZero());
+ EXPECT_TRUE(c->ConstantValue()->Index(1)->Type()->Is<type::AbstractFloat>());
+ EXPECT_EQ(c->ConstantValue()->Index(1)->ValueAs<AFloat>(), 0_a);
+
+ auto* v = Sem().GetVal(materialized);
+ ASSERT_NE(v, nullptr);
+ EXPECT_TRUE(v->Is<sem::Materialize>());
+ EXPECT_TRUE(v->ConstantValue()->Is<constant::Splat>());
+ EXPECT_TRUE(v->ConstantValue()->AnyZero());
+ EXPECT_TRUE(v->ConstantValue()->AllZero());
+
+ EXPECT_TRUE(v->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_TRUE(v->ConstantValue()->Index(0)->AllZero());
+ EXPECT_TRUE(v->ConstantValue()->Index(0)->Type()->Is<type::F32>());
+ EXPECT_EQ(v->ConstantValue()->Index(0)->ValueAs<f32>(), 0_f);
+
+ EXPECT_TRUE(v->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_TRUE(v->ConstantValue()->Index(1)->AllZero());
+ EXPECT_TRUE(v->ConstantValue()->Index(1)->Type()->Is<type::F32>());
+ EXPECT_EQ(v->ConstantValue()->Index(1)->ValueAs<f32>(), 0_f);
+}
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/resolver/const_eval_indexing_test.cc b/src/tint/resolver/const_eval_indexing_test.cc
index 4d8c8cb..d311d30 100644
--- a/src/tint/resolver/const_eval_indexing_test.cc
+++ b/src/tint/resolver/const_eval_indexing_test.cc
@@ -29,7 +29,6 @@
ASSERT_NE(sem, nullptr);
ASSERT_TRUE(sem->Type()->Is<type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<i32>(), 3_i);
@@ -133,7 +132,6 @@
ASSERT_NE(sem, nullptr);
ASSERT_TRUE(sem->Type()->Is<type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<i32>(), 2_i);
@@ -152,12 +150,10 @@
EXPECT_EQ(vec->Width(), 2u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 3._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 1._a);
@@ -174,7 +170,6 @@
ASSERT_NE(sem, nullptr);
ASSERT_TRUE(sem->Type()->Is<type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->AllZero());
EXPECT_EQ(sem->ConstantValue()->ValueAs<i32>(), 2_i);
@@ -194,12 +189,10 @@
EXPECT_EQ(vec->Width(), 2u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 5._a);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 6._a);
@@ -241,17 +234,14 @@
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
- EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<f32>(), 4_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<f32>(), 5_f);
- EXPECT_TRUE(sem->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(sem->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(sem->ConstantValue()->Index(2)->ValueAs<f32>(), 6_f);
@@ -310,36 +300,29 @@
EXPECT_EQ(ty->columns(), 2u);
EXPECT_EQ(ty->rows(), 3u);
EXPECT_EQ(mat->ConstantValue()->Type(), mat->Type());
- EXPECT_FALSE(mat->ConstantValue()->AllEqual());
EXPECT_TRUE(mat->ConstantValue()->AnyZero());
EXPECT_FALSE(mat->ConstantValue()->AllZero());
- EXPECT_TRUE(mat->ConstantValue()->Index(0)->Index(0)->AllEqual());
EXPECT_FALSE(mat->ConstantValue()->Index(0)->Index(0)->AnyZero());
EXPECT_FALSE(mat->ConstantValue()->Index(0)->Index(0)->AllZero());
EXPECT_EQ(mat->ConstantValue()->Index(0)->Index(0)->ValueAs<f32>(), 7_f);
- EXPECT_TRUE(mat->ConstantValue()->Index(0)->Index(1)->AllEqual());
EXPECT_TRUE(mat->ConstantValue()->Index(0)->Index(1)->AnyZero());
EXPECT_TRUE(mat->ConstantValue()->Index(0)->Index(1)->AllZero());
EXPECT_EQ(mat->ConstantValue()->Index(0)->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(mat->ConstantValue()->Index(0)->Index(2)->AllEqual());
EXPECT_FALSE(mat->ConstantValue()->Index(0)->Index(2)->AnyZero());
EXPECT_FALSE(mat->ConstantValue()->Index(0)->Index(2)->AllZero());
EXPECT_EQ(mat->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 9_f);
- EXPECT_TRUE(mat->ConstantValue()->Index(1)->Index(0)->AllEqual());
EXPECT_FALSE(mat->ConstantValue()->Index(1)->Index(0)->AnyZero());
EXPECT_FALSE(mat->ConstantValue()->Index(1)->Index(0)->AllZero());
EXPECT_EQ(mat->ConstantValue()->Index(1)->Index(0)->ValueAs<f32>(), 10_f);
- EXPECT_TRUE(mat->ConstantValue()->Index(1)->Index(1)->AllEqual());
EXPECT_FALSE(mat->ConstantValue()->Index(1)->Index(1)->AnyZero());
EXPECT_FALSE(mat->ConstantValue()->Index(1)->Index(1)->AllZero());
EXPECT_EQ(mat->ConstantValue()->Index(1)->Index(1)->ValueAs<f32>(), 11_f);
- EXPECT_TRUE(mat->ConstantValue()->Index(1)->Index(2)->AllEqual());
EXPECT_FALSE(mat->ConstantValue()->Index(1)->Index(2)->AnyZero());
EXPECT_FALSE(mat->ConstantValue()->Index(1)->Index(2)->AllZero());
EXPECT_EQ(mat->ConstantValue()->Index(1)->Index(2)->ValueAs<f32>(), 12_f);
@@ -352,21 +335,17 @@
EXPECT_TRUE(ty->type()->Is<type::F32>());
EXPECT_EQ(ty->Width(), 3u);
EXPECT_EQ(vec->ConstantValue()->Type(), vec->Type());
- EXPECT_FALSE(vec->ConstantValue()->AllEqual());
EXPECT_TRUE(vec->ConstantValue()->AnyZero());
EXPECT_FALSE(vec->ConstantValue()->AllZero());
- EXPECT_TRUE(vec->ConstantValue()->Index(0)->AllEqual());
EXPECT_FALSE(vec->ConstantValue()->Index(0)->AnyZero());
EXPECT_FALSE(vec->ConstantValue()->Index(0)->AllZero());
EXPECT_EQ(vec->ConstantValue()->Index(0)->ValueAs<f32>(), 7_f);
- EXPECT_TRUE(vec->ConstantValue()->Index(1)->AllEqual());
EXPECT_TRUE(vec->ConstantValue()->Index(1)->AnyZero());
EXPECT_TRUE(vec->ConstantValue()->Index(1)->AllZero());
EXPECT_EQ(vec->ConstantValue()->Index(1)->ValueAs<f32>(), 0_f);
- EXPECT_TRUE(vec->ConstantValue()->Index(2)->AllEqual());
EXPECT_FALSE(vec->ConstantValue()->Index(2)->AnyZero());
EXPECT_FALSE(vec->ConstantValue()->Index(2)->AllZero());
EXPECT_EQ(vec->ConstantValue()->Index(2)->ValueAs<f32>(), 9_f);
@@ -376,7 +355,6 @@
EXPECT_NE(f, nullptr);
EXPECT_TRUE(f->Type()->Is<type::F32>());
EXPECT_EQ(f->ConstantValue()->Type(), f->Type());
- EXPECT_TRUE(f->ConstantValue()->AllEqual());
EXPECT_FALSE(f->ConstantValue()->AnyZero());
EXPECT_FALSE(f->ConstantValue()->AllZero());
EXPECT_EQ(f->ConstantValue()->ValueAs<f32>(), 9_f);
diff --git a/src/tint/resolver/const_eval_member_access_test.cc b/src/tint/resolver/const_eval_member_access_test.cc
index 4fcba8b..9a74e6c 100644
--- a/src/tint/resolver/const_eval_member_access_test.cc
+++ b/src/tint/resolver/const_eval_member_access_test.cc
@@ -46,13 +46,11 @@
EXPECT_EQ(str->Members().Length(), 2u);
ASSERT_NE(outer->ConstantValue(), nullptr);
EXPECT_TYPE(outer->ConstantValue()->Type(), outer->Type());
- EXPECT_FALSE(outer->ConstantValue()->AllEqual());
EXPECT_TRUE(outer->ConstantValue()->AnyZero());
EXPECT_FALSE(outer->ConstantValue()->AllZero());
auto* o1 = Sem().Get(o1_expr);
ASSERT_NE(o1->ConstantValue(), nullptr);
- EXPECT_FALSE(o1->ConstantValue()->AllEqual());
EXPECT_FALSE(o1->ConstantValue()->AnyZero());
EXPECT_FALSE(o1->ConstantValue()->AllZero());
EXPECT_TRUE(o1->ConstantValue()->Type()->Is<sem::Struct>());
@@ -63,7 +61,6 @@
auto* i2 = Sem().Get(i2_expr);
ASSERT_NE(i2->ConstantValue(), nullptr);
- EXPECT_TRUE(i2->ConstantValue()->AllEqual());
EXPECT_FALSE(i2->ConstantValue()->AnyZero());
EXPECT_FALSE(i2->ConstantValue()->AllZero());
EXPECT_TRUE(i2->ConstantValue()->Type()->Is<type::U32>());
@@ -85,7 +82,6 @@
EXPECT_TYPE(cv->Type(), sem->Type());
EXPECT_TRUE(cv->Index(0)->Type()->Is<type::Vector>());
EXPECT_TRUE(cv->Index(0)->Index(0)->Type()->Is<type::AbstractFloat>());
- EXPECT_FALSE(cv->AllEqual());
EXPECT_FALSE(cv->AnyZero());
EXPECT_FALSE(cv->AllZero());
auto* c0 = cv->Index(0);
@@ -124,7 +120,6 @@
EXPECT_TYPE(cv->Type(), sem->Type());
EXPECT_TRUE(cv->Index(0)->Type()->Is<type::Vector>());
EXPECT_TRUE(cv->Index(0)->Index(0)->Type()->Is<type::AbstractFloat>());
- EXPECT_FALSE(cv->AllEqual());
EXPECT_FALSE(cv->AnyZero());
EXPECT_FALSE(cv->AllZero());
@@ -201,7 +196,6 @@
EXPECT_TYPE(cv->Type(), sem->Type());
EXPECT_TRUE(cv->Index(0)->Type()->Is<type::Vector>());
EXPECT_TRUE(cv->Index(0)->Index(0)->Type()->Is<type::F32>());
- EXPECT_FALSE(cv->AllEqual());
EXPECT_FALSE(cv->AnyZero());
EXPECT_FALSE(cv->AllZero());
diff --git a/src/tint/resolver/const_eval_test.h b/src/tint/resolver/const_eval_test.h
index de25b20..8cbea04 100644
--- a/src/tint/resolver/const_eval_test.h
+++ b/src/tint/resolver/const_eval_test.h
@@ -23,6 +23,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/tint/resolver/resolver_test_helper.h"
+#include "src/tint/switch.h"
#include "src/tint/type/test_helper.h"
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index f718a46..47e691c 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -60,6 +60,7 @@
#include "src/tint/builtin/builtin_value.h"
#include "src/tint/scope_stack.h"
#include "src/tint/sem/builtin.h"
+#include "src/tint/switch.h"
#include "src/tint/symbol_table.h"
#include "src/tint/utils/block_allocator.h"
#include "src/tint/utils/compiler_macros.h"
@@ -440,7 +441,8 @@
auto* resolved = scope_stack_.Get(to);
if (!resolved) {
auto s = symbols_.NameFor(to);
- if (auto builtin_fn = sem::ParseBuiltinType(s); builtin_fn != sem::BuiltinType::kNone) {
+ if (auto builtin_fn = builtin::ParseFunction(s);
+ builtin_fn != builtin::Function::kNone) {
graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_fn));
return;
}
@@ -838,7 +840,7 @@
return "<unknown>";
});
}
- if (auto builtin_fn = BuiltinFunction(); builtin_fn != sem::BuiltinType::kNone) {
+ if (auto builtin_fn = BuiltinFunction(); builtin_fn != builtin::Function::kNone) {
return "builtin function '" + utils::ToString(builtin_fn) + "'";
}
if (auto builtin_ty = BuiltinType(); builtin_ty != builtin::Builtin::kUndefined) {
diff --git a/src/tint/resolver/dependency_graph.h b/src/tint/resolver/dependency_graph.h
index 429a47a..f58b2a2 100644
--- a/src/tint/resolver/dependency_graph.h
+++ b/src/tint/resolver/dependency_graph.h
@@ -22,11 +22,11 @@
#include "src/tint/builtin/access.h"
#include "src/tint/builtin/builtin.h"
#include "src/tint/builtin/builtin_value.h"
+#include "src/tint/builtin/function.h"
#include "src/tint/builtin/interpolation_sampling.h"
#include "src/tint/builtin/interpolation_type.h"
#include "src/tint/builtin/texel_format.h"
#include "src/tint/diagnostic/diagnostic.h"
-#include "src/tint/sem/builtin_type.h"
#include "src/tint/symbol_table.h"
#include "src/tint/utils/hashmap.h"
@@ -44,7 +44,7 @@
/// - const ast::TypeDecl* (as const ast::Node*)
/// - const ast::Variable* (as const ast::Node*)
/// - const ast::Function* (as const ast::Node*)
-/// - sem::BuiltinType
+/// - builtin::Function
/// - builtin::Access
/// - builtin::AddressSpace
/// - builtin::Builtin
@@ -75,13 +75,13 @@
return nullptr;
}
- /// @return the builtin function if the ResolvedIdentifier holds sem::BuiltinType, otherwise
- /// sem::BuiltinType::kNone
- sem::BuiltinType BuiltinFunction() const {
- if (auto n = std::get_if<sem::BuiltinType>(&value_)) {
+ /// @return the builtin function if the ResolvedIdentifier holds builtin::Function, otherwise
+ /// builtin::Function::kNone
+ builtin::Function BuiltinFunction() const {
+ if (auto n = std::get_if<builtin::Function>(&value_)) {
return *n;
}
- return sem::BuiltinType::kNone;
+ return builtin::Function::kNone;
}
/// @return the access if the ResolvedIdentifier holds builtin::Access, otherwise
@@ -172,7 +172,7 @@
private:
std::variant<UnresolvedIdentifier,
const ast::Node*,
- sem::BuiltinType,
+ builtin::Function,
builtin::Access,
builtin::AddressSpace,
builtin::Builtin,
diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc
index c81c336..c9ce3b8 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -1181,7 +1181,7 @@
namespace resolve_to_builtin_func {
using ResolverDependencyGraphResolveToBuiltinFunc =
- ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, sem::BuiltinType>>;
+ ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, builtin::Function>>;
TEST_P(ResolverDependencyGraphResolveToBuiltinFunc, Resolve) {
const auto use = std::get<0>(GetParam());
@@ -1200,17 +1200,17 @@
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToBuiltinFunc,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
- testing::ValuesIn(sem::kBuiltinTypes)));
+ testing::ValuesIn(builtin::kFunctions)));
INSTANTIATE_TEST_SUITE_P(Values,
ResolverDependencyGraphResolveToBuiltinFunc,
testing::Combine(testing::ValuesIn(kValueUseKinds),
- testing::ValuesIn(sem::kBuiltinTypes)));
+ testing::ValuesIn(builtin::kFunctions)));
INSTANTIATE_TEST_SUITE_P(Functions,
ResolverDependencyGraphResolveToBuiltinFunc,
testing::Combine(testing::ValuesIn(kFuncUseKinds),
- testing::ValuesIn(sem::kBuiltinTypes)));
+ testing::ValuesIn(builtin::kFunctions)));
} // namespace resolve_to_builtin_func
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index e8fe271..18e2f81 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -24,6 +24,7 @@
#include "src/tint/sem/pipeline_stage_set.h"
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
+#include "src/tint/switch.h"
#include "src/tint/type/abstract_float.h"
#include "src/tint/type/abstract_int.h"
#include "src/tint/type/abstract_numeric.h"
@@ -1096,7 +1097,7 @@
public:
explicit Impl(ProgramBuilder& builder);
- Builtin Lookup(sem::BuiltinType builtin_type,
+ Builtin Lookup(builtin::Function builtin_type,
utils::VectorRef<const type::Type*> args,
sem::EvaluationStage earliest_eval_stage,
const Source& source) override;
@@ -1264,11 +1265,11 @@
Impl::Impl(ProgramBuilder& b) : builder(b) {}
-Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
+Impl::Builtin Impl::Lookup(builtin::Function builtin_type,
utils::VectorRef<const type::Type*> args,
sem::EvaluationStage earliest_eval_stage,
const Source& source) {
- const char* intrinsic_name = sem::str(builtin_type);
+ const char* intrinsic_name = builtin::str(builtin_type);
// Generates an error when no overloads match the provided arguments
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
diff --git a/src/tint/resolver/intrinsic_table.h b/src/tint/resolver/intrinsic_table.h
index 515e839..78e2e7a 100644
--- a/src/tint/resolver/intrinsic_table.h
+++ b/src/tint/resolver/intrinsic_table.h
@@ -92,7 +92,7 @@
/// after shader creation time (sem::EvaluationStage::kConstant).
/// @param source the source of the builtin call
/// @return the semantic builtin if found, otherwise nullptr
- virtual Builtin Lookup(sem::BuiltinType type,
+ virtual Builtin Lookup(builtin::Function type,
utils::VectorRef<const type::Type*> args,
sem::EvaluationStage earliest_eval_stage,
const Source& source) = 0;
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index 1683d27..895d489 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -7748,102 +7748,102 @@
{
/* [931] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[235],
+ /* matcher indices */ &kMatcherIndices[130],
},
{
/* [932] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[58],
+ /* matcher indices */ &kMatcherIndices[235],
},
{
/* [933] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[116],
+ /* matcher indices */ &kMatcherIndices[237],
},
{
/* [934] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[118],
+ /* matcher indices */ &kMatcherIndices[58],
},
{
/* [935] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[122],
+ /* matcher indices */ &kMatcherIndices[116],
},
{
/* [936] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[124],
+ /* matcher indices */ &kMatcherIndices[118],
},
{
/* [937] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[128],
+ /* matcher indices */ &kMatcherIndices[122],
},
{
/* [938] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[130],
+ /* matcher indices */ &kMatcherIndices[124],
},
{
/* [939] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[234],
+ /* matcher indices */ &kMatcherIndices[128],
},
{
/* [940] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[235],
+ /* matcher indices */ &kMatcherIndices[130],
},
{
/* [941] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[236],
+ /* matcher indices */ &kMatcherIndices[234],
},
{
/* [942] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[237],
+ /* matcher indices */ &kMatcherIndices[235],
},
{
/* [943] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[132],
+ /* matcher indices */ &kMatcherIndices[236],
},
{
/* [944] */
/* usage */ ParameterUsage::kTexture,
- /* matcher indices */ &kMatcherIndices[238],
+ /* matcher indices */ &kMatcherIndices[237],
},
{
/* [945] */
- /* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[5],
+ /* usage */ ParameterUsage::kTexture,
+ /* matcher indices */ &kMatcherIndices[132],
},
{
/* [946] */
- /* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[3],
+ /* usage */ ParameterUsage::kTexture,
+ /* matcher indices */ &kMatcherIndices[238],
},
{
/* [947] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[39],
+ /* matcher indices */ &kMatcherIndices[5],
},
{
/* [948] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[37],
+ /* matcher indices */ &kMatcherIndices[3],
},
{
/* [949] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[3],
+ /* matcher indices */ &kMatcherIndices[39],
},
{
/* [950] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[34],
+ /* matcher indices */ &kMatcherIndices[37],
},
{
/* [951] */
@@ -7858,17 +7858,17 @@
{
/* [953] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[9],
+ /* matcher indices */ &kMatcherIndices[3],
},
{
/* [954] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[3],
+ /* matcher indices */ &kMatcherIndices[34],
},
{
/* [955] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[105],
+ /* matcher indices */ &kMatcherIndices[9],
},
{
/* [956] */
@@ -7878,7 +7878,7 @@
{
/* [957] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[42],
+ /* matcher indices */ &kMatcherIndices[105],
},
{
/* [958] */
@@ -7888,7 +7888,7 @@
{
/* [959] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[1],
+ /* matcher indices */ &kMatcherIndices[42],
},
{
/* [960] */
@@ -7898,7 +7898,7 @@
{
/* [961] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[39],
+ /* matcher indices */ &kMatcherIndices[1],
},
{
/* [962] */
@@ -7908,7 +7908,7 @@
{
/* [963] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[23],
+ /* matcher indices */ &kMatcherIndices[39],
},
{
/* [964] */
@@ -7918,12 +7918,12 @@
{
/* [965] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[158],
+ /* matcher indices */ &kMatcherIndices[23],
},
{
/* [966] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[158],
+ /* matcher indices */ &kMatcherIndices[3],
},
{
/* [967] */
@@ -7943,22 +7943,22 @@
{
/* [970] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[106],
+ /* matcher indices */ &kMatcherIndices[158],
},
{
/* [971] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[3],
+ /* matcher indices */ &kMatcherIndices[158],
},
{
/* [972] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[160],
+ /* matcher indices */ &kMatcherIndices[106],
},
{
/* [973] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[160],
+ /* matcher indices */ &kMatcherIndices[3],
},
{
/* [974] */
@@ -7978,22 +7978,22 @@
{
/* [977] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[134],
+ /* matcher indices */ &kMatcherIndices[160],
},
{
/* [978] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[3],
+ /* matcher indices */ &kMatcherIndices[160],
},
{
/* [979] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[172],
+ /* matcher indices */ &kMatcherIndices[134],
},
{
/* [980] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[172],
+ /* matcher indices */ &kMatcherIndices[3],
},
{
/* [981] */
@@ -8013,141 +8013,151 @@
{
/* [984] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[178],
+ /* matcher indices */ &kMatcherIndices[172],
},
{
/* [985] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[180],
+ /* matcher indices */ &kMatcherIndices[172],
},
{
/* [986] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[182],
+ /* matcher indices */ &kMatcherIndices[178],
},
{
/* [987] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[184],
+ /* matcher indices */ &kMatcherIndices[180],
},
{
/* [988] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[186],
+ /* matcher indices */ &kMatcherIndices[182],
},
{
/* [989] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[188],
+ /* matcher indices */ &kMatcherIndices[184],
},
{
/* [990] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[190],
+ /* matcher indices */ &kMatcherIndices[186],
},
{
/* [991] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[192],
+ /* matcher indices */ &kMatcherIndices[188],
},
{
/* [992] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[194],
+ /* matcher indices */ &kMatcherIndices[190],
},
{
/* [993] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[196],
+ /* matcher indices */ &kMatcherIndices[192],
},
{
/* [994] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[198],
+ /* matcher indices */ &kMatcherIndices[194],
},
{
/* [995] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[200],
+ /* matcher indices */ &kMatcherIndices[196],
},
{
/* [996] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[202],
+ /* matcher indices */ &kMatcherIndices[198],
},
{
/* [997] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[204],
+ /* matcher indices */ &kMatcherIndices[200],
},
{
/* [998] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[206],
+ /* matcher indices */ &kMatcherIndices[202],
},
{
/* [999] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[208],
+ /* matcher indices */ &kMatcherIndices[204],
},
{
/* [1000] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[210],
+ /* matcher indices */ &kMatcherIndices[206],
},
{
/* [1001] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[212],
+ /* matcher indices */ &kMatcherIndices[208],
},
{
/* [1002] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[214],
+ /* matcher indices */ &kMatcherIndices[210],
},
{
/* [1003] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[216],
+ /* matcher indices */ &kMatcherIndices[212],
},
{
/* [1004] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[218],
+ /* matcher indices */ &kMatcherIndices[214],
},
{
/* [1005] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[220],
+ /* matcher indices */ &kMatcherIndices[216],
},
{
/* [1006] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[222],
+ /* matcher indices */ &kMatcherIndices[218],
},
{
/* [1007] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[224],
+ /* matcher indices */ &kMatcherIndices[220],
},
{
/* [1008] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[226],
+ /* matcher indices */ &kMatcherIndices[222],
},
{
/* [1009] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[228],
+ /* matcher indices */ &kMatcherIndices[224],
},
{
/* [1010] */
/* usage */ ParameterUsage::kNone,
- /* matcher indices */ &kMatcherIndices[230],
+ /* matcher indices */ &kMatcherIndices[226],
},
{
/* [1011] */
/* usage */ ParameterUsage::kNone,
+ /* matcher indices */ &kMatcherIndices[228],
+ },
+ {
+ /* [1012] */
+ /* usage */ ParameterUsage::kNone,
+ /* matcher indices */ &kMatcherIndices[230],
+ },
+ {
+ /* [1013] */
+ /* usage */ ParameterUsage::kNone,
/* matcher indices */ &kMatcherIndices[106],
},
};
@@ -8910,7 +8920,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[36],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[134],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -8922,7 +8932,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[27],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[977],
+ /* parameters */ &kParameters[979],
/* return matcher indices */ &kMatcherIndices[134],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -8934,7 +8944,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[27],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[978],
+ /* parameters */ &kParameters[980],
/* return matcher indices */ &kMatcherIndices[134],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::VecSplat,
@@ -9030,7 +9040,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[979],
+ /* parameters */ &kParameters[981],
/* return matcher indices */ &kMatcherIndices[114],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9042,7 +9052,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[980],
+ /* parameters */ &kParameters[982],
/* return matcher indices */ &kMatcherIndices[174],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9054,7 +9064,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[18],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[981],
+ /* parameters */ &kParameters[983],
/* return matcher indices */ &kMatcherIndices[154],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9066,7 +9076,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[20],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[982],
+ /* parameters */ &kParameters[984],
/* return matcher indices */ &kMatcherIndices[156],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9078,7 +9088,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[22],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[983],
+ /* parameters */ &kParameters[985],
/* return matcher indices */ &kMatcherIndices[176],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9546,7 +9556,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[36],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[106],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -9558,7 +9568,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[27],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[970],
+ /* parameters */ &kParameters[972],
/* return matcher indices */ &kMatcherIndices[106],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -9570,7 +9580,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[27],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[971],
+ /* parameters */ &kParameters[973],
/* return matcher indices */ &kMatcherIndices[106],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::VecSplat,
@@ -9618,7 +9628,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[972],
+ /* parameters */ &kParameters[974],
/* return matcher indices */ &kMatcherIndices[138],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9630,7 +9640,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[973],
+ /* parameters */ &kParameters[975],
/* return matcher indices */ &kMatcherIndices[168],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9642,7 +9652,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[18],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[974],
+ /* parameters */ &kParameters[976],
/* return matcher indices */ &kMatcherIndices[148],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9654,7 +9664,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[20],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[975],
+ /* parameters */ &kParameters[977],
/* return matcher indices */ &kMatcherIndices[126],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9666,7 +9676,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[22],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[976],
+ /* parameters */ &kParameters[978],
/* return matcher indices */ &kMatcherIndices[170],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -9678,7 +9688,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[933],
+ /* parameters */ &kParameters[935],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9690,7 +9700,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[934],
+ /* parameters */ &kParameters[936],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9702,7 +9712,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[935],
+ /* parameters */ &kParameters[937],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9714,7 +9724,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[936],
+ /* parameters */ &kParameters[938],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9726,7 +9736,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[937],
+ /* parameters */ &kParameters[939],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9738,7 +9748,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[938],
+ /* parameters */ &kParameters[940],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9750,7 +9760,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[939],
+ /* parameters */ &kParameters[941],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9762,7 +9772,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[940],
+ /* parameters */ &kParameters[942],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9774,7 +9784,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[941],
+ /* parameters */ &kParameters[943],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -9786,7 +9796,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[942],
+ /* parameters */ &kParameters[944],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
@@ -10014,7 +10024,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[36],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[23],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10026,7 +10036,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[27],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[963],
+ /* parameters */ &kParameters[965],
/* return matcher indices */ &kMatcherIndices[23],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10038,7 +10048,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[27],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[964],
+ /* parameters */ &kParameters[966],
/* return matcher indices */ &kMatcherIndices[23],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::VecSplat,
@@ -10062,7 +10072,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[965],
+ /* parameters */ &kParameters[967],
/* return matcher indices */ &kMatcherIndices[112],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10074,7 +10084,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[966],
+ /* parameters */ &kParameters[968],
/* return matcher indices */ &kMatcherIndices[164],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10086,7 +10096,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[18],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[967],
+ /* parameters */ &kParameters[969],
/* return matcher indices */ &kMatcherIndices[136],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10098,7 +10108,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[20],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[968],
+ /* parameters */ &kParameters[970],
/* return matcher indices */ &kMatcherIndices[120],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10110,7 +10120,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[22],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[969],
+ /* parameters */ &kParameters[971],
/* return matcher indices */ &kMatcherIndices[166],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10530,7 +10540,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[178],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10542,7 +10552,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[984],
+ /* parameters */ &kParameters[986],
/* return matcher indices */ &kMatcherIndices[178],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10578,7 +10588,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[985],
+ /* parameters */ &kParameters[987],
/* return matcher indices */ &kMatcherIndices[182],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10590,7 +10600,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[986],
+ /* parameters */ &kParameters[988],
/* return matcher indices */ &kMatcherIndices[180],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10602,7 +10612,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[184],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10614,7 +10624,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[987],
+ /* parameters */ &kParameters[989],
/* return matcher indices */ &kMatcherIndices[184],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10650,7 +10660,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[988],
+ /* parameters */ &kParameters[990],
/* return matcher indices */ &kMatcherIndices[188],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10662,7 +10672,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[989],
+ /* parameters */ &kParameters[991],
/* return matcher indices */ &kMatcherIndices[186],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10674,7 +10684,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[190],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10686,7 +10696,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[990],
+ /* parameters */ &kParameters[992],
/* return matcher indices */ &kMatcherIndices[190],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10722,7 +10732,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[991],
+ /* parameters */ &kParameters[993],
/* return matcher indices */ &kMatcherIndices[194],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10734,7 +10744,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[992],
+ /* parameters */ &kParameters[994],
/* return matcher indices */ &kMatcherIndices[192],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10746,7 +10756,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[196],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10758,7 +10768,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[993],
+ /* parameters */ &kParameters[995],
/* return matcher indices */ &kMatcherIndices[196],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10794,7 +10804,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[994],
+ /* parameters */ &kParameters[996],
/* return matcher indices */ &kMatcherIndices[200],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10806,7 +10816,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[995],
+ /* parameters */ &kParameters[997],
/* return matcher indices */ &kMatcherIndices[198],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10818,7 +10828,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[202],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10830,7 +10840,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[996],
+ /* parameters */ &kParameters[998],
/* return matcher indices */ &kMatcherIndices[202],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10866,7 +10876,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[997],
+ /* parameters */ &kParameters[999],
/* return matcher indices */ &kMatcherIndices[206],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10878,7 +10888,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[998],
+ /* parameters */ &kParameters[1000],
/* return matcher indices */ &kMatcherIndices[204],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10890,7 +10900,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[208],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10902,7 +10912,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[999],
+ /* parameters */ &kParameters[1001],
/* return matcher indices */ &kMatcherIndices[208],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -10938,7 +10948,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1000],
+ /* parameters */ &kParameters[1002],
/* return matcher indices */ &kMatcherIndices[212],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10950,7 +10960,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1001],
+ /* parameters */ &kParameters[1003],
/* return matcher indices */ &kMatcherIndices[210],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -10962,7 +10972,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[214],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -10974,7 +10984,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1002],
+ /* parameters */ &kParameters[1004],
/* return matcher indices */ &kMatcherIndices[214],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -11010,7 +11020,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1003],
+ /* parameters */ &kParameters[1005],
/* return matcher indices */ &kMatcherIndices[218],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -11022,7 +11032,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1004],
+ /* parameters */ &kParameters[1006],
/* return matcher indices */ &kMatcherIndices[216],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -11034,7 +11044,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[220],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -11046,7 +11056,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1005],
+ /* parameters */ &kParameters[1007],
/* return matcher indices */ &kMatcherIndices[220],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -11082,7 +11092,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1006],
+ /* parameters */ &kParameters[1008],
/* return matcher indices */ &kMatcherIndices[224],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -11094,7 +11104,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1007],
+ /* parameters */ &kParameters[1009],
/* return matcher indices */ &kMatcherIndices[222],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -11106,7 +11116,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ &kMatcherIndices[226],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
@@ -11118,7 +11128,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[37],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1008],
+ /* parameters */ &kParameters[1010],
/* return matcher indices */ &kMatcherIndices[226],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
@@ -11154,7 +11164,7 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[16],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1009],
+ /* parameters */ &kParameters[1011],
/* return matcher indices */ &kMatcherIndices[230],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -11166,397 +11176,13 @@
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[14],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1010],
+ /* parameters */ &kParameters[1012],
/* return matcher indices */ &kMatcherIndices[228],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
},
{
/* [231] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[672],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpPlus,
- },
- {
- /* [232] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[674],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpPlus,
- },
- {
- /* [233] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[676],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpPlus,
- },
- {
- /* [234] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[678],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpPlus,
- },
- {
- /* [235] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 2,
- /* template types */ &kTemplateTypes[10],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[680],
- /* return matcher indices */ &kMatcherIndices[14],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpPlus,
- },
- {
- /* [236] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[682],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpMinus,
- },
- {
- /* [237] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[684],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpMinus,
- },
- {
- /* [238] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[686],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpMinus,
- },
- {
- /* [239] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[688],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpMinus,
- },
- {
- /* [240] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 2,
- /* template types */ &kTemplateTypes[10],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[690],
- /* return matcher indices */ &kMatcherIndices[14],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpMinus,
- },
- {
- /* [241] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[710],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpDivide,
- },
- {
- /* [242] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[712],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpDivide,
- },
- {
- /* [243] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[714],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpDivide,
- },
- {
- /* [244] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[716],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpDivide,
- },
- {
- /* [245] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[718],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpModulo,
- },
- {
- /* [246] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[720],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpModulo,
- },
- {
- /* [247] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[722],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpModulo,
- },
- {
- /* [248] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[24],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[724],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpModulo,
- },
- {
- /* [249] */
- /* num parameters */ 2,
- /* num template types */ 0,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[38],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[730],
- /* return matcher indices */ &kMatcherIndices[39],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpAnd,
- },
- {
- /* [250] */
- /* num parameters */ 2,
- /* num template types */ 0,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[38],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[732],
- /* return matcher indices */ &kMatcherIndices[37],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpAnd,
- },
- {
- /* [251] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[29],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[734],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpAnd,
- },
- {
- /* [252] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[29],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[736],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpAnd,
- },
- {
- /* [253] */
- /* num parameters */ 2,
- /* num template types */ 0,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[38],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[738],
- /* return matcher indices */ &kMatcherIndices[39],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpOr,
- },
- {
- /* [254] */
- /* num parameters */ 2,
- /* num template types */ 0,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[38],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[740],
- /* return matcher indices */ &kMatcherIndices[37],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpOr,
- },
- {
- /* [255] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[29],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[742],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpOr,
- },
- {
- /* [256] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[29],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[744],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpOr,
- },
- {
- /* [257] */
- /* num parameters */ 3,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[10],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[468],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::mix,
- },
- {
- /* [258] */
- /* num parameters */ 3,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[10],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[471],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::mix,
- },
- {
- /* [259] */
- /* num parameters */ 3,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[10],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[474],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::mix,
- },
- {
- /* [260] */
- /* num parameters */ 3,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[27],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[480],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::select_bool,
- },
- {
- /* [261] */
- /* num parameters */ 3,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[27],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[483],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::select_bool,
- },
- {
- /* [262] */
- /* num parameters */ 3,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[27],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[486],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::select_boolvec,
- },
- {
- /* [263] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11568,11 +11194,11 @@
/* const eval */ nullptr,
},
{
- /* [264] */
+ /* [232] */
/* num parameters */ 1,
- /* num template types */ 0,
+ /* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[38],
+ /* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[931],
/* return matcher indices */ &kMatcherIndices[105],
@@ -11580,199 +11206,607 @@
/* const eval */ nullptr,
},
{
- /* [265] */
+ /* [233] */
/* num parameters */ 1,
/* num template types */ 0,
- /* num template numbers */ 2,
+ /* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
- /* template numbers */ &kTemplateNumbers[6],
+ /* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[932],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
},
{
- /* [266] */
- /* num parameters */ 0,
+ /* [234] */
+ /* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
- /* return matcher indices */ &kMatcherIndices[9],
- /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::Zero,
+ /* parameters */ &kParameters[933],
+ /* return matcher indices */ &kMatcherIndices[105],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ nullptr,
+ },
+ {
+ /* [235] */
+ /* num parameters */ 1,
+ /* num template types */ 0,
+ /* num template numbers */ 2,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[6],
+ /* parameters */ &kParameters[934],
+ /* return matcher indices */ &kMatcherIndices[105],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ nullptr,
+ },
+ {
+ /* [236] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[672],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpPlus,
+ },
+ {
+ /* [237] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[674],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpPlus,
+ },
+ {
+ /* [238] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[676],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpPlus,
+ },
+ {
+ /* [239] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[678],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpPlus,
+ },
+ {
+ /* [240] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 2,
+ /* template types */ &kTemplateTypes[10],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[680],
+ /* return matcher indices */ &kMatcherIndices[14],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpPlus,
+ },
+ {
+ /* [241] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[682],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpMinus,
+ },
+ {
+ /* [242] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[684],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpMinus,
+ },
+ {
+ /* [243] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[686],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpMinus,
+ },
+ {
+ /* [244] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[688],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpMinus,
+ },
+ {
+ /* [245] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 2,
+ /* template types */ &kTemplateTypes[10],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[690],
+ /* return matcher indices */ &kMatcherIndices[14],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpMinus,
+ },
+ {
+ /* [246] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[710],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpDivide,
+ },
+ {
+ /* [247] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[712],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpDivide,
+ },
+ {
+ /* [248] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[714],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpDivide,
+ },
+ {
+ /* [249] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[716],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpDivide,
+ },
+ {
+ /* [250] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[718],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpModulo,
+ },
+ {
+ /* [251] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[720],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpModulo,
+ },
+ {
+ /* [252] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[722],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpModulo,
+ },
+ {
+ /* [253] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[24],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[724],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpModulo,
+ },
+ {
+ /* [254] */
+ /* num parameters */ 2,
+ /* num template types */ 0,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[730],
+ /* return matcher indices */ &kMatcherIndices[39],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpAnd,
+ },
+ {
+ /* [255] */
+ /* num parameters */ 2,
+ /* num template types */ 0,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[732],
+ /* return matcher indices */ &kMatcherIndices[37],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpAnd,
+ },
+ {
+ /* [256] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[29],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[734],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpAnd,
+ },
+ {
+ /* [257] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[29],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[736],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpAnd,
+ },
+ {
+ /* [258] */
+ /* num parameters */ 2,
+ /* num template types */ 0,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[738],
+ /* return matcher indices */ &kMatcherIndices[39],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpOr,
+ },
+ {
+ /* [259] */
+ /* num parameters */ 2,
+ /* num template types */ 0,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[740],
+ /* return matcher indices */ &kMatcherIndices[37],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpOr,
+ },
+ {
+ /* [260] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[29],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[742],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpOr,
+ },
+ {
+ /* [261] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[29],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[744],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpOr,
+ },
+ {
+ /* [262] */
+ /* num parameters */ 3,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[10],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[468],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::mix,
+ },
+ {
+ /* [263] */
+ /* num parameters */ 3,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[10],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[471],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::mix,
+ },
+ {
+ /* [264] */
+ /* num parameters */ 3,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[10],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[474],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::mix,
+ },
+ {
+ /* [265] */
+ /* num parameters */ 3,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[27],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[480],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::select_bool,
+ },
+ {
+ /* [266] */
+ /* num parameters */ 3,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[27],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[483],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::select_bool,
},
{
/* [267] */
- /* num parameters */ 1,
- /* num template types */ 0,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[38],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[953],
- /* return matcher indices */ &kMatcherIndices[9],
- /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::Identity,
+ /* num parameters */ 3,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[27],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[486],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::select_boolvec,
},
{
/* [268] */
- /* num parameters */ 1,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[31],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[954],
- /* return matcher indices */ &kMatcherIndices[9],
- /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::Conv,
- },
- {
- /* [269] */
/* num parameters */ 0,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
- /* return matcher indices */ &kMatcherIndices[105],
+ /* parameters */ &kParameters[1014],
+ /* return matcher indices */ &kMatcherIndices[9],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
},
{
- /* [270] */
+ /* [269] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[955],
- /* return matcher indices */ &kMatcherIndices[105],
+ /* return matcher indices */ &kMatcherIndices[9],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
},
{
- /* [271] */
+ /* [270] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[32],
+ /* template types */ &kTemplateTypes[31],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[956],
- /* return matcher indices */ &kMatcherIndices[105],
+ /* return matcher indices */ &kMatcherIndices[9],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
},
{
- /* [272] */
+ /* [271] */
/* num parameters */ 0,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
- /* return matcher indices */ &kMatcherIndices[42],
+ /* parameters */ &kParameters[1014],
+ /* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
},
{
- /* [273] */
+ /* [272] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[957],
- /* return matcher indices */ &kMatcherIndices[42],
+ /* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
},
{
- /* [274] */
+ /* [273] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[33],
+ /* template types */ &kTemplateTypes[32],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[958],
- /* return matcher indices */ &kMatcherIndices[42],
+ /* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
},
{
- /* [275] */
+ /* [274] */
/* num parameters */ 0,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
- /* return matcher indices */ &kMatcherIndices[1],
+ /* parameters */ &kParameters[1014],
+ /* return matcher indices */ &kMatcherIndices[42],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
},
{
- /* [276] */
+ /* [275] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[959],
- /* return matcher indices */ &kMatcherIndices[1],
+ /* return matcher indices */ &kMatcherIndices[42],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
},
{
- /* [277] */
+ /* [276] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[34],
+ /* template types */ &kTemplateTypes[33],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[960],
- /* return matcher indices */ &kMatcherIndices[1],
+ /* return matcher indices */ &kMatcherIndices[42],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
},
{
- /* [278] */
+ /* [277] */
/* num parameters */ 0,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
- /* return matcher indices */ &kMatcherIndices[39],
+ /* parameters */ &kParameters[1014],
+ /* return matcher indices */ &kMatcherIndices[1],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Zero,
},
{
- /* [279] */
+ /* [278] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[961],
+ /* return matcher indices */ &kMatcherIndices[1],
+ /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::Identity,
+ },
+ {
+ /* [279] */
+ /* num parameters */ 1,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[34],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[962],
+ /* return matcher indices */ &kMatcherIndices[1],
+ /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::Conv,
+ },
+ {
+ /* [280] */
+ /* num parameters */ 0,
+ /* num template types */ 0,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[1014],
+ /* return matcher indices */ &kMatcherIndices[39],
+ /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::Zero,
+ },
+ {
+ /* [281] */
+ /* num parameters */ 1,
+ /* num template types */ 0,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[38],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[963],
/* return matcher indices */ &kMatcherIndices[39],
/* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Identity,
},
{
- /* [280] */
+ /* [282] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[35],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[962],
+ /* parameters */ &kParameters[964],
/* return matcher indices */ &kMatcherIndices[39],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
},
{
- /* [281] */
+ /* [283] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11784,7 +11818,7 @@
/* const eval */ &ConstEval::abs,
},
{
- /* [282] */
+ /* [284] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11796,7 +11830,7 @@
/* const eval */ &ConstEval::abs,
},
{
- /* [283] */
+ /* [285] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11808,7 +11842,7 @@
/* const eval */ &ConstEval::acos,
},
{
- /* [284] */
+ /* [286] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11820,7 +11854,7 @@
/* const eval */ &ConstEval::acos,
},
{
- /* [285] */
+ /* [287] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11832,7 +11866,7 @@
/* const eval */ &ConstEval::acosh,
},
{
- /* [286] */
+ /* [288] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11844,7 +11878,7 @@
/* const eval */ &ConstEval::acosh,
},
{
- /* [287] */
+ /* [289] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -11856,7 +11890,7 @@
/* const eval */ &ConstEval::all,
},
{
- /* [288] */
+ /* [290] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -11868,7 +11902,7 @@
/* const eval */ &ConstEval::all,
},
{
- /* [289] */
+ /* [291] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -11880,7 +11914,7 @@
/* const eval */ &ConstEval::any,
},
{
- /* [290] */
+ /* [292] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -11892,7 +11926,7 @@
/* const eval */ &ConstEval::any,
},
{
- /* [291] */
+ /* [293] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11904,7 +11938,7 @@
/* const eval */ &ConstEval::asin,
},
{
- /* [292] */
+ /* [294] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11916,7 +11950,7 @@
/* const eval */ &ConstEval::asin,
},
{
- /* [293] */
+ /* [295] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11928,7 +11962,7 @@
/* const eval */ &ConstEval::asinh,
},
{
- /* [294] */
+ /* [296] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11940,7 +11974,7 @@
/* const eval */ &ConstEval::asinh,
},
{
- /* [295] */
+ /* [297] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11952,7 +11986,7 @@
/* const eval */ &ConstEval::atan,
},
{
- /* [296] */
+ /* [298] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11964,7 +11998,7 @@
/* const eval */ &ConstEval::atan,
},
{
- /* [297] */
+ /* [299] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -11976,7 +12010,7 @@
/* const eval */ &ConstEval::atan2,
},
{
- /* [298] */
+ /* [300] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -11988,7 +12022,7 @@
/* const eval */ &ConstEval::atan2,
},
{
- /* [299] */
+ /* [301] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12000,7 +12034,7 @@
/* const eval */ &ConstEval::atanh,
},
{
- /* [300] */
+ /* [302] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12012,7 +12046,7 @@
/* const eval */ &ConstEval::atanh,
},
{
- /* [301] */
+ /* [303] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12024,7 +12058,7 @@
/* const eval */ &ConstEval::ceil,
},
{
- /* [302] */
+ /* [304] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12036,7 +12070,7 @@
/* const eval */ &ConstEval::ceil,
},
{
- /* [303] */
+ /* [305] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12048,7 +12082,7 @@
/* const eval */ &ConstEval::clamp,
},
{
- /* [304] */
+ /* [306] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12060,7 +12094,7 @@
/* const eval */ &ConstEval::clamp,
},
{
- /* [305] */
+ /* [307] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12072,7 +12106,7 @@
/* const eval */ &ConstEval::cos,
},
{
- /* [306] */
+ /* [308] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12084,7 +12118,7 @@
/* const eval */ &ConstEval::cos,
},
{
- /* [307] */
+ /* [309] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12096,7 +12130,7 @@
/* const eval */ &ConstEval::cosh,
},
{
- /* [308] */
+ /* [310] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12108,7 +12142,7 @@
/* const eval */ &ConstEval::cosh,
},
{
- /* [309] */
+ /* [311] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12120,7 +12154,7 @@
/* const eval */ &ConstEval::countLeadingZeros,
},
{
- /* [310] */
+ /* [312] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12132,7 +12166,7 @@
/* const eval */ &ConstEval::countLeadingZeros,
},
{
- /* [311] */
+ /* [313] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12144,7 +12178,7 @@
/* const eval */ &ConstEval::countOneBits,
},
{
- /* [312] */
+ /* [314] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12156,7 +12190,7 @@
/* const eval */ &ConstEval::countOneBits,
},
{
- /* [313] */
+ /* [315] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12168,7 +12202,7 @@
/* const eval */ &ConstEval::countTrailingZeros,
},
{
- /* [314] */
+ /* [316] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12180,7 +12214,7 @@
/* const eval */ &ConstEval::countTrailingZeros,
},
{
- /* [315] */
+ /* [317] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12192,7 +12226,7 @@
/* const eval */ &ConstEval::degrees,
},
{
- /* [316] */
+ /* [318] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12204,7 +12238,7 @@
/* const eval */ &ConstEval::degrees,
},
{
- /* [317] */
+ /* [319] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12216,7 +12250,7 @@
/* const eval */ &ConstEval::distance,
},
{
- /* [318] */
+ /* [320] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12228,7 +12262,7 @@
/* const eval */ &ConstEval::distance,
},
{
- /* [319] */
+ /* [321] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12240,7 +12274,7 @@
/* const eval */ nullptr,
},
{
- /* [320] */
+ /* [322] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12252,7 +12286,7 @@
/* const eval */ nullptr,
},
{
- /* [321] */
+ /* [323] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12264,7 +12298,7 @@
/* const eval */ nullptr,
},
{
- /* [322] */
+ /* [324] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12276,7 +12310,7 @@
/* const eval */ nullptr,
},
{
- /* [323] */
+ /* [325] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12288,7 +12322,7 @@
/* const eval */ nullptr,
},
{
- /* [324] */
+ /* [326] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12300,7 +12334,7 @@
/* const eval */ nullptr,
},
{
- /* [325] */
+ /* [327] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12312,7 +12346,7 @@
/* const eval */ nullptr,
},
{
- /* [326] */
+ /* [328] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12324,7 +12358,7 @@
/* const eval */ nullptr,
},
{
- /* [327] */
+ /* [329] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12336,7 +12370,7 @@
/* const eval */ nullptr,
},
{
- /* [328] */
+ /* [330] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12348,7 +12382,7 @@
/* const eval */ nullptr,
},
{
- /* [329] */
+ /* [331] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12360,7 +12394,7 @@
/* const eval */ nullptr,
},
{
- /* [330] */
+ /* [332] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12372,7 +12406,7 @@
/* const eval */ nullptr,
},
{
- /* [331] */
+ /* [333] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12384,7 +12418,7 @@
/* const eval */ &ConstEval::exp,
},
{
- /* [332] */
+ /* [334] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12396,7 +12430,7 @@
/* const eval */ &ConstEval::exp,
},
{
- /* [333] */
+ /* [335] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12408,7 +12442,7 @@
/* const eval */ &ConstEval::exp2,
},
{
- /* [334] */
+ /* [336] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12420,7 +12454,7 @@
/* const eval */ &ConstEval::exp2,
},
{
- /* [335] */
+ /* [337] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12432,7 +12466,7 @@
/* const eval */ &ConstEval::extractBits,
},
{
- /* [336] */
+ /* [338] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12444,7 +12478,7 @@
/* const eval */ &ConstEval::extractBits,
},
{
- /* [337] */
+ /* [339] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12456,7 +12490,7 @@
/* const eval */ &ConstEval::firstLeadingBit,
},
{
- /* [338] */
+ /* [340] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12468,7 +12502,7 @@
/* const eval */ &ConstEval::firstLeadingBit,
},
{
- /* [339] */
+ /* [341] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12480,7 +12514,7 @@
/* const eval */ &ConstEval::firstTrailingBit,
},
{
- /* [340] */
+ /* [342] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12492,7 +12526,7 @@
/* const eval */ &ConstEval::firstTrailingBit,
},
{
- /* [341] */
+ /* [343] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12504,7 +12538,7 @@
/* const eval */ &ConstEval::floor,
},
{
- /* [342] */
+ /* [344] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12516,7 +12550,7 @@
/* const eval */ &ConstEval::floor,
},
{
- /* [343] */
+ /* [345] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12528,7 +12562,7 @@
/* const eval */ &ConstEval::fma,
},
{
- /* [344] */
+ /* [346] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12540,7 +12574,7 @@
/* const eval */ &ConstEval::fma,
},
{
- /* [345] */
+ /* [347] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12552,7 +12586,7 @@
/* const eval */ &ConstEval::fract,
},
{
- /* [346] */
+ /* [348] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12564,7 +12598,7 @@
/* const eval */ &ConstEval::fract,
},
{
- /* [347] */
+ /* [349] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12576,7 +12610,7 @@
/* const eval */ &ConstEval::frexp,
},
{
- /* [348] */
+ /* [350] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12588,7 +12622,7 @@
/* const eval */ &ConstEval::frexp,
},
{
- /* [349] */
+ /* [351] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12600,7 +12634,7 @@
/* const eval */ nullptr,
},
{
- /* [350] */
+ /* [352] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12612,7 +12646,7 @@
/* const eval */ nullptr,
},
{
- /* [351] */
+ /* [353] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12624,7 +12658,7 @@
/* const eval */ nullptr,
},
{
- /* [352] */
+ /* [354] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12636,7 +12670,7 @@
/* const eval */ nullptr,
},
{
- /* [353] */
+ /* [355] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12648,7 +12682,7 @@
/* const eval */ nullptr,
},
{
- /* [354] */
+ /* [356] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12660,7 +12694,7 @@
/* const eval */ nullptr,
},
{
- /* [355] */
+ /* [357] */
/* num parameters */ 4,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12672,7 +12706,7 @@
/* const eval */ &ConstEval::insertBits,
},
{
- /* [356] */
+ /* [358] */
/* num parameters */ 4,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12684,7 +12718,7 @@
/* const eval */ &ConstEval::insertBits,
},
{
- /* [357] */
+ /* [359] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12696,7 +12730,7 @@
/* const eval */ &ConstEval::inverseSqrt,
},
{
- /* [358] */
+ /* [360] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12708,7 +12742,7 @@
/* const eval */ &ConstEval::inverseSqrt,
},
{
- /* [359] */
+ /* [361] */
/* num parameters */ 2,
/* num template types */ 2,
/* num template numbers */ 0,
@@ -12720,7 +12754,7 @@
/* const eval */ &ConstEval::ldexp,
},
{
- /* [360] */
+ /* [362] */
/* num parameters */ 2,
/* num template types */ 2,
/* num template numbers */ 1,
@@ -12732,7 +12766,7 @@
/* const eval */ &ConstEval::ldexp,
},
{
- /* [361] */
+ /* [363] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12744,7 +12778,7 @@
/* const eval */ &ConstEval::length,
},
{
- /* [362] */
+ /* [364] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12756,7 +12790,7 @@
/* const eval */ &ConstEval::length,
},
{
- /* [363] */
+ /* [365] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12768,7 +12802,7 @@
/* const eval */ &ConstEval::log,
},
{
- /* [364] */
+ /* [366] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12780,7 +12814,7 @@
/* const eval */ &ConstEval::log,
},
{
- /* [365] */
+ /* [367] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12792,7 +12826,7 @@
/* const eval */ &ConstEval::log2,
},
{
- /* [366] */
+ /* [368] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12804,7 +12838,7 @@
/* const eval */ &ConstEval::log2,
},
{
- /* [367] */
+ /* [369] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12816,7 +12850,7 @@
/* const eval */ &ConstEval::max,
},
{
- /* [368] */
+ /* [370] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12828,7 +12862,7 @@
/* const eval */ &ConstEval::max,
},
{
- /* [369] */
+ /* [371] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12840,7 +12874,7 @@
/* const eval */ &ConstEval::min,
},
{
- /* [370] */
+ /* [372] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12852,7 +12886,7 @@
/* const eval */ &ConstEval::min,
},
{
- /* [371] */
+ /* [373] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12864,7 +12898,7 @@
/* const eval */ &ConstEval::modf,
},
{
- /* [372] */
+ /* [374] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12876,7 +12910,7 @@
/* const eval */ &ConstEval::modf,
},
{
- /* [373] */
+ /* [375] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12888,7 +12922,7 @@
/* const eval */ &ConstEval::pow,
},
{
- /* [374] */
+ /* [376] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12900,7 +12934,7 @@
/* const eval */ &ConstEval::pow,
},
{
- /* [375] */
+ /* [377] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -12912,7 +12946,7 @@
/* const eval */ &ConstEval::quantizeToF16,
},
{
- /* [376] */
+ /* [378] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
@@ -12924,7 +12958,7 @@
/* const eval */ &ConstEval::quantizeToF16,
},
{
- /* [377] */
+ /* [379] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12936,7 +12970,7 @@
/* const eval */ &ConstEval::radians,
},
{
- /* [378] */
+ /* [380] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12948,7 +12982,7 @@
/* const eval */ &ConstEval::radians,
},
{
- /* [379] */
+ /* [381] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12960,7 +12994,7 @@
/* const eval */ &ConstEval::reverseBits,
},
{
- /* [380] */
+ /* [382] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12972,7 +13006,7 @@
/* const eval */ &ConstEval::reverseBits,
},
{
- /* [381] */
+ /* [383] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -12984,7 +13018,7 @@
/* const eval */ &ConstEval::round,
},
{
- /* [382] */
+ /* [384] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -12996,7 +13030,7 @@
/* const eval */ &ConstEval::round,
},
{
- /* [383] */
+ /* [385] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13008,7 +13042,7 @@
/* const eval */ &ConstEval::saturate,
},
{
- /* [384] */
+ /* [386] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13020,7 +13054,7 @@
/* const eval */ &ConstEval::saturate,
},
{
- /* [385] */
+ /* [387] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13032,7 +13066,7 @@
/* const eval */ &ConstEval::sign,
},
{
- /* [386] */
+ /* [388] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13044,7 +13078,7 @@
/* const eval */ &ConstEval::sign,
},
{
- /* [387] */
+ /* [389] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13056,7 +13090,7 @@
/* const eval */ &ConstEval::sin,
},
{
- /* [388] */
+ /* [390] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13068,7 +13102,7 @@
/* const eval */ &ConstEval::sin,
},
{
- /* [389] */
+ /* [391] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13080,7 +13114,7 @@
/* const eval */ &ConstEval::sinh,
},
{
- /* [390] */
+ /* [392] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13092,7 +13126,7 @@
/* const eval */ &ConstEval::sinh,
},
{
- /* [391] */
+ /* [393] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13104,7 +13138,7 @@
/* const eval */ &ConstEval::smoothstep,
},
{
- /* [392] */
+ /* [394] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13116,7 +13150,7 @@
/* const eval */ &ConstEval::smoothstep,
},
{
- /* [393] */
+ /* [395] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13128,7 +13162,7 @@
/* const eval */ &ConstEval::sqrt,
},
{
- /* [394] */
+ /* [396] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13140,7 +13174,7 @@
/* const eval */ &ConstEval::sqrt,
},
{
- /* [395] */
+ /* [397] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13152,7 +13186,7 @@
/* const eval */ &ConstEval::step,
},
{
- /* [396] */
+ /* [398] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13164,7 +13198,7 @@
/* const eval */ &ConstEval::step,
},
{
- /* [397] */
+ /* [399] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13176,7 +13210,7 @@
/* const eval */ &ConstEval::tan,
},
{
- /* [398] */
+ /* [400] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13188,7 +13222,7 @@
/* const eval */ &ConstEval::tan,
},
{
- /* [399] */
+ /* [401] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13200,7 +13234,7 @@
/* const eval */ &ConstEval::tanh,
},
{
- /* [400] */
+ /* [402] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13212,7 +13246,7 @@
/* const eval */ &ConstEval::tanh,
},
{
- /* [401] */
+ /* [403] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13224,7 +13258,7 @@
/* const eval */ &ConstEval::trunc,
},
{
- /* [402] */
+ /* [404] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13236,31 +13270,31 @@
/* const eval */ &ConstEval::trunc,
},
{
- /* [403] */
+ /* [405] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[0],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[943],
+ /* parameters */ &kParameters[945],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
},
{
- /* [404] */
+ /* [406] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[944],
+ /* parameters */ &kParameters[946],
/* return matcher indices */ &kMatcherIndices[105],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ nullptr,
},
{
- /* [405] */
+ /* [407] */
/* num parameters */ 3,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13272,7 +13306,7 @@
/* const eval */ nullptr,
},
{
- /* [406] */
+ /* [408] */
/* num parameters */ 3,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13284,79 +13318,79 @@
/* const eval */ nullptr,
},
{
- /* [407] */
+ /* [409] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[947],
+ /* parameters */ &kParameters[949],
/* return matcher indices */ &kMatcherIndices[39],
/* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::OpNot,
},
{
- /* [408] */
+ /* [410] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[948],
+ /* parameters */ &kParameters[950],
/* return matcher indices */ &kMatcherIndices[37],
/* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::OpNot,
},
{
- /* [409] */
- /* num parameters */ 1,
- /* num template types */ 1,
- /* num template numbers */ 0,
- /* template types */ &kTemplateTypes[29],
- /* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[949],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpComplement,
- },
- {
- /* [410] */
- /* num parameters */ 1,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[29],
- /* template numbers */ &kTemplateNumbers[4],
- /* parameters */ &kParameters[950],
- /* return matcher indices */ &kMatcherIndices[34],
- /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpComplement,
- },
- {
/* [411] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[28],
+ /* template types */ &kTemplateTypes[29],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[951],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* const eval */ &ConstEval::OpUnaryMinus,
+ /* const eval */ &ConstEval::OpComplement,
},
{
/* [412] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[28],
+ /* template types */ &kTemplateTypes[29],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[952],
/* return matcher indices */ &kMatcherIndices[34],
/* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpComplement,
+ },
+ {
+ /* [413] */
+ /* num parameters */ 1,
+ /* num template types */ 1,
+ /* num template numbers */ 0,
+ /* template types */ &kTemplateTypes[28],
+ /* template numbers */ &kTemplateNumbers[10],
+ /* parameters */ &kParameters[953],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+ /* const eval */ &ConstEval::OpUnaryMinus,
+ },
+ {
+ /* [414] */
+ /* num parameters */ 1,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[28],
+ /* template numbers */ &kTemplateNumbers[4],
+ /* parameters */ &kParameters[954],
+ /* return matcher indices */ &kMatcherIndices[34],
+ /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::OpUnaryMinus,
},
{
- /* [413] */
+ /* [415] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13368,7 +13402,7 @@
/* const eval */ &ConstEval::OpXor,
},
{
- /* [414] */
+ /* [416] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13380,7 +13414,7 @@
/* const eval */ &ConstEval::OpXor,
},
{
- /* [415] */
+ /* [417] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13392,7 +13426,7 @@
/* const eval */ &ConstEval::OpEqual,
},
{
- /* [416] */
+ /* [418] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13404,7 +13438,7 @@
/* const eval */ &ConstEval::OpEqual,
},
{
- /* [417] */
+ /* [419] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13416,7 +13450,7 @@
/* const eval */ &ConstEval::OpNotEqual,
},
{
- /* [418] */
+ /* [420] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13428,7 +13462,7 @@
/* const eval */ &ConstEval::OpNotEqual,
},
{
- /* [419] */
+ /* [421] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13440,7 +13474,7 @@
/* const eval */ &ConstEval::OpLessThan,
},
{
- /* [420] */
+ /* [422] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13452,7 +13486,7 @@
/* const eval */ &ConstEval::OpLessThan,
},
{
- /* [421] */
+ /* [423] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13464,7 +13498,7 @@
/* const eval */ &ConstEval::OpGreaterThan,
},
{
- /* [422] */
+ /* [424] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13476,7 +13510,7 @@
/* const eval */ &ConstEval::OpGreaterThan,
},
{
- /* [423] */
+ /* [425] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13488,7 +13522,7 @@
/* const eval */ &ConstEval::OpLessThanEqual,
},
{
- /* [424] */
+ /* [426] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13500,7 +13534,7 @@
/* const eval */ &ConstEval::OpLessThanEqual,
},
{
- /* [425] */
+ /* [427] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13512,7 +13546,7 @@
/* const eval */ &ConstEval::OpGreaterThanEqual,
},
{
- /* [426] */
+ /* [428] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13524,7 +13558,7 @@
/* const eval */ &ConstEval::OpGreaterThanEqual,
},
{
- /* [427] */
+ /* [429] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13536,7 +13570,7 @@
/* const eval */ &ConstEval::OpShiftLeft,
},
{
- /* [428] */
+ /* [430] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13548,7 +13582,7 @@
/* const eval */ &ConstEval::OpShiftLeft,
},
{
- /* [429] */
+ /* [431] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13560,7 +13594,7 @@
/* const eval */ &ConstEval::OpShiftRight,
},
{
- /* [430] */
+ /* [432] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13572,7 +13606,7 @@
/* const eval */ &ConstEval::OpShiftRight,
},
{
- /* [431] */
+ /* [433] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13584,7 +13618,7 @@
/* const eval */ nullptr,
},
{
- /* [432] */
+ /* [434] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13596,7 +13630,7 @@
/* const eval */ &ConstEval::cross,
},
{
- /* [433] */
+ /* [435] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13608,7 +13642,7 @@
/* const eval */ &ConstEval::determinant,
},
{
- /* [434] */
+ /* [436] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13620,7 +13654,7 @@
/* const eval */ &ConstEval::dot,
},
{
- /* [435] */
+ /* [437] */
/* num parameters */ 2,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13632,7 +13666,7 @@
/* const eval */ nullptr,
},
{
- /* [436] */
+ /* [438] */
/* num parameters */ 2,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13644,7 +13678,7 @@
/* const eval */ nullptr,
},
{
- /* [437] */
+ /* [439] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13656,7 +13690,7 @@
/* const eval */ &ConstEval::faceForward,
},
{
- /* [438] */
+ /* [440] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13668,7 +13702,7 @@
/* const eval */ &ConstEval::normalize,
},
{
- /* [439] */
+ /* [441] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13680,7 +13714,7 @@
/* const eval */ &ConstEval::pack2x16float,
},
{
- /* [440] */
+ /* [442] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13692,7 +13726,7 @@
/* const eval */ &ConstEval::pack2x16snorm,
},
{
- /* [441] */
+ /* [443] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13704,7 +13738,7 @@
/* const eval */ &ConstEval::pack2x16unorm,
},
{
- /* [442] */
+ /* [444] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13716,7 +13750,7 @@
/* const eval */ &ConstEval::pack4x8snorm,
},
{
- /* [443] */
+ /* [445] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13728,7 +13762,7 @@
/* const eval */ &ConstEval::pack4x8unorm,
},
{
- /* [444] */
+ /* [446] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13740,7 +13774,7 @@
/* const eval */ &ConstEval::reflect,
},
{
- /* [445] */
+ /* [447] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13752,19 +13786,19 @@
/* const eval */ &ConstEval::refract,
},
{
- /* [446] */
+ /* [448] */
/* num parameters */ 0,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ nullptr,
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
},
{
- /* [447] */
+ /* [449] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 2,
@@ -13776,7 +13810,7 @@
/* const eval */ &ConstEval::transpose,
},
{
- /* [448] */
+ /* [450] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13788,7 +13822,7 @@
/* const eval */ &ConstEval::unpack2x16float,
},
{
- /* [449] */
+ /* [451] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13800,7 +13834,7 @@
/* const eval */ &ConstEval::unpack2x16snorm,
},
{
- /* [450] */
+ /* [452] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13812,7 +13846,7 @@
/* const eval */ &ConstEval::unpack2x16unorm,
},
{
- /* [451] */
+ /* [453] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13824,7 +13858,7 @@
/* const eval */ &ConstEval::unpack4x8snorm,
},
{
- /* [452] */
+ /* [454] */
/* num parameters */ 1,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -13836,19 +13870,19 @@
/* const eval */ &ConstEval::unpack4x8unorm,
},
{
- /* [453] */
+ /* [455] */
/* num parameters */ 0,
/* num template types */ 0,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[38],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1012],
+ /* parameters */ &kParameters[1014],
/* return matcher indices */ nullptr,
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
},
{
- /* [454] */
+ /* [456] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
@@ -13860,37 +13894,13 @@
/* const eval */ nullptr,
},
{
- /* [455] */
+ /* [457] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[945],
- /* return matcher indices */ &kMatcherIndices[3],
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
- },
- {
- /* [456] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
- /* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[654],
- /* return matcher indices */ nullptr,
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
- },
- {
- /* [457] */
- /* num parameters */ 2,
- /* num template types */ 1,
- /* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
- /* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[656],
+ /* parameters */ &kParameters[947],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
@@ -13902,8 +13912,8 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[658],
- /* return matcher indices */ &kMatcherIndices[3],
+ /* parameters */ &kParameters[654],
+ /* return matcher indices */ nullptr,
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
},
@@ -13914,7 +13924,7 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[660],
+ /* parameters */ &kParameters[656],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
@@ -13926,7 +13936,7 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[662],
+ /* parameters */ &kParameters[658],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
@@ -13938,7 +13948,7 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[664],
+ /* parameters */ &kParameters[660],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
@@ -13950,7 +13960,7 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[666],
+ /* parameters */ &kParameters[662],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
@@ -13962,7 +13972,7 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[668],
+ /* parameters */ &kParameters[664],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
@@ -13974,13 +13984,37 @@
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[26],
/* template numbers */ &kTemplateNumbers[9],
- /* parameters */ &kParameters[670],
+ /* parameters */ &kParameters[666],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
},
{
/* [465] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[26],
+ /* template numbers */ &kTemplateNumbers[9],
+ /* parameters */ &kParameters[668],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+ /* const eval */ nullptr,
+ },
+ {
+ /* [466] */
+ /* num parameters */ 2,
+ /* num template types */ 1,
+ /* num template numbers */ 1,
+ /* template types */ &kTemplateTypes[26],
+ /* template numbers */ &kTemplateNumbers[9],
+ /* parameters */ &kParameters[670],
+ /* return matcher indices */ &kMatcherIndices[3],
+ /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+ /* const eval */ nullptr,
+ },
+ {
+ /* [467] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
@@ -13992,19 +14026,19 @@
/* const eval */ nullptr,
},
{
- /* [466] */
+ /* [468] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[25],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[946],
+ /* parameters */ &kParameters[948],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ &ConstEval::Identity,
},
{
- /* [467] */
+ /* [469] */
/* num parameters */ 2,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -14016,7 +14050,7 @@
/* const eval */ &ConstEval::OpLogicalAnd,
},
{
- /* [468] */
+ /* [470] */
/* num parameters */ 2,
/* num template types */ 0,
/* num template numbers */ 0,
@@ -14028,13 +14062,13 @@
/* const eval */ &ConstEval::OpLogicalOr,
},
{
- /* [469] */
+ /* [471] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[36],
/* template numbers */ &kTemplateNumbers[10],
- /* parameters */ &kParameters[1011],
+ /* parameters */ &kParameters[1013],
/* return matcher indices */ &kMatcherIndices[232],
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* const eval */ &ConstEval::Conv,
@@ -14047,357 +14081,357 @@
/* fn abs<T : fia_fiu32_f16>(T) -> T */
/* fn abs<N : num, T : fia_fiu32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[281],
+ /* overloads */ &kOverloads[283],
},
{
/* [1] */
/* fn acos<T : fa_f32_f16>(@test_value(0.96891242171) T) -> T */
/* fn acos<N : num, T : fa_f32_f16>(@test_value(0.96891242171) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[283],
+ /* overloads */ &kOverloads[285],
},
{
/* [2] */
/* fn acosh<T : fa_f32_f16>(@test_value(1.5430806348) T) -> T */
/* fn acosh<N : num, T : fa_f32_f16>(@test_value(1.5430806348) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[285],
+ /* overloads */ &kOverloads[287],
},
{
/* [3] */
/* fn all(bool) -> bool */
/* fn all<N : num>(vec<N, bool>) -> bool */
/* num overloads */ 2,
- /* overloads */ &kOverloads[287],
+ /* overloads */ &kOverloads[289],
},
{
/* [4] */
/* fn any(bool) -> bool */
/* fn any<N : num>(vec<N, bool>) -> bool */
/* num overloads */ 2,
- /* overloads */ &kOverloads[289],
+ /* overloads */ &kOverloads[291],
},
{
/* [5] */
/* fn arrayLength<T, A : access>(ptr<storage, array<T>, A>) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[431],
+ /* overloads */ &kOverloads[433],
},
{
/* [6] */
/* fn asin<T : fa_f32_f16>(@test_value(0.479425538604) T) -> T */
/* fn asin<N : num, T : fa_f32_f16>(@test_value(0.479425538604) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[291],
+ /* overloads */ &kOverloads[293],
},
{
/* [7] */
/* fn asinh<T : fa_f32_f16>(T) -> T */
/* fn asinh<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[293],
+ /* overloads */ &kOverloads[295],
},
{
/* [8] */
/* fn atan<T : fa_f32_f16>(T) -> T */
/* fn atan<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[295],
+ /* overloads */ &kOverloads[297],
},
{
/* [9] */
/* fn atan2<T : fa_f32_f16>(T, T) -> T */
/* fn atan2<T : fa_f32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[297],
+ /* overloads */ &kOverloads[299],
},
{
/* [10] */
/* fn atanh<T : fa_f32_f16>(@test_value(0.5) T) -> T */
/* fn atanh<N : num, T : fa_f32_f16>(@test_value(0.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[299],
+ /* overloads */ &kOverloads[301],
},
{
/* [11] */
/* fn ceil<T : fa_f32_f16>(@test_value(1.5) T) -> T */
/* fn ceil<N : num, T : fa_f32_f16>(@test_value(1.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[301],
+ /* overloads */ &kOverloads[303],
},
{
/* [12] */
/* fn clamp<T : fia_fiu32_f16>(T, T, T) -> T */
/* fn clamp<T : fia_fiu32_f16, N : num>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[303],
+ /* overloads */ &kOverloads[305],
},
{
/* [13] */
/* fn cos<T : fa_f32_f16>(@test_value(0) T) -> T */
/* fn cos<N : num, T : fa_f32_f16>(@test_value(0) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[305],
+ /* overloads */ &kOverloads[307],
},
{
/* [14] */
/* fn cosh<T : fa_f32_f16>(@test_value(0) T) -> T */
/* fn cosh<N : num, T : fa_f32_f16>(@test_value(0) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[307],
+ /* overloads */ &kOverloads[309],
},
{
/* [15] */
/* fn countLeadingZeros<T : iu32>(T) -> T */
/* fn countLeadingZeros<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[309],
+ /* overloads */ &kOverloads[311],
},
{
/* [16] */
/* fn countOneBits<T : iu32>(T) -> T */
/* fn countOneBits<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[311],
+ /* overloads */ &kOverloads[313],
},
{
/* [17] */
/* fn countTrailingZeros<T : iu32>(T) -> T */
/* fn countTrailingZeros<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[313],
+ /* overloads */ &kOverloads[315],
},
{
/* [18] */
/* fn cross<T : fa_f32_f16>(vec3<T>, vec3<T>) -> vec3<T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[432],
+ /* overloads */ &kOverloads[434],
},
{
/* [19] */
/* fn degrees<T : fa_f32_f16>(T) -> T */
/* fn degrees<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[315],
+ /* overloads */ &kOverloads[317],
},
{
/* [20] */
/* fn determinant<N : num, T : fa_f32_f16>(mat<N, N, T>) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[433],
+ /* overloads */ &kOverloads[435],
},
{
/* [21] */
/* fn distance<T : fa_f32_f16>(T, T) -> T */
/* fn distance<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>) -> T */
/* num overloads */ 2,
- /* overloads */ &kOverloads[317],
+ /* overloads */ &kOverloads[319],
},
{
/* [22] */
/* fn dot<N : num, T : fia_fiu32_f16>(vec<N, T>, vec<N, T>) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[434],
+ /* overloads */ &kOverloads[436],
},
{
/* [23] */
/* fn dot4I8Packed(u32, u32) -> i32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[435],
+ /* overloads */ &kOverloads[437],
},
{
/* [24] */
/* fn dot4U8Packed(u32, u32) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[436],
+ /* overloads */ &kOverloads[438],
},
{
/* [25] */
/* fn dpdx(f32) -> f32 */
/* fn dpdx<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[319],
+ /* overloads */ &kOverloads[321],
},
{
/* [26] */
/* fn dpdxCoarse(f32) -> f32 */
/* fn dpdxCoarse<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[321],
+ /* overloads */ &kOverloads[323],
},
{
/* [27] */
/* fn dpdxFine(f32) -> f32 */
/* fn dpdxFine<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[323],
+ /* overloads */ &kOverloads[325],
},
{
/* [28] */
/* fn dpdy(f32) -> f32 */
/* fn dpdy<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[325],
+ /* overloads */ &kOverloads[327],
},
{
/* [29] */
/* fn dpdyCoarse(f32) -> f32 */
/* fn dpdyCoarse<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[327],
+ /* overloads */ &kOverloads[329],
},
{
/* [30] */
/* fn dpdyFine(f32) -> f32 */
/* fn dpdyFine<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[329],
+ /* overloads */ &kOverloads[331],
},
{
/* [31] */
/* fn exp<T : fa_f32_f16>(T) -> T */
/* fn exp<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[331],
+ /* overloads */ &kOverloads[333],
},
{
/* [32] */
/* fn exp2<T : fa_f32_f16>(T) -> T */
/* fn exp2<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[333],
+ /* overloads */ &kOverloads[335],
},
{
/* [33] */
/* fn extractBits<T : iu32>(T, u32, u32) -> T */
/* fn extractBits<N : num, T : iu32>(vec<N, T>, u32, u32) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[335],
+ /* overloads */ &kOverloads[337],
},
{
/* [34] */
/* fn faceForward<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[437],
+ /* overloads */ &kOverloads[439],
},
{
/* [35] */
/* fn firstLeadingBit<T : iu32>(T) -> T */
/* fn firstLeadingBit<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[337],
+ /* overloads */ &kOverloads[339],
},
{
/* [36] */
/* fn firstTrailingBit<T : iu32>(T) -> T */
/* fn firstTrailingBit<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[339],
+ /* overloads */ &kOverloads[341],
},
{
/* [37] */
/* fn floor<T : fa_f32_f16>(@test_value(1.5) T) -> T */
/* fn floor<N : num, T : fa_f32_f16>(@test_value(1.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[341],
+ /* overloads */ &kOverloads[343],
},
{
/* [38] */
/* fn fma<T : fa_f32_f16>(T, T, T) -> T */
/* fn fma<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[343],
+ /* overloads */ &kOverloads[345],
},
{
/* [39] */
/* fn fract<T : fa_f32_f16>(@test_value(1.25) T) -> T */
/* fn fract<N : num, T : fa_f32_f16>(@test_value(1.25) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[345],
+ /* overloads */ &kOverloads[347],
},
{
/* [40] */
/* fn frexp<T : fa_f32_f16>(T) -> __frexp_result<T> */
/* fn frexp<N : num, T : fa_f32_f16>(vec<N, T>) -> __frexp_result_vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[347],
+ /* overloads */ &kOverloads[349],
},
{
/* [41] */
/* fn fwidth(f32) -> f32 */
/* fn fwidth<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[349],
+ /* overloads */ &kOverloads[351],
},
{
/* [42] */
/* fn fwidthCoarse(f32) -> f32 */
/* fn fwidthCoarse<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[351],
+ /* overloads */ &kOverloads[353],
},
{
/* [43] */
/* fn fwidthFine(f32) -> f32 */
/* fn fwidthFine<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[353],
+ /* overloads */ &kOverloads[355],
},
{
/* [44] */
/* fn insertBits<T : iu32>(T, T, u32, u32) -> T */
/* fn insertBits<N : num, T : iu32>(vec<N, T>, vec<N, T>, u32, u32) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[355],
+ /* overloads */ &kOverloads[357],
},
{
/* [45] */
/* fn inverseSqrt<T : fa_f32_f16>(T) -> T */
/* fn inverseSqrt<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[357],
+ /* overloads */ &kOverloads[359],
},
{
/* [46] */
/* fn ldexp<T : fa_f32_f16, U : ia_i32>(T, U) -> T */
/* fn ldexp<N : num, T : fa_f32_f16, U : ia_i32>(vec<N, T>, vec<N, U>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[359],
+ /* overloads */ &kOverloads[361],
},
{
/* [47] */
/* fn length<T : fa_f32_f16>(@test_value(0) T) -> T */
/* fn length<N : num, T : fa_f32_f16>(@test_value(0) vec<N, T>) -> T */
/* num overloads */ 2,
- /* overloads */ &kOverloads[361],
+ /* overloads */ &kOverloads[363],
},
{
/* [48] */
/* fn log<T : fa_f32_f16>(T) -> T */
/* fn log<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[363],
+ /* overloads */ &kOverloads[365],
},
{
/* [49] */
/* fn log2<T : fa_f32_f16>(T) -> T */
/* fn log2<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[365],
+ /* overloads */ &kOverloads[367],
},
{
/* [50] */
/* fn max<T : fia_fiu32_f16>(T, T) -> T */
/* fn max<N : num, T : fia_fiu32_f16>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[367],
+ /* overloads */ &kOverloads[369],
},
{
/* [51] */
/* fn min<T : fia_fiu32_f16>(T, T) -> T */
/* fn min<N : num, T : fia_fiu32_f16>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[369],
+ /* overloads */ &kOverloads[371],
},
{
/* [52] */
@@ -14405,104 +14439,104 @@
/* fn mix<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
/* fn mix<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>, T) -> vec<N, T> */
/* num overloads */ 3,
- /* overloads */ &kOverloads[257],
+ /* overloads */ &kOverloads[262],
},
{
/* [53] */
/* fn modf<T : fa_f32_f16>(@test_value(-1.5) T) -> __modf_result<T> */
/* fn modf<N : num, T : fa_f32_f16>(@test_value(-1.5) vec<N, T>) -> __modf_result_vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[371],
+ /* overloads */ &kOverloads[373],
},
{
/* [54] */
/* fn normalize<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[438],
+ /* overloads */ &kOverloads[440],
},
{
/* [55] */
/* fn pack2x16float(vec2<f32>) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[439],
+ /* overloads */ &kOverloads[441],
},
{
/* [56] */
/* fn pack2x16snorm(vec2<f32>) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[440],
+ /* overloads */ &kOverloads[442],
},
{
/* [57] */
/* fn pack2x16unorm(vec2<f32>) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[441],
+ /* overloads */ &kOverloads[443],
},
{
/* [58] */
/* fn pack4x8snorm(vec4<f32>) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[442],
+ /* overloads */ &kOverloads[444],
},
{
/* [59] */
/* fn pack4x8unorm(vec4<f32>) -> u32 */
/* num overloads */ 1,
- /* overloads */ &kOverloads[443],
+ /* overloads */ &kOverloads[445],
},
{
/* [60] */
/* fn pow<T : fa_f32_f16>(T, T) -> T */
/* fn pow<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[373],
+ /* overloads */ &kOverloads[375],
},
{
/* [61] */
/* fn quantizeToF16(f32) -> f32 */
/* fn quantizeToF16<N : num>(vec<N, f32>) -> vec<N, f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[375],
+ /* overloads */ &kOverloads[377],
},
{
/* [62] */
/* fn radians<T : fa_f32_f16>(T) -> T */
/* fn radians<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[377],
+ /* overloads */ &kOverloads[379],
},
{
/* [63] */
/* fn reflect<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[444],
+ /* overloads */ &kOverloads[446],
},
{
/* [64] */
/* fn refract<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>, T) -> vec<N, T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[445],
+ /* overloads */ &kOverloads[447],
},
{
/* [65] */
/* fn reverseBits<T : iu32>(T) -> T */
/* fn reverseBits<N : num, T : iu32>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[379],
+ /* overloads */ &kOverloads[381],
},
{
/* [66] */
/* fn round<T : fa_f32_f16>(@test_value(3.5) T) -> T */
/* fn round<N : num, T : fa_f32_f16>(@test_value(3.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[381],
+ /* overloads */ &kOverloads[383],
},
{
/* [67] */
/* fn saturate<T : fa_f32_f16>(@test_value(2) T) -> T */
/* fn saturate<T : fa_f32_f16, N : num>(@test_value(2) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[383],
+ /* overloads */ &kOverloads[385],
},
{
/* [68] */
@@ -14510,124 +14544,124 @@
/* fn select<T : scalar, N : num>(vec<N, T>, vec<N, T>, bool) -> vec<N, T> */
/* fn select<N : num, T : scalar>(vec<N, T>, vec<N, T>, vec<N, bool>) -> vec<N, T> */
/* num overloads */ 3,
- /* overloads */ &kOverloads[260],
+ /* overloads */ &kOverloads[265],
},
{
/* [69] */
/* fn sign<T : fia_fi32_f16>(T) -> T */
/* fn sign<N : num, T : fia_fi32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[385],
+ /* overloads */ &kOverloads[387],
},
{
/* [70] */
/* fn sin<T : fa_f32_f16>(@test_value(1.57079632679) T) -> T */
/* fn sin<N : num, T : fa_f32_f16>(@test_value(1.57079632679) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[387],
+ /* overloads */ &kOverloads[389],
},
{
/* [71] */
/* fn sinh<T : fa_f32_f16>(T) -> T */
/* fn sinh<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[389],
+ /* overloads */ &kOverloads[391],
},
{
/* [72] */
/* fn smoothstep<T : fa_f32_f16>(@test_value(2) T, @test_value(4) T, @test_value(3) T) -> T */
/* fn smoothstep<N : num, T : fa_f32_f16>(@test_value(2) vec<N, T>, @test_value(4) vec<N, T>, @test_value(3) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[391],
+ /* overloads */ &kOverloads[393],
},
{
/* [73] */
/* fn sqrt<T : fa_f32_f16>(T) -> T */
/* fn sqrt<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[393],
+ /* overloads */ &kOverloads[395],
},
{
/* [74] */
/* fn step<T : fa_f32_f16>(T, T) -> T */
/* fn step<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[395],
+ /* overloads */ &kOverloads[397],
},
{
/* [75] */
/* fn storageBarrier() */
/* num overloads */ 1,
- /* overloads */ &kOverloads[446],
+ /* overloads */ &kOverloads[448],
},
{
/* [76] */
/* fn tan<T : fa_f32_f16>(T) -> T */
/* fn tan<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[397],
+ /* overloads */ &kOverloads[399],
},
{
/* [77] */
/* fn tanh<T : fa_f32_f16>(T) -> T */
/* fn tanh<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[399],
+ /* overloads */ &kOverloads[401],
},
{
/* [78] */
/* fn transpose<M : num, N : num, T : fa_f32_f16>(mat<M, N, T>) -> mat<N, M, T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[447],
+ /* overloads */ &kOverloads[449],
},
{
/* [79] */
/* fn trunc<T : fa_f32_f16>(@test_value(1.5) T) -> T */
/* fn trunc<N : num, T : fa_f32_f16>(@test_value(1.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[401],
+ /* overloads */ &kOverloads[403],
},
{
/* [80] */
/* fn unpack2x16float(u32) -> vec2<f32> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[448],
+ /* overloads */ &kOverloads[450],
},
{
/* [81] */
/* fn unpack2x16snorm(u32) -> vec2<f32> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[449],
+ /* overloads */ &kOverloads[451],
},
{
/* [82] */
/* fn unpack2x16unorm(u32) -> vec2<f32> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[450],
+ /* overloads */ &kOverloads[452],
},
{
/* [83] */
/* fn unpack4x8snorm(u32) -> vec4<f32> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[451],
+ /* overloads */ &kOverloads[453],
},
{
/* [84] */
/* fn unpack4x8unorm(u32) -> vec4<f32> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[452],
+ /* overloads */ &kOverloads[454],
},
{
/* [85] */
/* fn workgroupBarrier() */
/* num overloads */ 1,
- /* overloads */ &kOverloads[453],
+ /* overloads */ &kOverloads[455],
},
{
/* [86] */
/* fn workgroupUniformLoad<T>(ptr<workgroup, T, read_write>) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[454],
+ /* overloads */ &kOverloads[456],
},
{
/* [87] */
@@ -14692,10 +14726,12 @@
{
/* [90] */
/* fn textureNumLayers<T : fiu32>(texture: texture_2d_array<T>) -> u32 */
+ /* fn textureNumLayers<T : fiu32>(texture: texture_cube_array<T>) -> u32 */
/* fn textureNumLayers(texture: texture_depth_2d_array) -> u32 */
+ /* fn textureNumLayers(texture: texture_depth_cube_array) -> u32 */
/* fn textureNumLayers<F : texel_format, A : write>(texture: texture_storage_2d_array<F, A>) -> u32 */
- /* num overloads */ 3,
- /* overloads */ &kOverloads[263],
+ /* num overloads */ 5,
+ /* overloads */ &kOverloads[231],
},
{
/* [91] */
@@ -14717,7 +14753,7 @@
/* fn textureNumSamples<T : fiu32>(texture: texture_multisampled_2d<T>) -> u32 */
/* fn textureNumSamples(texture: texture_depth_multisampled_2d) -> u32 */
/* num overloads */ 2,
- /* overloads */ &kOverloads[403],
+ /* overloads */ &kOverloads[405],
},
{
/* [93] */
@@ -14811,7 +14847,7 @@
/* fn textureSampleBaseClampToEdge(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>) -> vec4<f32> */
/* fn textureSampleBaseClampToEdge(texture: texture_external, sampler: sampler, coords: vec2<f32>) -> vec4<f32> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[405],
+ /* overloads */ &kOverloads[407],
},
{
/* [100] */
@@ -14848,73 +14884,73 @@
/* [102] */
/* fn atomicLoad<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[455],
+ /* overloads */ &kOverloads[457],
},
{
/* [103] */
/* fn atomicStore<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) */
/* num overloads */ 1,
- /* overloads */ &kOverloads[456],
+ /* overloads */ &kOverloads[458],
},
{
/* [104] */
/* fn atomicAdd<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[457],
+ /* overloads */ &kOverloads[459],
},
{
/* [105] */
/* fn atomicSub<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[458],
+ /* overloads */ &kOverloads[460],
},
{
/* [106] */
/* fn atomicMax<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[459],
+ /* overloads */ &kOverloads[461],
},
{
/* [107] */
/* fn atomicMin<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[460],
+ /* overloads */ &kOverloads[462],
},
{
/* [108] */
/* fn atomicAnd<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[461],
+ /* overloads */ &kOverloads[463],
},
{
/* [109] */
/* fn atomicOr<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[462],
+ /* overloads */ &kOverloads[464],
},
{
/* [110] */
/* fn atomicXor<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[463],
+ /* overloads */ &kOverloads[465],
},
{
/* [111] */
/* fn atomicExchange<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[464],
+ /* overloads */ &kOverloads[466],
},
{
/* [112] */
/* fn atomicCompareExchangeWeak<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T, T) -> __atomic_compare_exchange_result<T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[465],
+ /* overloads */ &kOverloads[467],
},
{
/* [113] */
/* fn _tint_materialize<T>(T) -> T */
/* num overloads */ 1,
- /* overloads */ &kOverloads[466],
+ /* overloads */ &kOverloads[468],
},
};
@@ -14924,21 +14960,21 @@
/* op !(bool) -> bool */
/* op !<N : num>(vec<N, bool>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[407],
+ /* overloads */ &kOverloads[409],
},
{
/* [1] */
/* op ~<T : ia_iu32>(T) -> T */
/* op ~<T : ia_iu32, N : num>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[409],
+ /* overloads */ &kOverloads[411],
},
{
/* [2] */
/* op -<T : fia_fi32_f16>(T) -> T */
/* op -<T : fia_fi32_f16, N : num>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[411],
+ /* overloads */ &kOverloads[413],
},
};
constexpr uint8_t kUnaryOperatorNot = 0;
@@ -14954,7 +14990,7 @@
/* op +<T : fia_fiu32_f16, N : num>(T, vec<N, T>) -> vec<N, T> */
/* op +<T : fa_f32_f16, N : num, M : num>(mat<N, M, T>, mat<N, M, T>) -> mat<N, M, T> */
/* num overloads */ 5,
- /* overloads */ &kOverloads[231],
+ /* overloads */ &kOverloads[236],
},
{
/* [1] */
@@ -14964,7 +15000,7 @@
/* op -<T : fia_fiu32_f16, N : num>(T, vec<N, T>) -> vec<N, T> */
/* op -<T : fa_f32_f16, N : num, M : num>(mat<N, M, T>, mat<N, M, T>) -> mat<N, M, T> */
/* num overloads */ 5,
- /* overloads */ &kOverloads[236],
+ /* overloads */ &kOverloads[241],
},
{
/* [2] */
@@ -14987,7 +15023,7 @@
/* op /<T : fia_fiu32_f16, N : num>(vec<N, T>, T) -> vec<N, T> */
/* op /<T : fia_fiu32_f16, N : num>(T, vec<N, T>) -> vec<N, T> */
/* num overloads */ 4,
- /* overloads */ &kOverloads[241],
+ /* overloads */ &kOverloads[246],
},
{
/* [4] */
@@ -14996,14 +15032,14 @@
/* op %<T : fia_fiu32_f16, N : num>(vec<N, T>, T) -> vec<N, T> */
/* op %<T : fia_fiu32_f16, N : num>(T, vec<N, T>) -> vec<N, T> */
/* num overloads */ 4,
- /* overloads */ &kOverloads[245],
+ /* overloads */ &kOverloads[250],
},
{
/* [5] */
/* op ^<T : ia_iu32>(T, T) -> T */
/* op ^<T : ia_iu32, N : num>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[413],
+ /* overloads */ &kOverloads[415],
},
{
/* [6] */
@@ -15012,7 +15048,7 @@
/* op &<T : ia_iu32>(T, T) -> T */
/* op &<T : ia_iu32, N : num>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 4,
- /* overloads */ &kOverloads[249],
+ /* overloads */ &kOverloads[254],
},
{
/* [7] */
@@ -15021,75 +15057,75 @@
/* op |<T : ia_iu32>(T, T) -> T */
/* op |<T : ia_iu32, N : num>(vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 4,
- /* overloads */ &kOverloads[253],
+ /* overloads */ &kOverloads[258],
},
{
/* [8] */
/* op &&(bool, bool) -> bool */
/* num overloads */ 1,
- /* overloads */ &kOverloads[467],
+ /* overloads */ &kOverloads[469],
},
{
/* [9] */
/* op ||(bool, bool) -> bool */
/* num overloads */ 1,
- /* overloads */ &kOverloads[468],
+ /* overloads */ &kOverloads[470],
},
{
/* [10] */
/* op ==<T : scalar>(T, T) -> bool */
/* op ==<T : scalar, N : num>(vec<N, T>, vec<N, T>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[415],
+ /* overloads */ &kOverloads[417],
},
{
/* [11] */
/* op !=<T : scalar>(T, T) -> bool */
/* op !=<T : scalar, N : num>(vec<N, T>, vec<N, T>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[417],
+ /* overloads */ &kOverloads[419],
},
{
/* [12] */
/* op <<T : fia_fiu32_f16>(T, T) -> bool */
/* op <<T : fia_fiu32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[419],
+ /* overloads */ &kOverloads[421],
},
{
/* [13] */
/* op ><T : fia_fiu32_f16>(T, T) -> bool */
/* op ><T : fia_fiu32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[421],
+ /* overloads */ &kOverloads[423],
},
{
/* [14] */
/* op <=<T : fia_fiu32_f16>(T, T) -> bool */
/* op <=<T : fia_fiu32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[423],
+ /* overloads */ &kOverloads[425],
},
{
/* [15] */
/* op >=<T : fia_fiu32_f16>(T, T) -> bool */
/* op >=<T : fiu32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, bool> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[425],
+ /* overloads */ &kOverloads[427],
},
{
/* [16] */
/* op <<<T : ia_iu32>(T, u32) -> T */
/* op <<<T : ia_iu32, N : num>(vec<N, T>, vec<N, u32>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[427],
+ /* overloads */ &kOverloads[429],
},
{
/* [17] */
/* op >><T : ia_iu32>(T, u32) -> T */
/* op >><T : ia_iu32, N : num>(vec<N, T>, vec<N, u32>) -> vec<N, T> */
/* num overloads */ 2,
- /* overloads */ &kOverloads[429],
+ /* overloads */ &kOverloads[431],
},
};
constexpr uint8_t kBinaryOperatorPlus = 0;
@@ -15118,7 +15154,7 @@
/* ctor i32(i32) -> i32 */
/* conv i32<T : scalar_no_i32>(T) -> i32 */
/* num overloads */ 3,
- /* overloads */ &kOverloads[266],
+ /* overloads */ &kOverloads[268],
},
{
/* [1] */
@@ -15126,7 +15162,7 @@
/* ctor u32(u32) -> u32 */
/* conv u32<T : scalar_no_u32>(T) -> u32 */
/* num overloads */ 3,
- /* overloads */ &kOverloads[269],
+ /* overloads */ &kOverloads[271],
},
{
/* [2] */
@@ -15134,7 +15170,7 @@
/* ctor f32(f32) -> f32 */
/* conv f32<T : scalar_no_f32>(T) -> f32 */
/* num overloads */ 3,
- /* overloads */ &kOverloads[272],
+ /* overloads */ &kOverloads[274],
},
{
/* [3] */
@@ -15142,7 +15178,7 @@
/* ctor f16(f16) -> f16 */
/* conv f16<T : scalar_no_f16>(T) -> f16 */
/* num overloads */ 3,
- /* overloads */ &kOverloads[275],
+ /* overloads */ &kOverloads[277],
},
{
/* [4] */
@@ -15150,7 +15186,7 @@
/* ctor bool(bool) -> bool */
/* conv bool<T : scalar_no_bool>(T) -> bool */
/* num overloads */ 3,
- /* overloads */ &kOverloads[278],
+ /* overloads */ &kOverloads[280],
},
{
/* [5] */
@@ -15305,7 +15341,7 @@
/* [17] */
/* conv packedVec3<T : concrete_scalar>(vec3<T>) -> packedVec3<T> */
/* num overloads */ 1,
- /* overloads */ &kOverloads[469],
+ /* overloads */ &kOverloads[471],
},
};
diff --git a/src/tint/resolver/intrinsic_table_test.cc b/src/tint/resolver/intrinsic_table_test.cc
index 7f0399d..c842af5 100644
--- a/src/tint/resolver/intrinsic_table_test.cc
+++ b/src/tint/resolver/intrinsic_table_test.cc
@@ -37,7 +37,6 @@
using ::testing::HasSubstr;
-using BuiltinType = sem::BuiltinType;
using Parameter = sem::Parameter;
using ParameterUsage = sem::ParameterUsage;
@@ -54,11 +53,11 @@
TEST_F(IntrinsicTableTest, MatchF32) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kCos, utils::Vector{f32},
+ auto result = table->Lookup(builtin::Function::kCos, utils::Vector{f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kCos);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
@@ -66,7 +65,7 @@
TEST_F(IntrinsicTableTest, MismatchF32) {
auto* i32 = create<type::I32>();
- auto result = table->Lookup(BuiltinType::kCos, utils::Vector{i32},
+ auto result = table->Lookup(builtin::Function::kCos, utils::Vector{i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -76,11 +75,11 @@
auto* f32 = create<type::F32>();
auto* u32 = create<type::U32>();
auto* vec2_f32 = create<type::Vector>(f32, 2u);
- auto result = table->Lookup(BuiltinType::kUnpack2X16Float, utils::Vector{u32},
+ auto result = table->Lookup(builtin::Function::kUnpack2X16Float, utils::Vector{u32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kUnpack2X16Float);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kUnpack2X16Float);
EXPECT_EQ(result.sem->ReturnType(), vec2_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
@@ -88,7 +87,7 @@
TEST_F(IntrinsicTableTest, MismatchU32) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kUnpack2X16Float, utils::Vector{f32},
+ auto result = table->Lookup(builtin::Function::kUnpack2X16Float, utils::Vector{f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -99,11 +98,11 @@
auto* i32 = create<type::I32>();
auto* vec4_f32 = create<type::Vector>(f32, 4u);
auto* tex = create<type::SampledTexture>(type::TextureDimension::k1d, f32);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, i32, i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, i32, i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureLoad);
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -117,7 +116,7 @@
TEST_F(IntrinsicTableTest, MismatchI32) {
auto* f32 = create<type::F32>();
auto* tex = create<type::SampledTexture>(type::TextureDimension::k1d, f32);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, f32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -125,11 +124,11 @@
TEST_F(IntrinsicTableTest, MatchIU32AsI32) {
auto* i32 = create<type::I32>();
- auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{i32},
+ auto result = table->Lookup(builtin::Function::kCountOneBits, utils::Vector{i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kCountOneBits);
EXPECT_EQ(result.sem->ReturnType(), i32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), i32);
@@ -137,11 +136,11 @@
TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
auto* u32 = create<type::U32>();
- auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{u32},
+ auto result = table->Lookup(builtin::Function::kCountOneBits, utils::Vector{u32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kCountOneBits);
EXPECT_EQ(result.sem->ReturnType(), u32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
@@ -149,7 +148,7 @@
TEST_F(IntrinsicTableTest, MismatchIU32) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{f32},
+ auto result = table->Lookup(builtin::Function::kCountOneBits, utils::Vector{f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -157,11 +156,11 @@
TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
auto* i32 = create<type::I32>();
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{i32, i32, i32},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{i32, i32, i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kClamp);
EXPECT_EQ(result.sem->ReturnType(), i32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), i32);
@@ -171,11 +170,11 @@
TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
auto* u32 = create<type::U32>();
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{u32, u32, u32},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{u32, u32, u32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kClamp);
EXPECT_EQ(result.sem->ReturnType(), u32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
@@ -185,11 +184,11 @@
TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{f32, f32, f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kClamp);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
@@ -199,7 +198,7 @@
TEST_F(IntrinsicTableTest, MismatchFIU32) {
auto* bool_ = create<type::Bool>();
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{bool_, bool_, bool_},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{bool_, bool_, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -208,11 +207,11 @@
TEST_F(IntrinsicTableTest, MatchBool) {
auto* f32 = create<type::F32>();
auto* bool_ = create<type::Bool>();
- auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_},
+ auto result = table->Lookup(builtin::Function::kSelect, utils::Vector{f32, f32, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kSelect);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
@@ -222,7 +221,7 @@
TEST_F(IntrinsicTableTest, MismatchBool) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, f32},
+ auto result = table->Lookup(builtin::Function::kSelect, utils::Vector{f32, f32, f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -233,11 +232,11 @@
auto* atomicI32 = create<type::Atomic>(i32);
auto* ptr = create<type::Pointer>(atomicI32, builtin::AddressSpace::kWorkgroup,
builtin::Access::kReadWrite);
- auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr},
+ auto result = table->Lookup(builtin::Function::kAtomicLoad, utils::Vector{ptr},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kAtomicLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kAtomicLoad);
EXPECT_EQ(result.sem->ReturnType(), i32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), ptr);
@@ -246,7 +245,7 @@
TEST_F(IntrinsicTableTest, MismatchPointer) {
auto* i32 = create<type::I32>();
auto* atomicI32 = create<type::Atomic>(i32);
- auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{atomicI32},
+ auto result = table->Lookup(builtin::Function::kAtomicLoad, utils::Vector{atomicI32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -257,11 +256,11 @@
create<type::Array>(create<type::U32>(), create<type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
auto* arr_ptr =
create<type::Pointer>(arr, builtin::AddressSpace::kStorage, builtin::Access::kReadWrite);
- auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr},
+ auto result = table->Lookup(builtin::Function::kArrayLength, utils::Vector{arr_ptr},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kArrayLength);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kArrayLength);
EXPECT_TRUE(result.sem->ReturnType()->Is<type::U32>());
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
auto* param_type = result.sem->Parameters()[0]->Type();
@@ -271,7 +270,7 @@
TEST_F(IntrinsicTableTest, MismatchArray) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{f32},
+ auto result = table->Lookup(builtin::Function::kArrayLength, utils::Vector{f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -283,11 +282,12 @@
auto* vec4_f32 = create<type::Vector>(f32, 4u);
auto* tex = create<type::SampledTexture>(type::TextureDimension::k2d, f32);
auto* sampler = create<type::Sampler>(type::SamplerKind::kSampler);
- auto result = table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, sampler, vec2_f32},
- sem::EvaluationStage::kConstant, Source{});
+ auto result =
+ table->Lookup(builtin::Function::kTextureSample, utils::Vector{tex, sampler, vec2_f32},
+ sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureSample);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureSample);
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -302,8 +302,9 @@
auto* f32 = create<type::F32>();
auto* vec2_f32 = create<type::Vector>(f32, 2u);
auto* tex = create<type::SampledTexture>(type::TextureDimension::k2d, f32);
- auto result = table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, f32, vec2_f32},
- sem::EvaluationStage::kConstant, Source{});
+ auto result =
+ table->Lookup(builtin::Function::kTextureSample, utils::Vector{tex, f32, vec2_f32},
+ sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
}
@@ -314,11 +315,11 @@
auto* vec2_i32 = create<type::Vector>(i32, 2u);
auto* vec4_f32 = create<type::Vector>(f32, 4u);
auto* tex = create<type::SampledTexture>(type::TextureDimension::k2d, f32);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureLoad);
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -335,11 +336,11 @@
auto* vec2_i32 = create<type::Vector>(i32, 2u);
auto* vec4_f32 = create<type::Vector>(f32, 4u);
auto* tex = create<type::MultisampledTexture>(type::TextureDimension::k2d, f32);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureLoad);
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -355,11 +356,11 @@
auto* i32 = create<type::I32>();
auto* vec2_i32 = create<type::Vector>(i32, 2u);
auto* tex = create<type::DepthTexture>(type::TextureDimension::k2d);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureLoad);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -375,11 +376,11 @@
auto* i32 = create<type::I32>();
auto* vec2_i32 = create<type::Vector>(i32, 2u);
auto* tex = create<type::DepthMultisampledTexture>(type::TextureDimension::k2d);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureLoad);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -396,11 +397,11 @@
auto* vec2_i32 = create<type::Vector>(i32, 2u);
auto* vec4_f32 = create<type::Vector>(f32, 4u);
auto* tex = create<type::ExternalTexture>();
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{tex, vec2_i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureLoad);
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 2u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -419,11 +420,12 @@
create<type::StorageTexture>(type::TextureDimension::k2d, builtin::TexelFormat::kR32Float,
builtin::Access::kWrite, subtype);
- auto result = table->Lookup(BuiltinType::kTextureStore, utils::Vector{tex, vec2_i32, vec4_f32},
- sem::EvaluationStage::kConstant, Source{});
+ auto result =
+ table->Lookup(builtin::Function::kTextureStore, utils::Vector{tex, vec2_i32, vec4_f32},
+ sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureStore);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kTextureStore);
EXPECT_TRUE(result.sem->ReturnType()->Is<type::Void>());
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
@@ -438,7 +440,7 @@
auto* f32 = create<type::F32>();
auto* i32 = create<type::I32>();
auto* vec2_i32 = create<type::Vector>(i32, 2u);
- auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{f32, vec2_i32},
+ auto result = table->Lookup(builtin::Function::kTextureLoad, utils::Vector{f32, vec2_i32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -446,7 +448,7 @@
TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kCos,
+ auto result = table->Lookup(builtin::Function::kCos,
utils::Vector{
create<type::Reference>(f32, builtin::AddressSpace::kFunction,
builtin::Access::kReadWrite),
@@ -454,7 +456,7 @@
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kCos);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
@@ -462,11 +464,11 @@
TEST_F(IntrinsicTableTest, MatchTemplateType) {
auto* f32 = create<type::F32>();
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{f32, f32, f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kClamp);
EXPECT_EQ(result.sem->ReturnType(), f32);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
EXPECT_EQ(result.sem->Parameters()[1]->Type(), f32);
@@ -476,7 +478,7 @@
TEST_F(IntrinsicTableTest, MismatchTemplateType) {
auto* f32 = create<type::F32>();
auto* u32 = create<type::U32>();
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, u32, f32},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{f32, u32, f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -485,11 +487,12 @@
TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
auto* f32 = create<type::F32>();
auto* vec2_f32 = create<type::Vector>(f32, 2u);
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, vec2_f32, vec2_f32},
- sem::EvaluationStage::kConstant, Source{});
+ auto result =
+ table->Lookup(builtin::Function::kClamp, utils::Vector{vec2_f32, vec2_f32, vec2_f32},
+ sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kClamp);
EXPECT_EQ(result.sem->ReturnType(), vec2_f32);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), vec2_f32);
@@ -501,7 +504,7 @@
auto* f32 = create<type::F32>();
auto* u32 = create<type::U32>();
auto* vec2_f32 = create<type::Vector>(f32, 2u);
- auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, u32, vec2_f32},
+ auto result = table->Lookup(builtin::Function::kClamp, utils::Vector{vec2_f32, u32, vec2_f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -511,11 +514,11 @@
auto* f32 = create<type::F32>();
auto* vec3_f32 = create<type::Vector>(f32, 3u);
auto* mat3_f32 = create<type::Matrix>(vec3_f32, 3u);
- auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3_f32},
+ auto result = table->Lookup(builtin::Function::kDeterminant, utils::Vector{mat3_f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- EXPECT_EQ(result.sem->Type(), BuiltinType::kDeterminant);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kDeterminant);
EXPECT_EQ(result.sem->ReturnType(), f32);
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), mat3_f32);
@@ -525,7 +528,7 @@
auto* f32 = create<type::F32>();
auto* vec2_f32 = create<type::Vector>(f32, 2u);
auto* mat3x2_f32 = create<type::Matrix>(vec2_f32, 3u);
- auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3x2_f32},
+ auto result = table->Lookup(builtin::Function::kDeterminant, utils::Vector{mat3x2_f32},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -534,12 +537,12 @@
TEST_F(IntrinsicTableTest, MatchDifferentArgsElementType_Builtin_ConstantEval) {
auto* af = create<type::AbstractFloat>();
auto* bool_ = create<type::Bool>();
- auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{af, af, bool_},
+ auto result = table->Lookup(builtin::Function::kSelect, utils::Vector{af, af, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result.sem->Stage(), sem::EvaluationStage::kConstant);
- EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kSelect);
EXPECT_EQ(result.sem->ReturnType(), af);
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_EQ(result.sem->Parameters()[0]->Type(), af);
@@ -551,12 +554,12 @@
auto* af = create<type::AbstractFloat>();
auto* bool_ref = create<type::Reference>(create<type::Bool>(), builtin::AddressSpace::kFunction,
builtin::Access::kReadWrite);
- auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{af, af, bool_ref},
+ auto result = table->Lookup(builtin::Function::kSelect, utils::Vector{af, af, bool_ref},
sem::EvaluationStage::kRuntime, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result.sem->Stage(), sem::EvaluationStage::kConstant);
- EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
+ EXPECT_EQ(result.sem->Type(), builtin::Function::kSelect);
EXPECT_TRUE(result.sem->ReturnType()->Is<type::F32>());
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
EXPECT_TRUE(result.sem->Parameters()[0]->Type()->Is<type::F32>());
@@ -594,7 +597,7 @@
// None of the arguments match, so expect the overloads with 2 parameters to
// come first
auto* bool_ = create<type::Bool>();
- table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{bool_, bool_},
+ table->Lookup(builtin::Function::kTextureDimensions, utils::Vector{bool_, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(Diagnostics().str(),
R"(error: no matching call to textureDimensions(bool, bool)
@@ -633,7 +636,7 @@
TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) {
auto* tex = create<type::DepthTexture>(type::TextureDimension::k2d);
auto* bool_ = create<type::Bool>();
- table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{tex, bool_},
+ table->Lookup(builtin::Function::kTextureDimensions, utils::Vector{tex, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(Diagnostics().str(),
R"(error: no matching call to textureDimensions(texture_depth_2d, bool)
@@ -673,16 +676,16 @@
auto* f32 = create<type::F32>();
auto* vec2_f32 = create<type::Vector>(create<type::F32>(), 2u);
auto* bool_ = create<type::Bool>();
- auto a = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_},
+ auto a = table->Lookup(builtin::Function::kSelect, utils::Vector{f32, f32, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(a.sem, nullptr) << Diagnostics().str();
- auto b = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_},
+ auto b = table->Lookup(builtin::Function::kSelect, utils::Vector{f32, f32, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(b.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
- auto c = table->Lookup(BuiltinType::kSelect, utils::Vector{vec2_f32, vec2_f32, bool_},
+ auto c = table->Lookup(builtin::Function::kSelect, utils::Vector{vec2_f32, vec2_f32, bool_},
sem::EvaluationStage::kConstant, Source{});
ASSERT_NE(c.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
@@ -1022,7 +1025,7 @@
auto* f32 = create<type::F32>();
utils::Vector<const type::Type*, 0> arg_tys;
arg_tys.Resize(257, f32);
- auto result = table->Lookup(BuiltinType::kAbs, std::move(arg_tys),
+ auto result = table->Lookup(builtin::Function::kAbs, std::move(arg_tys),
sem::EvaluationStage::kConstant, Source{});
ASSERT_EQ(result.sem, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
@@ -1261,7 +1264,7 @@
auto* arg_a = GetParam().arg_a(*this);
auto* arg_b = GetParam().arg_b(*this);
auto* arg_c = GetParam().arg_c(*this);
- auto builtin = table->Lookup(sem::BuiltinType::kClamp, utils::Vector{arg_a, arg_b, arg_c},
+ auto builtin = table->Lookup(builtin::Function::kClamp, utils::Vector{arg_a, arg_b, arg_c},
sem::EvaluationStage::kConstant, Source{{12, 34}});
bool matched = builtin.sem != nullptr;
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index 839389a..6fa2010 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -16,6 +16,7 @@
#include "src/tint/resolver/resolver.h"
#include "src/tint/resolver/resolver_test_helper.h"
+#include "src/tint/switch.h"
#include "src/tint/type/test_helper.h"
#include "gmock/gmock.h"
@@ -939,7 +940,7 @@
break;
}
case Method::kTintMaterializeBuiltin: {
- auto* call = Call(sem::str(sem::BuiltinType::kTintMaterialize), abstract_expr());
+ auto* call = Call(builtin::str(builtin::Function::kTintMaterialize), abstract_expr());
WrapInFunction(Decl(Const("c", call)));
break;
}
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index f51e5cc..2cd40e9 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -260,7 +260,7 @@
ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS
}
- if (rhs && !validator_.VariableInitializer(v, builtin::AddressSpace::kUndefined, ty, rhs)) {
+ if (rhs && !validator_.VariableInitializer(v, ty, rhs)) {
return nullptr;
}
@@ -323,7 +323,7 @@
return nullptr;
}
- if (rhs && !validator_.VariableInitializer(v, builtin::AddressSpace::kUndefined, ty, rhs)) {
+ if (rhs && !validator_.VariableInitializer(v, ty, rhs)) {
return nullptr;
}
@@ -417,7 +417,7 @@
ty = rhs->Type();
}
- if (!validator_.VariableInitializer(c, builtin::AddressSpace::kUndefined, ty, rhs)) {
+ if (!validator_.VariableInitializer(c, ty, rhs)) {
return nullptr;
}
@@ -516,7 +516,7 @@
access = DefaultAccessForAddressSpace(address_space);
}
- if (rhs && !validator_.VariableInitializer(var, address_space, storage_ty, rhs)) {
+ if (rhs && !validator_.VariableInitializer(var, storage_ty, rhs)) {
return nullptr;
}
@@ -2156,7 +2156,12 @@
return Switch(
sem_.Get(ast_node), //
[&](type::Type* t) { return ty_init_or_conv(t); },
- [&](sem::Function* f) { return FunctionCall(expr, f, args, arg_behaviors); },
+ [&](sem::Function* f) -> sem::Call* {
+ if (!TINT_LIKELY(CheckNotTemplated("function", ident))) {
+ return nullptr;
+ }
+ return FunctionCall(expr, f, args, arg_behaviors);
+ },
[&](sem::Expression* e) {
sem_.ErrorUnexpectedExprKind(e, "call target");
return nullptr;
@@ -2167,7 +2172,10 @@
});
}
- if (auto f = resolved->BuiltinFunction(); f != sem::BuiltinType::kNone) {
+ if (auto f = resolved->BuiltinFunction(); f != builtin::Function::kNone) {
+ if (!TINT_LIKELY(CheckNotTemplated("builtin", ident))) {
+ return nullptr;
+ }
return BuiltinCall(expr, f, args);
}
@@ -2239,7 +2247,7 @@
template <size_t N>
sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
- sem::BuiltinType builtin_type,
+ builtin::Function builtin_type,
utils::Vector<const sem::ValueExpression*, N>& args) {
auto arg_stage = sem::EvaluationStage::kConstant;
for (auto* arg : args) {
@@ -2255,7 +2263,7 @@
}
}
- if (builtin_type == sem::BuiltinType::kTintMaterialize) {
+ if (builtin_type == builtin::Function::kTintMaterialize) {
args[0] = Materialize(args[0]);
if (!args[0]) {
return nullptr;
@@ -2307,14 +2315,14 @@
return nullptr;
}
- if (IsTextureBuiltin(builtin_type)) {
+ if (sem::IsTextureBuiltin(builtin_type)) {
if (!validator_.TextureBuiltinFunction(call)) {
return nullptr;
}
CollectTextureSamplerPairs(builtin.sem, call->Arguments());
}
- if (builtin_type == sem::BuiltinType::kWorkgroupUniformLoad) {
+ if (builtin_type == builtin::Function::kWorkgroupUniformLoad) {
if (!validator_.WorkgroupUniformLoad(call)) {
return nullptr;
}
@@ -2331,13 +2339,7 @@
auto& b = *builder_;
auto check_no_tmpl_args = [&](type::Type* ty) -> type::Type* {
- if (TINT_UNLIKELY(ident->Is<ast::TemplatedIdentifier>())) {
- AddError("type '" + b.Symbols().NameFor(ident->symbol) +
- "' does not take template arguments",
- ident->source);
- return nullptr;
- }
- return ty;
+ return TINT_LIKELY(CheckNotTemplated("type", ident)) ? ty : nullptr;
};
auto f32 = [&] { return b.create<type::F32>(); };
auto i32 = [&] { return b.create<type::I32>(); };
@@ -3019,25 +3021,15 @@
return user;
},
[&](const type::Type* ty) -> sem::TypeExpression* {
- if (TINT_UNLIKELY(ident->Is<ast::TemplatedIdentifier>())) {
- AddError("type '" + builder_->Symbols().NameFor(ident->symbol) +
- "' does not take template arguments",
- ident->source);
- sem_.NoteDeclarationSource(ast_node);
+ if (!TINT_LIKELY(CheckNotTemplated("type", ident))) {
return nullptr;
}
-
return builder_->create<sem::TypeExpression>(expr, current_statement_, ty);
},
[&](const sem::Function* fn) -> sem::FunctionExpression* {
- if (TINT_UNLIKELY(ident->Is<ast::TemplatedIdentifier>())) {
- AddError("function '" + builder_->Symbols().NameFor(ident->symbol) +
- "' does not take template arguments",
- ident->source);
- sem_.NoteDeclarationSource(ast_node);
+ if (!TINT_LIKELY(CheckNotTemplated("function", ident))) {
return nullptr;
}
-
return builder_->create<sem::FunctionExpression>(expr, current_statement_, fn);
});
}
@@ -3050,7 +3042,7 @@
return builder_->create<sem::TypeExpression>(expr, current_statement_, ty);
}
- if (resolved->BuiltinFunction() != sem::BuiltinType::kNone) {
+ if (resolved->BuiltinFunction() != builtin::Function::kNone) {
AddError("missing '(' for builtin function call", expr->source.End());
return nullptr;
}
@@ -3484,7 +3476,10 @@
}
bool Resolver::Enable(const ast::Enable* enable) {
- enabled_extensions_.Add(enable->extension);
+ for (auto* ext : enable->extensions) {
+ Mark(ext);
+ enabled_extensions_.Add(ext->name);
+ }
return true;
}
@@ -4282,6 +4277,16 @@
[&](const ast::BlockStatement* block) {
return handle_attributes(block, sem, "block statements");
},
+ [&](const ast::ForLoopStatement* f) {
+ return handle_attributes(f, sem, "for statements");
+ },
+ [&](const ast::IfStatement* i) { return handle_attributes(i, sem, "if statements"); },
+ [&](const ast::SwitchStatement* s) {
+ return handle_attributes(s, sem, "switch statements");
+ },
+ [&](const ast::WhileStatement* w) {
+ return handle_attributes(w, sem, "while statements");
+ },
[&](Default) { return true; })) {
return nullptr;
}
@@ -4329,6 +4334,21 @@
}
}
+bool Resolver::CheckNotTemplated(const char* use, const ast::Identifier* ident) {
+ if (TINT_UNLIKELY(ident->Is<ast::TemplatedIdentifier>())) {
+ AddError(std::string(use) + " '" + builder_->Symbols().NameFor(ident->symbol) +
+ "' does not take template arguments",
+ ident->source);
+ if (auto resolved = dependencies_.resolved_identifiers.Get(ident)) {
+ if (auto* ast_node = resolved->Node()) {
+ sem_.NoteDeclarationSource(ast_node);
+ }
+ }
+ return false;
+ }
+ return true;
+}
+
void Resolver::ErrorMismatchedResolvedIdentifier(const Source& source,
const ResolvedIdentifier& resolved,
std::string_view wanted) {
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 8acf602..266f3a2 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -204,7 +204,7 @@
sem::Expression* Identifier(const ast::IdentifierExpression*);
template <size_t N>
sem::Call* BuiltinCall(const ast::CallExpression*,
- sem::BuiltinType,
+ builtin::Function,
utils::Vector<const sem::ValueExpression*, N>& args);
sem::ValueExpression* Literal(const ast::LiteralExpression*);
sem::ValueExpression* MemberAccessor(const ast::MemberAccessorExpression*);
@@ -480,6 +480,11 @@
template <typename NODE>
void ApplyDiagnosticSeverities(NODE* node);
+ /// Checks @p ident is not an ast::TemplatedIdentifier.
+ /// If @p ident is a ast::TemplatedIdentifier, then an error diagnostic is raised.
+ /// @returns true if @p ident is not a ast::TemplatedIdentifier.
+ bool CheckNotTemplated(const char* use, const ast::Identifier* ident);
+
/// Raises an error diagnostic that the resolved identifier @p resolved was not of the expected
/// kind.
/// @param source the source of the error diagnostic
diff --git a/src/tint/resolver/sem_helper.cc b/src/tint/resolver/sem_helper.cc
index 45bdf41..36cc4c7 100644
--- a/src/tint/resolver/sem_helper.cc
+++ b/src/tint/resolver/sem_helper.cc
@@ -19,6 +19,7 @@
#include "src/tint/sem/function_expression.h"
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/value_expression.h"
+#include "src/tint/switch.h"
namespace tint::resolver {
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index bc4ac1d..7a4d25e 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -37,7 +37,9 @@
#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/variable.h"
#include "src/tint/sem/while_statement.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/block_allocator.h"
+#include "src/tint/utils/defer.h"
#include "src/tint/utils/map.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/utils/unique_vector.h"
@@ -45,6 +47,10 @@
// Set to `1` to dump the uniformity graph for each function in graphviz format.
#define TINT_DUMP_UNIFORMITY_GRAPH 0
+#if TINT_DUMP_UNIFORMITY_GRAPH
+#include <iostream>
+#endif
+
namespace tint::resolver {
namespace {
@@ -123,7 +129,7 @@
const ast::Node* ast = nullptr;
/// The function call argument index, if applicable.
- uint32_t arg_index;
+ uint32_t arg_index = 0xffffffffu;
/// The set of edges from this node to other nodes in the graph.
utils::UniqueVector<Node*, 4> edges;
@@ -547,14 +553,18 @@
stmt,
[&](const ast::AssignmentStatement* a) {
- auto [cf1, v1] = ProcessExpression(cf, a->rhs);
if (a->lhs->Is<ast::PhonyExpression>()) {
- return cf1;
- } else {
- auto [cf2, l2] = ProcessLValueExpression(cf1, a->lhs);
- l2->AddEdge(v1);
- return cf2;
+ auto [cf_r, _] = ProcessExpression(cf, a->rhs);
+ return cf_r;
}
+ auto [cf_l, v_l, ident] = ProcessLValueExpression(cf, a->lhs);
+ auto [cf_r, v_r] = ProcessExpression(cf_l, a->rhs);
+ v_l->AddEdge(v_r);
+
+ // Update the variable node for the LHS variable.
+ current_function_->variables.Set(ident, v_l);
+
+ return cf_r;
},
[&](const ast::BlockStatement* b) {
@@ -696,18 +706,31 @@
},
[&](const ast::CompoundAssignmentStatement* c) {
- // The compound assignment statement `a += b` is equivalent to `a = a + b`.
- // Note: we set load_rule=true when evaluating the LHS the first time, as the
- // resolver does not add a load node for it.
- auto [cf1, v1] = ProcessExpression(cf, c->lhs, /* load_rule */ true);
- auto [cf2, v2] = ProcessExpression(cf1, c->rhs);
- auto* result = CreateNode({"binary_expr_result"});
- result->AddEdge(v1);
- result->AddEdge(v2);
+ // The compound assignment statement `a += b` is equivalent to:
+ // let p = &a;
+ // *p = *p + b;
- auto [cf3, l3] = ProcessLValueExpression(cf2, c->lhs);
- l3->AddEdge(result);
- return cf3;
+ // Evaluate the LHS.
+ auto [cf1, l1, ident] = ProcessLValueExpression(cf, c->lhs);
+
+ // Get the current value loaded from the LHS reference before evaluating the RHS.
+ auto* lhs_load = current_function_->variables.Get(ident);
+
+ // Evaluate the RHS.
+ auto [cf2, v2] = ProcessExpression(cf1, c->rhs);
+
+ // Create a node for the resulting value.
+ auto* result = CreateNode({"binary_expr_result"});
+ result->AddEdge(v2);
+ if (lhs_load) {
+ result->AddEdge(lhs_load);
+ }
+
+ // Update the variable node for the LHS variable.
+ l1->AddEdge(result);
+ current_function_->variables.Set(ident, l1);
+
+ return cf2;
},
[&](const ast::ContinueStatement* c) {
@@ -958,16 +981,25 @@
[&](const ast::IncrementDecrementStatement* i) {
// The increment/decrement statement `i++` is equivalent to `i = i + 1`.
- // Note: we set load_rule=true when evaluating the LHS the first time, as the
- // resolver does not add a load node for it.
- auto [cf1, v1] = ProcessExpression(cf, i->lhs, /* load_rule */ true);
- auto* result = CreateNode({"incdec_result"});
- result->AddEdge(v1);
- result->AddEdge(cf1);
- auto [cf2, l2] = ProcessLValueExpression(cf1, i->lhs);
- l2->AddEdge(result);
- return cf2;
+ // Evaluate the LHS.
+ auto [cf1, l1, ident] = ProcessLValueExpression(cf, i->lhs);
+
+ // Get the current value loaded from the LHS reference.
+ auto* lhs_load = current_function_->variables.Get(ident);
+
+ // Create a node for the resulting value.
+ auto* result = CreateNode({"incdec_result"});
+ result->AddEdge(cf1);
+ if (lhs_load) {
+ result->AddEdge(lhs_load);
+ }
+
+ // Update the variable node for the LHS variable.
+ l1->AddEdge(result);
+ current_function_->variables.Set(ident, l1);
+
+ return cf1;
},
[&](const ast::LoopStatement* l) {
@@ -1365,48 +1397,60 @@
return false;
}
+ /// LValue holds the Nodes returned by ProcessLValueExpression()
+ struct LValue {
+ /// The control-flow node for an LValue expression
+ Node* cf = nullptr;
+
+ /// The new value node for an LValue expression
+ Node* new_val = nullptr;
+
+ /// The root identifier for an LValue expression.
+ const sem::Variable* root_identifier = nullptr;
+ };
+
/// Process an LValue expression.
/// @param cf the input control flow node
/// @param expr the expression to process
/// @returns a pair of (control flow node, variable node)
- std::pair<Node*, Node*> ProcessLValueExpression(Node* cf,
- const ast::Expression* expr,
- bool is_partial_reference = false) {
+ LValue ProcessLValueExpression(Node* cf,
+ const ast::Expression* expr,
+ bool is_partial_reference = false) {
return Switch(
expr,
[&](const ast::IdentifierExpression* i) {
auto* sem = sem_.GetVal(i)->UnwrapLoad()->As<sem::VariableUser>();
if (sem->Variable()->Is<sem::GlobalVariable>()) {
- return std::make_pair(cf, current_function_->may_be_non_uniform);
+ return LValue{cf, current_function_->may_be_non_uniform, nullptr};
} else if (auto* local = sem->Variable()->As<sem::LocalVariable>()) {
// Create a new value node for this variable.
auto* value = CreateNode({NameFor(i), "_lvalue"});
- auto* old_value = current_function_->variables.Set(local, value);
// If i is part of an expression that is a partial reference to a variable (e.g.
// index or member access), we link back to the variable's previous value. If
// the previous value was non-uniform, a partial assignment will not make it
// uniform.
+ auto* old_value = current_function_->variables.Get(local);
if (is_partial_reference && old_value) {
value->AddEdge(old_value);
}
- return std::make_pair(cf, value);
+ return LValue{cf, value, local};
} else {
TINT_ICE(Resolver, diagnostics_)
<< "unknown lvalue identifier expression type: "
<< std::string(sem->Variable()->TypeInfo().name);
- return std::pair<Node*, Node*>(nullptr, nullptr);
+ return LValue{};
}
},
[&](const ast::IndexAccessorExpression* i) {
- auto [cf1, l1] =
+ auto [cf1, l1, root_ident] =
ProcessLValueExpression(cf, i->object, /*is_partial_reference*/ true);
auto [cf2, v2] = ProcessExpression(cf1, i->index);
l1->AddEdge(v2);
- return std::pair<Node*, Node*>(cf2, l1);
+ return LValue{cf2, l1, root_ident};
},
[&](const ast::MemberAccessorExpression* m) {
@@ -1419,17 +1463,16 @@
// that is being written to.
auto* root_ident = sem_.Get(u)->RootIdentifier();
auto* deref = CreateNode({NameFor(root_ident), "_deref"});
- auto* old_value = current_function_->variables.Set(root_ident, deref);
- if (old_value) {
- // If derefercing a partial reference or partial pointer, we link back to
+ if (auto* old_value = current_function_->variables.Get(root_ident)) {
+ // If dereferencing a partial reference or partial pointer, we link back to
// the variable's previous value. If the previous value was non-uniform, a
// partial assignment will not make it uniform.
if (is_partial_reference || IsDerefOfPartialPointer(u)) {
deref->AddEdge(old_value);
}
}
- return std::pair<Node*, Node*>(cf, deref);
+ return LValue{cf, deref, root_ident};
}
return ProcessLValueExpression(cf, u->expr, is_partial_reference);
},
@@ -1437,7 +1480,7 @@
[&](Default) {
TINT_ICE(Resolver, diagnostics_)
<< "unknown lvalue expression type: " << std::string(expr->TypeInfo().name);
- return std::pair<Node*, Node*>(nullptr, nullptr);
+ return LValue{};
});
}
@@ -1514,12 +1557,12 @@
// some texture sampling builtins, and atomics.
if (builtin->IsBarrier()) {
callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, default_severity};
- } else if (builtin->Type() == sem::BuiltinType::kWorkgroupUniformLoad) {
+ } else if (builtin->Type() == builtin::Function::kWorkgroupUniformLoad) {
callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, default_severity};
} else if (builtin->IsDerivative() ||
- builtin->Type() == sem::BuiltinType::kTextureSample ||
- builtin->Type() == sem::BuiltinType::kTextureSampleBias ||
- builtin->Type() == sem::BuiltinType::kTextureSampleCompare) {
+ builtin->Type() == builtin::Function::kTextureSample ||
+ builtin->Type() == builtin::Function::kTextureSampleBias ||
+ builtin->Type() == builtin::Function::kTextureSampleCompare) {
// Get the severity of derivative uniformity violations in this context.
auto severity = sem_.DiagnosticSeverity(
call, builtin::DiagnosticRule::kDerivativeUniformity);
@@ -1626,7 +1669,7 @@
}
} else {
auto* builtin = sem->Target()->As<sem::Builtin>();
- if (builtin && builtin->Type() == sem::BuiltinType::kWorkgroupUniformLoad) {
+ if (builtin && builtin->Type() == builtin::Function::kWorkgroupUniformLoad) {
// The workgroupUniformLoad builtin requires its parameter to be uniform.
current_function_->RequiredToBeUniform(default_severity)->AddEdge(args[i]);
} else {
diff --git a/src/tint/resolver/uniformity_test.cc b/src/tint/resolver/uniformity_test.cc
index 51608bd..e166a06 100644
--- a/src/tint/resolver/uniformity_test.cc
+++ b/src/tint/resolver/uniformity_test.cc
@@ -7402,6 +7402,377 @@
)");
}
+TEST_F(UniformityAnalysisTest, CompoundAssignment_Global) {
+ // Use compound assignment on a global variable.
+ // Tests that we do not assume there is always a variable node for the LHS, but we still process
+ // the expression.
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> rw : i32;
+
+var<private> v : array<i32, 4>;
+
+fn bar(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ return 0;
+}
+
+fn foo() {
+ var f = rw;
+ v[bar(&f)] += 1;
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:8:5 error: 'workgroupBarrier' must only be called from uniform control flow
+ workgroupBarrier();
+ ^^^^^^^^^^^^^^^^
+
+test:7:3 note: control flow depends on possibly non-uniform value
+ if (*p == 0) {
+ ^^
+
+test:7:8 note: parameter 'p' of 'bar' may be non-uniform
+ if (*p == 0) {
+ ^
+
+test:15:9 note: possibly non-uniform value passed via pointer here
+ v[bar(&f)] += 1;
+ ^
+
+test:14:11 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+ var f = rw;
+ ^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, IncDec_StillNonUniform) {
+ // Use increment on a variable that is already non-uniform.
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> rw : i32;
+
+fn foo() {
+ var v = rw;
+ v++;
+ if (v == 0) {
+ workgroupBarrier();
+ }
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:8:5 error: 'workgroupBarrier' must only be called from uniform control flow
+ workgroupBarrier();
+ ^^^^^^^^^^^^^^^^
+
+test:7:3 note: control flow depends on possibly non-uniform value
+ if (v == 0) {
+ ^^
+
+test:5:11 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+ var v = rw;
+ ^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, IncDec_Global) {
+ // Use increment on a global variable.
+ // Tests that we do not assume there is always a variable node for the LHS, but we still process
+ // the expression.
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> rw : i32;
+
+var<private> v : array<i32, 4>;
+
+fn bar(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ return 0;
+}
+
+fn foo() {
+ var f = rw;
+ v[bar(&f)]++;
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:8:5 error: 'workgroupBarrier' must only be called from uniform control flow
+ workgroupBarrier();
+ ^^^^^^^^^^^^^^^^
+
+test:7:3 note: control flow depends on possibly non-uniform value
+ if (*p == 0) {
+ ^^
+
+test:7:8 note: parameter 'p' of 'bar' may be non-uniform
+ if (*p == 0) {
+ ^
+
+test:15:9 note: possibly non-uniform value passed via pointer here
+ v[bar(&f)]++;
+ ^
+
+test:14:11 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+ var f = rw;
+ ^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, AssignmentEval_LHS_Then_RHS_Pass) {
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn b(p : ptr<function, i32>) -> i32 {
+ *p = non_uniform;
+ return 0;
+}
+
+fn a(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ return 0;
+}
+
+fn foo() {
+ var i = 0;
+ var arr : array<i32, 4>;
+ arr[a(&i)] = arr[b(&i)];
+}
+)";
+
+ RunTest(src, true);
+}
+
+TEST_F(UniformityAnalysisTest, AssignmentEval_LHS_Then_RHS_Fail) {
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn a(p : ptr<function, i32>) -> i32 {
+ *p = non_uniform;
+ return 0;
+}
+
+fn b(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ return 0;
+}
+
+fn foo() {
+ var i = 0;
+ var arr : array<i32, 4>;
+ arr[a(&i)] = arr[b(&i)];
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:11:5 error: 'workgroupBarrier' must only be called from uniform control flow
+ workgroupBarrier();
+ ^^^^^^^^^^^^^^^^
+
+test:10:3 note: control flow depends on possibly non-uniform value
+ if (*p == 0) {
+ ^^
+
+test:10:8 note: parameter 'p' of 'b' may be non-uniform
+ if (*p == 0) {
+ ^
+
+test:19:22 note: possibly non-uniform value passed via pointer here
+ arr[a(&i)] = arr[b(&i)];
+ ^
+
+test:19:9 note: contents of pointer may become non-uniform after calling 'a'
+ arr[a(&i)] = arr[b(&i)];
+ ^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, CompoundAssignmentEval_LHS_Then_RHS_Pass) {
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn b(p : ptr<function, i32>) -> i32 {
+ *p = non_uniform;
+ return 0;
+}
+
+fn a(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ return 0;
+}
+
+fn foo() {
+ var i = 0;
+ var arr : array<i32, 4>;
+ arr[a(&i)] += arr[b(&i)];
+}
+)";
+
+ RunTest(src, true);
+}
+
+TEST_F(UniformityAnalysisTest, CompoundAssignmentEval_LHS_Then_RHS_Fail) {
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn a(p : ptr<function, i32>) -> i32 {
+ *p = non_uniform;
+ return 0;
+}
+
+fn b(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ return 0;
+}
+
+fn foo() {
+ var i = 0;
+ var arr : array<i32, 4>;
+ arr[a(&i)] += arr[b(&i)];
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:11:5 error: 'workgroupBarrier' must only be called from uniform control flow
+ workgroupBarrier();
+ ^^^^^^^^^^^^^^^^
+
+test:10:3 note: control flow depends on possibly non-uniform value
+ if (*p == 0) {
+ ^^
+
+test:10:8 note: parameter 'p' of 'b' may be non-uniform
+ if (*p == 0) {
+ ^
+
+test:19:23 note: possibly non-uniform value passed via pointer here
+ arr[a(&i)] += arr[b(&i)];
+ ^
+
+test:19:9 note: contents of pointer may become non-uniform after calling 'a'
+ arr[a(&i)] += arr[b(&i)];
+ ^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, CompoundAssignmentEval_RHS_Makes_LHS_NonUniform_After_Load) {
+ // Test that the LHS is loaded from before the RHS makes is evaluated.
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn bar(p : ptr<function, i32>) -> i32 {
+ *p = non_uniform;
+ return 0;
+}
+
+fn foo() {
+ var i = 0;
+ var arr : array<i32, 4>;
+ i += arr[bar(&i)];
+ if (i == 0) {
+ workgroupBarrier();
+ }
+}
+)";
+
+ RunTest(src, true);
+}
+
+TEST_F(UniformityAnalysisTest, CompoundAssignmentEval_RHS_Makes_LHS_Uniform_After_Load) {
+ // Test that the LHS is loaded from before the RHS makes is evaluated.
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn bar(p : ptr<function, i32>) -> i32 {
+ *p = 0;
+ return 0;
+}
+
+fn foo() {
+ var i = non_uniform;
+ var arr : array<i32, 4>;
+ i += arr[bar(&i)];
+ if (i == 0) {
+ workgroupBarrier();
+ }
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:14:5 error: 'workgroupBarrier' must only be called from uniform control flow
+ workgroupBarrier();
+ ^^^^^^^^^^^^^^^^
+
+test:13:3 note: control flow depends on possibly non-uniform value
+ if (i == 0) {
+ ^^
+
+test:10:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+ var i = non_uniform;
+ ^^^^^^^^^^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, CompoundAssignmentEval_LHS_OnlyOnce) {
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn bar(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ *p = non_uniform;
+ return 0;
+}
+
+fn foo(){
+ var f : i32 = 0;
+ var arr : array<i32, 4>;
+ arr[bar(&f)] += 1;
+}
+)";
+
+ RunTest(src, true);
+}
+
+TEST_F(UniformityAnalysisTest, IncDec_LHS_OnlyOnce) {
+ std::string src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn bar(p : ptr<function, i32>) -> i32 {
+ if (*p == 0) {
+ workgroupBarrier();
+ }
+ *p = non_uniform;
+ return 0;
+}
+
+fn foo(){
+ var f : i32 = 0;
+ var arr : array<i32, 4>;
+ arr[bar(&f)]++;
+}
+)";
+
+ RunTest(src, true);
+}
+
TEST_F(UniformityAnalysisTest, ShortCircuiting_UniformLHS) {
std::string src = R"(
@group(0) @binding(0) var<storage, read> uniform_global : i32;
@@ -8005,6 +8376,278 @@
}
}
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnForStatement_CallInInitializer) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(for (var b = (non_uniform == 42 && dpdx(1.0) > 0.0); false;) {
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'dpdx' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnForStatement_CallInCondition) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(for (; non_uniform == 42 && dpdx(1.0) > 0.0;) {
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'dpdx' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnForStatement_CallInIncrement) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(for (var b = false; false; b = (non_uniform == 42 && dpdx(1.0) > 0.0)) {
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'dpdx' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnForStatement_CallInBody) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+@group(0) @binding(1) var t : texture_2d<f32>;
+@group(0) @binding(2) var s : sampler;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(for (; non_uniform == 42;) {
+ let color = textureSample(t, s, vec2(0, 0));
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'textureSample' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnIfStatement_CallInCondition) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(if (non_uniform == 42 && dpdx(1.0) > 0.0) {
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'dpdx' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnIfStatement_CallInBody) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+@group(0) @binding(1) var t : texture_2d<f32>;
+@group(0) @binding(2) var s : sampler;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(if (non_uniform == 42) {
+ let color = textureSample(t, s, vec2(0, 0));
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'textureSample' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnIfStatement_CallInElse) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+@group(0) @binding(1) var t : texture_2d<f32>;
+@group(0) @binding(2) var s : sampler;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(if (non_uniform == 42) {
+ } else {
+ let color = textureSample(t, s, vec2(0, 0));
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'textureSample' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnSwitchStatement_CallInCondition) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(switch (i32(non_uniform == 42 && dpdx(1.0) > 0.0)) {
+ default {}
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'dpdx' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnSwitchStatement_CallInBody) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+@group(0) @binding(1) var t : texture_2d<f32>;
+@group(0) @binding(2) var s : sampler;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(switch (non_uniform) {
+ default {
+ let color = textureSample(t, s, vec2(0, 0));
+ }
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'textureSample' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnWhileStatement_CallInCondition) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(while (non_uniform == 42 && dpdx(1.0) > 0.0) {
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'dpdx' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
+TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnWhileStatement_CallInBody) {
+ auto& param = GetParam();
+ utils::StringStream ss;
+ ss << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+@group(0) @binding(1) var t : texture_2d<f32>;
+@group(0) @binding(2) var s : sampler;
+fn foo() {
+ )"
+ << "@diagnostic(" << param << ", derivative_uniformity)"
+ << R"(while (non_uniform == 42) {
+ let color = textureSample(t, s, vec2(0, 0));
+ }
+}
+)";
+
+ RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
+ if (param == builtin::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ utils::StringStream err;
+ err << ToStr(param) << ": 'textureSample' must only be called";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
INSTANTIATE_TEST_SUITE_P(UniformityAnalysisTest,
UniformityAnalysisDiagnosticFilterTest,
::testing::Values(builtin::DiagnosticSeverity::kError,
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index f8f4c4d..c3b8a3d 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -373,7 +373,6 @@
}
bool Validator::VariableInitializer(const ast::Variable* v,
- builtin::AddressSpace address_space,
const type::Type* storage_ty,
const sem::ValueExpression* initializer) const {
auto* initializer_ty = initializer->Type();
@@ -388,23 +387,6 @@
return false;
}
- if (v->Is<ast::Var>()) {
- switch (address_space) {
- case builtin::AddressSpace::kPrivate:
- case builtin::AddressSpace::kFunction:
- break; // Allowed an initializer
- default:
- // https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
- // Optionally has an initializer expression, if the variable is in the private or
- // function address spaces.
- AddError("var of address space '" + utils::ToString(address_space) +
- "' cannot have an initializer. var initializers are only supported "
- "for the address spaces 'private' and 'function'",
- v->source);
- return false;
- }
- }
-
return true;
}
@@ -728,6 +710,23 @@
}
}
+ if (var->initializer) {
+ switch (v->AddressSpace()) {
+ case builtin::AddressSpace::kPrivate:
+ case builtin::AddressSpace::kFunction:
+ break; // Allowed an initializer
+ default:
+ // https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
+ // Optionally has an initializer expression, if the variable is in the private or
+ // function address spaces.
+ AddError("var of address space '" + utils::ToString(v->AddressSpace()) +
+ "' cannot have an initializer. var initializers are only supported "
+ "for the address spaces 'private' and 'function'",
+ var->source);
+ return false;
+ }
+ }
+
if (!CheckTypeAccessAddressSpace(v->Type()->UnwrapRef(), v->Access(), v->AddressSpace(),
var->attributes, var->source)) {
return false;
diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h
index 45c98c8..e0e3051 100644
--- a/src/tint/resolver/validator.h
+++ b/src/tint/resolver/validator.h
@@ -429,12 +429,10 @@
/// Validates a variable initializer
/// @param v the variable to validate
- /// @param address_space the address space of the variable
/// @param storage_type the type of the storage
/// @param initializer the RHS initializer expression
/// @returns true on succes, false otherwise
bool VariableInitializer(const ast::Variable* v,
- builtin::AddressSpace address_space,
const type::Type* storage_type,
const sem::ValueExpression* initializer) const;
diff --git a/src/tint/resolver/variable_validation_test.cc b/src/tint/resolver/variable_validation_test.cc
index 6ca3a08..7f62e8e 100644
--- a/src/tint/resolver/variable_validation_test.cc
+++ b/src/tint/resolver/variable_validation_test.cc
@@ -58,6 +58,26 @@
EXPECT_EQ(r()->error(), "12:34 error: builtin 'storageBarrier' does not return a value");
}
+TEST_F(ResolverVariableValidationTest, GlobalVarNoAddressSpace) {
+ // var a : i32;
+ GlobalVar(Source{{12, 34}}, "a", ty.i32());
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: module-scope 'var' declarations that are not of texture or sampler types must provide an address space)");
+}
+
+TEST_F(ResolverVariableValidationTest, GlobalVarWithInitializerNoAddressSpace) {
+ // var a = 1;
+ GlobalVar(Source{{12, 34}}, "a", Expr(1_a));
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: module-scope 'var' declarations that are not of texture or sampler types must provide an address space)");
+}
+
TEST_F(ResolverVariableValidationTest, GlobalVarUsedAtModuleScope) {
// var<private> a : i32;
// var<private> b : i32 = a;
diff --git a/src/tint/sem/builtin.cc b/src/tint/sem/builtin.cc
index 4fd2c34..4f33ebb 100644
--- a/src/tint/sem/builtin.cc
+++ b/src/tint/sem/builtin.cc
@@ -27,74 +27,76 @@
namespace tint::sem {
const char* Builtin::str() const {
- return sem::str(type_);
+ return builtin::str(type_);
}
-bool IsCoarseDerivativeBuiltin(BuiltinType i) {
- return i == BuiltinType::kDpdxCoarse || i == BuiltinType::kDpdyCoarse ||
- i == BuiltinType::kFwidthCoarse;
+bool IsCoarseDerivativeBuiltin(builtin::Function i) {
+ return i == builtin::Function::kDpdxCoarse || i == builtin::Function::kDpdyCoarse ||
+ i == builtin::Function::kFwidthCoarse;
}
-bool IsFineDerivativeBuiltin(BuiltinType i) {
- return i == BuiltinType::kDpdxFine || i == BuiltinType::kDpdyFine ||
- i == BuiltinType::kFwidthFine;
+bool IsFineDerivativeBuiltin(builtin::Function i) {
+ return i == builtin::Function::kDpdxFine || i == builtin::Function::kDpdyFine ||
+ i == builtin::Function::kFwidthFine;
}
-bool IsDerivativeBuiltin(BuiltinType i) {
- return i == BuiltinType::kDpdx || i == BuiltinType::kDpdy || i == BuiltinType::kFwidth ||
- IsCoarseDerivativeBuiltin(i) || IsFineDerivativeBuiltin(i);
+bool IsDerivativeBuiltin(builtin::Function i) {
+ return i == builtin::Function::kDpdx || i == builtin::Function::kDpdy ||
+ i == builtin::Function::kFwidth || IsCoarseDerivativeBuiltin(i) ||
+ IsFineDerivativeBuiltin(i);
}
-bool IsTextureBuiltin(BuiltinType i) {
- return IsImageQueryBuiltin(i) || //
- i == BuiltinType::kTextureGather || //
- i == BuiltinType::kTextureGatherCompare || //
- i == BuiltinType::kTextureLoad || //
- i == BuiltinType::kTextureSample || //
- i == BuiltinType::kTextureSampleBaseClampToEdge || //
- i == BuiltinType::kTextureSampleBias || //
- i == BuiltinType::kTextureSampleCompare || //
- i == BuiltinType::kTextureSampleCompareLevel || //
- i == BuiltinType::kTextureSampleGrad || //
- i == BuiltinType::kTextureSampleLevel || //
- i == BuiltinType::kTextureStore;
+bool IsTextureBuiltin(builtin::Function i) {
+ return IsImageQueryBuiltin(i) || //
+ i == builtin::Function::kTextureGather || //
+ i == builtin::Function::kTextureGatherCompare || //
+ i == builtin::Function::kTextureLoad || //
+ i == builtin::Function::kTextureSample || //
+ i == builtin::Function::kTextureSampleBaseClampToEdge || //
+ i == builtin::Function::kTextureSampleBias || //
+ i == builtin::Function::kTextureSampleCompare || //
+ i == builtin::Function::kTextureSampleCompareLevel || //
+ i == builtin::Function::kTextureSampleGrad || //
+ i == builtin::Function::kTextureSampleLevel || //
+ i == builtin::Function::kTextureStore;
}
-bool IsImageQueryBuiltin(BuiltinType i) {
- return i == BuiltinType::kTextureDimensions || i == BuiltinType::kTextureNumLayers ||
- i == BuiltinType::kTextureNumLevels || i == BuiltinType::kTextureNumSamples;
+bool IsImageQueryBuiltin(builtin::Function i) {
+ return i == builtin::Function::kTextureDimensions ||
+ i == builtin::Function::kTextureNumLayers || i == builtin::Function::kTextureNumLevels ||
+ i == builtin::Function::kTextureNumSamples;
}
-bool IsDataPackingBuiltin(BuiltinType i) {
- return i == BuiltinType::kPack4X8Snorm || i == BuiltinType::kPack4X8Unorm ||
- i == BuiltinType::kPack2X16Snorm || i == BuiltinType::kPack2X16Unorm ||
- i == BuiltinType::kPack2X16Float;
+bool IsDataPackingBuiltin(builtin::Function i) {
+ return i == builtin::Function::kPack4X8Snorm || i == builtin::Function::kPack4X8Unorm ||
+ i == builtin::Function::kPack2X16Snorm || i == builtin::Function::kPack2X16Unorm ||
+ i == builtin::Function::kPack2X16Float;
}
-bool IsDataUnpackingBuiltin(BuiltinType i) {
- return i == BuiltinType::kUnpack4X8Snorm || i == BuiltinType::kUnpack4X8Unorm ||
- i == BuiltinType::kUnpack2X16Snorm || i == BuiltinType::kUnpack2X16Unorm ||
- i == BuiltinType::kUnpack2X16Float;
+bool IsDataUnpackingBuiltin(builtin::Function i) {
+ return i == builtin::Function::kUnpack4X8Snorm || i == builtin::Function::kUnpack4X8Unorm ||
+ i == builtin::Function::kUnpack2X16Snorm || i == builtin::Function::kUnpack2X16Unorm ||
+ i == builtin::Function::kUnpack2X16Float;
}
-bool IsBarrierBuiltin(BuiltinType i) {
- return i == BuiltinType::kWorkgroupBarrier || i == BuiltinType::kStorageBarrier;
+bool IsBarrierBuiltin(builtin::Function i) {
+ return i == builtin::Function::kWorkgroupBarrier || i == builtin::Function::kStorageBarrier;
}
-bool IsAtomicBuiltin(BuiltinType i) {
- return i == sem::BuiltinType::kAtomicLoad || i == sem::BuiltinType::kAtomicStore ||
- i == sem::BuiltinType::kAtomicAdd || i == sem::BuiltinType::kAtomicSub ||
- i == sem::BuiltinType::kAtomicMax || i == sem::BuiltinType::kAtomicMin ||
- i == sem::BuiltinType::kAtomicAnd || i == sem::BuiltinType::kAtomicOr ||
- i == sem::BuiltinType::kAtomicXor || i == sem::BuiltinType::kAtomicExchange ||
- i == sem::BuiltinType::kAtomicCompareExchangeWeak;
+bool IsAtomicBuiltin(builtin::Function i) {
+ return i == builtin::Function::kAtomicLoad || i == builtin::Function::kAtomicStore ||
+ i == builtin::Function::kAtomicAdd || i == builtin::Function::kAtomicSub ||
+ i == builtin::Function::kAtomicMax || i == builtin::Function::kAtomicMin ||
+ i == builtin::Function::kAtomicAnd || i == builtin::Function::kAtomicOr ||
+ i == builtin::Function::kAtomicXor || i == builtin::Function::kAtomicExchange ||
+ i == builtin::Function::kAtomicCompareExchangeWeak;
}
-bool IsDP4aBuiltin(BuiltinType i) {
- return i == sem::BuiltinType::kDot4I8Packed || i == sem::BuiltinType::kDot4U8Packed;
+bool IsDP4aBuiltin(builtin::Function i) {
+ return i == builtin::Function::kDot4I8Packed || i == builtin::Function::kDot4U8Packed;
}
-Builtin::Builtin(BuiltinType type,
+Builtin::Builtin(builtin::Function type,
const type::Type* return_type,
utils::VectorRef<Parameter*> parameters,
EvaluationStage eval_stage,
@@ -150,18 +152,18 @@
bool Builtin::HasSideEffects() const {
switch (type_) {
- case sem::BuiltinType::kAtomicAdd:
- case sem::BuiltinType::kAtomicAnd:
- case sem::BuiltinType::kAtomicCompareExchangeWeak:
- case sem::BuiltinType::kAtomicExchange:
- case sem::BuiltinType::kAtomicMax:
- case sem::BuiltinType::kAtomicMin:
- case sem::BuiltinType::kAtomicOr:
- case sem::BuiltinType::kAtomicStore:
- case sem::BuiltinType::kAtomicSub:
- case sem::BuiltinType::kAtomicXor:
- case sem::BuiltinType::kTextureStore:
- case sem::BuiltinType::kWorkgroupUniformLoad:
+ case builtin::Function::kAtomicAdd:
+ case builtin::Function::kAtomicAnd:
+ case builtin::Function::kAtomicCompareExchangeWeak:
+ case builtin::Function::kAtomicExchange:
+ case builtin::Function::kAtomicMax:
+ case builtin::Function::kAtomicMin:
+ case builtin::Function::kAtomicOr:
+ case builtin::Function::kAtomicStore:
+ case builtin::Function::kAtomicSub:
+ case builtin::Function::kAtomicXor:
+ case builtin::Function::kTextureStore:
+ case builtin::Function::kWorkgroupUniformLoad:
return true;
default:
break;
diff --git a/src/tint/sem/builtin.h b/src/tint/sem/builtin.h
index 55d882e..b535e72 100644
--- a/src/tint/sem/builtin.h
+++ b/src/tint/sem/builtin.h
@@ -19,7 +19,7 @@
#include <vector>
#include "src/tint/builtin/extension.h"
-#include "src/tint/sem/builtin_type.h"
+#include "src/tint/builtin/function.h"
#include "src/tint/sem/call_target.h"
#include "src/tint/sem/pipeline_stage_set.h"
#include "src/tint/utils/hash.h"
@@ -29,52 +29,52 @@
/// Determines if the given `i` is a coarse derivative
/// @param i the builtin type
/// @returns true if the given derivative is coarse.
-bool IsCoarseDerivativeBuiltin(BuiltinType i);
+bool IsCoarseDerivativeBuiltin(builtin::Function i);
/// Determines if the given `i` is a fine derivative
/// @param i the builtin type
/// @returns true if the given derivative is fine.
-bool IsFineDerivativeBuiltin(BuiltinType i);
+bool IsFineDerivativeBuiltin(builtin::Function i);
/// Determine if the given `i` is a derivative builtin
/// @param i the builtin type
/// @returns true if the given `i` is a derivative builtin
-bool IsDerivativeBuiltin(BuiltinType i);
+bool IsDerivativeBuiltin(builtin::Function i);
/// Determines if the given `i` is a texture operation builtin
/// @param i the builtin type
/// @returns true if the given `i` is a texture operation builtin
-bool IsTextureBuiltin(BuiltinType i);
+bool IsTextureBuiltin(builtin::Function i);
/// Determines if the given `i` is a image query builtin
/// @param i the builtin type
/// @returns true if the given `i` is a image query builtin
-bool IsImageQueryBuiltin(BuiltinType i);
+bool IsImageQueryBuiltin(builtin::Function i);
/// Determines if the given `i` is a data packing builtin
/// @param i the builtin
/// @returns true if the given `i` is a data packing builtin
-bool IsDataPackingBuiltin(BuiltinType i);
+bool IsDataPackingBuiltin(builtin::Function i);
/// Determines if the given `i` is a data unpacking builtin
/// @param i the builtin
/// @returns true if the given `i` is a data unpacking builtin
-bool IsDataUnpackingBuiltin(BuiltinType i);
+bool IsDataUnpackingBuiltin(builtin::Function i);
/// Determines if the given `i` is a barrier builtin
/// @param i the builtin
/// @returns true if the given `i` is a barrier builtin
-bool IsBarrierBuiltin(BuiltinType i);
+bool IsBarrierBuiltin(builtin::Function i);
/// Determines if the given `i` is a atomic builtin
/// @param i the builtin
/// @returns true if the given `i` is a atomic builtin
-bool IsAtomicBuiltin(BuiltinType i);
+bool IsAtomicBuiltin(builtin::Function i);
/// Determins if the given `i` is a DP4a builtin
/// @param i the builtin
/// @returns true if the given `i` is a DP4a builtin
-bool IsDP4aBuiltin(BuiltinType i);
+bool IsDP4aBuiltin(builtin::Function i);
/// Builtin holds the semantic information for a builtin function.
class Builtin final : public Castable<Builtin, CallTarget> {
@@ -87,7 +87,7 @@
/// @param supported_stages the pipeline stages that this builtin can be used in
/// @param is_deprecated true if the particular overload is considered deprecated
/// @param must_use true if the builtin was annotated with `@must_use`
- Builtin(BuiltinType type,
+ Builtin(builtin::Function type,
const type::Type* return_type,
utils::VectorRef<Parameter*> parameters,
EvaluationStage eval_stage,
@@ -99,7 +99,7 @@
~Builtin() override;
/// @return the type of the builtin
- BuiltinType Type() const { return type_; }
+ builtin::Function Type() const { return type_; }
/// @return the pipeline stages that this builtin can be used in
PipelineStageSet SupportedStages() const { return supported_stages_; }
@@ -151,7 +151,7 @@
builtin::Extension RequiredExtension() const;
private:
- const BuiltinType type_;
+ const builtin::Function type_;
const PipelineStageSet supported_stages_;
const bool is_deprecated_;
};
diff --git a/src/tint/sem/builtin_test.cc b/src/tint/sem/builtin_test.cc
index ff66e1b..ef63dc6 100644
--- a/src/tint/sem/builtin_test.cc
+++ b/src/tint/sem/builtin_test.cc
@@ -21,7 +21,7 @@
struct BuiltinData {
const char* name;
- BuiltinType builtin;
+ builtin::Function builtin;
};
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
@@ -29,98 +29,98 @@
return out;
}
-using BuiltinTypeTest = testing::TestWithParam<BuiltinData>;
+using BuiltinFunctionTest = testing::TestWithParam<BuiltinData>;
-TEST_P(BuiltinTypeTest, Parse) {
+TEST_P(BuiltinFunctionTest, Parse) {
auto param = GetParam();
- EXPECT_EQ(ParseBuiltinType(param.name), param.builtin);
+ EXPECT_EQ(builtin::ParseFunction(param.name), param.builtin);
}
INSTANTIATE_TEST_SUITE_P(
- BuiltinTypeTest,
- BuiltinTypeTest,
- testing::Values(BuiltinData{"abs", BuiltinType::kAbs},
- BuiltinData{"acos", BuiltinType::kAcos},
- BuiltinData{"all", BuiltinType::kAll},
- BuiltinData{"any", BuiltinType::kAny},
- BuiltinData{"arrayLength", BuiltinType::kArrayLength},
- BuiltinData{"asin", BuiltinType::kAsin},
- BuiltinData{"atan", BuiltinType::kAtan},
- BuiltinData{"atan2", BuiltinType::kAtan2},
- BuiltinData{"ceil", BuiltinType::kCeil},
- BuiltinData{"clamp", BuiltinType::kClamp},
- BuiltinData{"cos", BuiltinType::kCos},
- BuiltinData{"cosh", BuiltinType::kCosh},
- BuiltinData{"countOneBits", BuiltinType::kCountOneBits},
- BuiltinData{"cross", BuiltinType::kCross},
- BuiltinData{"determinant", BuiltinType::kDeterminant},
- BuiltinData{"distance", BuiltinType::kDistance},
- BuiltinData{"dot", BuiltinType::kDot},
- BuiltinData{"dot4I8Packed", BuiltinType::kDot4I8Packed},
- BuiltinData{"dot4U8Packed", BuiltinType::kDot4U8Packed},
- BuiltinData{"dpdx", BuiltinType::kDpdx},
- BuiltinData{"dpdxCoarse", BuiltinType::kDpdxCoarse},
- BuiltinData{"dpdxFine", BuiltinType::kDpdxFine},
- BuiltinData{"dpdy", BuiltinType::kDpdy},
- BuiltinData{"dpdyCoarse", BuiltinType::kDpdyCoarse},
- BuiltinData{"dpdyFine", BuiltinType::kDpdyFine},
- BuiltinData{"exp", BuiltinType::kExp},
- BuiltinData{"exp2", BuiltinType::kExp2},
- BuiltinData{"faceForward", BuiltinType::kFaceForward},
- BuiltinData{"floor", BuiltinType::kFloor},
- BuiltinData{"fma", BuiltinType::kFma},
- BuiltinData{"fract", BuiltinType::kFract},
- BuiltinData{"frexp", BuiltinType::kFrexp},
- BuiltinData{"fwidth", BuiltinType::kFwidth},
- BuiltinData{"fwidthCoarse", BuiltinType::kFwidthCoarse},
- BuiltinData{"fwidthFine", BuiltinType::kFwidthFine},
- BuiltinData{"inverseSqrt", BuiltinType::kInverseSqrt},
- BuiltinData{"ldexp", BuiltinType::kLdexp},
- BuiltinData{"length", BuiltinType::kLength},
- BuiltinData{"log", BuiltinType::kLog},
- BuiltinData{"log2", BuiltinType::kLog2},
- BuiltinData{"max", BuiltinType::kMax},
- BuiltinData{"min", BuiltinType::kMin},
- BuiltinData{"mix", BuiltinType::kMix},
- BuiltinData{"modf", BuiltinType::kModf},
- BuiltinData{"normalize", BuiltinType::kNormalize},
- BuiltinData{"pow", BuiltinType::kPow},
- BuiltinData{"reflect", BuiltinType::kReflect},
- BuiltinData{"reverseBits", BuiltinType::kReverseBits},
- BuiltinData{"round", BuiltinType::kRound},
- BuiltinData{"select", BuiltinType::kSelect},
- BuiltinData{"sign", BuiltinType::kSign},
- BuiltinData{"sin", BuiltinType::kSin},
- BuiltinData{"sinh", BuiltinType::kSinh},
- BuiltinData{"smoothstep", BuiltinType::kSmoothstep},
- BuiltinData{"sqrt", BuiltinType::kSqrt},
- BuiltinData{"step", BuiltinType::kStep},
- BuiltinData{"storageBarrier", BuiltinType::kStorageBarrier},
- BuiltinData{"tan", BuiltinType::kTan},
- BuiltinData{"tanh", BuiltinType::kTanh},
- BuiltinData{"textureDimensions", BuiltinType::kTextureDimensions},
- BuiltinData{"textureLoad", BuiltinType::kTextureLoad},
- BuiltinData{"textureNumLayers", BuiltinType::kTextureNumLayers},
- BuiltinData{"textureNumLevels", BuiltinType::kTextureNumLevels},
- BuiltinData{"textureNumSamples", BuiltinType::kTextureNumSamples},
- BuiltinData{"textureSample", BuiltinType::kTextureSample},
- BuiltinData{"textureSampleBias", BuiltinType::kTextureSampleBias},
- BuiltinData{"textureSampleCompare", BuiltinType::kTextureSampleCompare},
+ BuiltinFunctionTest,
+ BuiltinFunctionTest,
+ testing::Values(BuiltinData{"abs", builtin::Function::kAbs},
+ BuiltinData{"acos", builtin::Function::kAcos},
+ BuiltinData{"all", builtin::Function::kAll},
+ BuiltinData{"any", builtin::Function::kAny},
+ BuiltinData{"arrayLength", builtin::Function::kArrayLength},
+ BuiltinData{"asin", builtin::Function::kAsin},
+ BuiltinData{"atan", builtin::Function::kAtan},
+ BuiltinData{"atan2", builtin::Function::kAtan2},
+ BuiltinData{"ceil", builtin::Function::kCeil},
+ BuiltinData{"clamp", builtin::Function::kClamp},
+ BuiltinData{"cos", builtin::Function::kCos},
+ BuiltinData{"cosh", builtin::Function::kCosh},
+ BuiltinData{"countOneBits", builtin::Function::kCountOneBits},
+ BuiltinData{"cross", builtin::Function::kCross},
+ BuiltinData{"determinant", builtin::Function::kDeterminant},
+ BuiltinData{"distance", builtin::Function::kDistance},
+ BuiltinData{"dot", builtin::Function::kDot},
+ BuiltinData{"dot4I8Packed", builtin::Function::kDot4I8Packed},
+ BuiltinData{"dot4U8Packed", builtin::Function::kDot4U8Packed},
+ BuiltinData{"dpdx", builtin::Function::kDpdx},
+ BuiltinData{"dpdxCoarse", builtin::Function::kDpdxCoarse},
+ BuiltinData{"dpdxFine", builtin::Function::kDpdxFine},
+ BuiltinData{"dpdy", builtin::Function::kDpdy},
+ BuiltinData{"dpdyCoarse", builtin::Function::kDpdyCoarse},
+ BuiltinData{"dpdyFine", builtin::Function::kDpdyFine},
+ BuiltinData{"exp", builtin::Function::kExp},
+ BuiltinData{"exp2", builtin::Function::kExp2},
+ BuiltinData{"faceForward", builtin::Function::kFaceForward},
+ BuiltinData{"floor", builtin::Function::kFloor},
+ BuiltinData{"fma", builtin::Function::kFma},
+ BuiltinData{"fract", builtin::Function::kFract},
+ BuiltinData{"frexp", builtin::Function::kFrexp},
+ BuiltinData{"fwidth", builtin::Function::kFwidth},
+ BuiltinData{"fwidthCoarse", builtin::Function::kFwidthCoarse},
+ BuiltinData{"fwidthFine", builtin::Function::kFwidthFine},
+ BuiltinData{"inverseSqrt", builtin::Function::kInverseSqrt},
+ BuiltinData{"ldexp", builtin::Function::kLdexp},
+ BuiltinData{"length", builtin::Function::kLength},
+ BuiltinData{"log", builtin::Function::kLog},
+ BuiltinData{"log2", builtin::Function::kLog2},
+ BuiltinData{"max", builtin::Function::kMax},
+ BuiltinData{"min", builtin::Function::kMin},
+ BuiltinData{"mix", builtin::Function::kMix},
+ BuiltinData{"modf", builtin::Function::kModf},
+ BuiltinData{"normalize", builtin::Function::kNormalize},
+ BuiltinData{"pow", builtin::Function::kPow},
+ BuiltinData{"reflect", builtin::Function::kReflect},
+ BuiltinData{"reverseBits", builtin::Function::kReverseBits},
+ BuiltinData{"round", builtin::Function::kRound},
+ BuiltinData{"select", builtin::Function::kSelect},
+ BuiltinData{"sign", builtin::Function::kSign},
+ BuiltinData{"sin", builtin::Function::kSin},
+ BuiltinData{"sinh", builtin::Function::kSinh},
+ BuiltinData{"smoothstep", builtin::Function::kSmoothstep},
+ BuiltinData{"sqrt", builtin::Function::kSqrt},
+ BuiltinData{"step", builtin::Function::kStep},
+ BuiltinData{"storageBarrier", builtin::Function::kStorageBarrier},
+ BuiltinData{"tan", builtin::Function::kTan},
+ BuiltinData{"tanh", builtin::Function::kTanh},
+ BuiltinData{"textureDimensions", builtin::Function::kTextureDimensions},
+ BuiltinData{"textureLoad", builtin::Function::kTextureLoad},
+ BuiltinData{"textureNumLayers", builtin::Function::kTextureNumLayers},
+ BuiltinData{"textureNumLevels", builtin::Function::kTextureNumLevels},
+ BuiltinData{"textureNumSamples", builtin::Function::kTextureNumSamples},
+ BuiltinData{"textureSample", builtin::Function::kTextureSample},
+ BuiltinData{"textureSampleBias", builtin::Function::kTextureSampleBias},
+ BuiltinData{"textureSampleCompare", builtin::Function::kTextureSampleCompare},
BuiltinData{"textureSampleCompareLevel",
- BuiltinType::kTextureSampleCompareLevel},
- BuiltinData{"textureSampleGrad", BuiltinType::kTextureSampleGrad},
- BuiltinData{"textureSampleLevel", BuiltinType::kTextureSampleLevel},
- BuiltinData{"trunc", BuiltinType::kTrunc},
- BuiltinData{"unpack2x16float", BuiltinType::kUnpack2X16Float},
- BuiltinData{"unpack2x16snorm", BuiltinType::kUnpack2X16Snorm},
- BuiltinData{"unpack2x16unorm", BuiltinType::kUnpack2X16Unorm},
- BuiltinData{"unpack4x8snorm", BuiltinType::kUnpack4X8Snorm},
- BuiltinData{"unpack4x8unorm", BuiltinType::kUnpack4X8Unorm},
- BuiltinData{"workgroupBarrier", BuiltinType::kWorkgroupBarrier},
- BuiltinData{"workgroupUniformLoad", BuiltinType::kWorkgroupUniformLoad}));
+ builtin::Function::kTextureSampleCompareLevel},
+ BuiltinData{"textureSampleGrad", builtin::Function::kTextureSampleGrad},
+ BuiltinData{"textureSampleLevel", builtin::Function::kTextureSampleLevel},
+ BuiltinData{"trunc", builtin::Function::kTrunc},
+ BuiltinData{"unpack2x16float", builtin::Function::kUnpack2X16Float},
+ BuiltinData{"unpack2x16snorm", builtin::Function::kUnpack2X16Snorm},
+ BuiltinData{"unpack2x16unorm", builtin::Function::kUnpack2X16Unorm},
+ BuiltinData{"unpack4x8snorm", builtin::Function::kUnpack4X8Snorm},
+ BuiltinData{"unpack4x8unorm", builtin::Function::kUnpack4X8Unorm},
+ BuiltinData{"workgroupBarrier", builtin::Function::kWorkgroupBarrier},
+ BuiltinData{"workgroupUniformLoad", builtin::Function::kWorkgroupUniformLoad}));
-TEST_F(BuiltinTypeTest, ParseNoMatch) {
- EXPECT_EQ(ParseBuiltinType("not_builtin"), BuiltinType::kNone);
+TEST_F(BuiltinFunctionTest, ParseNoMatch) {
+ EXPECT_EQ(builtin::ParseFunction("not_builtin"), builtin::Function::kNone);
}
} // namespace
diff --git a/src/tint/sem/builtin_type.cc b/src/tint/sem/builtin_type.cc
deleted file mode 100644
index 8abcec0..0000000
--- a/src/tint/sem/builtin_type.cc
+++ /dev/null
@@ -1,614 +0,0 @@
-// Copyright 2021 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by tools/src/cmd/gen
-// using the template:
-// src/tint/sem/builtin_type.cc.tmpl
-//
-// Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/tint/sem/builtin_type.h"
-
-namespace tint::sem {
-
-BuiltinType ParseBuiltinType(const std::string& name) {
- if (name == "abs") {
- return BuiltinType::kAbs;
- }
- if (name == "acos") {
- return BuiltinType::kAcos;
- }
- if (name == "acosh") {
- return BuiltinType::kAcosh;
- }
- if (name == "all") {
- return BuiltinType::kAll;
- }
- if (name == "any") {
- return BuiltinType::kAny;
- }
- if (name == "arrayLength") {
- return BuiltinType::kArrayLength;
- }
- if (name == "asin") {
- return BuiltinType::kAsin;
- }
- if (name == "asinh") {
- return BuiltinType::kAsinh;
- }
- if (name == "atan") {
- return BuiltinType::kAtan;
- }
- if (name == "atan2") {
- return BuiltinType::kAtan2;
- }
- if (name == "atanh") {
- return BuiltinType::kAtanh;
- }
- if (name == "ceil") {
- return BuiltinType::kCeil;
- }
- if (name == "clamp") {
- return BuiltinType::kClamp;
- }
- if (name == "cos") {
- return BuiltinType::kCos;
- }
- if (name == "cosh") {
- return BuiltinType::kCosh;
- }
- if (name == "countLeadingZeros") {
- return BuiltinType::kCountLeadingZeros;
- }
- if (name == "countOneBits") {
- return BuiltinType::kCountOneBits;
- }
- if (name == "countTrailingZeros") {
- return BuiltinType::kCountTrailingZeros;
- }
- if (name == "cross") {
- return BuiltinType::kCross;
- }
- if (name == "degrees") {
- return BuiltinType::kDegrees;
- }
- if (name == "determinant") {
- return BuiltinType::kDeterminant;
- }
- if (name == "distance") {
- return BuiltinType::kDistance;
- }
- if (name == "dot") {
- return BuiltinType::kDot;
- }
- if (name == "dot4I8Packed") {
- return BuiltinType::kDot4I8Packed;
- }
- if (name == "dot4U8Packed") {
- return BuiltinType::kDot4U8Packed;
- }
- if (name == "dpdx") {
- return BuiltinType::kDpdx;
- }
- if (name == "dpdxCoarse") {
- return BuiltinType::kDpdxCoarse;
- }
- if (name == "dpdxFine") {
- return BuiltinType::kDpdxFine;
- }
- if (name == "dpdy") {
- return BuiltinType::kDpdy;
- }
- if (name == "dpdyCoarse") {
- return BuiltinType::kDpdyCoarse;
- }
- if (name == "dpdyFine") {
- return BuiltinType::kDpdyFine;
- }
- if (name == "exp") {
- return BuiltinType::kExp;
- }
- if (name == "exp2") {
- return BuiltinType::kExp2;
- }
- if (name == "extractBits") {
- return BuiltinType::kExtractBits;
- }
- if (name == "faceForward") {
- return BuiltinType::kFaceForward;
- }
- if (name == "firstLeadingBit") {
- return BuiltinType::kFirstLeadingBit;
- }
- if (name == "firstTrailingBit") {
- return BuiltinType::kFirstTrailingBit;
- }
- if (name == "floor") {
- return BuiltinType::kFloor;
- }
- if (name == "fma") {
- return BuiltinType::kFma;
- }
- if (name == "fract") {
- return BuiltinType::kFract;
- }
- if (name == "frexp") {
- return BuiltinType::kFrexp;
- }
- if (name == "fwidth") {
- return BuiltinType::kFwidth;
- }
- if (name == "fwidthCoarse") {
- return BuiltinType::kFwidthCoarse;
- }
- if (name == "fwidthFine") {
- return BuiltinType::kFwidthFine;
- }
- if (name == "insertBits") {
- return BuiltinType::kInsertBits;
- }
- if (name == "inverseSqrt") {
- return BuiltinType::kInverseSqrt;
- }
- if (name == "ldexp") {
- return BuiltinType::kLdexp;
- }
- if (name == "length") {
- return BuiltinType::kLength;
- }
- if (name == "log") {
- return BuiltinType::kLog;
- }
- if (name == "log2") {
- return BuiltinType::kLog2;
- }
- if (name == "max") {
- return BuiltinType::kMax;
- }
- if (name == "min") {
- return BuiltinType::kMin;
- }
- if (name == "mix") {
- return BuiltinType::kMix;
- }
- if (name == "modf") {
- return BuiltinType::kModf;
- }
- if (name == "normalize") {
- return BuiltinType::kNormalize;
- }
- if (name == "pack2x16float") {
- return BuiltinType::kPack2X16Float;
- }
- if (name == "pack2x16snorm") {
- return BuiltinType::kPack2X16Snorm;
- }
- if (name == "pack2x16unorm") {
- return BuiltinType::kPack2X16Unorm;
- }
- if (name == "pack4x8snorm") {
- return BuiltinType::kPack4X8Snorm;
- }
- if (name == "pack4x8unorm") {
- return BuiltinType::kPack4X8Unorm;
- }
- if (name == "pow") {
- return BuiltinType::kPow;
- }
- if (name == "quantizeToF16") {
- return BuiltinType::kQuantizeToF16;
- }
- if (name == "radians") {
- return BuiltinType::kRadians;
- }
- if (name == "reflect") {
- return BuiltinType::kReflect;
- }
- if (name == "refract") {
- return BuiltinType::kRefract;
- }
- if (name == "reverseBits") {
- return BuiltinType::kReverseBits;
- }
- if (name == "round") {
- return BuiltinType::kRound;
- }
- if (name == "saturate") {
- return BuiltinType::kSaturate;
- }
- if (name == "select") {
- return BuiltinType::kSelect;
- }
- if (name == "sign") {
- return BuiltinType::kSign;
- }
- if (name == "sin") {
- return BuiltinType::kSin;
- }
- if (name == "sinh") {
- return BuiltinType::kSinh;
- }
- if (name == "smoothstep") {
- return BuiltinType::kSmoothstep;
- }
- if (name == "sqrt") {
- return BuiltinType::kSqrt;
- }
- if (name == "step") {
- return BuiltinType::kStep;
- }
- if (name == "storageBarrier") {
- return BuiltinType::kStorageBarrier;
- }
- if (name == "tan") {
- return BuiltinType::kTan;
- }
- if (name == "tanh") {
- return BuiltinType::kTanh;
- }
- if (name == "transpose") {
- return BuiltinType::kTranspose;
- }
- if (name == "trunc") {
- return BuiltinType::kTrunc;
- }
- if (name == "unpack2x16float") {
- return BuiltinType::kUnpack2X16Float;
- }
- if (name == "unpack2x16snorm") {
- return BuiltinType::kUnpack2X16Snorm;
- }
- if (name == "unpack2x16unorm") {
- return BuiltinType::kUnpack2X16Unorm;
- }
- if (name == "unpack4x8snorm") {
- return BuiltinType::kUnpack4X8Snorm;
- }
- if (name == "unpack4x8unorm") {
- return BuiltinType::kUnpack4X8Unorm;
- }
- if (name == "workgroupBarrier") {
- return BuiltinType::kWorkgroupBarrier;
- }
- if (name == "workgroupUniformLoad") {
- return BuiltinType::kWorkgroupUniformLoad;
- }
- if (name == "textureDimensions") {
- return BuiltinType::kTextureDimensions;
- }
- if (name == "textureGather") {
- return BuiltinType::kTextureGather;
- }
- if (name == "textureGatherCompare") {
- return BuiltinType::kTextureGatherCompare;
- }
- if (name == "textureNumLayers") {
- return BuiltinType::kTextureNumLayers;
- }
- if (name == "textureNumLevels") {
- return BuiltinType::kTextureNumLevels;
- }
- if (name == "textureNumSamples") {
- return BuiltinType::kTextureNumSamples;
- }
- if (name == "textureSample") {
- return BuiltinType::kTextureSample;
- }
- if (name == "textureSampleBias") {
- return BuiltinType::kTextureSampleBias;
- }
- if (name == "textureSampleCompare") {
- return BuiltinType::kTextureSampleCompare;
- }
- if (name == "textureSampleCompareLevel") {
- return BuiltinType::kTextureSampleCompareLevel;
- }
- if (name == "textureSampleGrad") {
- return BuiltinType::kTextureSampleGrad;
- }
- if (name == "textureSampleLevel") {
- return BuiltinType::kTextureSampleLevel;
- }
- if (name == "textureSampleBaseClampToEdge") {
- return BuiltinType::kTextureSampleBaseClampToEdge;
- }
- if (name == "textureStore") {
- return BuiltinType::kTextureStore;
- }
- if (name == "textureLoad") {
- return BuiltinType::kTextureLoad;
- }
- if (name == "atomicLoad") {
- return BuiltinType::kAtomicLoad;
- }
- if (name == "atomicStore") {
- return BuiltinType::kAtomicStore;
- }
- if (name == "atomicAdd") {
- return BuiltinType::kAtomicAdd;
- }
- if (name == "atomicSub") {
- return BuiltinType::kAtomicSub;
- }
- if (name == "atomicMax") {
- return BuiltinType::kAtomicMax;
- }
- if (name == "atomicMin") {
- return BuiltinType::kAtomicMin;
- }
- if (name == "atomicAnd") {
- return BuiltinType::kAtomicAnd;
- }
- if (name == "atomicOr") {
- return BuiltinType::kAtomicOr;
- }
- if (name == "atomicXor") {
- return BuiltinType::kAtomicXor;
- }
- if (name == "atomicExchange") {
- return BuiltinType::kAtomicExchange;
- }
- if (name == "atomicCompareExchangeWeak") {
- return BuiltinType::kAtomicCompareExchangeWeak;
- }
- if (name == "_tint_materialize") {
- return BuiltinType::kTintMaterialize;
- }
- return BuiltinType::kNone;
-}
-
-const char* str(BuiltinType i) {
- switch (i) {
- case BuiltinType::kNone:
- return "<none>";
- case BuiltinType::kAbs:
- return "abs";
- case BuiltinType::kAcos:
- return "acos";
- case BuiltinType::kAcosh:
- return "acosh";
- case BuiltinType::kAll:
- return "all";
- case BuiltinType::kAny:
- return "any";
- case BuiltinType::kArrayLength:
- return "arrayLength";
- case BuiltinType::kAsin:
- return "asin";
- case BuiltinType::kAsinh:
- return "asinh";
- case BuiltinType::kAtan:
- return "atan";
- case BuiltinType::kAtan2:
- return "atan2";
- case BuiltinType::kAtanh:
- return "atanh";
- case BuiltinType::kCeil:
- return "ceil";
- case BuiltinType::kClamp:
- return "clamp";
- case BuiltinType::kCos:
- return "cos";
- case BuiltinType::kCosh:
- return "cosh";
- case BuiltinType::kCountLeadingZeros:
- return "countLeadingZeros";
- case BuiltinType::kCountOneBits:
- return "countOneBits";
- case BuiltinType::kCountTrailingZeros:
- return "countTrailingZeros";
- case BuiltinType::kCross:
- return "cross";
- case BuiltinType::kDegrees:
- return "degrees";
- case BuiltinType::kDeterminant:
- return "determinant";
- case BuiltinType::kDistance:
- return "distance";
- case BuiltinType::kDot:
- return "dot";
- case BuiltinType::kDot4I8Packed:
- return "dot4I8Packed";
- case BuiltinType::kDot4U8Packed:
- return "dot4U8Packed";
- case BuiltinType::kDpdx:
- return "dpdx";
- case BuiltinType::kDpdxCoarse:
- return "dpdxCoarse";
- case BuiltinType::kDpdxFine:
- return "dpdxFine";
- case BuiltinType::kDpdy:
- return "dpdy";
- case BuiltinType::kDpdyCoarse:
- return "dpdyCoarse";
- case BuiltinType::kDpdyFine:
- return "dpdyFine";
- case BuiltinType::kExp:
- return "exp";
- case BuiltinType::kExp2:
- return "exp2";
- case BuiltinType::kExtractBits:
- return "extractBits";
- case BuiltinType::kFaceForward:
- return "faceForward";
- case BuiltinType::kFirstLeadingBit:
- return "firstLeadingBit";
- case BuiltinType::kFirstTrailingBit:
- return "firstTrailingBit";
- case BuiltinType::kFloor:
- return "floor";
- case BuiltinType::kFma:
- return "fma";
- case BuiltinType::kFract:
- return "fract";
- case BuiltinType::kFrexp:
- return "frexp";
- case BuiltinType::kFwidth:
- return "fwidth";
- case BuiltinType::kFwidthCoarse:
- return "fwidthCoarse";
- case BuiltinType::kFwidthFine:
- return "fwidthFine";
- case BuiltinType::kInsertBits:
- return "insertBits";
- case BuiltinType::kInverseSqrt:
- return "inverseSqrt";
- case BuiltinType::kLdexp:
- return "ldexp";
- case BuiltinType::kLength:
- return "length";
- case BuiltinType::kLog:
- return "log";
- case BuiltinType::kLog2:
- return "log2";
- case BuiltinType::kMax:
- return "max";
- case BuiltinType::kMin:
- return "min";
- case BuiltinType::kMix:
- return "mix";
- case BuiltinType::kModf:
- return "modf";
- case BuiltinType::kNormalize:
- return "normalize";
- case BuiltinType::kPack2X16Float:
- return "pack2x16float";
- case BuiltinType::kPack2X16Snorm:
- return "pack2x16snorm";
- case BuiltinType::kPack2X16Unorm:
- return "pack2x16unorm";
- case BuiltinType::kPack4X8Snorm:
- return "pack4x8snorm";
- case BuiltinType::kPack4X8Unorm:
- return "pack4x8unorm";
- case BuiltinType::kPow:
- return "pow";
- case BuiltinType::kQuantizeToF16:
- return "quantizeToF16";
- case BuiltinType::kRadians:
- return "radians";
- case BuiltinType::kReflect:
- return "reflect";
- case BuiltinType::kRefract:
- return "refract";
- case BuiltinType::kReverseBits:
- return "reverseBits";
- case BuiltinType::kRound:
- return "round";
- case BuiltinType::kSaturate:
- return "saturate";
- case BuiltinType::kSelect:
- return "select";
- case BuiltinType::kSign:
- return "sign";
- case BuiltinType::kSin:
- return "sin";
- case BuiltinType::kSinh:
- return "sinh";
- case BuiltinType::kSmoothstep:
- return "smoothstep";
- case BuiltinType::kSqrt:
- return "sqrt";
- case BuiltinType::kStep:
- return "step";
- case BuiltinType::kStorageBarrier:
- return "storageBarrier";
- case BuiltinType::kTan:
- return "tan";
- case BuiltinType::kTanh:
- return "tanh";
- case BuiltinType::kTranspose:
- return "transpose";
- case BuiltinType::kTrunc:
- return "trunc";
- case BuiltinType::kUnpack2X16Float:
- return "unpack2x16float";
- case BuiltinType::kUnpack2X16Snorm:
- return "unpack2x16snorm";
- case BuiltinType::kUnpack2X16Unorm:
- return "unpack2x16unorm";
- case BuiltinType::kUnpack4X8Snorm:
- return "unpack4x8snorm";
- case BuiltinType::kUnpack4X8Unorm:
- return "unpack4x8unorm";
- case BuiltinType::kWorkgroupBarrier:
- return "workgroupBarrier";
- case BuiltinType::kWorkgroupUniformLoad:
- return "workgroupUniformLoad";
- case BuiltinType::kTextureDimensions:
- return "textureDimensions";
- case BuiltinType::kTextureGather:
- return "textureGather";
- case BuiltinType::kTextureGatherCompare:
- return "textureGatherCompare";
- case BuiltinType::kTextureNumLayers:
- return "textureNumLayers";
- case BuiltinType::kTextureNumLevels:
- return "textureNumLevels";
- case BuiltinType::kTextureNumSamples:
- return "textureNumSamples";
- case BuiltinType::kTextureSample:
- return "textureSample";
- case BuiltinType::kTextureSampleBias:
- return "textureSampleBias";
- case BuiltinType::kTextureSampleCompare:
- return "textureSampleCompare";
- case BuiltinType::kTextureSampleCompareLevel:
- return "textureSampleCompareLevel";
- case BuiltinType::kTextureSampleGrad:
- return "textureSampleGrad";
- case BuiltinType::kTextureSampleLevel:
- return "textureSampleLevel";
- case BuiltinType::kTextureSampleBaseClampToEdge:
- return "textureSampleBaseClampToEdge";
- case BuiltinType::kTextureStore:
- return "textureStore";
- case BuiltinType::kTextureLoad:
- return "textureLoad";
- case BuiltinType::kAtomicLoad:
- return "atomicLoad";
- case BuiltinType::kAtomicStore:
- return "atomicStore";
- case BuiltinType::kAtomicAdd:
- return "atomicAdd";
- case BuiltinType::kAtomicSub:
- return "atomicSub";
- case BuiltinType::kAtomicMax:
- return "atomicMax";
- case BuiltinType::kAtomicMin:
- return "atomicMin";
- case BuiltinType::kAtomicAnd:
- return "atomicAnd";
- case BuiltinType::kAtomicOr:
- return "atomicOr";
- case BuiltinType::kAtomicXor:
- return "atomicXor";
- case BuiltinType::kAtomicExchange:
- return "atomicExchange";
- case BuiltinType::kAtomicCompareExchangeWeak:
- return "atomicCompareExchangeWeak";
- case BuiltinType::kTintMaterialize:
- return "_tint_materialize";
- }
- return "<unknown>";
-}
-
-utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i) {
- out << str(i);
- return out;
-}
-
-} // namespace tint::sem
diff --git a/src/tint/sem/builtin_type.cc.tmpl b/src/tint/sem/builtin_type.cc.tmpl
deleted file mode 100644
index 86a8623..0000000
--- a/src/tint/sem/builtin_type.cc.tmpl
+++ /dev/null
@@ -1,44 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate builtin_type.cc
-
-To update the generated file, run:
- ./tools/run gen
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-#include "src/tint/sem/builtin_type.h"
-
-namespace tint::sem {
-
-BuiltinType ParseBuiltinType(const std::string& name) {
-{{- range Sem.Builtins }}
- if (name == "{{.Name}}") {
- return BuiltinType::k{{PascalCase .Name}};
- }
-{{- end }}
- return BuiltinType::kNone;
-}
-
-const char* str(BuiltinType i) {
- switch (i) {
- case BuiltinType::kNone:
- return "<none>";
-{{- range Sem.Builtins }}
- case BuiltinType::k{{PascalCase .Name}}:
- return "{{.Name}}";
-{{- end }}
- }
- return "<unknown>";
-}
-
-utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i) {
- out << str(i);
- return out;
-}
-
-} // namespace tint::sem
diff --git a/src/tint/sem/builtin_type.h b/src/tint/sem/builtin_type.h
deleted file mode 100644
index 23f3749..0000000
--- a/src/tint/sem/builtin_type.h
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2021 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-////////////////////////////////////////////////////////////////////////////////
-// File generated by tools/src/cmd/gen
-// using the template:
-// src/tint/sem/builtin_type.h.tmpl
-//
-// Do not modify this file directly
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_
-#define SRC_TINT_SEM_BUILTIN_TYPE_H_
-
-#include <string>
-
-#include "src/tint/utils/string_stream.h"
-
-namespace tint::sem {
-
-/// Enumerator of all builtin functions
-enum class BuiltinType {
- kNone = -1,
- kAbs,
- kAcos,
- kAcosh,
- kAll,
- kAny,
- kArrayLength,
- kAsin,
- kAsinh,
- kAtan,
- kAtan2,
- kAtanh,
- kCeil,
- kClamp,
- kCos,
- kCosh,
- kCountLeadingZeros,
- kCountOneBits,
- kCountTrailingZeros,
- kCross,
- kDegrees,
- kDeterminant,
- kDistance,
- kDot,
- kDot4I8Packed,
- kDot4U8Packed,
- kDpdx,
- kDpdxCoarse,
- kDpdxFine,
- kDpdy,
- kDpdyCoarse,
- kDpdyFine,
- kExp,
- kExp2,
- kExtractBits,
- kFaceForward,
- kFirstLeadingBit,
- kFirstTrailingBit,
- kFloor,
- kFma,
- kFract,
- kFrexp,
- kFwidth,
- kFwidthCoarse,
- kFwidthFine,
- kInsertBits,
- kInverseSqrt,
- kLdexp,
- kLength,
- kLog,
- kLog2,
- kMax,
- kMin,
- kMix,
- kModf,
- kNormalize,
- kPack2X16Float,
- kPack2X16Snorm,
- kPack2X16Unorm,
- kPack4X8Snorm,
- kPack4X8Unorm,
- kPow,
- kQuantizeToF16,
- kRadians,
- kReflect,
- kRefract,
- kReverseBits,
- kRound,
- kSaturate,
- kSelect,
- kSign,
- kSin,
- kSinh,
- kSmoothstep,
- kSqrt,
- kStep,
- kStorageBarrier,
- kTan,
- kTanh,
- kTranspose,
- kTrunc,
- kUnpack2X16Float,
- kUnpack2X16Snorm,
- kUnpack2X16Unorm,
- kUnpack4X8Snorm,
- kUnpack4X8Unorm,
- kWorkgroupBarrier,
- kWorkgroupUniformLoad,
- kTextureDimensions,
- kTextureGather,
- kTextureGatherCompare,
- kTextureNumLayers,
- kTextureNumLevels,
- kTextureNumSamples,
- kTextureSample,
- kTextureSampleBias,
- kTextureSampleCompare,
- kTextureSampleCompareLevel,
- kTextureSampleGrad,
- kTextureSampleLevel,
- kTextureSampleBaseClampToEdge,
- kTextureStore,
- kTextureLoad,
- kAtomicLoad,
- kAtomicStore,
- kAtomicAdd,
- kAtomicSub,
- kAtomicMax,
- kAtomicMin,
- kAtomicAnd,
- kAtomicOr,
- kAtomicXor,
- kAtomicExchange,
- kAtomicCompareExchangeWeak,
- kTintMaterialize,
-};
-
-/// Matches the BuiltinType by name
-/// @param name the builtin name to parse
-/// @returns the parsed BuiltinType, or BuiltinType::kNone if `name` did not
-/// match any builtin.
-BuiltinType ParseBuiltinType(const std::string& name);
-
-/// @returns the name of the builtin function type. The spelling, including
-/// case, matches the name in the WGSL spec.
-const char* str(BuiltinType i);
-
-/// Emits the name of the builtin function type. The spelling, including case,
-/// matches the name in the WGSL spec.
-utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i);
-
-/// All builtin function
-constexpr BuiltinType kBuiltinTypes[] = {
- BuiltinType::kAbs,
- BuiltinType::kAcos,
- BuiltinType::kAcosh,
- BuiltinType::kAll,
- BuiltinType::kAny,
- BuiltinType::kArrayLength,
- BuiltinType::kAsin,
- BuiltinType::kAsinh,
- BuiltinType::kAtan,
- BuiltinType::kAtan2,
- BuiltinType::kAtanh,
- BuiltinType::kCeil,
- BuiltinType::kClamp,
- BuiltinType::kCos,
- BuiltinType::kCosh,
- BuiltinType::kCountLeadingZeros,
- BuiltinType::kCountOneBits,
- BuiltinType::kCountTrailingZeros,
- BuiltinType::kCross,
- BuiltinType::kDegrees,
- BuiltinType::kDeterminant,
- BuiltinType::kDistance,
- BuiltinType::kDot,
- BuiltinType::kDot4I8Packed,
- BuiltinType::kDot4U8Packed,
- BuiltinType::kDpdx,
- BuiltinType::kDpdxCoarse,
- BuiltinType::kDpdxFine,
- BuiltinType::kDpdy,
- BuiltinType::kDpdyCoarse,
- BuiltinType::kDpdyFine,
- BuiltinType::kExp,
- BuiltinType::kExp2,
- BuiltinType::kExtractBits,
- BuiltinType::kFaceForward,
- BuiltinType::kFirstLeadingBit,
- BuiltinType::kFirstTrailingBit,
- BuiltinType::kFloor,
- BuiltinType::kFma,
- BuiltinType::kFract,
- BuiltinType::kFrexp,
- BuiltinType::kFwidth,
- BuiltinType::kFwidthCoarse,
- BuiltinType::kFwidthFine,
- BuiltinType::kInsertBits,
- BuiltinType::kInverseSqrt,
- BuiltinType::kLdexp,
- BuiltinType::kLength,
- BuiltinType::kLog,
- BuiltinType::kLog2,
- BuiltinType::kMax,
- BuiltinType::kMin,
- BuiltinType::kMix,
- BuiltinType::kModf,
- BuiltinType::kNormalize,
- BuiltinType::kPack2X16Float,
- BuiltinType::kPack2X16Snorm,
- BuiltinType::kPack2X16Unorm,
- BuiltinType::kPack4X8Snorm,
- BuiltinType::kPack4X8Unorm,
- BuiltinType::kPow,
- BuiltinType::kQuantizeToF16,
- BuiltinType::kRadians,
- BuiltinType::kReflect,
- BuiltinType::kRefract,
- BuiltinType::kReverseBits,
- BuiltinType::kRound,
- BuiltinType::kSaturate,
- BuiltinType::kSelect,
- BuiltinType::kSign,
- BuiltinType::kSin,
- BuiltinType::kSinh,
- BuiltinType::kSmoothstep,
- BuiltinType::kSqrt,
- BuiltinType::kStep,
- BuiltinType::kStorageBarrier,
- BuiltinType::kTan,
- BuiltinType::kTanh,
- BuiltinType::kTranspose,
- BuiltinType::kTrunc,
- BuiltinType::kUnpack2X16Float,
- BuiltinType::kUnpack2X16Snorm,
- BuiltinType::kUnpack2X16Unorm,
- BuiltinType::kUnpack4X8Snorm,
- BuiltinType::kUnpack4X8Unorm,
- BuiltinType::kWorkgroupBarrier,
- BuiltinType::kWorkgroupUniformLoad,
- BuiltinType::kTextureDimensions,
- BuiltinType::kTextureGather,
- BuiltinType::kTextureGatherCompare,
- BuiltinType::kTextureNumLayers,
- BuiltinType::kTextureNumLevels,
- BuiltinType::kTextureNumSamples,
- BuiltinType::kTextureSample,
- BuiltinType::kTextureSampleBias,
- BuiltinType::kTextureSampleCompare,
- BuiltinType::kTextureSampleCompareLevel,
- BuiltinType::kTextureSampleGrad,
- BuiltinType::kTextureSampleLevel,
- BuiltinType::kTextureSampleBaseClampToEdge,
- BuiltinType::kTextureStore,
- BuiltinType::kTextureLoad,
- BuiltinType::kAtomicLoad,
- BuiltinType::kAtomicStore,
- BuiltinType::kAtomicAdd,
- BuiltinType::kAtomicSub,
- BuiltinType::kAtomicMax,
- BuiltinType::kAtomicMin,
- BuiltinType::kAtomicAnd,
- BuiltinType::kAtomicOr,
- BuiltinType::kAtomicXor,
- BuiltinType::kAtomicExchange,
- BuiltinType::kAtomicCompareExchangeWeak,
- BuiltinType::kTintMaterialize,
-};
-
-/// All builtin function names
-constexpr const char* kBuiltinStrings[] = {
- "abs",
- "acos",
- "acosh",
- "all",
- "any",
- "arrayLength",
- "asin",
- "asinh",
- "atan",
- "atan2",
- "atanh",
- "ceil",
- "clamp",
- "cos",
- "cosh",
- "countLeadingZeros",
- "countOneBits",
- "countTrailingZeros",
- "cross",
- "degrees",
- "determinant",
- "distance",
- "dot",
- "dot4I8Packed",
- "dot4U8Packed",
- "dpdx",
- "dpdxCoarse",
- "dpdxFine",
- "dpdy",
- "dpdyCoarse",
- "dpdyFine",
- "exp",
- "exp2",
- "extractBits",
- "faceForward",
- "firstLeadingBit",
- "firstTrailingBit",
- "floor",
- "fma",
- "fract",
- "frexp",
- "fwidth",
- "fwidthCoarse",
- "fwidthFine",
- "insertBits",
- "inverseSqrt",
- "ldexp",
- "length",
- "log",
- "log2",
- "max",
- "min",
- "mix",
- "modf",
- "normalize",
- "pack2x16float",
- "pack2x16snorm",
- "pack2x16unorm",
- "pack4x8snorm",
- "pack4x8unorm",
- "pow",
- "quantizeToF16",
- "radians",
- "reflect",
- "refract",
- "reverseBits",
- "round",
- "saturate",
- "select",
- "sign",
- "sin",
- "sinh",
- "smoothstep",
- "sqrt",
- "step",
- "storageBarrier",
- "tan",
- "tanh",
- "transpose",
- "trunc",
- "unpack2x16float",
- "unpack2x16snorm",
- "unpack2x16unorm",
- "unpack4x8snorm",
- "unpack4x8unorm",
- "workgroupBarrier",
- "workgroupUniformLoad",
- "textureDimensions",
- "textureGather",
- "textureGatherCompare",
- "textureNumLayers",
- "textureNumLevels",
- "textureNumSamples",
- "textureSample",
- "textureSampleBias",
- "textureSampleCompare",
- "textureSampleCompareLevel",
- "textureSampleGrad",
- "textureSampleLevel",
- "textureSampleBaseClampToEdge",
- "textureStore",
- "textureLoad",
- "atomicLoad",
- "atomicStore",
- "atomicAdd",
- "atomicSub",
- "atomicMax",
- "atomicMin",
- "atomicAnd",
- "atomicOr",
- "atomicXor",
- "atomicExchange",
- "atomicCompareExchangeWeak",
- "_tint_materialize",
-};
-
-} // namespace tint::sem
-
-#endif // SRC_TINT_SEM_BUILTIN_TYPE_H_
diff --git a/src/tint/sem/builtin_type.h.tmpl b/src/tint/sem/builtin_type.h.tmpl
deleted file mode 100644
index 366db95..0000000
--- a/src/tint/sem/builtin_type.h.tmpl
+++ /dev/null
@@ -1,61 +0,0 @@
-{{- /*
---------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate builtin_type.h
-
-To update the generated file, run:
- ./tools/run gen
-
-See:
-* tools/src/cmd/gen for structures used by this template
-* https://golang.org/pkg/text/template/ for documentation on the template syntax
---------------------------------------------------------------------------------
-*/ -}}
-
-#ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_
-#define SRC_TINT_SEM_BUILTIN_TYPE_H_
-
-#include <string>
-
-#include "src/tint/utils/string_stream.h"
-
-namespace tint::sem {
-
-/// Enumerator of all builtin functions
-enum class BuiltinType {
- kNone = -1,
-{{- range Sem.Builtins }}
- k{{PascalCase .Name}},
-{{- end }}
-};
-
-/// Matches the BuiltinType by name
-/// @param name the builtin name to parse
-/// @returns the parsed BuiltinType, or BuiltinType::kNone if `name` did not
-/// match any builtin.
-BuiltinType ParseBuiltinType(const std::string& name);
-
-/// @returns the name of the builtin function type. The spelling, including
-/// case, matches the name in the WGSL spec.
-const char* str(BuiltinType i);
-
-/// Emits the name of the builtin function type. The spelling, including case,
-/// matches the name in the WGSL spec.
-utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i);
-
-/// All builtin function
-constexpr BuiltinType kBuiltinTypes[] = {
-{{- range Sem.Builtins }}
- BuiltinType::k{{PascalCase .Name}},
-{{- end }}
-};
-
-/// All builtin function names
-constexpr const char* kBuiltinStrings[] = {
-{{- range Sem.Builtins }}
- "{{.Name}}",
-{{- end }}
-};
-
-} // namespace tint::sem
-
-#endif // SRC_TINT_SEM_BUILTIN_TYPE_H_
diff --git a/src/tint/sem/diagnostic_severity_test.cc b/src/tint/sem/diagnostic_severity_test.cc
index fa57b55..a22b43e 100644
--- a/src/tint/sem/diagnostic_severity_test.cc
+++ b/src/tint/sem/diagnostic_severity_test.cc
@@ -31,45 +31,121 @@
// @diagnostic(off, chromium_unreachable_code)
// fn foo() {
// @diagnostic(info, chromium_unreachable_code) {
+ // @diagnostic(error, chromium_unreachable_code)
// if (true) @diagnostic(warning, chromium_unreachable_code) {
// return;
+ // } else if (false) {
+ // return;
+ // } else @diagnostic(info, chromium_unreachable_code) {
+ // return;
+ // }
+ // return;
+ //
+ // @diagnostic(error, chromium_unreachable_code)
+ // switch (42) {
+ // case 0 @diagnostic(warning, chromium_unreachable_code) {
+ // return;
+ // }
+ // default {
+ // return;
+ // }
+ // }
+ //
+ // @diagnostic(error, chromium_unreachable_code)
+ // for (var i = 0; false; i++) @diagnostic(warning, chromium_unreachable_code) {
+ // return;
+ // }
+ // }
+ //
+ // @diagnostic(error, chromium_unreachable_code)
+ // while (false) @diagnostic(warning, chromium_unreachable_code) {
+ // return;
// }
// }
// }
//
// fn bar() {
- // {
- // if (true) {
- // return;
- // }
- // }
+ // return;
// }
auto rule = builtin::DiagnosticRule::kChromiumUnreachableCode;
auto func_severity = builtin::DiagnosticSeverity::kOff;
auto block_severity = builtin::DiagnosticSeverity::kInfo;
- auto if_severity = builtin::DiagnosticSeverity::kInfo;
+ auto if_severity = builtin::DiagnosticSeverity::kError;
+ auto if_body_severity = builtin::DiagnosticSeverity::kWarning;
+ auto else_body_severity = builtin::DiagnosticSeverity::kInfo;
+ auto switch_severity = builtin::DiagnosticSeverity::kError;
+ auto case_severity = builtin::DiagnosticSeverity::kWarning;
+ auto for_severity = builtin::DiagnosticSeverity::kError;
+ auto for_body_severity = builtin::DiagnosticSeverity::kWarning;
+ auto while_severity = builtin::DiagnosticSeverity::kError;
+ auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
auto attr = [&](auto severity) {
return utils::Vector{DiagnosticAttribute(severity, "chromium_unreachable_code")};
};
- auto* return_1 = Return();
- auto* if_1 = If(Expr(true), Block(utils::Vector{return_1}, attr(if_severity)));
- auto* block_1 = Block(utils::Vector{if_1}, attr(block_severity));
+ auto* return_foo_if = Return();
+ auto* return_foo_elseif = Return();
+ auto* return_foo_else = Return();
+ auto* return_foo_block = Return();
+ auto* return_foo_case = Return();
+ auto* return_foo_default = Return();
+ auto* return_foo_for = Return();
+ auto* return_foo_while = Return();
+ auto* else_stmt = Block(utils::Vector{return_foo_else}, attr(else_body_severity));
+ auto* elseif = If(Expr(false), Block(return_foo_elseif), Else(else_stmt));
+ auto* if_foo = If(Expr(true), Block(utils::Vector{return_foo_if}, attr(if_body_severity)),
+ Else(elseif), attr(if_severity));
+ auto* case_stmt =
+ Case(CaseSelector(0_a), Block(utils::Vector{return_foo_case}, attr(case_severity)));
+ auto* swtch = Switch(42_a, utils::Vector{case_stmt, DefaultCase(Block(return_foo_default))},
+ attr(switch_severity));
+ auto* fl =
+ For(Decl(Var("i", ty.i32())), false, Increment("i"),
+ Block(utils::Vector{return_foo_for}, attr(for_body_severity)), attr(for_severity));
+ auto* wl = While(false, Block(utils::Vector{return_foo_while}, attr(while_body_severity)),
+ attr(while_severity));
+ auto* block_1 =
+ Block(utils::Vector{if_foo, return_foo_block, swtch, fl, wl}, attr(block_severity));
auto* func_attr = DiagnosticAttribute(func_severity, "chromium_unreachable_code");
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{block_1}, utils::Vector{func_attr});
- auto* return_2 = Return();
- auto* bar = Func("bar", {}, ty.void_(), utils::Vector{return_2});
+ auto* return_bar = Return();
+ auto* bar = Func("bar", {}, ty.void_(), utils::Vector{return_bar});
auto p = Build();
EXPECT_TRUE(p.IsValid()) << p.Diagnostics().str();
EXPECT_EQ(p.Sem().DiagnosticSeverity(foo, rule), func_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(block_1, rule), block_severity);
- EXPECT_EQ(p.Sem().DiagnosticSeverity(if_1, rule), block_severity);
- EXPECT_EQ(p.Sem().DiagnosticSeverity(return_1, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(if_foo, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(if_foo->condition, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(if_foo->body, rule), if_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_if, rule), if_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(elseif, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(elseif->condition, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(elseif->body, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_elseif, rule), if_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(else_stmt, rule), else_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_else, rule), else_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(swtch, rule), switch_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(swtch->condition, rule), switch_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(case_stmt, rule), switch_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(case_stmt->body, rule), case_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_case, rule), case_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_default, rule), switch_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(fl, rule), while_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->initializer, rule), for_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->condition, rule), for_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->continuing, rule), for_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->body, rule), for_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_for, rule), for_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(wl, rule), while_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(wl->condition, rule), while_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(wl->body, rule), while_body_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_while, rule), while_body_severity);
+
EXPECT_EQ(p.Sem().DiagnosticSeverity(bar, rule), global_severity);
- EXPECT_EQ(p.Sem().DiagnosticSeverity(return_2, rule), global_severity);
+ EXPECT_EQ(p.Sem().DiagnosticSeverity(return_bar, rule), global_severity);
}
};
diff --git a/src/tint/sem/external_texture.h b/src/tint/sem/external_texture.h
new file mode 100644
index 0000000..2ad5673
--- /dev/null
+++ b/src/tint/sem/external_texture.h
@@ -0,0 +1,45 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_SEM_EXTERNAL_TEXTURE_H_
+#define SRC_TINT_SEM_EXTERNAL_TEXTURE_H_
+
+#include <unordered_map>
+
+#include "src/tint/sem/binding_point.h"
+
+namespace tint::sem::external_texture {
+
+/// This struct identifies the binding groups and locations for new bindings to
+/// use when transforming a texture_external instance.
+struct BindingPoints {
+ /// The desired binding location of the texture_2d representing plane #1 when
+ /// a texture_external binding is expanded.
+ BindingPoint plane_1;
+ /// The desired binding location of the ExternalTextureParams uniform when a
+ /// texture_external binding is expanded.
+ BindingPoint params;
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(plane_1, params);
+};
+
+/// BindingsMap is a map where the key is the binding location of a
+/// texture_external and the value is a struct containing the desired
+/// locations for new bindings expanded from the texture_external instance.
+using BindingsMap = std::unordered_map<BindingPoint, BindingPoints>;
+
+} // namespace tint::sem::external_texture
+
+#endif // SRC_TINT_SEM_EXTERNAL_TEXTURE_H_
diff --git a/src/tint/sem/info.cc b/src/tint/sem/info.cc
index e124c1c..52a04b5 100644
--- a/src/tint/sem/info.cc
+++ b/src/tint/sem/info.cc
@@ -18,6 +18,7 @@
#include "src/tint/sem/module.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/value_expression.h"
+#include "src/tint/switch.h"
namespace tint::sem {
diff --git a/src/tint/sem/value_expression.cc b/src/tint/sem/value_expression.cc
index 9fe4615..9aacfa3 100644
--- a/src/tint/sem/value_expression.cc
+++ b/src/tint/sem/value_expression.cc
@@ -18,6 +18,7 @@
#include "src/tint/sem/load.h"
#include "src/tint/sem/materialize.h"
+#include "src/tint/switch.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::ValueExpression);
diff --git a/src/tint/sem/value_expression_test.cc b/src/tint/sem/value_expression_test.cc
index 1758894..0a2c9ef 100644
--- a/src/tint/sem/value_expression_test.cc
+++ b/src/tint/sem/value_expression_test.cc
@@ -29,9 +29,9 @@
~MockConstant() override {}
const type::Type* Type() const override { return type; }
const constant::Value* Index(size_t) const override { return {}; }
+ size_t NumElements() const override { return 0; }
bool AllZero() const override { return {}; }
bool AnyZero() const override { return {}; }
- bool AllEqual() const override { return {}; }
size_t Hash() const override { return 0; }
MockConstant* Clone(constant::CloneContext&) const override { return nullptr; }
diff --git a/src/tint/switch.h b/src/tint/switch.h
new file mode 100644
index 0000000..41bb99a
--- /dev/null
+++ b/src/tint/switch.h
@@ -0,0 +1,262 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_SWITCH_H_
+#define SRC_TINT_SWITCH_H_
+
+#include <tuple>
+#include <utility>
+
+#include "src/tint/castable.h"
+#include "src/tint/utils/bitcast.h"
+#include "src/tint/utils/defer.h"
+
+namespace tint {
+
+/// Default can be used as the default case for a Switch(), when all previous cases failed to match.
+///
+/// Example:
+/// ```
+/// Switch(object,
+/// [&](TypeA*) { /* ... */ },
+/// [&](TypeB*) { /* ... */ },
+/// [&](Default) { /* If not TypeA or TypeB */ });
+/// ```
+struct Default {};
+
+} // namespace tint
+
+namespace tint::detail {
+
+/// Evaluates to the Switch case type being matched by the switch case function `FN`.
+/// @note does not handle the Default case
+/// @see Switch().
+template <typename FN>
+using SwitchCaseType = std::remove_pointer_t<traits::ParameterType<std::remove_reference_t<FN>, 0>>;
+
+/// Evaluates to true if the function `FN` has the signature of a Default case in a Switch().
+/// @see Switch().
+template <typename FN>
+inline constexpr bool IsDefaultCase =
+ std::is_same_v<traits::ParameterType<std::remove_reference_t<FN>, 0>, Default>;
+
+/// Searches the list of Switch cases for a Default case, returning the index of the Default case.
+/// If the a Default case is not found in the tuple, then -1 is returned.
+template <typename TUPLE, std::size_t START_IDX = 0>
+constexpr int IndexOfDefaultCase() {
+ if constexpr (START_IDX < std::tuple_size_v<TUPLE>) {
+ return IsDefaultCase<std::tuple_element_t<START_IDX, TUPLE>>
+ ? static_cast<int>(START_IDX)
+ : IndexOfDefaultCase<TUPLE, START_IDX + 1>();
+ } else {
+ return -1;
+ }
+}
+
+/// Resolves to T if T is not nullptr_t, otherwise resolves to Ignore.
+template <typename T>
+using NullptrToIgnore = std::conditional_t<std::is_same_v<T, std::nullptr_t>, Ignore, T>;
+
+/// Resolves to `const TYPE` if any of `CASE_RETURN_TYPES` are const or pointer-to-const, otherwise
+/// resolves to TYPE.
+template <typename TYPE, typename... CASE_RETURN_TYPES>
+using PropagateReturnConst = std::conditional_t<
+ // Are any of the pointer-stripped types const?
+ (std::is_const_v<std::remove_pointer_t<CASE_RETURN_TYPES>> || ...),
+ const TYPE, // Yes: Apply const to TYPE
+ TYPE>; // No: Passthrough
+
+/// SwitchReturnTypeImpl is the implementation of SwitchReturnType
+template <bool IS_CASTABLE, typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
+struct SwitchReturnTypeImpl;
+
+/// SwitchReturnTypeImpl specialization for non-castable case types and an explicitly specified
+/// return type.
+template <typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
+struct SwitchReturnTypeImpl</*IS_CASTABLE*/ false, REQUESTED_TYPE, CASE_RETURN_TYPES...> {
+ /// Resolves to `REQUESTED_TYPE`
+ using type = REQUESTED_TYPE;
+};
+
+/// SwitchReturnTypeImpl specialization for non-castable case types and an inferred return type.
+template <typename... CASE_RETURN_TYPES>
+struct SwitchReturnTypeImpl</*IS_CASTABLE*/ false, Infer, CASE_RETURN_TYPES...> {
+ /// Resolves to the common type for all the cases return types.
+ using type = std::common_type_t<CASE_RETURN_TYPES...>;
+};
+
+/// SwitchReturnTypeImpl specialization for castable case types and an explicitly specified return
+/// type.
+template <typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
+struct SwitchReturnTypeImpl</*IS_CASTABLE*/ true, REQUESTED_TYPE, CASE_RETURN_TYPES...> {
+ public:
+ /// Resolves to `const REQUESTED_TYPE*` or `REQUESTED_TYPE*`
+ using type = PropagateReturnConst<std::remove_pointer_t<REQUESTED_TYPE>, CASE_RETURN_TYPES...>*;
+};
+
+/// SwitchReturnTypeImpl specialization for castable case types and an inferred return type.
+template <typename... CASE_RETURN_TYPES>
+struct SwitchReturnTypeImpl</*IS_CASTABLE*/ true, Infer, CASE_RETURN_TYPES...> {
+ private:
+ using InferredType =
+ CastableCommonBase<detail::NullptrToIgnore<std::remove_pointer_t<CASE_RETURN_TYPES>>...>;
+
+ public:
+ /// `const T*` or `T*`, where T is the common base type for all the castable case types.
+ using type = PropagateReturnConst<InferredType, CASE_RETURN_TYPES...>*;
+};
+
+/// Resolves to the return type for a Switch() with the requested return type `REQUESTED_TYPE` and
+/// case statement return types. If `REQUESTED_TYPE` is Infer then the return type will be inferred
+/// from the case return types.
+template <typename REQUESTED_TYPE, typename... CASE_RETURN_TYPES>
+using SwitchReturnType = typename SwitchReturnTypeImpl<
+ IsCastable<NullptrToIgnore<std::remove_pointer_t<CASE_RETURN_TYPES>>...>,
+ REQUESTED_TYPE,
+ CASE_RETURN_TYPES...>::type;
+
+} // namespace tint::detail
+
+namespace tint {
+
+/// Switch is used to dispatch one of the provided callback case handler functions based on the type
+/// of `object` and the parameter type of the case handlers. Switch will sequentially check the type
+/// of `object` against each of the switch case handler functions, and will invoke the first case
+/// handler function which has a parameter type that matches the object type. When a case handler is
+/// matched, it will be called with the single argument of `object` cast to the case handler's
+/// parameter type. Switch will invoke at most one case handler. Each of the case functions must
+/// have the signature `R(T*)` or `R(const T*)`, where `T` is the type matched by that case and `R`
+/// is the return type, consistent across all case handlers.
+///
+/// An optional default case function with the signature `R(Default)` can be used as the last case.
+/// This default case will be called if all previous cases failed to match.
+///
+/// If `object` is nullptr and a default case is provided, then the default case will be called. If
+/// `object` is nullptr and no default case is provided, then no cases will be called.
+///
+/// Example:
+/// ```
+/// Switch(object,
+/// [&](TypeA*) { /* ... */ },
+/// [&](TypeB*) { /* ... */ });
+///
+/// Switch(object,
+/// [&](TypeA*) { /* ... */ },
+/// [&](TypeB*) { /* ... */ },
+/// [&](Default) { /* Called if object is not TypeA or TypeB */ });
+/// ```
+///
+/// @param object the object who's type is used to
+/// @param cases the switch cases
+/// @return the value returned by the called case. If no cases matched, then the zero value for the
+/// consistent case type.
+template <typename RETURN_TYPE = detail::Infer, typename T = CastableBase, typename... CASES>
+inline auto Switch(T* object, CASES&&... cases) {
+ using ReturnType = detail::SwitchReturnType<RETURN_TYPE, traits::ReturnType<CASES>...>;
+ static constexpr int kDefaultIndex = detail::IndexOfDefaultCase<std::tuple<CASES...>>();
+ static constexpr bool kHasDefaultCase = kDefaultIndex >= 0;
+ static constexpr bool kHasReturnType = !std::is_same_v<ReturnType, void>;
+
+ // Static assertions
+ static constexpr bool kDefaultIsOK =
+ kDefaultIndex == -1 || kDefaultIndex == static_cast<int>(sizeof...(CASES) - 1);
+ static constexpr bool kReturnIsOK =
+ kHasDefaultCase || !kHasReturnType || std::is_constructible_v<ReturnType>;
+ static_assert(kDefaultIsOK, "Default case must be last in Switch()");
+ static_assert(kReturnIsOK,
+ "Switch() requires either a Default case or a return type that is either void or "
+ "default-constructable");
+
+ if (!object) { // Object is nullptr, so no cases can match
+ if constexpr (kHasDefaultCase) {
+ // Evaluate default case.
+ auto&& default_case =
+ std::get<kDefaultIndex>(std::forward_as_tuple(std::forward<CASES>(cases)...));
+ return static_cast<ReturnType>(default_case(Default{}));
+ } else {
+ // No default case, no case can match.
+ if constexpr (kHasReturnType) {
+ return ReturnType{};
+ } else {
+ return;
+ }
+ }
+ }
+
+ // Replacement for std::aligned_storage as this is broken on earlier versions of MSVC.
+ using ReturnTypeOrU8 = std::conditional_t<kHasReturnType, ReturnType, uint8_t>;
+ struct alignas(alignof(ReturnTypeOrU8)) ReturnStorage {
+ uint8_t data[sizeof(ReturnTypeOrU8)];
+ };
+ ReturnStorage storage;
+ auto* result = utils::Bitcast<ReturnTypeOrU8*>(&storage);
+
+ const TypeInfo& type_info = object->TypeInfo();
+
+ // Examines the parameter type of the case function.
+ // If the parameter is a pointer type that `object` is of, or derives from, then that case
+ // function is called with `object` cast to that type, and `try_case` returns true.
+ // If the parameter is of type `Default`, then that case function is called and `try_case`
+ // returns true.
+ // Otherwise `try_case` returns false.
+ // If the case function is called and it returns a value, then this is copy constructed to the
+ // `result` pointer.
+ auto try_case = [&](auto&& case_fn) {
+ using CaseFunc = std::decay_t<decltype(case_fn)>;
+ using CaseType = detail::SwitchCaseType<CaseFunc>;
+ bool success = false;
+ if constexpr (std::is_same_v<CaseType, Default>) {
+ if constexpr (kHasReturnType) {
+ new (result) ReturnType(static_cast<ReturnType>(case_fn(Default{})));
+ } else {
+ case_fn(Default{});
+ }
+ success = true;
+ } else {
+ if (type_info.Is<CaseType>()) {
+ auto* v = static_cast<CaseType*>(object);
+ if constexpr (kHasReturnType) {
+ new (result) ReturnType(static_cast<ReturnType>(case_fn(v)));
+ } else {
+ case_fn(v);
+ }
+ success = true;
+ }
+ }
+ return success;
+ };
+
+ // Use a logical-or fold expression to try each of the cases in turn, until one matches the
+ // object type or a Default is reached. `handled` is true if a case function was called.
+ bool handled = ((try_case(std::forward<CASES>(cases)) || ...));
+
+ if constexpr (kHasReturnType) {
+ if constexpr (kHasDefaultCase) {
+ // Default case means there must be a returned value.
+ // No need to check handled, no requirement for a zero-initializer of ReturnType.
+ TINT_DEFER(result->~ReturnType());
+ return *result;
+ } else {
+ if (handled) {
+ TINT_DEFER(result->~ReturnType());
+ return *result;
+ }
+ return ReturnType{};
+ }
+ }
+}
+
+} // namespace tint
+
+#endif // SRC_TINT_SWITCH_H_
diff --git a/src/tint/castable_bench.cc b/src/tint/switch_bench.cc
similarity index 99%
rename from src/tint/castable_bench.cc
rename to src/tint/switch_bench.cc
index c9d0c43..ea6098b 100644
--- a/src/tint/castable_bench.cc
+++ b/src/tint/switch_bench.cc
@@ -16,7 +16,7 @@
#include "benchmark/benchmark.h"
-#include "src/tint/castable.h"
+#include "src/tint/switch.h"
namespace tint {
namespace {
diff --git a/src/tint/switch_test.cc b/src/tint/switch_test.cc
new file mode 100644
index 0000000..d93f830
--- /dev/null
+++ b/src/tint/switch_test.cc
@@ -0,0 +1,552 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/switch.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace {
+
+struct Animal : public tint::Castable<Animal> {};
+struct Amphibian : public tint::Castable<Amphibian, Animal> {};
+struct Mammal : public tint::Castable<Mammal, Animal> {};
+struct Reptile : public tint::Castable<Reptile, Animal> {};
+struct Frog : public tint::Castable<Frog, Amphibian> {};
+struct Bear : public tint::Castable<Bear, Mammal> {};
+struct Lizard : public tint::Castable<Lizard, Reptile> {};
+struct Gecko : public tint::Castable<Gecko, Lizard> {};
+struct Iguana : public tint::Castable<Iguana, Lizard> {};
+
+TEST(Castable, SwitchNoDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ bool frog_matched_amphibian = false;
+ Switch(
+ frog.get(), //
+ [&](Reptile*) { FAIL() << "frog is not reptile"; },
+ [&](Mammal*) { FAIL() << "frog is not mammal"; },
+ [&](Amphibian* amphibian) {
+ EXPECT_EQ(amphibian, frog.get());
+ frog_matched_amphibian = true;
+ });
+ EXPECT_TRUE(frog_matched_amphibian);
+ }
+ {
+ bool bear_matched_mammal = false;
+ Switch(
+ bear.get(), //
+ [&](Reptile*) { FAIL() << "bear is not reptile"; },
+ [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
+ [&](Mammal* mammal) {
+ EXPECT_EQ(mammal, bear.get());
+ bear_matched_mammal = true;
+ });
+ EXPECT_TRUE(bear_matched_mammal);
+ }
+ {
+ bool gecko_matched_reptile = false;
+ Switch(
+ gecko.get(), //
+ [&](Mammal*) { FAIL() << "gecko is not mammal"; },
+ [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
+ [&](Reptile* reptile) {
+ EXPECT_EQ(reptile, gecko.get());
+ gecko_matched_reptile = true;
+ });
+ EXPECT_TRUE(gecko_matched_reptile);
+ }
+}
+
+TEST(Castable, SwitchWithUnusedDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ bool frog_matched_amphibian = false;
+ Switch(
+ frog.get(), //
+ [&](Reptile*) { FAIL() << "frog is not reptile"; },
+ [&](Mammal*) { FAIL() << "frog is not mammal"; },
+ [&](Amphibian* amphibian) {
+ EXPECT_EQ(amphibian, frog.get());
+ frog_matched_amphibian = true;
+ },
+ [&](Default) { FAIL() << "default should not have been selected"; });
+ EXPECT_TRUE(frog_matched_amphibian);
+ }
+ {
+ bool bear_matched_mammal = false;
+ Switch(
+ bear.get(), //
+ [&](Reptile*) { FAIL() << "bear is not reptile"; },
+ [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
+ [&](Mammal* mammal) {
+ EXPECT_EQ(mammal, bear.get());
+ bear_matched_mammal = true;
+ },
+ [&](Default) { FAIL() << "default should not have been selected"; });
+ EXPECT_TRUE(bear_matched_mammal);
+ }
+ {
+ bool gecko_matched_reptile = false;
+ Switch(
+ gecko.get(), //
+ [&](Mammal*) { FAIL() << "gecko is not mammal"; },
+ [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
+ [&](Reptile* reptile) {
+ EXPECT_EQ(reptile, gecko.get());
+ gecko_matched_reptile = true;
+ },
+ [&](Default) { FAIL() << "default should not have been selected"; });
+ EXPECT_TRUE(gecko_matched_reptile);
+ }
+}
+
+TEST(Castable, SwitchDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ bool frog_matched_default = false;
+ Switch(
+ frog.get(), //
+ [&](Reptile*) { FAIL() << "frog is not reptile"; },
+ [&](Mammal*) { FAIL() << "frog is not mammal"; },
+ [&](Default) { frog_matched_default = true; });
+ EXPECT_TRUE(frog_matched_default);
+ }
+ {
+ bool bear_matched_default = false;
+ Switch(
+ bear.get(), //
+ [&](Reptile*) { FAIL() << "bear is not reptile"; },
+ [&](Amphibian*) { FAIL() << "bear is not amphibian"; },
+ [&](Default) { bear_matched_default = true; });
+ EXPECT_TRUE(bear_matched_default);
+ }
+ {
+ bool gecko_matched_default = false;
+ Switch(
+ gecko.get(), //
+ [&](Mammal*) { FAIL() << "gecko is not mammal"; },
+ [&](Amphibian*) { FAIL() << "gecko is not amphibian"; },
+ [&](Default) { gecko_matched_default = true; });
+ EXPECT_TRUE(gecko_matched_default);
+ }
+}
+
+TEST(Castable, SwitchMatchFirst) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ {
+ bool frog_matched_animal = false;
+ Switch(
+ frog.get(),
+ [&](Animal* animal) {
+ EXPECT_EQ(animal, frog.get());
+ frog_matched_animal = true;
+ },
+ [&](Amphibian*) { FAIL() << "animal should have been matched first"; });
+ EXPECT_TRUE(frog_matched_animal);
+ }
+ {
+ bool frog_matched_amphibian = false;
+ Switch(
+ frog.get(),
+ [&](Amphibian* amphibain) {
+ EXPECT_EQ(amphibain, frog.get());
+ frog_matched_amphibian = true;
+ },
+ [&](Animal*) { FAIL() << "amphibian should have been matched first"; });
+ EXPECT_TRUE(frog_matched_amphibian);
+ }
+}
+
+TEST(Castable, SwitchReturnValueWithDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ const char* result = Switch(
+ frog.get(), //
+ [](Mammal*) { return "mammal"; }, //
+ [](Amphibian*) { return "amphibian"; }, //
+ [](Default) { return "unknown"; });
+ static_assert(std::is_same_v<decltype(result), const char*>);
+ EXPECT_EQ(std::string(result), "amphibian");
+ }
+ {
+ const char* result = Switch(
+ bear.get(), //
+ [](Mammal*) { return "mammal"; }, //
+ [](Amphibian*) { return "amphibian"; }, //
+ [](Default) { return "unknown"; });
+ static_assert(std::is_same_v<decltype(result), const char*>);
+ EXPECT_EQ(std::string(result), "mammal");
+ }
+ {
+ const char* result = Switch(
+ gecko.get(), //
+ [](Mammal*) { return "mammal"; }, //
+ [](Amphibian*) { return "amphibian"; }, //
+ [](Default) { return "unknown"; });
+ static_assert(std::is_same_v<decltype(result), const char*>);
+ EXPECT_EQ(std::string(result), "unknown");
+ }
+}
+
+TEST(Castable, SwitchReturnValueWithoutDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ const char* result = Switch(
+ frog.get(), //
+ [](Mammal*) { return "mammal"; }, //
+ [](Amphibian*) { return "amphibian"; });
+ static_assert(std::is_same_v<decltype(result), const char*>);
+ EXPECT_EQ(std::string(result), "amphibian");
+ }
+ {
+ const char* result = Switch(
+ bear.get(), //
+ [](Mammal*) { return "mammal"; }, //
+ [](Amphibian*) { return "amphibian"; });
+ static_assert(std::is_same_v<decltype(result), const char*>);
+ EXPECT_EQ(std::string(result), "mammal");
+ }
+ {
+ auto* result = Switch(
+ gecko.get(), //
+ [](Mammal*) { return "mammal"; }, //
+ [](Amphibian*) { return "amphibian"; });
+ static_assert(std::is_same_v<decltype(result), const char*>);
+ EXPECT_EQ(result, nullptr);
+ }
+}
+
+TEST(Castable, SwitchInferPODReturnTypeWithDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto result = Switch(
+ frog.get(), //
+ [](Mammal*) { return 1; }, //
+ [](Amphibian*) { return 2.0f; }, //
+ [](Default) { return 3.0; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 2.0);
+ }
+ {
+ auto result = Switch(
+ bear.get(), //
+ [](Mammal*) { return 1.0; }, //
+ [](Amphibian*) { return 2.0f; }, //
+ [](Default) { return 3; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 1.0);
+ }
+ {
+ auto result = Switch(
+ gecko.get(), //
+ [](Mammal*) { return 1.0f; }, //
+ [](Amphibian*) { return 2; }, //
+ [](Default) { return 3.0; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 3.0);
+ }
+}
+
+TEST(Castable, SwitchInferPODReturnTypeWithoutDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto result = Switch(
+ frog.get(), //
+ [](Mammal*) { return 1; }, //
+ [](Amphibian*) { return 2.0f; });
+ static_assert(std::is_same_v<decltype(result), float>);
+ EXPECT_EQ(result, 2.0f);
+ }
+ {
+ auto result = Switch(
+ bear.get(), //
+ [](Mammal*) { return 1.0f; }, //
+ [](Amphibian*) { return 2; });
+ static_assert(std::is_same_v<decltype(result), float>);
+ EXPECT_EQ(result, 1.0f);
+ }
+ {
+ auto result = Switch(
+ gecko.get(), //
+ [](Mammal*) { return 1.0; }, //
+ [](Amphibian*) { return 2.0f; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 0.0);
+ }
+}
+
+TEST(Castable, SwitchInferCastableReturnTypeWithDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto* result = Switch(
+ frog.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian*) { return nullptr; }, //
+ [](Default) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), Mammal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+ {
+ auto* result = Switch(
+ bear.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return const_cast<const Amphibian*>(p); },
+ [](Default) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), const Animal*>);
+ EXPECT_EQ(result, bear.get());
+ }
+ {
+ auto* result = Switch(
+ gecko.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return p; }, //
+ [](Default) -> CastableBase* { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), CastableBase*>);
+ EXPECT_EQ(result, nullptr);
+ }
+}
+
+TEST(Castable, SwitchInferCastableReturnTypeWithoutDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto* result = Switch(
+ frog.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian*) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), Mammal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+ {
+ auto* result = Switch(
+ bear.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return const_cast<const Amphibian*>(p); }); //
+ static_assert(std::is_same_v<decltype(result), const Animal*>);
+ EXPECT_EQ(result, bear.get());
+ }
+ {
+ auto* result = Switch(
+ gecko.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return p; });
+ static_assert(std::is_same_v<decltype(result), Animal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+}
+
+TEST(Castable, SwitchExplicitPODReturnTypeWithDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto result = Switch<double>(
+ frog.get(), //
+ [](Mammal*) { return 1; }, //
+ [](Amphibian*) { return 2.0f; }, //
+ [](Default) { return 3.0; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 2.0f);
+ }
+ {
+ auto result = Switch<double>(
+ bear.get(), //
+ [](Mammal*) { return 1; }, //
+ [](Amphibian*) { return 2; }, //
+ [](Default) { return 3; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 1.0f);
+ }
+ {
+ auto result = Switch<double>(
+ gecko.get(), //
+ [](Mammal*) { return 1.0f; }, //
+ [](Amphibian*) { return 2.0f; }, //
+ [](Default) { return 3.0f; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 3.0f);
+ }
+}
+
+TEST(Castable, SwitchExplicitPODReturnTypeWithoutDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto result = Switch<double>(
+ frog.get(), //
+ [](Mammal*) { return 1; }, //
+ [](Amphibian*) { return 2.0f; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 2.0f);
+ }
+ {
+ auto result = Switch<double>(
+ bear.get(), //
+ [](Mammal*) { return 1.0f; }, //
+ [](Amphibian*) { return 2; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 1.0f);
+ }
+ {
+ auto result = Switch<double>(
+ gecko.get(), //
+ [](Mammal*) { return 1.0; }, //
+ [](Amphibian*) { return 2.0f; });
+ static_assert(std::is_same_v<decltype(result), double>);
+ EXPECT_EQ(result, 0.0);
+ }
+}
+
+TEST(Castable, SwitchExplicitCastableReturnTypeWithDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto* result = Switch<Animal>(
+ frog.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian*) { return nullptr; }, //
+ [](Default) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), Animal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+ {
+ auto* result = Switch<CastableBase>(
+ bear.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return const_cast<const Amphibian*>(p); },
+ [](Default) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), const CastableBase*>);
+ EXPECT_EQ(result, bear.get());
+ }
+ {
+ auto* result = Switch<const Animal>(
+ gecko.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return p; }, //
+ [](Default) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), const Animal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+}
+
+TEST(Castable, SwitchExplicitCastableReturnTypeWithoutDefault) {
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ std::unique_ptr<Animal> bear = std::make_unique<Bear>();
+ std::unique_ptr<Animal> gecko = std::make_unique<Gecko>();
+ {
+ auto* result = Switch<Animal>(
+ frog.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian*) { return nullptr; });
+ static_assert(std::is_same_v<decltype(result), Animal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+ {
+ auto* result = Switch<CastableBase>(
+ bear.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return const_cast<const Amphibian*>(p); }); //
+ static_assert(std::is_same_v<decltype(result), const CastableBase*>);
+ EXPECT_EQ(result, bear.get());
+ }
+ {
+ auto* result = Switch<const Animal*>(
+ gecko.get(), //
+ [](Mammal* p) { return p; }, //
+ [](Amphibian* p) { return p; });
+ static_assert(std::is_same_v<decltype(result), const Animal*>);
+ EXPECT_EQ(result, nullptr);
+ }
+}
+
+TEST(Castable, SwitchNull) {
+ Animal* null = nullptr;
+ Switch(
+ null, //
+ [&](Amphibian*) { FAIL() << "should not be called"; },
+ [&](Animal*) { FAIL() << "should not be called"; });
+}
+
+TEST(Castable, SwitchNullNoDefault) {
+ Animal* null = nullptr;
+ bool default_called = false;
+ Switch(
+ null, //
+ [&](Amphibian*) { FAIL() << "should not be called"; },
+ [&](Animal*) { FAIL() << "should not be called"; },
+ [&](Default) { default_called = true; });
+ EXPECT_TRUE(default_called);
+}
+
+TEST(Castable, SwitchReturnNoDefaultInitializer) {
+ struct Object {
+ explicit Object(int v) : value(v) {}
+ int value;
+ };
+
+ std::unique_ptr<Animal> frog = std::make_unique<Frog>();
+ {
+ auto result = Switch(
+ frog.get(), //
+ [](Mammal*) { return Object(1); }, //
+ [](Amphibian*) { return Object(2); }, //
+ [](Default) { return Object(3); });
+ static_assert(std::is_same_v<decltype(result), Object>);
+ EXPECT_EQ(result.value, 2);
+ }
+ {
+ auto result = Switch(
+ frog.get(), //
+ [](Mammal*) { return Object(1); }, //
+ [](Default) { return Object(3); });
+ static_assert(std::is_same_v<decltype(result), Object>);
+ EXPECT_EQ(result.value, 3);
+ }
+}
+
+} // namespace
+
+TINT_INSTANTIATE_TYPEINFO(Animal);
+TINT_INSTANTIATE_TYPEINFO(Amphibian);
+TINT_INSTANTIATE_TYPEINFO(Mammal);
+TINT_INSTANTIATE_TYPEINFO(Reptile);
+TINT_INSTANTIATE_TYPEINFO(Frog);
+TINT_INSTANTIATE_TYPEINFO(Bear);
+TINT_INSTANTIATE_TYPEINFO(Lizard);
+TINT_INSTANTIATE_TYPEINFO(Gecko);
+
+} // namespace tint
diff --git a/src/tint/transform/array_length_from_uniform.cc b/src/tint/transform/array_length_from_uniform.cc
index 78535f1..a396965 100644
--- a/src/tint/transform/array_length_from_uniform.cc
+++ b/src/tint/transform/array_length_from_uniform.cc
@@ -37,7 +37,7 @@
for (auto* fn : program->AST().Functions()) {
if (auto* sem_fn = program->Sem().Get(fn)) {
for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
- if (builtin->Type() == sem::BuiltinType::kArrayLength) {
+ if (builtin->Type() == builtin::Function::kArrayLength) {
return true;
}
}
@@ -199,7 +199,7 @@
auto* call = sem.Get(call_expr)->UnwrapMaterialize()->As<sem::Call>();
auto* builtin = call->Target()->As<sem::Builtin>();
- if (!builtin || builtin->Type() != sem::BuiltinType::kArrayLength) {
+ if (!builtin || builtin->Type() != builtin::Function::kArrayLength) {
continue;
}
diff --git a/src/tint/transform/builtin_polyfill.cc b/src/tint/transform/builtin_polyfill.cc
index 259eb11..cc770ab 100644
--- a/src/tint/transform/builtin_polyfill.cc
+++ b/src/tint/transform/builtin_polyfill.cc
@@ -23,6 +23,8 @@
#include "src/tint/sem/builtin.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/type_expression.h"
+#include "src/tint/sem/value_conversion.h"
+#include "src/tint/switch.h"
#include "src/tint/type/storage_texture.h"
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/map.h"
@@ -40,17 +42,123 @@
/// PIMPL state for the transform
struct BuiltinPolyfill::State {
/// Constructor
- /// @param c the CloneContext
- /// @param p the builtins to polyfill
- State(CloneContext& c, Builtins p) : ctx(c), polyfill(p) {
+ /// @param program the source program
+ /// @param config the transform config
+ State(const Program* program, const Config& config) : src(program), cfg(config) {
has_full_ptr_params = false;
- for (auto* enable : c.src->AST().Enables()) {
- if (enable->extension == builtin::Extension::kChromiumExperimentalFullPtrParameters) {
+ for (auto* enable : src->AST().Enables()) {
+ if (enable->HasExtension(builtin::Extension::kChromiumExperimentalFullPtrParameters)) {
has_full_ptr_params = true;
+ break;
}
}
}
+ /// Runs the transform
+ /// @returns the new program or SkipTransform if the transform is not required
+ Transform::ApplyResult Run() {
+ for (auto* node : src->ASTNodes().Objects()) {
+ Switch(
+ node, //
+ [&](const ast::CallExpression* expr) { Call(expr); },
+ [&](const ast::BinaryExpression* bin_op) {
+ if (auto* s = src->Sem().Get(bin_op);
+ !s || s->Stage() == sem::EvaluationStage::kConstant ||
+ s->Stage() == sem::EvaluationStage::kNotEvaluated) {
+ return; // Don't polyfill @const expressions
+ }
+ switch (bin_op->op) {
+ case ast::BinaryOp::kShiftLeft:
+ case ast::BinaryOp::kShiftRight: {
+ if (cfg.builtins.bitshift_modulo) {
+ ctx.Replace(bin_op,
+ [this, bin_op] { return BitshiftModulo(bin_op); });
+ made_changes = true;
+ }
+ break;
+ }
+ case ast::BinaryOp::kDivide: {
+ if (cfg.builtins.int_div_mod) {
+ auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
+ if (lhs_ty->is_integer_scalar_or_vector()) {
+ ctx.Replace(bin_op,
+ [this, bin_op] { return IntDivMod(bin_op); });
+ made_changes = true;
+ }
+ }
+ break;
+ }
+ case ast::BinaryOp::kModulo: {
+ if (cfg.builtins.int_div_mod) {
+ auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
+ if (lhs_ty->is_integer_scalar_or_vector()) {
+ ctx.Replace(bin_op,
+ [this, bin_op] { return IntDivMod(bin_op); });
+ made_changes = true;
+ }
+ }
+ if (cfg.builtins.precise_float_mod) {
+ auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
+ if (lhs_ty->is_float_scalar_or_vector()) {
+ ctx.Replace(bin_op,
+ [this, bin_op] { return PreciseFloatMod(bin_op); });
+ made_changes = true;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ },
+ [&](const ast::Expression* expr) {
+ if (cfg.builtins.bgra8unorm) {
+ if (auto* ty_expr = src->Sem().Get<sem::TypeExpression>(expr)) {
+ if (auto* tex = ty_expr->Type()->As<type::StorageTexture>()) {
+ if (tex->texel_format() == builtin::TexelFormat::kBgra8Unorm) {
+ ctx.Replace(expr, [this, tex] {
+ return ctx.dst->Expr(ctx.dst->ty.storage_texture(
+ tex->dim(), builtin::TexelFormat::kRgba8Unorm,
+ tex->access()));
+ });
+ made_changes = true;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ if (!made_changes) {
+ return SkipTransform;
+ }
+
+ ctx.Clone();
+ return Program(std::move(b));
+ }
+
+ private:
+ /// The source program
+ Program const* const src;
+ /// The transform config
+ const Config& cfg;
+ /// The destination program builder
+ ProgramBuilder b;
+ /// The clone context
+ CloneContext ctx{&b, src};
+ /// The source clone context
+ const sem::Info& sem = src->Sem();
+ /// Polyfill functions for binary operators.
+ utils::Hashmap<BinaryOpSignature, Symbol, 8> binary_op_polyfills;
+ /// Polyfill builtins.
+ utils::Hashmap<const sem::Builtin*, Symbol, 8> builtin_polyfills;
+ /// Polyfill f32 conversion to i32 or u32 (or vectors of)
+ utils::Hashmap<const type::Type*, Symbol, 2> f32_conv_polyfills;
+ // Tracks whether the chromium_experimental_full_ptr_parameters extension has been enabled.
+ bool has_full_ptr_params = false;
+ /// True if the transform has made changes (i.e. the program needs cloning)
+ bool made_changes = false;
+
////////////////////////////////////////////////////////////////////////////
// Function polyfills
////////////////////////////////////////////////////////////////////////////
@@ -71,7 +179,7 @@
};
utils::Vector<const ast::Statement*, 4> body;
- switch (polyfill.acosh) {
+ switch (cfg.builtins.acosh) {
case Level::kFull:
// return log(x + sqrt(x*x - 1));
body.Push(b.Return(
@@ -85,7 +193,7 @@
}
default:
TINT_ICE(Transform, b.Diagnostics())
- << "unhandled polyfill level: " << static_cast<int>(polyfill.acosh);
+ << "unhandled polyfill level: " << static_cast<int>(cfg.builtins.acosh);
return {};
}
@@ -125,7 +233,7 @@
};
utils::Vector<const ast::Statement*, 1> body;
- switch (polyfill.atanh) {
+ switch (cfg.builtins.atanh) {
case Level::kFull:
// return log((1+x) / (1-x)) * 0.5
body.Push(
@@ -138,7 +246,7 @@
break;
default:
TINT_ICE(Transform, b.Diagnostics())
- << "unhandled polyfill level: " << static_cast<int>(polyfill.acosh);
+ << "unhandled polyfill level: " << static_cast<int>(cfg.builtins.acosh);
return {};
}
@@ -306,7 +414,7 @@
b.Decl(b.Let("e", b.Call("min", u32(W), b.Add("s", "count")))),
};
- switch (polyfill.extract_bits) {
+ switch (cfg.builtins.extract_bits) {
case Level::kFull:
body.Push(b.Decl(b.Let("shl", b.Sub(u32(W), "e"))));
body.Push(b.Decl(b.Let("shr", b.Add("shl", "s"))));
@@ -328,7 +436,7 @@
break;
default:
TINT_ICE(Transform, b.Diagnostics())
- << "unhandled polyfill level: " << static_cast<int>(polyfill.extract_bits);
+ << "unhandled polyfill level: " << static_cast<int>(cfg.builtins.extract_bits);
return {};
}
@@ -532,7 +640,7 @@
utils::Vector<const ast::Statement*, 8> body;
- switch (polyfill.insert_bits) {
+ switch (cfg.builtins.insert_bits) {
case Level::kFull:
// let e = offset + count;
body.Push(b.Decl(b.Let("e", b.Add("offset", "count"))));
@@ -566,7 +674,7 @@
break;
default:
TINT_ICE(Transform, b.Diagnostics())
- << "unhandled polyfill level: " << static_cast<int>(polyfill.insert_bits);
+ << "unhandled polyfill level: " << static_cast<int>(cfg.builtins.insert_bits);
return {};
}
@@ -718,6 +826,52 @@
return name;
}
+ /// Builds the polyfill function to value convert a scalar or vector of f32 to an i32 or u32 (or
+ /// vector of).
+ /// @param source the type of the value being converted
+ /// @param target the target conversion type
+ /// @return the polyfill function name
+ Symbol ConvF32ToIU32(const type::Type* source, const type::Type* target) {
+ struct Limits {
+ AFloat low_condition;
+ AInt low_limit;
+ AFloat high_condition;
+ AInt high_limit;
+ };
+ const bool is_signed = target->is_signed_integer_scalar_or_vector();
+ const Limits limits = is_signed ? Limits{
+ /* low_condition */ -AFloat(0x80000000),
+ /* low_limit */ -AInt(0x80000000),
+ /* high_condition */ AFloat(0x7fffff80),
+ /* high_limit */ AInt(0x7fffffff),
+ }
+ : Limits{
+ /* low_condition */ AFloat(0),
+ /* low_limit */ AInt(0),
+ /* high_condition */ AFloat(0xffffff00),
+ /* high_limit */ AInt(0xffffffff),
+ };
+
+ const uint32_t width = WidthOf(target);
+
+ // select(target(v), low_limit, v < low_condition)
+ auto* select_low = b.Call(builtin::Function::kSelect, //
+ b.Call(T(target), "v"), //
+ ScalarOrVector(width, limits.low_limit), //
+ b.LessThan("v", ScalarOrVector(width, limits.low_condition)));
+
+ // select(high_limit, select_low, v < high_condition)
+ auto* select_high = b.Call(builtin::Function::kSelect, //
+ ScalarOrVector(width, limits.high_limit), //
+ select_low, //
+ b.LessThan("v", ScalarOrVector(width, limits.high_condition)));
+
+ auto name = b.Symbols().New(is_signed ? "tint_ftoi" : "tint_ftou");
+ b.Func(name, utils::Vector{b.Param("v", T(source))}, T(target),
+ utils::Vector{b.Return(select_high)});
+ return name;
+ }
+
////////////////////////////////////////////////////////////////////////////
// Inline polyfills
////////////////////////////////////////////////////////////////////////////
@@ -727,8 +881,8 @@
/// @param bin_op the original BinaryExpression
/// @return the polyfill value for bitshift operation
const ast::Expression* BitshiftModulo(const ast::BinaryExpression* bin_op) {
- auto* lhs_ty = ctx.src->TypeOf(bin_op->lhs)->UnwrapRef();
- auto* rhs_ty = ctx.src->TypeOf(bin_op->rhs)->UnwrapRef();
+ auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
+ auto* rhs_ty = src->TypeOf(bin_op->rhs)->UnwrapRef();
auto* lhs_el_ty = type::Type::DeepestElementOf(lhs_ty);
const ast::Expression* mask = b.Expr(AInt(lhs_el_ty->Size() * 8 - 1));
if (rhs_ty->Is<type::Vector>()) {
@@ -744,8 +898,8 @@
/// @param bin_op the original BinaryExpression
/// @return the polyfill divide or modulo
const ast::Expression* IntDivMod(const ast::BinaryExpression* bin_op) {
- auto* lhs_ty = ctx.src->TypeOf(bin_op->lhs)->UnwrapRef();
- auto* rhs_ty = ctx.src->TypeOf(bin_op->rhs)->UnwrapRef();
+ auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
+ auto* rhs_ty = src->TypeOf(bin_op->rhs)->UnwrapRef();
BinaryOpSignature sig{bin_op->op, lhs_ty, rhs_ty};
auto fn = binary_op_polyfills.GetOrCreate(sig, [&] {
const bool is_div = bin_op->op == ast::BinaryOp::kDivide;
@@ -839,8 +993,8 @@
/// @param bin_op the original BinaryExpression
/// @return the polyfill divide or modulo
const ast::Expression* PreciseFloatMod(const ast::BinaryExpression* bin_op) {
- auto* lhs_ty = ctx.src->TypeOf(bin_op->lhs)->UnwrapRef();
- auto* rhs_ty = ctx.src->TypeOf(bin_op->rhs)->UnwrapRef();
+ auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
+ auto* rhs_ty = src->TypeOf(bin_op->rhs)->UnwrapRef();
BinaryOpSignature sig{bin_op->op, lhs_ty, rhs_ty};
auto fn = binary_op_polyfills.GetOrCreate(sig, [&] {
uint32_t lhs_width = 1;
@@ -887,24 +1041,8 @@
return b.Call(fn, lhs, rhs);
}
- private:
- /// The clone context
- CloneContext& ctx;
- /// The builtins to polyfill
- Builtins polyfill;
- /// The destination program builder
- ProgramBuilder& b = *ctx.dst;
- /// The source clone context
- const sem::Info& sem = ctx.src->Sem();
-
- // Polyfill functions for binary operators.
- utils::Hashmap<BinaryOpSignature, Symbol, 8> binary_op_polyfills;
-
- // Tracks whether the chromium_experimental_full_ptr_parameters extension has been enabled.
- bool has_full_ptr_params;
-
/// @returns the AST type for the given sem type
- ast::Type T(const type::Type* ty) const { return CreateASTTypeFor(ctx, ty); }
+ ast::Type T(const type::Type* ty) { return CreateASTTypeFor(ctx, ty); }
/// @returns 1 if `ty` is not a vector, otherwise the vector width
uint32_t WidthOf(const type::Type* ty) const {
@@ -917,7 +1055,7 @@
/// @returns a scalar or vector with the given width, with each element with
/// the given value.
template <typename T>
- const ast::Expression* ScalarOrVector(uint32_t width, T value) const {
+ const ast::Expression* ScalarOrVector(uint32_t width, T value) {
if (width == 1) {
return b.Expr(value);
}
@@ -931,6 +1069,204 @@
}
return b.Call(b.ty.vec<To>(width), e);
}
+
+ /// Examines the call expression @p expr, applying any necessary polyfill transforms
+ void Call(const ast::CallExpression* expr) {
+ auto* call = src->Sem().Get(expr)->UnwrapMaterialize()->As<sem::Call>();
+ if (!call || call->Stage() == sem::EvaluationStage::kConstant ||
+ call->Stage() == sem::EvaluationStage::kNotEvaluated) {
+ return; // Don't polyfill @const expressions
+ }
+ Symbol fn = Switch(
+ call->Target(), //
+ [&](const sem::Builtin* builtin) {
+ switch (builtin->Type()) {
+ case builtin::Function::kAcosh:
+ if (cfg.builtins.acosh != Level::kNone) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return acosh(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kAsinh:
+ if (cfg.builtins.asinh) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return asinh(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kAtanh:
+ if (cfg.builtins.atanh != Level::kNone) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return atanh(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kClamp:
+ if (cfg.builtins.clamp_int) {
+ auto& sig = builtin->Signature();
+ if (sig.parameters[0]->Type()->is_integer_scalar_or_vector()) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return clampInteger(builtin->ReturnType()); });
+ }
+ }
+ return Symbol{};
+
+ case builtin::Function::kCountLeadingZeros:
+ if (cfg.builtins.count_leading_zeros) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return countLeadingZeros(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kCountTrailingZeros:
+ if (cfg.builtins.count_trailing_zeros) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return countTrailingZeros(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kExtractBits:
+ if (cfg.builtins.extract_bits != Level::kNone) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return extractBits(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kFirstLeadingBit:
+ if (cfg.builtins.first_leading_bit) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return firstLeadingBit(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kFirstTrailingBit:
+ if (cfg.builtins.first_trailing_bit) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return firstTrailingBit(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kInsertBits:
+ if (cfg.builtins.insert_bits != Level::kNone) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return insertBits(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kReflect:
+ // Only polyfill for vec2<f32>. See https://crbug.com/tint/1798 for
+ // more details.
+ if (cfg.builtins.reflect_vec2_f32) {
+ auto& sig = builtin->Signature();
+ auto* vec = sig.return_type->As<type::Vector>();
+ if (vec && vec->Width() == 2 && vec->type()->Is<type::F32>()) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return reflect(builtin->ReturnType()); });
+ }
+ }
+ return Symbol{};
+
+ case builtin::Function::kSaturate:
+ if (cfg.builtins.saturate) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return saturate(builtin->ReturnType()); });
+ }
+ return Symbol{};
+
+ case builtin::Function::kSign:
+ if (cfg.builtins.sign_int) {
+ auto* ty = builtin->ReturnType();
+ if (ty->is_signed_integer_scalar_or_vector()) {
+ return builtin_polyfills.GetOrCreate(builtin,
+ [&] { return sign_int(ty); });
+ }
+ }
+ return Symbol{};
+
+ case builtin::Function::kTextureSampleBaseClampToEdge:
+ if (cfg.builtins.texture_sample_base_clamp_to_edge_2d_f32) {
+ auto& sig = builtin->Signature();
+ auto* tex = sig.Parameter(sem::ParameterUsage::kTexture);
+ if (auto* stex = tex->Type()->As<type::SampledTexture>()) {
+ if (stex->type()->Is<type::F32>()) {
+ return builtin_polyfills.GetOrCreate(builtin, [&] {
+ return textureSampleBaseClampToEdge_2d_f32();
+ });
+ }
+ }
+ }
+ return Symbol{};
+
+ case builtin::Function::kTextureStore:
+ if (cfg.builtins.bgra8unorm) {
+ auto& sig = builtin->Signature();
+ auto* tex = sig.Parameter(sem::ParameterUsage::kTexture);
+ if (auto* stex = tex->Type()->As<type::StorageTexture>()) {
+ if (stex->texel_format() == builtin::TexelFormat::kBgra8Unorm) {
+ size_t value_idx = static_cast<size_t>(
+ sig.IndexOf(sem::ParameterUsage::kValue));
+ ctx.Replace(expr, [this, expr, value_idx] {
+ utils::Vector<const ast::Expression*, 3> args;
+ for (auto* arg : expr->args) {
+ arg = ctx.Clone(arg);
+ if (args.Length() == value_idx) { // value
+ arg = ctx.dst->MemberAccessor(arg, "bgra");
+ }
+ args.Push(arg);
+ }
+ return ctx.dst->Call(
+ utils::ToString(builtin::Function::kTextureStore),
+ std::move(args));
+ });
+ made_changes = true;
+ }
+ }
+ }
+ return Symbol{};
+
+ case builtin::Function::kQuantizeToF16:
+ if (cfg.builtins.quantize_to_vec_f16) {
+ if (auto* vec = builtin->ReturnType()->As<type::Vector>()) {
+ return builtin_polyfills.GetOrCreate(
+ builtin, [&] { return quantizeToF16(vec); });
+ }
+ }
+ return Symbol{};
+
+ case builtin::Function::kWorkgroupUniformLoad:
+ if (cfg.builtins.workgroup_uniform_load) {
+ return builtin_polyfills.GetOrCreate(builtin, [&] {
+ return workgroupUniformLoad(builtin->ReturnType());
+ });
+ }
+ return Symbol{};
+
+ default:
+ return Symbol{};
+ }
+ },
+ [&](const sem::ValueConversion* conv) {
+ if (cfg.builtins.conv_f32_to_iu32) {
+ auto* src_ty = conv->Source();
+ if (tint::Is<type::F32>(type::Type::ElementOf(src_ty))) {
+ auto* dst_ty = conv->Target();
+ if (tint::IsAnyOf<type::I32, type::U32>(type::Type::ElementOf(dst_ty))) {
+ return f32_conv_polyfills.GetOrCreate(dst_ty, [&] { //
+ return ConvF32ToIU32(src_ty, dst_ty);
+ });
+ }
+ }
+ }
+ return Symbol{};
+ });
+
+ if (fn.IsValid()) {
+ ctx.Replace(call->Declaration(),
+ [this, fn, expr] { return ctx.dst->Call(fn, ctx.Clone(expr->args)); });
+ made_changes = true;
+ }
+ }
};
BuiltinPolyfill::BuiltinPolyfill() = default;
@@ -944,261 +1280,7 @@
if (!cfg) {
return SkipTransform;
}
-
- auto& polyfill = cfg->builtins;
-
- utils::Hashmap<const sem::Builtin*, Symbol, 8> builtin_polyfills;
-
- ProgramBuilder b;
- CloneContext ctx{&b, src, /* auto_clone_symbols */ true};
- State s{ctx, polyfill};
-
- bool made_changes = false;
- for (auto* node : src->ASTNodes().Objects()) {
- Switch(
- node,
- [&](const ast::CallExpression* expr) {
- auto* call = src->Sem().Get(expr)->UnwrapMaterialize()->As<sem::Call>();
- if (!call || call->Stage() == sem::EvaluationStage::kConstant ||
- call->Stage() == sem::EvaluationStage::kNotEvaluated) {
- return; // Don't polyfill @const expressions
- }
- auto* builtin = call->Target()->As<sem::Builtin>();
- if (!builtin) {
- return;
- }
- Symbol fn;
- switch (builtin->Type()) {
- case sem::BuiltinType::kAcosh:
- if (polyfill.acosh != Level::kNone) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.acosh(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kAsinh:
- if (polyfill.asinh) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.asinh(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kAtanh:
- if (polyfill.atanh != Level::kNone) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.atanh(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kClamp:
- if (polyfill.clamp_int) {
- auto& sig = builtin->Signature();
- if (sig.parameters[0]->Type()->is_integer_scalar_or_vector()) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.clampInteger(builtin->ReturnType()); });
- }
- }
- break;
- case sem::BuiltinType::kCountLeadingZeros:
- if (polyfill.count_leading_zeros) {
- fn = builtin_polyfills.GetOrCreate(builtin, [&] {
- return s.countLeadingZeros(builtin->ReturnType());
- });
- }
- break;
- case sem::BuiltinType::kCountTrailingZeros:
- if (polyfill.count_trailing_zeros) {
- fn = builtin_polyfills.GetOrCreate(builtin, [&] {
- return s.countTrailingZeros(builtin->ReturnType());
- });
- }
- break;
- case sem::BuiltinType::kExtractBits:
- if (polyfill.extract_bits != Level::kNone) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.extractBits(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kFirstLeadingBit:
- if (polyfill.first_leading_bit) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.firstLeadingBit(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kFirstTrailingBit:
- if (polyfill.first_trailing_bit) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.firstTrailingBit(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kInsertBits:
- if (polyfill.insert_bits != Level::kNone) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.insertBits(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kReflect:
- // Only polyfill for vec2<f32>. See https://crbug.com/tint/1798 for more
- // details.
- if (polyfill.reflect_vec2_f32) {
- auto& sig = builtin->Signature();
- auto* vec = sig.return_type->As<type::Vector>();
- if (vec && vec->Width() == 2 && vec->type()->Is<type::F32>()) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.reflect(builtin->ReturnType()); });
- }
- }
- break;
- case sem::BuiltinType::kSaturate:
- if (polyfill.saturate) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.saturate(builtin->ReturnType()); });
- }
- break;
- case sem::BuiltinType::kSign:
- if (polyfill.sign_int) {
- auto* ty = builtin->ReturnType();
- if (ty->is_signed_integer_scalar_or_vector()) {
- fn = builtin_polyfills.GetOrCreate(builtin,
- [&] { return s.sign_int(ty); });
- }
- }
- break;
- case sem::BuiltinType::kTextureSampleBaseClampToEdge:
- if (polyfill.texture_sample_base_clamp_to_edge_2d_f32) {
- auto& sig = builtin->Signature();
- auto* tex = sig.Parameter(sem::ParameterUsage::kTexture);
- if (auto* stex = tex->Type()->As<type::SampledTexture>()) {
- if (stex->type()->Is<type::F32>()) {
- fn = builtin_polyfills.GetOrCreate(builtin, [&] {
- return s.textureSampleBaseClampToEdge_2d_f32();
- });
- }
- }
- }
- break;
- case sem::BuiltinType::kTextureStore:
- if (polyfill.bgra8unorm) {
- auto& sig = builtin->Signature();
- auto* tex = sig.Parameter(sem::ParameterUsage::kTexture);
- if (auto* stex = tex->Type()->As<type::StorageTexture>()) {
- if (stex->texel_format() == builtin::TexelFormat::kBgra8Unorm) {
- size_t value_idx = static_cast<size_t>(
- sig.IndexOf(sem::ParameterUsage::kValue));
- ctx.Replace(expr, [&ctx, expr, value_idx] {
- utils::Vector<const ast::Expression*, 3> args;
- for (auto* arg : expr->args) {
- arg = ctx.Clone(arg);
- if (args.Length() == value_idx) { // value
- arg = ctx.dst->MemberAccessor(arg, "bgra");
- }
- args.Push(arg);
- }
- return ctx.dst->Call(
- utils::ToString(sem::BuiltinType::kTextureStore),
- std::move(args));
- });
- made_changes = true;
- }
- }
- }
- break;
- case sem::BuiltinType::kQuantizeToF16:
- if (polyfill.quantize_to_vec_f16) {
- if (auto* vec = builtin->ReturnType()->As<type::Vector>()) {
- fn = builtin_polyfills.GetOrCreate(
- builtin, [&] { return s.quantizeToF16(vec); });
- }
- }
- break;
-
- case sem::BuiltinType::kWorkgroupUniformLoad:
- if (polyfill.workgroup_uniform_load) {
- fn = builtin_polyfills.GetOrCreate(builtin, [&] {
- return s.workgroupUniformLoad(builtin->ReturnType());
- });
- }
- break;
-
- default:
- break;
- }
-
- if (fn.IsValid()) {
- ctx.Replace(call->Declaration(), [&ctx, fn, expr] {
- return ctx.dst->Call(fn, ctx.Clone(expr->args));
- });
- made_changes = true;
- }
- },
- [&](const ast::BinaryExpression* bin_op) {
- if (auto* sem = src->Sem().Get(bin_op);
- !sem || sem->Stage() == sem::EvaluationStage::kConstant ||
- sem->Stage() == sem::EvaluationStage::kNotEvaluated) {
- return; // Don't polyfill @const expressions
- }
- switch (bin_op->op) {
- case ast::BinaryOp::kShiftLeft:
- case ast::BinaryOp::kShiftRight: {
- if (polyfill.bitshift_modulo) {
- ctx.Replace(bin_op, [bin_op, &s] { return s.BitshiftModulo(bin_op); });
- made_changes = true;
- }
- break;
- }
- case ast::BinaryOp::kDivide: {
- if (polyfill.int_div_mod) {
- auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
- if (lhs_ty->is_integer_scalar_or_vector()) {
- ctx.Replace(bin_op, [bin_op, &s] { return s.IntDivMod(bin_op); });
- made_changes = true;
- }
- }
- break;
- }
- case ast::BinaryOp::kModulo: {
- if (polyfill.int_div_mod) {
- auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
- if (lhs_ty->is_integer_scalar_or_vector()) {
- ctx.Replace(bin_op, [bin_op, &s] { return s.IntDivMod(bin_op); });
- made_changes = true;
- }
- }
- if (polyfill.precise_float_mod) {
- auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
- if (lhs_ty->is_float_scalar_or_vector()) {
- ctx.Replace(bin_op,
- [bin_op, &s] { return s.PreciseFloatMod(bin_op); });
- made_changes = true;
- }
- }
- break;
- }
- default:
- break;
- }
- },
- [&](const ast::Expression* expr) {
- if (polyfill.bgra8unorm) {
- if (auto* ty_expr = src->Sem().Get<sem::TypeExpression>(expr)) {
- if (auto* tex = ty_expr->Type()->As<type::StorageTexture>()) {
- if (tex->texel_format() == builtin::TexelFormat::kBgra8Unorm) {
- ctx.Replace(expr, [&ctx, tex] {
- return ctx.dst->Expr(ctx.dst->ty.storage_texture(
- tex->dim(), builtin::TexelFormat::kRgba8Unorm,
- tex->access()));
- });
- made_changes = true;
- }
- }
- }
- }
- });
- }
-
- if (!made_changes) {
- return SkipTransform;
- }
-
- ctx.Clone();
- return Program(std::move(b));
+ return State{src, *cfg}.Run();
}
BuiltinPolyfill::Config::Config(const Builtins& b) : builtins(b) {}
diff --git a/src/tint/transform/builtin_polyfill.h b/src/tint/transform/builtin_polyfill.h
index b070248..dee0bec 100644
--- a/src/tint/transform/builtin_polyfill.h
+++ b/src/tint/transform/builtin_polyfill.h
@@ -57,6 +57,8 @@
bool count_leading_zeros = false;
/// Should `countTrailingZeros()` be polyfilled?
bool count_trailing_zeros = false;
+ /// Should converting f32 to i32 or u32 be polyfilled?
+ bool conv_f32_to_iu32 = false;
/// What level should `extractBits()` be polyfilled?
Level extract_bits = Level::kNone;
/// Should `firstLeadingBit()` be polyfilled?
diff --git a/src/tint/transform/builtin_polyfill_test.cc b/src/tint/transform/builtin_polyfill_test.cc
index 8c0d787..65c1f29 100644
--- a/src/tint/transform/builtin_polyfill_test.cc
+++ b/src/tint/transform/builtin_polyfill_test.cc
@@ -815,6 +815,157 @@
}
////////////////////////////////////////////////////////////////////////////////
+// conv_f32_to_iu32
+////////////////////////////////////////////////////////////////////////////////
+DataMap polyfillConvF32ToIU32() {
+ BuiltinPolyfill::Builtins builtins;
+ builtins.conv_f32_to_iu32 = true;
+ DataMap data;
+ data.Add<BuiltinPolyfill::Config>(builtins);
+ return data;
+}
+
+TEST_F(BuiltinPolyfillTest, ShouldRunConvF32ToI32) {
+ auto* src = R"(
+fn f() {
+ let f = 42.0;
+ _ = i32(f);
+}
+)";
+
+ EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
+ EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillConvF32ToIU32()));
+}
+
+TEST_F(BuiltinPolyfillTest, ShouldRunConvF32ToU32) {
+ auto* src = R"(
+fn f() {
+ let f = 42.0;
+ _ = u32(f);
+}
+)";
+
+ EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
+ EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillConvF32ToIU32()));
+}
+
+TEST_F(BuiltinPolyfillTest, ShouldRunConvVec3F32ToVec3I32) {
+ auto* src = R"(
+fn f() {
+ let f = vec3(42.0);
+ _ = vec3<i32>(f);
+}
+)";
+
+ EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
+ EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillConvF32ToIU32()));
+}
+
+TEST_F(BuiltinPolyfillTest, ShouldRunConvVec3F32ToVec3U32) {
+ auto* src = R"(
+fn f() {
+ let f = vec3(42.0);
+ _ = vec3<u32>(f);
+}
+)";
+
+ EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
+ EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillConvF32ToIU32()));
+}
+
+TEST_F(BuiltinPolyfillTest, ConvF32ToI32) {
+ auto* src = R"(
+fn f() {
+ let f = 42.0;
+ _ = i32(f);
+}
+)";
+ auto* expect = R"(
+fn tint_ftoi(v : f32) -> i32 {
+ return select(2147483647, select(i32(v), -2147483648, (v < -2147483648.0)), (v < 2147483520.0));
+}
+
+fn f() {
+ let f = 42.0;
+ _ = tint_ftoi(f);
+}
+)";
+
+ auto got = Run<BuiltinPolyfill>(src, polyfillConvF32ToIU32());
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(BuiltinPolyfillTest, ConvF32ToU32) {
+ auto* src = R"(
+fn f() {
+ let f = 42.0;
+ _ = u32(f);
+}
+)";
+ auto* expect = R"(
+fn tint_ftou(v : f32) -> u32 {
+ return select(4294967295, select(u32(v), 0, (v < 0.0)), (v < 4294967040.0));
+}
+
+fn f() {
+ let f = 42.0;
+ _ = tint_ftou(f);
+}
+)";
+
+ auto got = Run<BuiltinPolyfill>(src, polyfillConvF32ToIU32());
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(BuiltinPolyfillTest, ConvVec3F32ToVec3I32) {
+ auto* src = R"(
+fn f() {
+ let f = vec3(42.0);
+ _ = vec3<i32>(f);
+}
+)";
+ auto* expect = R"(
+fn tint_ftoi(v : vec3<f32>) -> vec3<i32> {
+ return select(vec3(2147483647), select(vec3<i32>(v), vec3(-2147483648), (v < vec3(-2147483648.0))), (v < vec3(2147483520.0)));
+}
+
+fn f() {
+ let f = vec3(42.0);
+ _ = tint_ftoi(f);
+}
+)";
+
+ auto got = Run<BuiltinPolyfill>(src, polyfillConvF32ToIU32());
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(BuiltinPolyfillTest, ConvVec3F32ToVec3U32) {
+ auto* src = R"(
+fn f() {
+ let f = vec3(42.0);
+ _ = vec3<u32>(f);
+}
+)";
+ auto* expect = R"(
+fn tint_ftou(v : vec3<f32>) -> vec3<u32> {
+ return select(vec3(4294967295), select(vec3<u32>(v), vec3(0), (v < vec3(0.0))), (v < vec3(4294967040.0)));
+}
+
+fn f() {
+ let f = vec3(42.0);
+ _ = tint_ftou(f);
+}
+)";
+
+ auto got = Run<BuiltinPolyfill>(src, polyfillConvF32ToIU32());
+
+ EXPECT_EQ(expect, str(got));
+}
+
+////////////////////////////////////////////////////////////////////////////////
// countLeadingZeros
////////////////////////////////////////////////////////////////////////////////
DataMap polyfillCountLeadingZeros() {
diff --git a/src/tint/transform/calculate_array_length.cc b/src/tint/transform/calculate_array_length.cc
index 9f5b659..743a992 100644
--- a/src/tint/transform/calculate_array_length.cc
+++ b/src/tint/transform/calculate_array_length.cc
@@ -26,6 +26,7 @@
#include "src/tint/sem/statement.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/type/reference.h"
#include "src/tint/utils/hash.h"
@@ -44,7 +45,7 @@
for (auto* fn : program->AST().Functions()) {
if (auto* sem_fn = program->Sem().Get(fn)) {
for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
- if (builtin->Type() == sem::BuiltinType::kArrayLength) {
+ if (builtin->Type() == builtin::Function::kArrayLength) {
return true;
}
}
@@ -130,7 +131,7 @@
if (auto* call_expr = node->As<ast::CallExpression>()) {
auto* call = sem.Get(call_expr)->UnwrapMaterialize()->As<sem::Call>();
if (auto* builtin = call->Target()->As<sem::Builtin>()) {
- if (builtin->Type() == sem::BuiltinType::kArrayLength) {
+ if (builtin->Type() == builtin::Function::kArrayLength) {
// We're dealing with an arrayLength() call
if (auto* call_stmt = call->Stmt()->Declaration()->As<ast::CallStatement>()) {
diff --git a/src/tint/transform/combine_samplers.cc b/src/tint/transform/combine_samplers.cc
index 7b9f9fd..ca8111c 100644
--- a/src/tint/transform/combine_samplers.cc
+++ b/src/tint/transform/combine_samplers.cc
@@ -276,7 +276,7 @@
}
}
const ast::Expression* value = ctx.dst->Call(ctx.Clone(expr->target), args);
- if (builtin->Type() == sem::BuiltinType::kTextureLoad &&
+ if (builtin->Type() == builtin::Function::kTextureLoad &&
texture_var->Type()->UnwrapRef()->Is<type::DepthTexture>() &&
!call->Stmt()->Declaration()->Is<ast::CallStatement>()) {
value = ctx.dst->MemberAccessor(value, "x");
diff --git a/src/tint/transform/decompose_memory_access.cc b/src/tint/transform/decompose_memory_access.cc
index f3d92c5..f2146f3 100644
--- a/src/tint/transform/decompose_memory_access.cc
+++ b/src/tint/transform/decompose_memory_access.cc
@@ -30,6 +30,7 @@
#include "src/tint/sem/statement.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/type/array.h"
#include "src/tint/type/atomic.h"
#include "src/tint/type/reference.h"
@@ -124,7 +125,7 @@
/// AtomicKey is the unordered map key to an atomic intrinsic.
struct AtomicKey {
type::Type const* el_ty = nullptr; // element type
- sem::BuiltinType const op; // atomic op
+ builtin::Function const op; // atomic op
Symbol const buffer; // buffer name
bool operator==(const AtomicKey& rhs) const {
return el_ty == rhs.el_ty && op == rhs.op && buffer == rhs.buffer;
@@ -248,42 +249,42 @@
/// @returns a DecomposeMemoryAccess::Intrinsic attribute that can be applied to a stub function for
/// the atomic op and the type @p ty.
DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
- sem::BuiltinType ity,
+ builtin::Function ity,
const type::Type* ty,
const Symbol& buffer) {
auto op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
switch (ity) {
- case sem::BuiltinType::kAtomicLoad:
+ case builtin::Function::kAtomicLoad:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
break;
- case sem::BuiltinType::kAtomicStore:
+ case builtin::Function::kAtomicStore:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicStore;
break;
- case sem::BuiltinType::kAtomicAdd:
+ case builtin::Function::kAtomicAdd:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAdd;
break;
- case sem::BuiltinType::kAtomicSub:
+ case builtin::Function::kAtomicSub:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicSub;
break;
- case sem::BuiltinType::kAtomicMax:
+ case builtin::Function::kAtomicMax:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMax;
break;
- case sem::BuiltinType::kAtomicMin:
+ case builtin::Function::kAtomicMin:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMin;
break;
- case sem::BuiltinType::kAtomicAnd:
+ case builtin::Function::kAtomicAnd:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAnd;
break;
- case sem::BuiltinType::kAtomicOr:
+ case builtin::Function::kAtomicOr:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicOr;
break;
- case sem::BuiltinType::kAtomicXor:
+ case builtin::Function::kAtomicXor:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicXor;
break;
- case sem::BuiltinType::kAtomicExchange:
+ case builtin::Function::kAtomicExchange:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicExchange;
break;
- case sem::BuiltinType::kAtomicCompareExchangeWeak:
+ case builtin::Function::kAtomicCompareExchangeWeak:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
break;
default:
@@ -658,7 +659,7 @@
ast::Type ret_ty;
// For intrinsics that return a struct, there is no AST node for it, so create one now.
- if (intrinsic->Type() == sem::BuiltinType::kAtomicCompareExchangeWeak) {
+ if (intrinsic->Type() == builtin::Function::kAtomicCompareExchangeWeak) {
auto* str = intrinsic->ReturnType()->As<sem::Struct>();
TINT_ASSERT(Transform, str && str->Declaration() == nullptr);
@@ -937,7 +938,7 @@
if (auto* call_expr = node->As<ast::CallExpression>()) {
auto* call = sem.Get(call_expr)->UnwrapMaterialize()->As<sem::Call>();
if (auto* builtin = call->Target()->As<sem::Builtin>()) {
- if (builtin->Type() == sem::BuiltinType::kArrayLength) {
+ if (builtin->Type() == builtin::Function::kArrayLength) {
// arrayLength(X)
// Don't convert X into a load, this builtin actually requires the real pointer.
state.TakeAccess(call_expr->args[0]);
diff --git a/src/tint/transform/demote_to_helper.cc b/src/tint/transform/demote_to_helper.cc
index ac3c15e..c853ef0 100644
--- a/src/tint/transform/demote_to_helper.cc
+++ b/src/tint/transform/demote_to_helper.cc
@@ -23,6 +23,7 @@
#include "src/tint/sem/call.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/statement.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/utils/hoist_to_decl_before.h"
#include "src/tint/type/reference.h"
#include "src/tint/utils/map.h"
@@ -152,13 +153,13 @@
return;
}
- if (builtin->Type() == sem::BuiltinType::kTextureStore) {
+ if (builtin->Type() == builtin::Function::kTextureStore) {
// A call to textureStore() will always be a statement.
// Wrap it inside a conditional block.
auto* masked_call = b.If(b.Not(flag), b.Block(ctx.Clone(stmt->Declaration())));
ctx.Replace(stmt->Declaration(), masked_call);
} else if (builtin->IsAtomic() &&
- builtin->Type() != sem::BuiltinType::kAtomicLoad) {
+ builtin->Type() != builtin::Function::kAtomicLoad) {
// A call to an atomic builtin can be a statement or an expression.
if (auto* call_stmt = stmt->Declaration()->As<ast::CallStatement>();
call_stmt && call_stmt->expr == call) {
@@ -179,7 +180,7 @@
auto result = b.Sym();
ast::Type result_ty;
const ast::Statement* masked_call = nullptr;
- if (builtin->Type() == sem::BuiltinType::kAtomicCompareExchangeWeak) {
+ if (builtin->Type() == builtin::Function::kAtomicCompareExchangeWeak) {
// Special case for atomicCompareExchangeWeak as we cannot name its
// result type. We have to declare an equivalent struct and copy the
// original member values over to it.
diff --git a/src/tint/transform/merge_return.cc b/src/tint/transform/merge_return.cc
index 353fb13..f9f2feb 100644
--- a/src/tint/transform/merge_return.cc
+++ b/src/tint/transform/merge_return.cc
@@ -18,6 +18,7 @@
#include "src/tint/program_builder.h"
#include "src/tint/sem/statement.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/scoped_assignment.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::MergeReturn);
diff --git a/src/tint/transform/multiplanar_external_texture.cc b/src/tint/transform/multiplanar_external_texture.cc
index 27eeeb0..310bc46 100644
--- a/src/tint/transform/multiplanar_external_texture.cc
+++ b/src/tint/transform/multiplanar_external_texture.cc
@@ -121,7 +121,7 @@
// The binding points for the newly introduced bindings must have been provided to this
// transform. We fetch the new binding points by providing the original texture_external
// binding points into the passed map.
- BindingPoint bp = sem_var->BindingPoint();
+ sem::BindingPoint bp = sem_var->BindingPoint();
BindingsMap::const_iterator it = new_binding_points->bindings_map.find(bp);
if (it == new_binding_points->bindings_map.end()) {
@@ -196,7 +196,7 @@
if (builtin && !builtin->Parameters().IsEmpty() &&
builtin->Parameters()[0]->Type()->Is<type::ExternalTexture>() &&
- builtin->Type() != sem::BuiltinType::kTextureDimensions) {
+ builtin->Type() != builtin::Function::kTextureDimensions) {
if (auto* var_user =
sem.GetVal(expr->args[0])->UnwrapLoad()->As<sem::VariableUser>()) {
auto it = new_binding_symbols.find(var_user->Variable());
@@ -210,9 +210,9 @@
auto& syms = it->second;
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureLoad:
+ case builtin::Function::kTextureLoad:
return createTextureLoad(call, syms);
- case sem::BuiltinType::kTextureSampleBaseClampToEdge:
+ case builtin::Function::kTextureSampleBaseClampToEdge:
return createTextureSampleBaseClampToEdge(expr, syms);
default:
break;
@@ -310,13 +310,13 @@
/// builtin function.
/// @param call_type determines which function body to generate
/// @returns a statement list that makes of the body of the chosen function
- auto buildTextureBuiltinBody(sem::BuiltinType call_type) {
+ auto buildTextureBuiltinBody(builtin::Function call_type) {
utils::Vector<const ast::Statement*, 16> stmts;
const ast::CallExpression* single_plane_call = nullptr;
const ast::CallExpression* plane_0_call = nullptr;
const ast::CallExpression* plane_1_call = nullptr;
switch (call_type) {
- case sem::BuiltinType::kTextureSampleBaseClampToEdge:
+ case builtin::Function::kTextureSampleBaseClampToEdge:
stmts.Push(b.Decl(b.Let(
"modifiedCoords", b.Mul(b.MemberAccessor("params", "coordTransformationMatrix"),
b.vec3<f32>("coord", 1_a)))));
@@ -346,7 +346,7 @@
// textureSampleLevel(plane1, smp, plane1_clamped, 0.0);
plane_1_call = b.Call("textureSampleLevel", "plane1", "smp", "plane1_clamped", 0_a);
break;
- case sem::BuiltinType::kTextureLoad:
+ case builtin::Function::kTextureLoad:
// textureLoad(plane0, coord, 0);
single_plane_call = b.Call("textureLoad", "plane0", "coord", 0_a);
// textureLoad(plane0, coord, 0);
@@ -433,7 +433,7 @@
b.Param("params", b.ty(params_struct_sym)),
},
b.ty.vec4(b.ty.f32()),
- buildTextureBuiltinBody(sem::BuiltinType::kTextureSampleBaseClampToEdge));
+ buildTextureBuiltinBody(builtin::Function::kTextureSampleBaseClampToEdge));
}
return b.Call(texture_sample_external_sym, utils::Vector{
@@ -480,7 +480,7 @@
b.Param("params", b.ty(params_struct_sym)),
},
b.ty.vec4(b.ty.f32()), //
- buildTextureBuiltinBody(sem::BuiltinType::kTextureLoad));
+ buildTextureBuiltinBody(builtin::Function::kTextureLoad));
return name;
});
@@ -494,6 +494,7 @@
MultiplanarExternalTexture::NewBindingPoints::NewBindingPoints(BindingsMap inputBindingsMap)
: bindings_map(std::move(inputBindingsMap)) {}
+
MultiplanarExternalTexture::NewBindingPoints::~NewBindingPoints() = default;
MultiplanarExternalTexture::MultiplanarExternalTexture() = default;
diff --git a/src/tint/transform/multiplanar_external_texture.h b/src/tint/transform/multiplanar_external_texture.h
index 695e38c..656d0ad 100644
--- a/src/tint/transform/multiplanar_external_texture.h
+++ b/src/tint/transform/multiplanar_external_texture.h
@@ -19,15 +19,13 @@
#include <utility>
#include "src/tint/ast/struct_member.h"
+#include "src/tint/builtin/function.h"
#include "src/tint/sem/binding_point.h"
-#include "src/tint/sem/builtin_type.h"
+#include "src/tint/sem/external_texture.h"
#include "src/tint/transform/transform.h"
namespace tint::transform {
-/// BindingPoint is an alias to sem::BindingPoint
-using BindingPoint = sem::BindingPoint;
-
/// Within the MultiplanarExternalTexture transform, each instance of a
/// texture_external binding is unpacked into two texture_2d<f32> bindings
/// representing two possible planes of a texture and a uniform buffer binding
@@ -43,22 +41,12 @@
public:
/// This struct identifies the binding groups and locations for new bindings to
/// use when transforming a texture_external instance.
- struct BindingPoints {
- /// The desired binding location of the texture_2d representing plane #1 when
- /// a texture_external binding is expanded.
- BindingPoint plane_1;
- /// The desired binding location of the ExternalTextureParams uniform when a
- /// texture_external binding is expanded.
- BindingPoint params;
-
- /// Reflect the fields of this class so that it can be used by tint::ForeachField()
- TINT_REFLECT(plane_1, params);
- };
+ using BindingPoints = sem::external_texture::BindingPoints;
/// BindingsMap is a map where the key is the binding location of a
/// texture_external and the value is a struct containing the desired
/// locations for new bindings expanded from the texture_external instance.
- using BindingsMap = std::unordered_map<BindingPoint, BindingPoints>;
+ using BindingsMap = sem::external_texture::BindingsMap;
/// NewBindingPoints is consumed by the MultiplanarExternalTexture transform.
/// Data holds information about location of each texture_external binding and
diff --git a/src/tint/transform/packed_vec3.cc b/src/tint/transform/packed_vec3.cc
index 956adcb..8a23221 100644
--- a/src/tint/transform/packed_vec3.cc
+++ b/src/tint/transform/packed_vec3.cc
@@ -27,6 +27,7 @@
#include "src/tint/sem/statement.h"
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/type/array.h"
#include "src/tint/type/reference.h"
#include "src/tint/type/vector.h"
diff --git a/src/tint/transform/preserve_padding.cc b/src/tint/transform/preserve_padding.cc
index fbe785c..e8c95e3 100644
--- a/src/tint/transform/preserve_padding.cc
+++ b/src/tint/transform/preserve_padding.cc
@@ -19,6 +19,7 @@
#include "src/tint/program_builder.h"
#include "src/tint/sem/struct.h"
+#include "src/tint/switch.h"
#include "src/tint/type/reference.h"
#include "src/tint/utils/map.h"
#include "src/tint/utils/vector.h"
@@ -66,8 +67,8 @@
},
[&](const ast::Enable* enable) {
// Check if the full pointer parameters extension is already enabled.
- if (enable->extension ==
- builtin::Extension::kChromiumExperimentalFullPtrParameters) {
+ if (enable->HasExtension(
+ builtin::Extension::kChromiumExperimentalFullPtrParameters)) {
ext_enabled = true;
}
});
diff --git a/src/tint/transform/promote_side_effects_to_decl.cc b/src/tint/transform/promote_side_effects_to_decl.cc
index 65ec731..9db7e38 100644
--- a/src/tint/transform/promote_side_effects_to_decl.cc
+++ b/src/tint/transform/promote_side_effects_to_decl.cc
@@ -337,9 +337,8 @@
});
}
- // Starts the recursive processing of a statement's expression(s) to hoist
- // side-effects to lets.
- void ProcessStatement(const ast::Expression* expr) {
+ // Starts the recursive processing of a statement's expression(s) to hoist side-effects to lets.
+ void ProcessExpression(const ast::Expression* expr) {
if (!expr) {
return;
}
@@ -348,31 +347,6 @@
ProcessExpression(expr, maybe_hoist);
}
- // Special case for processing assignment statement expressions, as we must
- // evaluate the rhs before the lhs, and possibly hoist the rhs expression.
- void ProcessAssignment(const ast::Expression* lhs, const ast::Expression* rhs) {
- // Evaluate rhs before lhs
- tint::utils::Vector<const ast::Expression*, 8> maybe_hoist;
- if (ProcessExpression(rhs, maybe_hoist)) {
- maybe_hoist.Push(rhs);
- }
-
- // If the rhs has side-effects, it may affect the lhs, so hoist it right
- // away. e.g. "b[c] = a(0);"
- if (HasSideEffects(rhs)) {
- // Technically, we can always hoist rhs, but don't bother doing so when
- // the lhs is just a variable or phony.
- if (!lhs->IsAnyOf<ast::IdentifierExpression, ast::PhonyExpression>()) {
- Flush(maybe_hoist);
- }
- }
-
- // If maybe_hoist still has values, it means they are potential side-effect
- // receivers. We pass this in while processing the lhs, in which case they
- // may get hoisted if the lhs has side-effects. E.g. "b[a(0)] = c;".
- ProcessExpression(lhs, maybe_hoist);
- }
-
public:
explicit CollectHoistsState(CloneContext& ctx_in) : StateBase(ctx_in) {}
@@ -386,21 +360,26 @@
}
Switch(
- stmt, [&](const ast::AssignmentStatement* s) { ProcessAssignment(s->lhs, s->rhs); },
- [&](const ast::CallStatement* s) { //
- ProcessStatement(s->expr);
+ stmt, //
+ [&](const ast::AssignmentStatement* s) {
+ tint::utils::Vector<const ast::Expression*, 8> maybe_hoist;
+ ProcessExpression(s->lhs, maybe_hoist);
+ ProcessExpression(s->rhs, maybe_hoist);
},
- [&](const ast::ForLoopStatement* s) { ProcessStatement(s->condition); },
- [&](const ast::WhileStatement* s) { ProcessStatement(s->condition); },
+ [&](const ast::CallStatement* s) { //
+ ProcessExpression(s->expr);
+ },
+ [&](const ast::ForLoopStatement* s) { ProcessExpression(s->condition); },
+ [&](const ast::WhileStatement* s) { ProcessExpression(s->condition); },
[&](const ast::IfStatement* s) { //
- ProcessStatement(s->condition);
+ ProcessExpression(s->condition);
},
[&](const ast::ReturnStatement* s) { //
- ProcessStatement(s->value);
+ ProcessExpression(s->value);
},
- [&](const ast::SwitchStatement* s) { ProcessStatement(s->condition); },
+ [&](const ast::SwitchStatement* s) { ProcessExpression(s->condition); },
[&](const ast::VariableDeclStatement* s) {
- ProcessStatement(s->variable->initializer);
+ ProcessExpression(s->variable->initializer);
});
}
@@ -563,10 +542,10 @@
!sem.GetVal(s->rhs)->HasSideEffects()) {
return nullptr;
}
- // rhs before lhs
+ // lhs before rhs
tint::utils::Vector<const ast::Statement*, 8> stmts;
- ctx.Replace(s->rhs, Decompose(s->rhs, &stmts));
ctx.Replace(s->lhs, Decompose(s->lhs, &stmts));
+ ctx.Replace(s->rhs, Decompose(s->rhs, &stmts));
InsertBefore(stmts, s);
return ctx.CloneWithoutTransform(s);
},
diff --git a/src/tint/transform/promote_side_effects_to_decl_test.cc b/src/tint/transform/promote_side_effects_to_decl_test.cc
index 6ed4b27..636a809 100644
--- a/src/tint/transform/promote_side_effects_to_decl_test.cc
+++ b/src/tint/transform/promote_side_effects_to_decl_test.cc
@@ -2830,9 +2830,8 @@
fn f() {
var b = array<i32, 10>();
- let tint_symbol = a(1);
- let tint_symbol_1 = a(0);
- b[tint_symbol_1] = tint_symbol;
+ let tint_symbol = a(0);
+ b[tint_symbol] = a(1);
}
)";
@@ -2861,10 +2860,9 @@
fn f() {
var b = array<array<i32, 10>, 10>();
- let tint_symbol = a(2);
- let tint_symbol_1 = a(0);
- let tint_symbol_2 = a(1);
- b[tint_symbol_1][tint_symbol_2] = tint_symbol;
+ let tint_symbol = a(0);
+ let tint_symbol_1 = a(1);
+ b[tint_symbol][tint_symbol_1] = a(2);
}
)";
@@ -2893,11 +2891,10 @@
fn f() {
var b = array<array<array<i32, 10>, 10>, 10>();
- let tint_symbol = a(3);
- let tint_symbol_1 = a(0);
- let tint_symbol_2 = a(1);
- let tint_symbol_3 = a(2);
- b[tint_symbol_1][tint_symbol_2][tint_symbol_3] = tint_symbol;
+ let tint_symbol = a(0);
+ let tint_symbol_1 = a(1);
+ let tint_symbol_2 = a(2);
+ b[tint_symbol][tint_symbol_1][tint_symbol_2] = a(3);
}
)";
@@ -2930,11 +2927,9 @@
var b = array<i32, 3>();
var d = array<array<i32, 3>, 3>();
var a_1 = 0;
- let tint_symbol = a(0);
- let tint_symbol_1 = a_1;
- let tint_symbol_2 = d[tint_symbol][tint_symbol_1];
- let tint_symbol_3 = a(2);
- b[tint_symbol_3] = tint_symbol_2;
+ let tint_symbol = a(2);
+ let tint_symbol_1 = a(0);
+ b[tint_symbol] = d[tint_symbol_1][a_1];
}
)";
@@ -2963,9 +2958,8 @@
fn f() {
var b = vec3<i32>();
- let tint_symbol = a(1);
- let tint_symbol_1 = a(0);
- b[tint_symbol_1] = tint_symbol;
+ let tint_symbol = a(0);
+ b[tint_symbol] = a(1);
}
)";
@@ -2996,9 +2990,8 @@
fn f() {
var b = vec3<i32>();
var c = 0;
- let tint_symbol = c;
- let tint_symbol_1 = a(0);
- b[tint_symbol_1] = tint_symbol;
+ let tint_symbol = a(0);
+ b[tint_symbol] = c;
}
)";
@@ -3029,8 +3022,8 @@
fn f() {
var b = vec3<i32>();
var c = 0;
- let tint_symbol = a(0);
- b[c] = tint_symbol;
+ let tint_symbol = c;
+ b[tint_symbol] = a(0);
}
)";
diff --git a/src/tint/transform/renamer.cc b/src/tint/transform/renamer.cc
index 3ddb6c6..708c6ec 100644
--- a/src/tint/transform/renamer.cc
+++ b/src/tint/transform/renamer.cc
@@ -24,6 +24,7 @@
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
+#include "src/tint/switch.h"
#include "src/tint/text/unicode.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer);
diff --git a/src/tint/transform/robustness.cc b/src/tint/transform/robustness.cc
index b79a029..2eb74a1 100644
--- a/src/tint/transform/robustness.cc
+++ b/src/tint/transform/robustness.cc
@@ -28,6 +28,7 @@
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/value_expression.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/utils/hoist_to_decl_before.h"
#include "src/tint/type/reference.h"
@@ -231,7 +232,7 @@
// Must clamp, even if the index is constant.
auto* arr_ptr = b.AddressOf(ctx.Clone(expr->Object()->Declaration()));
- return b.Sub(b.Call(sem::BuiltinType::kArrayLength, arr_ptr), 1_u);
+ return b.Sub(b.Call(builtin::Function::kArrayLength, arr_ptr), 1_u);
}
if (auto count = arr->ConstantCount()) {
if (expr->Index()->ConstantValue()) {
@@ -343,7 +344,7 @@
if (expr_sem->Index()->Type()->is_signed_integer_scalar()) {
idx = b.Call<u32>(idx); // u32(idx)
}
- auto* clamped_idx = b.Call(sem::BuiltinType::kMin, idx, max);
+ auto* clamped_idx = b.Call(builtin::Function::kMin, idx, max);
ctx.Replace(expr->Declaration()->index, clamped_idx);
}
@@ -358,14 +359,14 @@
}
if (predicate) {
- if (builtin->Type() == sem::BuiltinType::kWorkgroupUniformLoad) {
+ if (builtin->Type() == builtin::Function::kWorkgroupUniformLoad) {
// https://www.w3.org/TR/WGSL/#workgroupUniformLoad-builtin:
// "Executes a control barrier synchronization function that affects memory and
// atomic operations in the workgroup address space."
// Because the call acts like a control barrier, we need to make sure that we still
// trigger a workgroup barrier if the predicate fails.
PredicateCall(call, predicate,
- b.Block(b.CallStmt(b.Call(sem::BuiltinType::kWorkgroupBarrier))));
+ b.Block(b.CallStmt(b.Call(builtin::Function::kWorkgroupBarrier))));
} else {
PredicateCall(call, predicate);
}
@@ -408,7 +409,7 @@
// let num_levels = textureNumLevels(texture-arg);
num_levels = b.Symbols().New("num_levels");
hoist.InsertBefore(
- stmt, b.Decl(b.Let(num_levels, b.Call(sem::BuiltinType::kTextureNumLevels,
+ stmt, b.Decl(b.Let(num_levels, b.Call(builtin::Function::kTextureNumLevels,
ctx.Clone(texture_arg)))));
// predicate: level_idx < num_levels
@@ -433,12 +434,12 @@
// predicate: all(coords < textureDimensions(texture))
auto* dimensions =
level_idx.IsValid()
- ? b.Call(sem::BuiltinType::kTextureDimensions, ctx.Clone(texture_arg),
- b.Call(sem::BuiltinType::kMin, b.Expr(level_idx),
+ ? b.Call(builtin::Function::kTextureDimensions, ctx.Clone(texture_arg),
+ b.Call(builtin::Function::kMin, b.Expr(level_idx),
b.Sub(num_levels, 1_a)))
- : b.Call(sem::BuiltinType::kTextureDimensions, ctx.Clone(texture_arg));
+ : b.Call(builtin::Function::kTextureDimensions, ctx.Clone(texture_arg));
predicate =
- And(predicate, b.Call(sem::BuiltinType::kAll, b.LessThan(coords, dimensions)));
+ And(predicate, b.Call(builtin::Function::kAll, b.LessThan(coords, dimensions)));
// Replace the level argument with `coord`
ctx.Replace(arg, b.Expr(coords));
@@ -448,7 +449,7 @@
if (array_arg_idx >= 0) {
// let array_idx = u32(array-arg)
auto* arg = expr->args[static_cast<size_t>(array_arg_idx)];
- auto* num_layers = b.Call(sem::BuiltinType::kTextureNumLayers, ctx.Clone(texture_arg));
+ auto* num_layers = b.Call(builtin::Function::kTextureNumLayers, ctx.Clone(texture_arg));
auto array_idx = b.Symbols().New("array_idx");
hoist.InsertBefore(stmt, b.Decl(b.Let(array_idx, CastToUnsigned(ctx.Clone(arg), 1u))));
@@ -493,10 +494,10 @@
const auto* arg = expr->args[static_cast<size_t>(level_arg_idx)];
level_idx = b.Symbols().New("level_idx");
const auto* num_levels =
- b.Call(sem::BuiltinType::kTextureNumLevels, ctx.Clone(texture_arg));
+ b.Call(builtin::Function::kTextureNumLevels, ctx.Clone(texture_arg));
const auto* max = b.Sub(num_levels, 1_a);
hoist.InsertBefore(
- stmt, b.Decl(b.Let(level_idx, b.Call(sem::BuiltinType::kMin,
+ stmt, b.Decl(b.Let(level_idx, b.Call(builtin::Function::kMin,
b.Call<u32>(ctx.Clone(arg)), max))));
ctx.Replace(arg, b.Expr(level_idx));
}
@@ -510,19 +511,19 @@
const auto width = WidthOf(param->Type());
const auto* dimensions =
level_idx.IsValid()
- ? b.Call(sem::BuiltinType::kTextureDimensions, ctx.Clone(texture_arg),
+ ? b.Call(builtin::Function::kTextureDimensions, ctx.Clone(texture_arg),
level_idx)
- : b.Call(sem::BuiltinType::kTextureDimensions, ctx.Clone(texture_arg));
+ : b.Call(builtin::Function::kTextureDimensions, ctx.Clone(texture_arg));
// dimensions is u32 or vecN<u32>
const auto* unsigned_max = b.Sub(dimensions, ScalarOrVec(b.Expr(1_a), width));
if (param->Type()->is_signed_integer_scalar_or_vector()) {
const auto* zero = ScalarOrVec(b.Expr(0_a), width);
const auto* signed_max = CastToSigned(unsigned_max, width);
- ctx.Replace(arg,
- b.Call(sem::BuiltinType::kClamp, ctx.Clone(arg), zero, signed_max));
+ ctx.Replace(
+ arg, b.Call(builtin::Function::kClamp, ctx.Clone(arg), zero, signed_max));
} else {
- ctx.Replace(arg, b.Call(sem::BuiltinType::kMin, ctx.Clone(arg), unsigned_max));
+ ctx.Replace(arg, b.Call(builtin::Function::kMin, ctx.Clone(arg), unsigned_max));
}
}
}
@@ -531,14 +532,15 @@
if (array_arg_idx >= 0) {
auto* param = builtin->Parameters()[static_cast<size_t>(array_arg_idx)];
auto* arg = expr->args[static_cast<size_t>(array_arg_idx)];
- auto* num_layers = b.Call(sem::BuiltinType::kTextureNumLayers, ctx.Clone(texture_arg));
+ auto* num_layers = b.Call(builtin::Function::kTextureNumLayers, ctx.Clone(texture_arg));
const auto* unsigned_max = b.Sub(num_layers, 1_a);
if (param->Type()->is_signed_integer_scalar()) {
const auto* signed_max = CastToSigned(unsigned_max, 1u);
- ctx.Replace(arg, b.Call(sem::BuiltinType::kClamp, ctx.Clone(arg), 0_a, signed_max));
+ ctx.Replace(arg,
+ b.Call(builtin::Function::kClamp, ctx.Clone(arg), 0_a, signed_max));
} else {
- ctx.Replace(arg, b.Call(sem::BuiltinType::kMin, ctx.Clone(arg), unsigned_max));
+ ctx.Replace(arg, b.Call(builtin::Function::kMin, ctx.Clone(arg), unsigned_max));
}
}
}
@@ -546,9 +548,10 @@
/// @param type builtin type
/// @returns true if the given builtin is a texture function that requires predication or
/// clamping of arguments.
- bool TextureBuiltinNeedsRobustness(sem::BuiltinType type) {
- return type == sem::BuiltinType::kTextureLoad || type == sem::BuiltinType::kTextureStore ||
- type == sem::BuiltinType::kTextureDimensions;
+ bool TextureBuiltinNeedsRobustness(builtin::Function type) {
+ return type == builtin::Function::kTextureLoad ||
+ type == builtin::Function::kTextureStore ||
+ type == builtin::Function::kTextureDimensions;
}
/// @returns a bitwise and of the two expressions, or the other expression if one is null.
diff --git a/src/tint/transform/simplify_pointers.cc b/src/tint/transform/simplify_pointers.cc
index e9c719e..bec9019 100644
--- a/src/tint/transform/simplify_pointers.cc
+++ b/src/tint/transform/simplify_pointers.cc
@@ -24,6 +24,7 @@
#include "src/tint/sem/function.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/unshadow.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::SimplifyPointers);
diff --git a/src/tint/transform/single_entry_point.cc b/src/tint/transform/single_entry_point.cc
index 8a8daeb..8be90bb 100644
--- a/src/tint/transform/single_entry_point.cc
+++ b/src/tint/transform/single_entry_point.cc
@@ -20,6 +20,7 @@
#include "src/tint/program_builder.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::SingleEntryPoint);
TINT_INSTANTIATE_TYPEINFO(tint::transform::SingleEntryPoint::Config);
diff --git a/src/tint/transform/spirv_atomic.cc b/src/tint/transform/spirv_atomic.cc
index 043861b..f41fbb7 100644
--- a/src/tint/transform/spirv_atomic.cc
+++ b/src/tint/transform/spirv_atomic.cc
@@ -26,6 +26,7 @@
#include "src/tint/sem/index_accessor_expression.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/statement.h"
+#include "src/tint/switch.h"
#include "src/tint/type/reference.h"
#include "src/tint/utils/map.h"
#include "src/tint/utils/unique_vector.h"
@@ -81,22 +82,22 @@
out_args[0] = b.AddressOf(out_args[0]);
// Replace all callsites of this stub to a call to the real builtin
- if (stub->builtin == sem::BuiltinType::kAtomicCompareExchangeWeak) {
+ if (stub->builtin == builtin::Function::kAtomicCompareExchangeWeak) {
// atomicCompareExchangeWeak returns a struct, so insert a call to it above
// the current statement, and replace the current call with the struct's
// `old_value` member.
auto* block = call->Stmt()->Block()->Declaration();
auto old_value = b.Symbols().New("old_value");
auto old_value_decl = b.Decl(b.Let(
- old_value,
- b.MemberAccessor(b.Call(sem::str(stub->builtin), std::move(out_args)),
- "old_value")));
+ old_value, b.MemberAccessor(
+ b.Call(builtin::str(stub->builtin), std::move(out_args)),
+ "old_value")));
ctx.InsertBefore(block->statements, call->Stmt()->Declaration(),
old_value_decl);
ctx.Replace(call->Declaration(), b.Expr(old_value));
} else {
ctx.Replace(call->Declaration(),
- b.Call(sem::str(stub->builtin), std::move(out_args)));
+ b.Call(builtin::str(stub->builtin), std::move(out_args)));
}
// Keep track of this expression. We'll need to modify the root identifier /
@@ -255,7 +256,7 @@
ctx.Replace(assign, [=] {
auto* lhs = ctx.CloneWithoutTransform(assign->lhs);
auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
- auto* call = b.Call(sem::str(sem::BuiltinType::kAtomicStore),
+ auto* call = b.Call(builtin::str(builtin::Function::kAtomicStore),
b.AddressOf(lhs), rhs);
return b.CallStmt(call);
});
@@ -266,7 +267,7 @@
if (is_ref_to_atomic_var(sem_rhs->UnwrapLoad())) {
ctx.Replace(assign->rhs, [=] {
auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
- return b.Call(sem::str(sem::BuiltinType::kAtomicLoad),
+ return b.Call(builtin::str(builtin::Function::kAtomicLoad),
b.AddressOf(rhs));
});
return;
@@ -278,7 +279,7 @@
if (is_ref_to_atomic_var(sem_init->UnwrapLoad())) {
ctx.Replace(var->initializer, [=] {
auto* rhs = ctx.CloneWithoutTransform(var->initializer);
- return b.Call(sem::str(sem::BuiltinType::kAtomicLoad),
+ return b.Call(builtin::str(builtin::Function::kAtomicLoad),
b.AddressOf(rhs));
});
return;
@@ -293,11 +294,11 @@
SpirvAtomic::SpirvAtomic() = default;
SpirvAtomic::~SpirvAtomic() = default;
-SpirvAtomic::Stub::Stub(ProgramID pid, ast::NodeID nid, sem::BuiltinType b)
+SpirvAtomic::Stub::Stub(ProgramID pid, ast::NodeID nid, builtin::Function b)
: Base(pid, nid, utils::Empty), builtin(b) {}
SpirvAtomic::Stub::~Stub() = default;
std::string SpirvAtomic::Stub::InternalName() const {
- return "@internal(spirv-atomic " + std::string(sem::str(builtin)) + ")";
+ return "@internal(spirv-atomic " + std::string(builtin::str(builtin)) + ")";
}
const SpirvAtomic::Stub* SpirvAtomic::Stub::Clone(CloneContext* ctx) const {
diff --git a/src/tint/transform/spirv_atomic.h b/src/tint/transform/spirv_atomic.h
index 0f99dba..b524200 100644
--- a/src/tint/transform/spirv_atomic.h
+++ b/src/tint/transform/spirv_atomic.h
@@ -18,7 +18,7 @@
#include <string>
#include "src/tint/ast/internal_attribute.h"
-#include "src/tint/sem/builtin_type.h"
+#include "src/tint/builtin/function.h"
#include "src/tint/transform/transform.h"
// Forward declarations
@@ -46,7 +46,7 @@
/// @param pid the identifier of the program that owns this node
/// @param nid the unique node identifier
/// @param builtin the atomic builtin this stub represents
- Stub(ProgramID pid, ast::NodeID nid, sem::BuiltinType builtin);
+ Stub(ProgramID pid, ast::NodeID nid, builtin::Function builtin);
/// Destructor
~Stub() override;
@@ -60,7 +60,7 @@
const Stub* Clone(CloneContext* ctx) const override;
/// The type of the intrinsic
- const sem::BuiltinType builtin;
+ const builtin::Function builtin;
};
/// @copydoc Transform::Apply
diff --git a/src/tint/transform/spirv_atomic_test.cc b/src/tint/transform/spirv_atomic_test.cc
index 7bb9f2a..29976b5 100644
--- a/src/tint/transform/spirv_atomic_test.cc
+++ b/src/tint/transform/spirv_atomic_test.cc
@@ -36,14 +36,14 @@
auto& b = parser.builder();
- sem::BuiltinType two_params[] = {
- sem::BuiltinType::kAtomicExchange, sem::BuiltinType::kAtomicAdd,
- sem::BuiltinType::kAtomicSub, sem::BuiltinType::kAtomicMin,
- sem::BuiltinType::kAtomicMax, sem::BuiltinType::kAtomicAnd,
- sem::BuiltinType::kAtomicOr, sem::BuiltinType::kAtomicXor,
+ builtin::Function two_params[] = {
+ builtin::Function::kAtomicExchange, builtin::Function::kAtomicAdd,
+ builtin::Function::kAtomicSub, builtin::Function::kAtomicMin,
+ builtin::Function::kAtomicMax, builtin::Function::kAtomicAnd,
+ builtin::Function::kAtomicOr, builtin::Function::kAtomicXor,
};
for (auto& a : two_params) {
- b.Func(std::string{"stub_"} + sem::str(a) + "_u32",
+ b.Func(std::string{"stub_"} + builtin::str(a) + "_u32",
utils::Vector{
b.Param("p0", b.ty.u32()),
b.Param("p1", b.ty.u32()),
@@ -55,7 +55,7 @@
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(), a),
});
- b.Func(std::string{"stub_"} + sem::str(a) + "_i32",
+ b.Func(std::string{"stub_"} + builtin::str(a) + "_i32",
utils::Vector{
b.Param("p0", b.ty.i32()),
b.Param("p1", b.ty.i32()),
@@ -79,7 +79,7 @@
},
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
- sem::BuiltinType::kAtomicLoad),
+ builtin::Function::kAtomicLoad),
});
b.Func("stub_atomicLoad_i32",
utils::Vector{
@@ -91,7 +91,7 @@
},
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
- sem::BuiltinType::kAtomicLoad),
+ builtin::Function::kAtomicLoad),
});
b.Func("stub_atomicStore_u32",
@@ -102,7 +102,7 @@
b.ty.void_(), utils::Empty,
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
- sem::BuiltinType::kAtomicStore),
+ builtin::Function::kAtomicStore),
});
b.Func("stub_atomicStore_i32",
utils::Vector{
@@ -112,7 +112,7 @@
b.ty.void_(), utils::Empty,
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
- sem::BuiltinType::kAtomicStore),
+ builtin::Function::kAtomicStore),
});
b.Func("stub_atomic_compare_exchange_weak_u32",
@@ -127,7 +127,7 @@
},
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(
- b.ID(), b.AllocateNodeID(), sem::BuiltinType::kAtomicCompareExchangeWeak),
+ b.ID(), b.AllocateNodeID(), builtin::Function::kAtomicCompareExchangeWeak),
});
b.Func("stub_atomic_compare_exchange_weak_i32",
utils::Vector{b.Param("p0", b.ty.i32()), b.Param("p1", b.ty.i32()),
@@ -138,7 +138,7 @@
},
utils::Vector{
b.ASTNodes().Create<SpirvAtomic::Stub>(
- b.ID(), b.AllocateNodeID(), sem::BuiltinType::kAtomicCompareExchangeWeak),
+ b.ID(), b.AllocateNodeID(), builtin::Function::kAtomicCompareExchangeWeak),
});
// Keep this pointer alive after Transform() returns
diff --git a/src/tint/transform/std140.cc b/src/tint/transform/std140.cc
index 7a9cffc..bfd8c80 100644
--- a/src/tint/transform/std140.cc
+++ b/src/tint/transform/std140.cc
@@ -25,6 +25,7 @@
#include "src/tint/sem/module.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/hashmap.h"
#include "src/tint/utils/transform.h"
diff --git a/src/tint/transform/substitute_override.cc b/src/tint/transform/substitute_override.cc
index 2d6b995..04a9da0 100644
--- a/src/tint/transform/substitute_override.cc
+++ b/src/tint/transform/substitute_override.cc
@@ -17,10 +17,12 @@
#include <functional>
#include <utility>
+#include "src/tint/builtin/function.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/builtin.h"
#include "src/tint/sem/index_accessor_expression.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::SubstituteOverride);
TINT_INSTANTIATE_TYPEINFO(tint::transform::SubstituteOverride::Config);
@@ -105,7 +107,7 @@
if (auto* access = sem->UnwrapMaterialize()->As<sem::IndexAccessorExpression>()) {
if (access->Object()->UnwrapMaterialize()->Type()->HoldsAbstract() &&
access->Index()->Stage() == sem::EvaluationStage::kOverride) {
- auto* obj = b.Call(sem::str(sem::BuiltinType::kTintMaterialize),
+ auto* obj = b.Call(builtin::str(builtin::Function::kTintMaterialize),
ctx.Clone(expr->object));
return b.IndexAccessor(obj, ctx.Clone(expr->index));
}
diff --git a/src/tint/transform/texture_1d_to_2d.cc b/src/tint/transform/texture_1d_to_2d.cc
index d1caaab..7c48db5 100644
--- a/src/tint/transform/texture_1d_to_2d.cc
+++ b/src/tint/transform/texture_1d_to_2d.cc
@@ -20,6 +20,7 @@
#include "src/tint/sem/function.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/type_expression.h"
+#include "src/tint/switch.h"
#include "src/tint/type/texture_dimension.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Texture1DTo2D);
@@ -137,7 +138,7 @@
return nullptr;
}
- if (builtin->Type() == sem::BuiltinType::kTextureDimensions) {
+ if (builtin->Type() == builtin::Function::kTextureDimensions) {
// If this textureDimensions() call is in a CallStatement, we can leave it
// unmodified since the return value will be dropped on the floor anyway.
if (call->Stmt()->Declaration()->Is<ast::CallStatement>()) {
diff --git a/src/tint/transform/unshadow.cc b/src/tint/transform/unshadow.cc
index 8f79544..9639cfc 100644
--- a/src/tint/transform/unshadow.cc
+++ b/src/tint/transform/unshadow.cc
@@ -23,6 +23,7 @@
#include "src/tint/sem/function.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Unshadow);
diff --git a/src/tint/transform/utils/get_insertion_point.cc b/src/tint/transform/utils/get_insertion_point.cc
index d10d134..bce7a7e 100644
--- a/src/tint/transform/utils/get_insertion_point.cc
+++ b/src/tint/transform/utils/get_insertion_point.cc
@@ -16,6 +16,7 @@
#include "src/tint/debug.h"
#include "src/tint/diagnostic/diagnostic.h"
#include "src/tint/sem/for_loop_statement.h"
+#include "src/tint/switch.h"
namespace tint::transform::utils {
diff --git a/src/tint/transform/vertex_pulling.cc b/src/tint/transform/vertex_pulling.cc
index e07dcfe..d887198 100644
--- a/src/tint/transform/vertex_pulling.cc
+++ b/src/tint/transform/vertex_pulling.cc
@@ -23,6 +23,7 @@
#include "src/tint/builtin/builtin_value.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/map.h"
#include "src/tint/utils/math.h"
diff --git a/src/tint/type/type.cc b/src/tint/type/type.cc
index 6163a9a..7ed62fa 100644
--- a/src/tint/type/type.cc
+++ b/src/tint/type/type.cc
@@ -14,6 +14,7 @@
#include "src/tint/type/type.h"
+#include "src/tint/switch.h"
#include "src/tint/type/abstract_float.h"
#include "src/tint/type/abstract_int.h"
#include "src/tint/type/array.h"
diff --git a/src/tint/utils/slice.h b/src/tint/utils/slice.h
index 719a53e..325c470 100644
--- a/src/tint/utils/slice.h
+++ b/src/tint/utils/slice.h
@@ -20,6 +20,7 @@
#include "src/tint/castable.h"
#include "src/tint/traits.h"
+#include "src/tint/utils/bitcast.h"
namespace tint::utils {
diff --git a/src/tint/writer/append_vector.cc b/src/tint/writer/append_vector.cc
index 98d9798..b66f9fd 100644
--- a/src/tint/writer/append_vector.cc
+++ b/src/tint/writer/append_vector.cc
@@ -21,6 +21,7 @@
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/value_expression.h"
+#include "src/tint/switch.h"
#include "src/tint/utils/transform.h"
using namespace tint::number_suffixes; // NOLINT
diff --git a/src/tint/writer/array_length_from_uniform_options.cc b/src/tint/writer/array_length_from_uniform_options.cc
index 7fd6e63..275867f 100644
--- a/src/tint/writer/array_length_from_uniform_options.cc
+++ b/src/tint/writer/array_length_from_uniform_options.cc
@@ -17,11 +17,15 @@
namespace tint::writer {
ArrayLengthFromUniformOptions::ArrayLengthFromUniformOptions() = default;
+
ArrayLengthFromUniformOptions::~ArrayLengthFromUniformOptions() = default;
+
ArrayLengthFromUniformOptions::ArrayLengthFromUniformOptions(const ArrayLengthFromUniformOptions&) =
default;
+
ArrayLengthFromUniformOptions& ArrayLengthFromUniformOptions::operator=(
const ArrayLengthFromUniformOptions&) = default;
+
ArrayLengthFromUniformOptions::ArrayLengthFromUniformOptions(ArrayLengthFromUniformOptions&&) =
default;
diff --git a/src/tint/writer/array_length_from_uniform_options.h b/src/tint/writer/array_length_from_uniform_options.h
index 41d873e..b8b304a 100644
--- a/src/tint/writer/array_length_from_uniform_options.h
+++ b/src/tint/writer/array_length_from_uniform_options.h
@@ -17,7 +17,7 @@
#include <unordered_map>
-#include "src/tint/sem/binding_point.h"
+#include "src/tint/writer/binding_point.h"
namespace tint::writer {
@@ -38,10 +38,10 @@
/// The binding point to use to generate a uniform buffer from which to read
/// buffer sizes.
- sem::BindingPoint ubo_binding;
+ BindingPoint ubo_binding;
/// The mapping from storage buffer binding points to the index into the
/// uniform buffer where the length of the buffer is stored.
- std::unordered_map<sem::BindingPoint, uint32_t> bindpoint_to_size_index;
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_size_index;
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
TINT_REFLECT(ubo_binding, bindpoint_to_size_index);
diff --git a/src/tint/writer/generate_external_texture_bindings.h b/src/tint/writer/binding_point.h
similarity index 60%
rename from src/tint/writer/generate_external_texture_bindings.h
rename to src/tint/writer/binding_point.h
index 8d0aad9..796c54a 100644
--- a/src/tint/writer/generate_external_texture_bindings.h
+++ b/src/tint/writer/binding_point.h
@@ -1,4 +1,4 @@
-// Copyright 2022 The Tint Authors.
+// Copyright 2023 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef SRC_TINT_WRITER_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
-#define SRC_TINT_WRITER_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
+#ifndef SRC_TINT_WRITER_BINDING_POINT_H_
+#define SRC_TINT_WRITER_BINDING_POINT_H_
-#include "src/tint/transform/multiplanar_external_texture.h"
+#include "src/tint/sem/binding_point.h"
namespace tint::writer {
-transform::MultiplanarExternalTexture::BindingsMap GenerateExternalTextureBindings(
- const Program* program);
+/// BindingPoint is an alias to sem::BindingPoint
+using BindingPoint = sem::BindingPoint;
} // namespace tint::writer
-#endif // SRC_TINT_WRITER_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
+#endif // SRC_TINT_WRITER_BINDING_POINT_H_
diff --git a/src/tint/writer/check_supported_extensions.cc b/src/tint/writer/check_supported_extensions.cc
index bde86a5..88ddcdd 100644
--- a/src/tint/writer/check_supported_extensions.cc
+++ b/src/tint/writer/check_supported_extensions.cc
@@ -33,13 +33,14 @@
}
for (auto* enable : module.Enables()) {
- auto ext = enable->extension;
- if (!set.Contains(ext)) {
- diags.add_error(diag::System::Writer,
- std::string(writer_name) + " backend does not support extension '" +
- utils::ToString(ext) + "'",
- enable->source);
- return false;
+ for (auto* ext : enable->extensions) {
+ if (!set.Contains(ext->name)) {
+ diags.add_error(diag::System::Writer,
+ std::string(writer_name) + " backend does not support extension '" +
+ utils::ToString(ext->name) + "'",
+ ext->source);
+ return false;
+ }
}
}
return true;
diff --git a/src/tint/writer/external_texture_options.cc b/src/tint/writer/external_texture_options.cc
new file mode 100644
index 0000000..e5ea26f
--- /dev/null
+++ b/src/tint/writer/external_texture_options.cc
@@ -0,0 +1,29 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/external_texture_options.h"
+
+namespace tint::writer {
+
+ExternalTextureOptions::ExternalTextureOptions() = default;
+
+ExternalTextureOptions::~ExternalTextureOptions() = default;
+
+ExternalTextureOptions::ExternalTextureOptions(const ExternalTextureOptions&) = default;
+
+ExternalTextureOptions& ExternalTextureOptions::operator=(const ExternalTextureOptions&) = default;
+
+ExternalTextureOptions::ExternalTextureOptions(ExternalTextureOptions&&) = default;
+
+} // namespace tint::writer
diff --git a/src/tint/writer/external_texture_options.h b/src/tint/writer/external_texture_options.h
new file mode 100644
index 0000000..926eabd
--- /dev/null
+++ b/src/tint/writer/external_texture_options.h
@@ -0,0 +1,57 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_EXTERNAL_TEXTURE_OPTIONS_H_
+#define SRC_TINT_WRITER_EXTERNAL_TEXTURE_OPTIONS_H_
+
+#include <unordered_map>
+
+#include "src/tint/sem/external_texture.h"
+
+namespace tint::writer {
+
+/// Options used to specify mappings of binding points for external textures.
+class ExternalTextureOptions {
+ public:
+ /// This struct identifies the binding groups and locations for new bindings to
+ /// use when transforming a texture_external instance.
+ using BindingPoints = sem::external_texture::BindingPoints;
+
+ /// BindingsMap is a map where the key is the binding location of a
+ /// texture_external and the value is a struct containing the desired
+ /// locations for new bindings expanded from the texture_external instance.
+ using BindingsMap = sem::external_texture::BindingsMap;
+
+ /// Constructor
+ ExternalTextureOptions();
+ /// Destructor
+ ~ExternalTextureOptions();
+ /// Copy constructor
+ ExternalTextureOptions(const ExternalTextureOptions&);
+ /// Copy assignment
+ /// @returns this ExternalTextureOptions
+ ExternalTextureOptions& operator=(const ExternalTextureOptions&);
+ /// Move constructor
+ ExternalTextureOptions(ExternalTextureOptions&&);
+
+ /// A map of new binding points to use.
+ BindingsMap bindings_map;
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(bindings_map);
+};
+
+} // namespace tint::writer
+
+#endif // SRC_TINT_WRITER_EXTERNAL_TEXTURE_OPTIONS_H_
diff --git a/src/tint/writer/flatten_bindings.cc b/src/tint/writer/flatten_bindings.cc
index bedec75..3b5b2ad 100644
--- a/src/tint/writer/flatten_bindings.cc
+++ b/src/tint/writer/flatten_bindings.cc
@@ -19,11 +19,12 @@
#include "src/tint/inspector/inspector.h"
#include "src/tint/transform/binding_remapper.h"
#include "src/tint/transform/manager.h"
+#include "src/tint/writer/binding_point.h"
namespace tint::writer {
+
std::optional<Program> FlattenBindings(const Program* program) {
// TODO(crbug.com/tint/1101): Make this more robust for multiple entry points.
- using BindingPoint = tint::transform::BindingPoint;
tint::transform::BindingRemapper::BindingPoints binding_points;
uint32_t next_buffer_idx = 0;
uint32_t next_sampler_idx = 0;
@@ -76,4 +77,5 @@
return {};
}
+
} // namespace tint::writer
diff --git a/src/tint/writer/glsl/generator.h b/src/tint/writer/glsl/generator.h
index 2bb4b03..ef7b65b 100644
--- a/src/tint/writer/glsl/generator.h
+++ b/src/tint/writer/glsl/generator.h
@@ -25,6 +25,7 @@
#include "src/tint/builtin/access.h"
#include "src/tint/sem/binding_point.h"
#include "src/tint/sem/sampler_texture_pair.h"
+#include "src/tint/writer/external_texture_options.h"
#include "src/tint/writer/glsl/version.h"
#include "src/tint/writer/text.h"
@@ -73,8 +74,8 @@
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
- /// Set to 'true' to generates binding mappings for external textures
- bool generate_external_texture_bindings = false;
+ /// Options used in the binding mappings for external textures
+ ExternalTextureOptions external_texture_options = {};
/// The GLSL version to emit
Version version;
@@ -83,7 +84,7 @@
TINT_REFLECT(disable_robustness,
allow_collisions,
disable_workgroup_init,
- generate_external_texture_bindings,
+ external_texture_options,
version);
};
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 02c1bac..311005b 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -17,6 +17,7 @@
#include <algorithm>
#include <cmath>
#include <iomanip>
+#include <limits>
#include <set>
#include <utility>
#include <vector>
@@ -39,6 +40,7 @@
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/add_block_attribute.h"
#include "src/tint/transform/add_empty_entry_point.h"
#include "src/tint/transform/binding_remapper.h"
@@ -51,6 +53,7 @@
#include "src/tint/transform/disable_uniformity_analysis.h"
#include "src/tint/transform/expand_compound_assignment.h"
#include "src/tint/transform/manager.h"
+#include "src/tint/transform/multiplanar_external_texture.h"
#include "src/tint/transform/pad_structs.h"
#include "src/tint/transform/preserve_padding.h"
#include "src/tint/transform/promote_initializers_to_let.h"
@@ -79,12 +82,18 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/append_vector.h"
#include "src/tint/writer/float_to_string.h"
-#include "src/tint/writer/generate_external_texture_bindings.h"
using namespace tint::number_suffixes; // NOLINT
+namespace tint::writer::glsl {
namespace {
+const char kTempNamePrefix[] = "tint_tmp";
+
+bool last_is_break(const ast::BlockStatement* stmts) {
+ return IsAnyOf<ast::BreakStatement>(stmts->Last());
+}
+
bool IsRelational(tint::ast::BinaryOp op) {
return op == tint::ast::BinaryOp::kEqual || op == tint::ast::BinaryOp::kNotEqual ||
op == tint::ast::BinaryOp::kLessThan || op == tint::ast::BinaryOp::kGreaterThan ||
@@ -102,15 +111,15 @@
}
}
-} // namespace
-
-namespace tint::writer::glsl {
-namespace {
-
-const char kTempNamePrefix[] = "tint_tmp";
-
-bool last_is_break(const ast::BlockStatement* stmts) {
- return IsAnyOf<ast::BreakStatement>(stmts->Last());
+void PrintI32(utils::StringStream& out, int32_t value) {
+ // GLSL parses `-2147483648` as a unary minus and `2147483648` as separate tokens, and the
+ // latter doesn't fit into an (32-bit) `int`. Emit `(-2147483647 - 1)` instead, which ensures
+ // the expression type is `int`.
+ if (auto int_min = std::numeric_limits<int32_t>::min(); value == int_min) {
+ out << "(" << int_min + 1 << " - 1)";
+ } else {
+ out << value;
+ }
}
void PrintF32(utils::StringStream& out, float value) {
@@ -171,10 +180,10 @@
manager.Add<transform::Robustness>();
}
- if (options.generate_external_texture_bindings) {
+ if (!options.external_texture_options.bindings_map.empty()) {
// Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
- auto new_bindings_map = writer::GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
+ options.external_texture_options.bindings_map);
manager.Add<transform::MultiplanarExternalTexture>();
}
@@ -184,6 +193,7 @@
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
polyfills.bgra8unorm = true;
polyfills.bitshift_modulo = true;
+ polyfills.conv_f32_to_iu32 = true;
polyfills.count_leading_zeros = true;
polyfills.count_trailing_zeros = true;
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
@@ -325,7 +335,7 @@
}
if (version_.IsES() && requires_default_precision_qualifier_) {
- current_buffer_->Insert("precision mediump float;", helpers_insertion_point++, indent);
+ current_buffer_->Insert("precision highp float;", helpers_insertion_point++, indent);
}
if (!helpers_.lines.empty()) {
@@ -337,10 +347,10 @@
return true;
}
-bool GeneratorImpl::RecordExtension(const ast::Enable* ext) {
+bool GeneratorImpl::RecordExtension(const ast::Enable* enable) {
// Deal with extension node here, recording it within the generator for later emition.
- if (ext->extension == builtin::Extension::kF16) {
+ if (enable->HasExtension(builtin::Extension::kF16)) {
requires_f16_extension_ = true;
}
@@ -768,48 +778,49 @@
if (builtin->IsTexture()) {
return EmitTextureCall(out, call, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kCountOneBits) {
+ if (builtin->Type() == builtin::Function::kCountOneBits) {
return EmitCountOneBitsCall(out, expr);
}
- if (builtin->Type() == sem::BuiltinType::kSelect) {
- return EmitSelectCall(out, expr);
+ if (builtin->Type() == builtin::Function::kSelect) {
+ return EmitSelectCall(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kDot) {
+ if (builtin->Type() == builtin::Function::kDot) {
return EmitDotCall(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kModf) {
+ if (builtin->Type() == builtin::Function::kModf) {
return EmitModfCall(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kFrexp) {
+ if (builtin->Type() == builtin::Function::kFrexp) {
return EmitFrexpCall(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kDegrees) {
+ if (builtin->Type() == builtin::Function::kDegrees) {
return EmitDegreesCall(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kRadians) {
+ if (builtin->Type() == builtin::Function::kRadians) {
return EmitRadiansCall(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kQuantizeToF16) {
+ if (builtin->Type() == builtin::Function::kQuantizeToF16) {
return EmitQuantizeToF16Call(out, expr, builtin);
}
- if (builtin->Type() == sem::BuiltinType::kArrayLength) {
+ if (builtin->Type() == builtin::Function::kArrayLength) {
return EmitArrayLength(out, expr);
}
- if (builtin->Type() == sem::BuiltinType::kExtractBits) {
+ if (builtin->Type() == builtin::Function::kExtractBits) {
return EmitExtractBits(out, expr);
}
- if (builtin->Type() == sem::BuiltinType::kInsertBits) {
+ if (builtin->Type() == builtin::Function::kInsertBits) {
return EmitInsertBits(out, expr);
}
- if (builtin->Type() == sem::BuiltinType::kFma && version_.IsES()) {
+ if (builtin->Type() == builtin::Function::kFma && version_.IsES()) {
return EmitEmulatedFMA(out, expr);
}
- if (builtin->Type() == sem::BuiltinType::kAbs &&
+ if (builtin->Type() == builtin::Function::kAbs &&
TypeOf(expr->args[0])->UnwrapRef()->is_unsigned_integer_scalar_or_vector()) {
// GLSL does not support abs() on unsigned arguments. However, it's a no-op.
return EmitExpression(out, expr->args[0]);
}
- if ((builtin->Type() == sem::BuiltinType::kAny || builtin->Type() == sem::BuiltinType::kAll) &&
+ if ((builtin->Type() == builtin::Function::kAny ||
+ builtin->Type() == builtin::Function::kAll) &&
TypeOf(expr->args[0])->UnwrapRef()->is_scalar()) {
// GLSL does not support any() or all() on scalar arguments. It's a no-op.
return EmitExpression(out, expr->args[0]);
@@ -911,7 +922,7 @@
};
switch (builtin->Type()) {
- case sem::BuiltinType::kAtomicLoad: {
+ case builtin::Function::kAtomicLoad: {
// GLSL does not have an atomicLoad, so we emulate it with
// atomicOr using 0 as the OR value
out << "atomicOr";
@@ -927,7 +938,7 @@
}
return true;
}
- case sem::BuiltinType::kAtomicCompareExchangeWeak: {
+ case builtin::Function::kAtomicCompareExchangeWeak: {
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
return false;
}
@@ -978,27 +989,27 @@
return true;
}
- case sem::BuiltinType::kAtomicAdd:
- case sem::BuiltinType::kAtomicSub:
+ case builtin::Function::kAtomicAdd:
+ case builtin::Function::kAtomicSub:
return call("atomicAdd");
- case sem::BuiltinType::kAtomicMax:
+ case builtin::Function::kAtomicMax:
return call("atomicMax");
- case sem::BuiltinType::kAtomicMin:
+ case builtin::Function::kAtomicMin:
return call("atomicMin");
- case sem::BuiltinType::kAtomicAnd:
+ case builtin::Function::kAtomicAnd:
return call("atomicAnd");
- case sem::BuiltinType::kAtomicOr:
+ case builtin::Function::kAtomicOr:
return call("atomicOr");
- case sem::BuiltinType::kAtomicXor:
+ case builtin::Function::kAtomicXor:
return call("atomicXor");
- case sem::BuiltinType::kAtomicExchange:
- case sem::BuiltinType::kAtomicStore:
+ case builtin::Function::kAtomicExchange:
+ case builtin::Function::kAtomicStore:
// GLSL does not have an atomicStore, so we emulate it with
// atomicExchange.
return call("atomicExchange");
@@ -1092,28 +1103,39 @@
return true;
}
-bool GeneratorImpl::EmitSelectCall(utils::StringStream& out, const ast::CallExpression* expr) {
+bool GeneratorImpl::EmitSelectCall(utils::StringStream& out,
+ const ast::CallExpression* expr,
+ const sem::Builtin* builtin) {
+ // GLSL does not support ternary expressions with a bool vector conditional,
+ // so polyfill with a helper.
+ if (auto* vec = builtin->Parameters()[2]->Type()->As<type::Vector>()) {
+ return CallBuiltinHelper(
+ out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
+ auto l = line(b);
+ l << " return ";
+ if (!EmitType(l, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
+ builtin::Access::kUndefined, "")) {
+ return false;
+ }
+ {
+ ScopedParen sp(l);
+ for (uint32_t i = 0; i < vec->Width(); i++) {
+ if (i > 0) {
+ l << ", ";
+ }
+ l << params[2] << "[" << i << "] ? " << params[1] << "[" << i
+ << "] : " << params[0] << "[" << i << "]";
+ }
+ }
+ l << ";";
+ return true;
+ });
+ }
+
auto* expr_false = expr->args[0];
auto* expr_true = expr->args[1];
auto* expr_cond = expr->args[2];
- // GLSL does not support ternary expressions with a bool vector conditional,
- // but it does support mix() with same.
- if (TypeOf(expr_cond)->UnwrapRef()->is_bool_vector()) {
- out << "mix(";
- if (!EmitExpression(out, expr_false)) {
- return false;
- }
- out << ", ";
- if (!EmitExpression(out, expr_true)) {
- return false;
- }
- out << ", ";
- if (!EmitExpression(out, expr_cond)) {
- return false;
- }
- out << ")";
- return true;
- }
+
ScopedParen paren(out);
if (!EmitExpression(out, expr_cond)) {
return false;
@@ -1320,13 +1342,13 @@
bool GeneratorImpl::EmitBarrierCall(utils::StringStream& out, const sem::Builtin* builtin) {
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction.
- if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
+ if (builtin->Type() == builtin::Function::kWorkgroupBarrier) {
out << "barrier()";
- } else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
+ } else if (builtin->Type() == builtin::Function::kStorageBarrier) {
out << "{ barrier(); memoryBarrierBuffer(); }";
} else {
TINT_UNREACHABLE(Writer, diagnostics_)
- << "unexpected barrier builtin type " << sem::str(builtin->Type());
+ << "unexpected barrier builtin type " << builtin::str(builtin->Type());
return false;
}
return true;
@@ -1396,7 +1418,7 @@
};
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureDimensions: {
+ case builtin::Function::kTextureDimensions: {
// textureDimensions() returns an unsigned scalar / vector in WGSL.
// textureSize() / imageSize() returns a signed scalar / vector in GLSL.
// Cast.
@@ -1435,7 +1457,7 @@
}
return true;
}
- case sem::BuiltinType::kTextureNumLayers: {
+ case builtin::Function::kTextureNumLayers: {
// textureNumLayers() returns an unsigned scalar in WGSL.
// textureSize() / imageSize() returns a signed scalar / vector in GLSL.
// Cast.
@@ -1469,7 +1491,7 @@
out << ").z";
return true;
}
- case sem::BuiltinType::kTextureNumLevels: {
+ case builtin::Function::kTextureNumLevels: {
// textureNumLevels() returns an unsigned scalar in WGSL.
// textureQueryLevels() returns a signed scalar in GLSL.
// Cast.
@@ -1483,7 +1505,7 @@
out << ")";
return true;
}
- case sem::BuiltinType::kTextureNumSamples: {
+ case builtin::Function::kTextureNumSamples: {
// textureNumSamples() returns an unsigned scalar in WGSL.
// textureSamples() returns a signed scalar in GLSL.
// Cast.
@@ -1506,36 +1528,36 @@
bool is_depth = texture_type->Is<type::DepthTexture>();
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureSample:
- case sem::BuiltinType::kTextureSampleBias:
+ case builtin::Function::kTextureSample:
+ case builtin::Function::kTextureSampleBias:
out << "texture";
if (is_depth) {
glsl_ret_width = 1u;
}
break;
- case sem::BuiltinType::kTextureSampleLevel:
+ case builtin::Function::kTextureSampleLevel:
out << "textureLod";
if (is_depth) {
glsl_ret_width = 1u;
}
break;
- case sem::BuiltinType::kTextureGather:
- case sem::BuiltinType::kTextureGatherCompare:
+ case builtin::Function::kTextureGather:
+ case builtin::Function::kTextureGatherCompare:
out << "textureGather";
append_depth_ref_to_coords = false;
break;
- case sem::BuiltinType::kTextureSampleGrad:
+ case builtin::Function::kTextureSampleGrad:
out << "textureGrad";
break;
- case sem::BuiltinType::kTextureSampleCompare:
- case sem::BuiltinType::kTextureSampleCompareLevel:
+ case builtin::Function::kTextureSampleCompare:
+ case builtin::Function::kTextureSampleCompareLevel:
out << "texture";
glsl_ret_width = 1;
break;
- case sem::BuiltinType::kTextureLoad:
+ case builtin::Function::kTextureLoad:
out << "texelFetch";
break;
- case sem::BuiltinType::kTextureStore:
+ case builtin::Function::kTextureStore:
out << "imageStore";
break;
default:
@@ -1614,7 +1636,7 @@
}
// GLSL's textureGather always requires a refZ parameter.
- if (is_depth && builtin->Type() == sem::BuiltinType::kTextureGather) {
+ if (is_depth && builtin->Type() == builtin::Function::kTextureGather) {
out << ", 0.0";
}
@@ -1625,7 +1647,7 @@
if (!EmitExpression(out, e)) {
return false;
}
- } else if (builtin->Type() == sem::BuiltinType::kTextureSample) {
+ } else if (builtin->Type() == builtin::Function::kTextureSample) {
out << ", 0.0f";
}
}
@@ -1669,114 +1691,114 @@
std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
switch (builtin->Type()) {
- case sem::BuiltinType::kAbs:
- case sem::BuiltinType::kAcos:
- case sem::BuiltinType::kAcosh:
- case sem::BuiltinType::kAll:
- case sem::BuiltinType::kAny:
- case sem::BuiltinType::kAsin:
- case sem::BuiltinType::kAsinh:
- case sem::BuiltinType::kAtan:
- case sem::BuiltinType::kAtanh:
- case sem::BuiltinType::kCeil:
- case sem::BuiltinType::kClamp:
- case sem::BuiltinType::kCos:
- case sem::BuiltinType::kCosh:
- case sem::BuiltinType::kCross:
- case sem::BuiltinType::kDeterminant:
- case sem::BuiltinType::kDistance:
- case sem::BuiltinType::kDot:
- case sem::BuiltinType::kExp:
- case sem::BuiltinType::kExp2:
- case sem::BuiltinType::kFloor:
- case sem::BuiltinType::kFrexp:
- case sem::BuiltinType::kLdexp:
- case sem::BuiltinType::kLength:
- case sem::BuiltinType::kLog:
- case sem::BuiltinType::kLog2:
- case sem::BuiltinType::kMax:
- case sem::BuiltinType::kMin:
- case sem::BuiltinType::kModf:
- case sem::BuiltinType::kNormalize:
- case sem::BuiltinType::kPow:
- case sem::BuiltinType::kReflect:
- case sem::BuiltinType::kRefract:
- case sem::BuiltinType::kRound:
- case sem::BuiltinType::kSign:
- case sem::BuiltinType::kSin:
- case sem::BuiltinType::kSinh:
- case sem::BuiltinType::kSqrt:
- case sem::BuiltinType::kStep:
- case sem::BuiltinType::kTan:
- case sem::BuiltinType::kTanh:
- case sem::BuiltinType::kTranspose:
- case sem::BuiltinType::kTrunc:
+ case builtin::Function::kAbs:
+ case builtin::Function::kAcos:
+ case builtin::Function::kAcosh:
+ case builtin::Function::kAll:
+ case builtin::Function::kAny:
+ case builtin::Function::kAsin:
+ case builtin::Function::kAsinh:
+ case builtin::Function::kAtan:
+ case builtin::Function::kAtanh:
+ case builtin::Function::kCeil:
+ case builtin::Function::kClamp:
+ case builtin::Function::kCos:
+ case builtin::Function::kCosh:
+ case builtin::Function::kCross:
+ case builtin::Function::kDeterminant:
+ case builtin::Function::kDistance:
+ case builtin::Function::kDot:
+ case builtin::Function::kExp:
+ case builtin::Function::kExp2:
+ case builtin::Function::kFloor:
+ case builtin::Function::kFrexp:
+ case builtin::Function::kLdexp:
+ case builtin::Function::kLength:
+ case builtin::Function::kLog:
+ case builtin::Function::kLog2:
+ case builtin::Function::kMax:
+ case builtin::Function::kMin:
+ case builtin::Function::kModf:
+ case builtin::Function::kNormalize:
+ case builtin::Function::kPow:
+ case builtin::Function::kReflect:
+ case builtin::Function::kRefract:
+ case builtin::Function::kRound:
+ case builtin::Function::kSign:
+ case builtin::Function::kSin:
+ case builtin::Function::kSinh:
+ case builtin::Function::kSqrt:
+ case builtin::Function::kStep:
+ case builtin::Function::kTan:
+ case builtin::Function::kTanh:
+ case builtin::Function::kTranspose:
+ case builtin::Function::kTrunc:
return builtin->str();
- case sem::BuiltinType::kAtan2:
+ case builtin::Function::kAtan2:
return "atan";
- case sem::BuiltinType::kCountOneBits:
+ case builtin::Function::kCountOneBits:
return "bitCount";
- case sem::BuiltinType::kDpdx:
+ case builtin::Function::kDpdx:
return "dFdx";
- case sem::BuiltinType::kDpdxCoarse:
+ case builtin::Function::kDpdxCoarse:
if (version_.IsES()) {
return "dFdx";
}
return "dFdxCoarse";
- case sem::BuiltinType::kDpdxFine:
+ case builtin::Function::kDpdxFine:
if (version_.IsES()) {
return "dFdx";
}
return "dFdxFine";
- case sem::BuiltinType::kDpdy:
+ case builtin::Function::kDpdy:
return "dFdy";
- case sem::BuiltinType::kDpdyCoarse:
+ case builtin::Function::kDpdyCoarse:
if (version_.IsES()) {
return "dFdy";
}
return "dFdyCoarse";
- case sem::BuiltinType::kDpdyFine:
+ case builtin::Function::kDpdyFine:
if (version_.IsES()) {
return "dFdy";
}
return "dFdyFine";
- case sem::BuiltinType::kFaceForward:
+ case builtin::Function::kFaceForward:
return "faceforward";
- case sem::BuiltinType::kFract:
+ case builtin::Function::kFract:
return "fract";
- case sem::BuiltinType::kFma:
+ case builtin::Function::kFma:
return "fma";
- case sem::BuiltinType::kFwidth:
- case sem::BuiltinType::kFwidthCoarse:
- case sem::BuiltinType::kFwidthFine:
+ case builtin::Function::kFwidth:
+ case builtin::Function::kFwidthCoarse:
+ case builtin::Function::kFwidthFine:
return "fwidth";
- case sem::BuiltinType::kInverseSqrt:
+ case builtin::Function::kInverseSqrt:
return "inversesqrt";
- case sem::BuiltinType::kMix:
+ case builtin::Function::kMix:
return "mix";
- case sem::BuiltinType::kPack2X16Float:
+ case builtin::Function::kPack2X16Float:
return "packHalf2x16";
- case sem::BuiltinType::kPack2X16Snorm:
+ case builtin::Function::kPack2X16Snorm:
return "packSnorm2x16";
- case sem::BuiltinType::kPack2X16Unorm:
+ case builtin::Function::kPack2X16Unorm:
return "packUnorm2x16";
- case sem::BuiltinType::kPack4X8Snorm:
+ case builtin::Function::kPack4X8Snorm:
return "packSnorm4x8";
- case sem::BuiltinType::kPack4X8Unorm:
+ case builtin::Function::kPack4X8Unorm:
return "packUnorm4x8";
- case sem::BuiltinType::kReverseBits:
+ case builtin::Function::kReverseBits:
return "bitfieldReverse";
- case sem::BuiltinType::kSmoothstep:
+ case builtin::Function::kSmoothstep:
return "smoothstep";
- case sem::BuiltinType::kUnpack2X16Float:
+ case builtin::Function::kUnpack2X16Float:
return "unpackHalf2x16";
- case sem::BuiltinType::kUnpack2X16Snorm:
+ case builtin::Function::kUnpack2X16Snorm:
return "unpackSnorm2x16";
- case sem::BuiltinType::kUnpack2X16Unorm:
+ case builtin::Function::kUnpack2X16Unorm:
return "unpackUnorm2x16";
- case sem::BuiltinType::kUnpack4X8Snorm:
+ case builtin::Function::kUnpack4X8Snorm:
return "unpackSnorm4x8";
- case sem::BuiltinType::kUnpack4X8Unorm:
+ case builtin::Function::kUnpack4X8Unorm:
return "unpackUnorm4x8";
default:
diagnostics_.add_error(diag::System::Writer,
@@ -2367,7 +2389,7 @@
return true;
},
[&](const type::I32*) {
- out << constant->ValueAs<AInt>();
+ PrintI32(out, constant->ValueAs<i32>());
return true;
},
[&](const type::U32*) {
@@ -2382,8 +2404,8 @@
ScopedParen sp(out);
- if (constant->AllEqual()) {
- return EmitConstant(out, constant->Index(0));
+ if (auto* splat = constant->As<constant::Splat>()) {
+ return EmitConstant(out, splat->el);
}
for (size_t i = 0; i < v->Width(); i++) {
@@ -2483,12 +2505,20 @@
}
return true;
},
- [&](const ast::IntLiteralExpression* l) {
- out << l->value;
- if (l->suffix == ast::IntLiteralExpression::Suffix::kU) {
- out << "u";
+ [&](const ast::IntLiteralExpression* i) {
+ switch (i->suffix) {
+ case ast::IntLiteralExpression::Suffix::kNone:
+ case ast::IntLiteralExpression::Suffix::kI: {
+ PrintI32(out, static_cast<int32_t>(i->value));
+ return true;
+ }
+ case ast::IntLiteralExpression::Suffix::kU: {
+ out << i->value << "u";
+ return true;
+ }
}
- return true;
+ diagnostics_.add_error(diag::System::Writer, "unknown integer literal suffix type");
+ return false;
},
[&](Default) {
diagnostics_.add_error(diag::System::Writer, "unknown literal type");
@@ -3209,7 +3239,7 @@
TextBuffer b;
TINT_DEFER(helpers_.Append(b));
- auto fn_name = UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
+ auto fn_name = UniqueIdentifier(std::string("tint_") + builtin::str(builtin->Type()));
std::vector<std::string> parameter_names;
{
auto decl = line(&b);
diff --git a/src/tint/writer/glsl/generator_impl.h b/src/tint/writer/glsl/generator_impl.h
index d954921..96042c1 100644
--- a/src/tint/writer/glsl/generator_impl.h
+++ b/src/tint/writer/glsl/generator_impl.h
@@ -234,8 +234,11 @@
/// Handles generating a call to the `countOneBits()` builtin
/// @param out the output of the expression stream
/// @param expr the call expression
+ /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted
- bool EmitSelectCall(utils::StringStream& out, const ast::CallExpression* expr);
+ bool EmitSelectCall(utils::StringStream& out,
+ const ast::CallExpression* expr,
+ const sem::Builtin* builtin);
/// Handles generating a call to the `dot()` builtin
/// @param out the output of the expression stream
/// @param expr the call expression
diff --git a/src/tint/writer/glsl/generator_impl_builtin_test.cc b/src/tint/writer/glsl/generator_impl_builtin_test.cc
index d281cdb..27cd717 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_test.cc
@@ -26,8 +26,6 @@
namespace tint::writer::glsl {
namespace {
-using BuiltinType = sem::BuiltinType;
-
using GlslGeneratorImplTest_Builtin = TestHelper;
enum class CallParamType {
@@ -38,7 +36,7 @@
};
struct BuiltinData {
- BuiltinType builtin;
+ builtin::Function builtin;
CallParamType type;
const char* glsl_name;
};
@@ -62,86 +60,86 @@
return out;
}
-const ast::CallExpression* GenerateCall(BuiltinType builtin,
+const ast::CallExpression* GenerateCall(builtin::Function builtin,
CallParamType type,
ProgramBuilder* builder) {
std::string name;
utils::StringStream str;
str << name << builtin;
switch (builtin) {
- case BuiltinType::kAcos:
- case BuiltinType::kAsin:
- case BuiltinType::kAtan:
- case BuiltinType::kCeil:
- case BuiltinType::kCos:
- case BuiltinType::kCosh:
- case BuiltinType::kDpdx:
- case BuiltinType::kDpdxCoarse:
- case BuiltinType::kDpdxFine:
- case BuiltinType::kDpdy:
- case BuiltinType::kDpdyCoarse:
- case BuiltinType::kDpdyFine:
- case BuiltinType::kExp:
- case BuiltinType::kExp2:
- case BuiltinType::kFloor:
- case BuiltinType::kFract:
- case BuiltinType::kFwidth:
- case BuiltinType::kFwidthCoarse:
- case BuiltinType::kFwidthFine:
- case BuiltinType::kInverseSqrt:
- case BuiltinType::kLength:
- case BuiltinType::kLog:
- case BuiltinType::kLog2:
- case BuiltinType::kNormalize:
- case BuiltinType::kRound:
- case BuiltinType::kSin:
- case BuiltinType::kSinh:
- case BuiltinType::kSqrt:
- case BuiltinType::kTan:
- case BuiltinType::kTanh:
- case BuiltinType::kTrunc:
- case BuiltinType::kSign:
+ case builtin::Function::kAcos:
+ case builtin::Function::kAsin:
+ case builtin::Function::kAtan:
+ case builtin::Function::kCeil:
+ case builtin::Function::kCos:
+ case builtin::Function::kCosh:
+ case builtin::Function::kDpdx:
+ case builtin::Function::kDpdxCoarse:
+ case builtin::Function::kDpdxFine:
+ case builtin::Function::kDpdy:
+ case builtin::Function::kDpdyCoarse:
+ case builtin::Function::kDpdyFine:
+ case builtin::Function::kExp:
+ case builtin::Function::kExp2:
+ case builtin::Function::kFloor:
+ case builtin::Function::kFract:
+ case builtin::Function::kFwidth:
+ case builtin::Function::kFwidthCoarse:
+ case builtin::Function::kFwidthFine:
+ case builtin::Function::kInverseSqrt:
+ case builtin::Function::kLength:
+ case builtin::Function::kLog:
+ case builtin::Function::kLog2:
+ case builtin::Function::kNormalize:
+ case builtin::Function::kRound:
+ case builtin::Function::kSin:
+ case builtin::Function::kSinh:
+ case builtin::Function::kSqrt:
+ case builtin::Function::kTan:
+ case builtin::Function::kTanh:
+ case builtin::Function::kTrunc:
+ case builtin::Function::kSign:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2");
} else {
return builder->Call(str.str(), "f2");
}
- case BuiltinType::kLdexp:
+ case builtin::Function::kLdexp:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "i2");
} else {
return builder->Call(str.str(), "f2", "i2");
}
- case BuiltinType::kAtan2:
- case BuiltinType::kDot:
- case BuiltinType::kDistance:
- case BuiltinType::kPow:
- case BuiltinType::kReflect:
- case BuiltinType::kStep:
+ case builtin::Function::kAtan2:
+ case builtin::Function::kDot:
+ case builtin::Function::kDistance:
+ case builtin::Function::kPow:
+ case builtin::Function::kReflect:
+ case builtin::Function::kStep:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2");
} else {
return builder->Call(str.str(), "f2", "f2");
}
- case BuiltinType::kCross:
+ case builtin::Function::kCross:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h3", "h3");
} else {
return builder->Call(str.str(), "f3", "f3");
}
- case BuiltinType::kFma:
- case BuiltinType::kMix:
- case BuiltinType::kFaceForward:
- case BuiltinType::kSmoothstep:
+ case builtin::Function::kFma:
+ case builtin::Function::kMix:
+ case builtin::Function::kFaceForward:
+ case builtin::Function::kSmoothstep:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2", "h2");
} else {
return builder->Call(str.str(), "f2", "f2", "f2");
}
- case BuiltinType::kAll:
- case BuiltinType::kAny:
+ case builtin::Function::kAll:
+ case builtin::Function::kAny:
return builder->Call(str.str(), "b2");
- case BuiltinType::kAbs:
+ case builtin::Function::kAbs:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2");
} else if (type == CallParamType::kF16) {
@@ -149,11 +147,11 @@
} else {
return builder->Call(str.str(), "u2");
}
- case BuiltinType::kCountOneBits:
- case BuiltinType::kReverseBits:
+ case builtin::Function::kCountOneBits:
+ case builtin::Function::kReverseBits:
return builder->Call(str.str(), "u2");
- case BuiltinType::kMax:
- case BuiltinType::kMin:
+ case builtin::Function::kMax:
+ case builtin::Function::kMin:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2", "f2");
} else if (type == CallParamType::kF16) {
@@ -161,7 +159,7 @@
} else {
return builder->Call(str.str(), "u2", "u2");
}
- case BuiltinType::kClamp:
+ case builtin::Function::kClamp:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2", "f2", "f2");
} else if (type == CallParamType::kF16) {
@@ -169,19 +167,19 @@
} else {
return builder->Call(str.str(), "u2", "u2", "u2");
}
- case BuiltinType::kSelect:
+ case builtin::Function::kSelect:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2", "b2");
} else {
return builder->Call(str.str(), "f2", "f2", "b2");
}
- case BuiltinType::kDeterminant:
+ case builtin::Function::kDeterminant:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "hm2x2");
} else {
return builder->Call(str.str(), "m2x2");
}
- case BuiltinType::kTranspose:
+ case builtin::Function::kTranspose:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "hm3x2");
} else {
@@ -235,110 +233,111 @@
INSTANTIATE_TEST_SUITE_P(
GlslGeneratorImplTest_Builtin,
GlslBuiltinTest,
- testing::Values(/* Logical built-in */
- BuiltinData{BuiltinType::kAll, CallParamType::kBool, "all"},
- BuiltinData{BuiltinType::kAny, CallParamType::kBool, "any"},
- /* Float built-in */
- BuiltinData{BuiltinType::kAbs, CallParamType::kF32, "abs"},
- BuiltinData{BuiltinType::kAbs, CallParamType::kF16, "abs"},
- BuiltinData{BuiltinType::kAcos, CallParamType::kF32, "acos"},
- BuiltinData{BuiltinType::kAcos, CallParamType::kF16, "acos"},
- BuiltinData{BuiltinType::kAsin, CallParamType::kF32, "asin"},
- BuiltinData{BuiltinType::kAsin, CallParamType::kF16, "asin"},
- BuiltinData{BuiltinType::kAtan, CallParamType::kF32, "atan"},
- BuiltinData{BuiltinType::kAtan, CallParamType::kF16, "atan"},
- BuiltinData{BuiltinType::kAtan2, CallParamType::kF32, "atan"},
- BuiltinData{BuiltinType::kAtan2, CallParamType::kF16, "atan"},
- BuiltinData{BuiltinType::kCeil, CallParamType::kF32, "ceil"},
- BuiltinData{BuiltinType::kCeil, CallParamType::kF16, "ceil"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kF32, "clamp"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kF16, "clamp"},
- BuiltinData{BuiltinType::kCos, CallParamType::kF32, "cos"},
- BuiltinData{BuiltinType::kCos, CallParamType::kF16, "cos"},
- BuiltinData{BuiltinType::kCosh, CallParamType::kF32, "cosh"},
- BuiltinData{BuiltinType::kCosh, CallParamType::kF16, "cosh"},
- BuiltinData{BuiltinType::kCross, CallParamType::kF32, "cross"},
- BuiltinData{BuiltinType::kCross, CallParamType::kF16, "cross"},
- BuiltinData{BuiltinType::kDistance, CallParamType::kF32, "distance"},
- BuiltinData{BuiltinType::kDistance, CallParamType::kF16, "distance"},
- BuiltinData{BuiltinType::kExp, CallParamType::kF32, "exp"},
- BuiltinData{BuiltinType::kExp, CallParamType::kF16, "exp"},
- BuiltinData{BuiltinType::kExp2, CallParamType::kF32, "exp2"},
- BuiltinData{BuiltinType::kExp2, CallParamType::kF16, "exp2"},
- BuiltinData{BuiltinType::kFaceForward, CallParamType::kF32, "faceforward"},
- BuiltinData{BuiltinType::kFaceForward, CallParamType::kF16, "faceforward"},
- BuiltinData{BuiltinType::kFloor, CallParamType::kF32, "floor"},
- BuiltinData{BuiltinType::kFloor, CallParamType::kF16, "floor"},
- BuiltinData{BuiltinType::kFma, CallParamType::kF32, "fma"},
- BuiltinData{BuiltinType::kFma, CallParamType::kF16, "fma"},
- BuiltinData{BuiltinType::kFract, CallParamType::kF32, "fract"},
- BuiltinData{BuiltinType::kFract, CallParamType::kF16, "fract"},
- BuiltinData{BuiltinType::kInverseSqrt, CallParamType::kF32, "inversesqrt"},
- BuiltinData{BuiltinType::kInverseSqrt, CallParamType::kF16, "inversesqrt"},
- BuiltinData{BuiltinType::kLdexp, CallParamType::kF32, "ldexp"},
- BuiltinData{BuiltinType::kLdexp, CallParamType::kF16, "ldexp"},
- BuiltinData{BuiltinType::kLength, CallParamType::kF32, "length"},
- BuiltinData{BuiltinType::kLength, CallParamType::kF16, "length"},
- BuiltinData{BuiltinType::kLog, CallParamType::kF32, "log"},
- BuiltinData{BuiltinType::kLog, CallParamType::kF16, "log"},
- BuiltinData{BuiltinType::kLog2, CallParamType::kF32, "log2"},
- BuiltinData{BuiltinType::kLog2, CallParamType::kF16, "log2"},
- BuiltinData{BuiltinType::kMax, CallParamType::kF32, "max"},
- BuiltinData{BuiltinType::kMax, CallParamType::kF16, "max"},
- BuiltinData{BuiltinType::kMin, CallParamType::kF32, "min"},
- BuiltinData{BuiltinType::kMin, CallParamType::kF16, "min"},
- BuiltinData{BuiltinType::kMix, CallParamType::kF32, "mix"},
- BuiltinData{BuiltinType::kMix, CallParamType::kF16, "mix"},
- BuiltinData{BuiltinType::kNormalize, CallParamType::kF32, "normalize"},
- BuiltinData{BuiltinType::kNormalize, CallParamType::kF16, "normalize"},
- BuiltinData{BuiltinType::kPow, CallParamType::kF32, "pow"},
- BuiltinData{BuiltinType::kPow, CallParamType::kF16, "pow"},
- BuiltinData{BuiltinType::kReflect, CallParamType::kF32, "reflect"},
- BuiltinData{BuiltinType::kReflect, CallParamType::kF16, "reflect"},
- BuiltinData{BuiltinType::kSign, CallParamType::kF32, "sign"},
- BuiltinData{BuiltinType::kSign, CallParamType::kF16, "sign"},
- BuiltinData{BuiltinType::kSin, CallParamType::kF32, "sin"},
- BuiltinData{BuiltinType::kSin, CallParamType::kF16, "sin"},
- BuiltinData{BuiltinType::kSinh, CallParamType::kF32, "sinh"},
- BuiltinData{BuiltinType::kSinh, CallParamType::kF16, "sinh"},
- BuiltinData{BuiltinType::kSmoothstep, CallParamType::kF32, "smoothstep"},
- BuiltinData{BuiltinType::kSmoothstep, CallParamType::kF16, "smoothstep"},
- BuiltinData{BuiltinType::kSqrt, CallParamType::kF32, "sqrt"},
- BuiltinData{BuiltinType::kSqrt, CallParamType::kF16, "sqrt"},
- BuiltinData{BuiltinType::kStep, CallParamType::kF32, "step"},
- BuiltinData{BuiltinType::kStep, CallParamType::kF16, "step"},
- BuiltinData{BuiltinType::kTan, CallParamType::kF32, "tan"},
- BuiltinData{BuiltinType::kTan, CallParamType::kF16, "tan"},
- BuiltinData{BuiltinType::kTanh, CallParamType::kF32, "tanh"},
- BuiltinData{BuiltinType::kTanh, CallParamType::kF16, "tanh"},
- BuiltinData{BuiltinType::kTrunc, CallParamType::kF32, "trunc"},
- BuiltinData{BuiltinType::kTrunc, CallParamType::kF16, "trunc"},
- /* Integer built-in */
- BuiltinData{BuiltinType::kAbs, CallParamType::kU32, "abs"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kU32, "clamp"},
- BuiltinData{BuiltinType::kCountOneBits, CallParamType::kU32, "bitCount"},
- BuiltinData{BuiltinType::kMax, CallParamType::kU32, "max"},
- BuiltinData{BuiltinType::kMin, CallParamType::kU32, "min"},
- BuiltinData{BuiltinType::kReverseBits, CallParamType::kU32, "bitfieldReverse"},
- BuiltinData{BuiltinType::kRound, CallParamType::kU32, "round"},
- /* Matrix built-in */
- BuiltinData{BuiltinType::kDeterminant, CallParamType::kF32, "determinant"},
- BuiltinData{BuiltinType::kDeterminant, CallParamType::kF16, "determinant"},
- BuiltinData{BuiltinType::kTranspose, CallParamType::kF32, "transpose"},
- BuiltinData{BuiltinType::kTranspose, CallParamType::kF16, "transpose"},
- /* Vector built-in */
- BuiltinData{BuiltinType::kDot, CallParamType::kF32, "dot"},
- BuiltinData{BuiltinType::kDot, CallParamType::kF16, "dot"},
- /* Derivate built-in */
- BuiltinData{BuiltinType::kDpdx, CallParamType::kF32, "dFdx"},
- BuiltinData{BuiltinType::kDpdxCoarse, CallParamType::kF32, "dFdx"},
- BuiltinData{BuiltinType::kDpdxFine, CallParamType::kF32, "dFdx"},
- BuiltinData{BuiltinType::kDpdy, CallParamType::kF32, "dFdy"},
- BuiltinData{BuiltinType::kDpdyCoarse, CallParamType::kF32, "dFdy"},
- BuiltinData{BuiltinType::kDpdyFine, CallParamType::kF32, "dFdy"},
- BuiltinData{BuiltinType::kFwidth, CallParamType::kF32, "fwidth"},
- BuiltinData{BuiltinType::kFwidthCoarse, CallParamType::kF32, "fwidth"},
- BuiltinData{BuiltinType::kFwidthFine, CallParamType::kF32, "fwidth"}));
+ testing::
+ Values(/* Logical built-in */
+ BuiltinData{builtin::Function::kAll, CallParamType::kBool, "all"},
+ BuiltinData{builtin::Function::kAny, CallParamType::kBool, "any"},
+ /* Float built-in */
+ BuiltinData{builtin::Function::kAbs, CallParamType::kF32, "abs"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kF16, "abs"},
+ BuiltinData{builtin::Function::kAcos, CallParamType::kF32, "acos"},
+ BuiltinData{builtin::Function::kAcos, CallParamType::kF16, "acos"},
+ BuiltinData{builtin::Function::kAsin, CallParamType::kF32, "asin"},
+ BuiltinData{builtin::Function::kAsin, CallParamType::kF16, "asin"},
+ BuiltinData{builtin::Function::kAtan, CallParamType::kF32, "atan"},
+ BuiltinData{builtin::Function::kAtan, CallParamType::kF16, "atan"},
+ BuiltinData{builtin::Function::kAtan2, CallParamType::kF32, "atan"},
+ BuiltinData{builtin::Function::kAtan2, CallParamType::kF16, "atan"},
+ BuiltinData{builtin::Function::kCeil, CallParamType::kF32, "ceil"},
+ BuiltinData{builtin::Function::kCeil, CallParamType::kF16, "ceil"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kF32, "clamp"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kF16, "clamp"},
+ BuiltinData{builtin::Function::kCos, CallParamType::kF32, "cos"},
+ BuiltinData{builtin::Function::kCos, CallParamType::kF16, "cos"},
+ BuiltinData{builtin::Function::kCosh, CallParamType::kF32, "cosh"},
+ BuiltinData{builtin::Function::kCosh, CallParamType::kF16, "cosh"},
+ BuiltinData{builtin::Function::kCross, CallParamType::kF32, "cross"},
+ BuiltinData{builtin::Function::kCross, CallParamType::kF16, "cross"},
+ BuiltinData{builtin::Function::kDistance, CallParamType::kF32, "distance"},
+ BuiltinData{builtin::Function::kDistance, CallParamType::kF16, "distance"},
+ BuiltinData{builtin::Function::kExp, CallParamType::kF32, "exp"},
+ BuiltinData{builtin::Function::kExp, CallParamType::kF16, "exp"},
+ BuiltinData{builtin::Function::kExp2, CallParamType::kF32, "exp2"},
+ BuiltinData{builtin::Function::kExp2, CallParamType::kF16, "exp2"},
+ BuiltinData{builtin::Function::kFaceForward, CallParamType::kF32, "faceforward"},
+ BuiltinData{builtin::Function::kFaceForward, CallParamType::kF16, "faceforward"},
+ BuiltinData{builtin::Function::kFloor, CallParamType::kF32, "floor"},
+ BuiltinData{builtin::Function::kFloor, CallParamType::kF16, "floor"},
+ BuiltinData{builtin::Function::kFma, CallParamType::kF32, "fma"},
+ BuiltinData{builtin::Function::kFma, CallParamType::kF16, "fma"},
+ BuiltinData{builtin::Function::kFract, CallParamType::kF32, "fract"},
+ BuiltinData{builtin::Function::kFract, CallParamType::kF16, "fract"},
+ BuiltinData{builtin::Function::kInverseSqrt, CallParamType::kF32, "inversesqrt"},
+ BuiltinData{builtin::Function::kInverseSqrt, CallParamType::kF16, "inversesqrt"},
+ BuiltinData{builtin::Function::kLdexp, CallParamType::kF32, "ldexp"},
+ BuiltinData{builtin::Function::kLdexp, CallParamType::kF16, "ldexp"},
+ BuiltinData{builtin::Function::kLength, CallParamType::kF32, "length"},
+ BuiltinData{builtin::Function::kLength, CallParamType::kF16, "length"},
+ BuiltinData{builtin::Function::kLog, CallParamType::kF32, "log"},
+ BuiltinData{builtin::Function::kLog, CallParamType::kF16, "log"},
+ BuiltinData{builtin::Function::kLog2, CallParamType::kF32, "log2"},
+ BuiltinData{builtin::Function::kLog2, CallParamType::kF16, "log2"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kF32, "max"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kF16, "max"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kF32, "min"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kF16, "min"},
+ BuiltinData{builtin::Function::kMix, CallParamType::kF32, "mix"},
+ BuiltinData{builtin::Function::kMix, CallParamType::kF16, "mix"},
+ BuiltinData{builtin::Function::kNormalize, CallParamType::kF32, "normalize"},
+ BuiltinData{builtin::Function::kNormalize, CallParamType::kF16, "normalize"},
+ BuiltinData{builtin::Function::kPow, CallParamType::kF32, "pow"},
+ BuiltinData{builtin::Function::kPow, CallParamType::kF16, "pow"},
+ BuiltinData{builtin::Function::kReflect, CallParamType::kF32, "reflect"},
+ BuiltinData{builtin::Function::kReflect, CallParamType::kF16, "reflect"},
+ BuiltinData{builtin::Function::kSign, CallParamType::kF32, "sign"},
+ BuiltinData{builtin::Function::kSign, CallParamType::kF16, "sign"},
+ BuiltinData{builtin::Function::kSin, CallParamType::kF32, "sin"},
+ BuiltinData{builtin::Function::kSin, CallParamType::kF16, "sin"},
+ BuiltinData{builtin::Function::kSinh, CallParamType::kF32, "sinh"},
+ BuiltinData{builtin::Function::kSinh, CallParamType::kF16, "sinh"},
+ BuiltinData{builtin::Function::kSmoothstep, CallParamType::kF32, "smoothstep"},
+ BuiltinData{builtin::Function::kSmoothstep, CallParamType::kF16, "smoothstep"},
+ BuiltinData{builtin::Function::kSqrt, CallParamType::kF32, "sqrt"},
+ BuiltinData{builtin::Function::kSqrt, CallParamType::kF16, "sqrt"},
+ BuiltinData{builtin::Function::kStep, CallParamType::kF32, "step"},
+ BuiltinData{builtin::Function::kStep, CallParamType::kF16, "step"},
+ BuiltinData{builtin::Function::kTan, CallParamType::kF32, "tan"},
+ BuiltinData{builtin::Function::kTan, CallParamType::kF16, "tan"},
+ BuiltinData{builtin::Function::kTanh, CallParamType::kF32, "tanh"},
+ BuiltinData{builtin::Function::kTanh, CallParamType::kF16, "tanh"},
+ BuiltinData{builtin::Function::kTrunc, CallParamType::kF32, "trunc"},
+ BuiltinData{builtin::Function::kTrunc, CallParamType::kF16, "trunc"},
+ /* Integer built-in */
+ BuiltinData{builtin::Function::kAbs, CallParamType::kU32, "abs"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kU32, "clamp"},
+ BuiltinData{builtin::Function::kCountOneBits, CallParamType::kU32, "bitCount"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kU32, "max"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kU32, "min"},
+ BuiltinData{builtin::Function::kReverseBits, CallParamType::kU32, "bitfieldReverse"},
+ BuiltinData{builtin::Function::kRound, CallParamType::kU32, "round"},
+ /* Matrix built-in */
+ BuiltinData{builtin::Function::kDeterminant, CallParamType::kF32, "determinant"},
+ BuiltinData{builtin::Function::kDeterminant, CallParamType::kF16, "determinant"},
+ BuiltinData{builtin::Function::kTranspose, CallParamType::kF32, "transpose"},
+ BuiltinData{builtin::Function::kTranspose, CallParamType::kF16, "transpose"},
+ /* Vector built-in */
+ BuiltinData{builtin::Function::kDot, CallParamType::kF32, "dot"},
+ BuiltinData{builtin::Function::kDot, CallParamType::kF16, "dot"},
+ /* Derivate built-in */
+ BuiltinData{builtin::Function::kDpdx, CallParamType::kF32, "dFdx"},
+ BuiltinData{builtin::Function::kDpdxCoarse, CallParamType::kF32, "dFdx"},
+ BuiltinData{builtin::Function::kDpdxFine, CallParamType::kF32, "dFdx"},
+ BuiltinData{builtin::Function::kDpdy, CallParamType::kF32, "dFdy"},
+ BuiltinData{builtin::Function::kDpdyCoarse, CallParamType::kF32, "dFdy"},
+ BuiltinData{builtin::Function::kDpdyFine, CallParamType::kF32, "dFdy"},
+ BuiltinData{builtin::Function::kFwidth, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kFwidthCoarse, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kFwidthFine, CallParamType::kF32, "fwidth"}));
TEST_F(GlslGeneratorImplTest_Builtin, Builtin_Call) {
auto* call = Call("dot", "param1", "param2");
@@ -379,7 +378,7 @@
gen.increment_indent();
utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
- EXPECT_EQ(out.str(), "mix(a, b, bvec2(true, false))");
+ EXPECT_EQ(out.str(), "tint_select(a, b, bvec2(true, false))");
}
TEST_F(GlslGeneratorImplTest_Builtin, FMA_f32) {
diff --git a/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc b/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc
index bbb3848..040adfe 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc
@@ -98,6 +98,8 @@
return R"(textureGather(Texture_Sampler, vec4(1.0f, 2.0f, 3.0f, float(4u)), 5.0f))";
case ValidTextureOverload::kNumLayers2dArray:
case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
return {"textureSize"};
case ValidTextureOverload::kNumLayersStorageWO2dArray:
return {"imageSize"};
diff --git a/src/tint/writer/glsl/generator_impl_function_test.cc b/src/tint/writer/glsl/generator_impl_function_test.cc
index 05d1460..bc085b9 100644
--- a/src/tint/writer/glsl/generator_impl_function_test.cc
+++ b/src/tint/writer/glsl/generator_impl_function_test.cc
@@ -98,7 +98,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
void func() {
return;
@@ -145,7 +145,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
layout(location = 0) in float foo_1;
layout(location = 1) out float value;
@@ -186,7 +186,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
float frag_main(vec4 coord) {
return coord.x;
@@ -239,7 +239,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
layout(location = 1) out float col1_1;
layout(location = 2) out float col2_1;
@@ -378,7 +378,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
struct UBO {
vec4 coord;
@@ -419,7 +419,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Uniforms {
vec4 coord;
@@ -460,7 +460,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
int a;
@@ -508,7 +508,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(),
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
int a;
@@ -553,7 +553,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
int a;
@@ -598,7 +598,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
int a;
@@ -645,7 +645,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
struct S {
float x;
@@ -692,7 +692,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(),
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct S {
float x;
@@ -728,7 +728,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-precision mediump float;
+precision highp float;
void tint_symbol() {
}
diff --git a/src/tint/writer/glsl/generator_impl_member_accessor_test.cc b/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
index 2eb1b8e..6d0d58e 100644
--- a/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
@@ -281,7 +281,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
int a;
@@ -334,7 +334,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
float z;
@@ -382,7 +382,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
float z;
@@ -430,7 +430,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
float z;
@@ -477,7 +477,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Data {
float z;
@@ -530,7 +530,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Inner {
vec3 a;
@@ -591,7 +591,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Inner {
vec3 a;
@@ -653,7 +653,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Inner {
vec3 a;
@@ -714,7 +714,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Inner {
vec3 a;
@@ -774,7 +774,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Inner {
vec3 a;
@@ -835,7 +835,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
auto* expected =
R"(#version 310 es
-precision mediump float;
+precision highp float;
struct Inner {
ivec3 a;
diff --git a/src/tint/writer/glsl/generator_impl_sanitizer_test.cc b/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
index e85d050..5ed2be7 100644
--- a/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
+++ b/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
@@ -43,7 +43,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
layout(binding = 1, std430) buffer my_struct_ssbo {
float a[];
@@ -83,7 +83,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
layout(binding = 1, std430) buffer my_struct_ssbo {
float z;
@@ -127,7 +127,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
layout(binding = 1, std430) buffer my_struct_ssbo {
float a[];
@@ -164,7 +164,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
void tint_symbol() {
int idx = 3;
@@ -206,7 +206,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
struct S {
int a;
@@ -252,7 +252,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
void tint_symbol() {
int v = 0;
@@ -301,7 +301,7 @@
auto got = gen.result();
auto* expect = R"(#version 310 es
-precision mediump float;
+precision highp float;
void tint_symbol() {
mat4 a[4] = mat4[4](mat4(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), mat4(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), mat4(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), mat4(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
diff --git a/src/tint/writer/glsl/generator_impl_switch_test.cc b/src/tint/writer/glsl/generator_impl_switch_test.cc
index b9ff49d..8e2f739 100644
--- a/src/tint/writer/glsl/generator_impl_switch_test.cc
+++ b/src/tint/writer/glsl/generator_impl_switch_test.cc
@@ -31,7 +31,7 @@
auto* case_stmt = create<ast::CaseStatement>(utils::Vector{CaseSelector(5_i)}, case_body);
auto* cond = Expr("cond");
- auto* s = create<ast::SwitchStatement>(cond, utils::Vector{case_stmt, def});
+ auto* s = create<ast::SwitchStatement>(cond, utils::Vector{case_stmt, def}, utils::Empty);
WrapInFunction(s);
GeneratorImpl& gen = Build();
@@ -58,7 +58,7 @@
def_body);
auto* cond = Expr("cond");
- auto* s = create<ast::SwitchStatement>(cond, utils::Vector{def});
+ auto* s = create<ast::SwitchStatement>(cond, utils::Vector{def}, utils::Empty);
WrapInFunction(s);
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/glsl/generator_impl_unary_op_test.cc b/src/tint/writer/glsl/generator_impl_unary_op_test.cc
index b7c5fd1..27e9d2c 100644
--- a/src/tint/writer/glsl/generator_impl_unary_op_test.cc
+++ b/src/tint/writer/glsl/generator_impl_unary_op_test.cc
@@ -80,5 +80,17 @@
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "-(expr)");
}
+
+TEST_F(GlslUnaryOpTest, IntMin) {
+ auto* op = Expr(i32(std::numeric_limits<int32_t>::min()));
+ WrapInFunction(op);
+
+ GeneratorImpl& gen = Build();
+
+ utils::StringStream out;
+ ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
+ EXPECT_EQ(out.str(), "(-2147483647 - 1)");
+}
+
} // namespace
} // namespace tint::writer::glsl
diff --git a/src/tint/writer/hlsl/generator.h b/src/tint/writer/hlsl/generator.h
index 74d79ba..2cdfe6f 100644
--- a/src/tint/writer/hlsl/generator.h
+++ b/src/tint/writer/hlsl/generator.h
@@ -28,6 +28,7 @@
#include "src/tint/sem/binding_point.h"
#include "src/tint/utils/bitset.h"
#include "src/tint/writer/array_length_from_uniform_options.h"
+#include "src/tint/writer/external_texture_options.h"
#include "src/tint/writer/text.h"
// Forward declarations
@@ -58,8 +59,8 @@
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
- /// Set to 'true' to generates binding mappings for external textures
- bool generate_external_texture_bindings = false;
+ /// Options used in the binding mappings for external textures
+ ExternalTextureOptions external_texture_options = {};
/// Options used to specify a mapping of binding points to indices into a UBO
/// from which to load buffer sizes.
@@ -76,7 +77,7 @@
TINT_REFLECT(disable_robustness,
root_constant_binding_point,
disable_workgroup_init,
- generate_external_texture_bindings,
+ external_texture_options,
array_length_from_uniform);
};
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index f0247c4..1cfbf64 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -40,6 +40,7 @@
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/add_empty_entry_point.h"
#include "src/tint/transform/array_length_from_uniform.h"
#include "src/tint/transform/builtin_polyfill.h"
@@ -52,6 +53,7 @@
#include "src/tint/transform/expand_compound_assignment.h"
#include "src/tint/transform/localize_struct_array_assignment.h"
#include "src/tint/transform/manager.h"
+#include "src/tint/transform/multiplanar_external_texture.h"
#include "src/tint/transform/num_workgroups_from_uniform.h"
#include "src/tint/transform/promote_initializers_to_let.h"
#include "src/tint/transform/promote_side_effects_to_decl.h"
@@ -80,7 +82,6 @@
#include "src/tint/writer/append_vector.h"
#include "src/tint/writer/check_supported_extensions.h"
#include "src/tint/writer/float_to_string.h"
-#include "src/tint/writer/generate_external_texture_bindings.h"
using namespace tint::number_suffixes; // NOLINT
@@ -187,10 +188,10 @@
manager.Add<transform::Robustness>();
}
- if (options.generate_external_texture_bindings) {
+ if (!options.external_texture_options.bindings_map.empty()) {
// Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
- auto new_bindings_map = GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
+ options.external_texture_options.bindings_map);
manager.Add<transform::MultiplanarExternalTexture>();
}
@@ -203,6 +204,7 @@
polyfills.clamp_int = true;
// TODO(crbug.com/tint/1449): Some of these can map to HLSL's `firstbitlow`
// and `firstbithigh`.
+ polyfills.conv_f32_to_iu32 = true;
polyfills.count_leading_zeros = true;
polyfills.count_trailing_zeros = true;
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kFull;
@@ -966,25 +968,25 @@
if (builtin->IsTexture()) {
return EmitTextureCall(out, call, builtin);
}
- if (type == sem::BuiltinType::kSelect) {
+ if (type == builtin::Function::kSelect) {
return EmitSelectCall(out, expr);
}
- if (type == sem::BuiltinType::kModf) {
+ if (type == builtin::Function::kModf) {
return EmitModfCall(out, expr, builtin);
}
- if (type == sem::BuiltinType::kFrexp) {
+ if (type == builtin::Function::kFrexp) {
return EmitFrexpCall(out, expr, builtin);
}
- if (type == sem::BuiltinType::kDegrees) {
+ if (type == builtin::Function::kDegrees) {
return EmitDegreesCall(out, expr, builtin);
}
- if (type == sem::BuiltinType::kRadians) {
+ if (type == builtin::Function::kRadians) {
return EmitRadiansCall(out, expr, builtin);
}
- if (type == sem::BuiltinType::kSign) {
+ if (type == builtin::Function::kSign) {
return EmitSignCall(out, call, builtin);
}
- if (type == sem::BuiltinType::kQuantizeToF16) {
+ if (type == builtin::Function::kQuantizeToF16) {
return EmitQuantizeToF16Call(out, expr, builtin);
}
if (builtin->IsDataPacking()) {
@@ -1011,7 +1013,7 @@
// Handle single argument builtins that only accept and return uint (not int overload). We need
// to explicitly cast the return value (we also cast the arg for good measure). See
// crbug.com/tint/1550
- if (type == sem::BuiltinType::kCountOneBits || type == sem::BuiltinType::kReverseBits) {
+ if (type == builtin::Function::kCountOneBits || type == builtin::Function::kReverseBits) {
auto* arg = call->Arguments()[0];
if (arg->Type()->UnwrapRef()->is_signed_integer_scalar_or_vector()) {
out << "asint(" << name << "(asuint(";
@@ -1805,7 +1807,7 @@
if (i > 0) {
pre << ", ";
}
- if (i == 1 && builtin->Type() == sem::BuiltinType::kAtomicSub) {
+ if (i == 1 && builtin->Type() == builtin::Function::kAtomicSub) {
// Sub uses InterlockedAdd with the operand negated.
pre << "-";
}
@@ -1824,7 +1826,7 @@
};
switch (builtin->Type()) {
- case sem::BuiltinType::kAtomicLoad: {
+ case builtin::Function::kAtomicLoad: {
// HLSL does not have an InterlockedLoad, so we emulate it with
// InterlockedOr using 0 as the OR value
auto pre = line();
@@ -1841,7 +1843,7 @@
out << result;
return true;
}
- case sem::BuiltinType::kAtomicStore: {
+ case builtin::Function::kAtomicStore: {
// HLSL does not have an InterlockedStore, so we emulate it with
// InterlockedExchange and discard the returned value
{ // T result = 0;
@@ -1872,7 +1874,7 @@
}
return true;
}
- case sem::BuiltinType::kAtomicCompareExchangeWeak: {
+ case builtin::Function::kAtomicCompareExchangeWeak: {
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
return false;
}
@@ -1921,26 +1923,26 @@
return true;
}
- case sem::BuiltinType::kAtomicAdd:
- case sem::BuiltinType::kAtomicSub:
+ case builtin::Function::kAtomicAdd:
+ case builtin::Function::kAtomicSub:
return call("InterlockedAdd");
- case sem::BuiltinType::kAtomicMax:
+ case builtin::Function::kAtomicMax:
return call("InterlockedMax");
- case sem::BuiltinType::kAtomicMin:
+ case builtin::Function::kAtomicMin:
return call("InterlockedMin");
- case sem::BuiltinType::kAtomicAnd:
+ case builtin::Function::kAtomicAnd:
return call("InterlockedAnd");
- case sem::BuiltinType::kAtomicOr:
+ case builtin::Function::kAtomicOr:
return call("InterlockedOr");
- case sem::BuiltinType::kAtomicXor:
+ case builtin::Function::kAtomicXor:
return call("InterlockedXor");
- case sem::BuiltinType::kAtomicExchange:
+ case builtin::Function::kAtomicExchange:
return call("InterlockedExchange");
default:
@@ -2114,21 +2116,21 @@
uint32_t dims = 2;
bool is_signed = false;
uint32_t scale = 65535;
- if (builtin->Type() == sem::BuiltinType::kPack4X8Snorm ||
- builtin->Type() == sem::BuiltinType::kPack4X8Unorm) {
+ if (builtin->Type() == builtin::Function::kPack4X8Snorm ||
+ builtin->Type() == builtin::Function::kPack4X8Unorm) {
dims = 4;
scale = 255;
}
- if (builtin->Type() == sem::BuiltinType::kPack4X8Snorm ||
- builtin->Type() == sem::BuiltinType::kPack2X16Snorm) {
+ if (builtin->Type() == builtin::Function::kPack4X8Snorm ||
+ builtin->Type() == builtin::Function::kPack2X16Snorm) {
is_signed = true;
scale = (scale - 1) / 2;
}
switch (builtin->Type()) {
- case sem::BuiltinType::kPack4X8Snorm:
- case sem::BuiltinType::kPack4X8Unorm:
- case sem::BuiltinType::kPack2X16Snorm:
- case sem::BuiltinType::kPack2X16Unorm: {
+ case builtin::Function::kPack4X8Snorm:
+ case builtin::Function::kPack4X8Unorm:
+ case builtin::Function::kPack2X16Snorm:
+ case builtin::Function::kPack2X16Unorm: {
{
auto l = line(b);
l << (is_signed ? "" : "u") << "int" << dims
@@ -2154,7 +2156,7 @@
}
break;
}
- case sem::BuiltinType::kPack2X16Float: {
+ case builtin::Function::kPack2X16Float: {
line(b) << "uint2 i = f32tof16(" << params[0] << ");";
line(b) << "return i.x | (i.y << 16);";
break;
@@ -2177,19 +2179,19 @@
uint32_t dims = 2;
bool is_signed = false;
uint32_t scale = 65535;
- if (builtin->Type() == sem::BuiltinType::kUnpack4X8Snorm ||
- builtin->Type() == sem::BuiltinType::kUnpack4X8Unorm) {
+ if (builtin->Type() == builtin::Function::kUnpack4X8Snorm ||
+ builtin->Type() == builtin::Function::kUnpack4X8Unorm) {
dims = 4;
scale = 255;
}
- if (builtin->Type() == sem::BuiltinType::kUnpack4X8Snorm ||
- builtin->Type() == sem::BuiltinType::kUnpack2X16Snorm) {
+ if (builtin->Type() == builtin::Function::kUnpack4X8Snorm ||
+ builtin->Type() == builtin::Function::kUnpack2X16Snorm) {
is_signed = true;
scale = (scale - 1) / 2;
}
switch (builtin->Type()) {
- case sem::BuiltinType::kUnpack4X8Snorm:
- case sem::BuiltinType::kUnpack2X16Snorm: {
+ case builtin::Function::kUnpack4X8Snorm:
+ case builtin::Function::kUnpack2X16Snorm: {
line(b) << "int j = int(" << params[0] << ");";
{ // Perform sign extension on the converted values.
auto l = line(b);
@@ -2205,8 +2207,8 @@
<< (is_signed ? "-1.0" : "0.0") << ", 1.0);";
break;
}
- case sem::BuiltinType::kUnpack4X8Unorm:
- case sem::BuiltinType::kUnpack2X16Unorm: {
+ case builtin::Function::kUnpack4X8Unorm:
+ case builtin::Function::kUnpack2X16Unorm: {
line(b) << "uint j = " << params[0] << ";";
{
auto l = line(b);
@@ -2222,7 +2224,7 @@
line(b) << "return float" << dims << "(i) / " << scale << ".0;";
break;
}
- case sem::BuiltinType::kUnpack2X16Float:
+ case builtin::Function::kUnpack2X16Float:
line(b) << "uint i = " << params[0] << ";";
line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
break;
@@ -2244,11 +2246,11 @@
out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
std::string functionName;
switch (builtin->Type()) {
- case sem::BuiltinType::kDot4I8Packed:
+ case builtin::Function::kDot4I8Packed:
line(b) << "int accumulator = 0;";
functionName = "dot4add_i8packed";
break;
- case sem::BuiltinType::kDot4U8Packed:
+ case builtin::Function::kDot4U8Packed:
line(b) << "uint accumulator = 0u;";
functionName = "dot4add_u8packed";
break;
@@ -2267,13 +2269,13 @@
bool GeneratorImpl::EmitBarrierCall(utils::StringStream& out, const sem::Builtin* builtin) {
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction.
- if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
+ if (builtin->Type() == builtin::Function::kWorkgroupBarrier) {
out << "GroupMemoryBarrierWithGroupSync()";
- } else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
+ } else if (builtin->Type() == builtin::Function::kStorageBarrier) {
out << "DeviceMemoryBarrierWithGroupSync()";
} else {
TINT_UNREACHABLE(Writer, diagnostics_)
- << "unexpected barrier builtin type " << sem::str(builtin->Type());
+ << "unexpected barrier builtin type " << builtin::str(builtin->Type());
return false;
}
return true;
@@ -2303,10 +2305,10 @@
auto* texture_type = TypeOf(texture)->UnwrapRef()->As<type::Texture>();
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureDimensions:
- case sem::BuiltinType::kTextureNumLayers:
- case sem::BuiltinType::kTextureNumLevels:
- case sem::BuiltinType::kTextureNumSamples: {
+ case builtin::Function::kTextureDimensions:
+ case builtin::Function::kTextureNumLayers:
+ case builtin::Function::kTextureNumLevels:
+ case builtin::Function::kTextureNumSamples: {
// All of these builtins use the GetDimensions() method on the texture
bool is_ms =
texture_type->IsAnyOf<type::MultisampledTexture, type::DepthMultisampledTexture>();
@@ -2314,7 +2316,7 @@
std::string swizzle;
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureDimensions:
+ case builtin::Function::kTextureDimensions:
switch (texture_type->dim()) {
case type::TextureDimension::kNone:
TINT_ICE(Writer, diagnostics_) << "texture dimension is kNone";
@@ -2342,7 +2344,7 @@
break;
}
break;
- case sem::BuiltinType::kTextureNumLayers:
+ case builtin::Function::kTextureNumLayers:
switch (texture_type->dim()) {
default:
TINT_ICE(Writer, diagnostics_) << "texture dimension is not arrayed";
@@ -2357,7 +2359,7 @@
break;
}
break;
- case sem::BuiltinType::kTextureNumLevels:
+ case builtin::Function::kTextureNumLevels:
switch (texture_type->dim()) {
default:
TINT_ICE(Writer, diagnostics_)
@@ -2380,7 +2382,7 @@
break;
}
break;
- case sem::BuiltinType::kTextureNumSamples:
+ case builtin::Function::kTextureNumSamples:
switch (texture_type->dim()) {
default:
TINT_ICE(Writer, diagnostics_)
@@ -2427,9 +2429,9 @@
// Declare a variable to hold the queried texture info
auto dims = UniqueIdentifier(kTempNamePrefix);
if (num_dimensions == 1) {
- line() << "int " << dims << ";";
+ line() << "uint " << dims << ";";
} else {
- line() << "int" << num_dimensions << " " << dims << ";";
+ line() << "uint" << num_dimensions << " " << dims << ";";
}
{ // texture.GetDimensions(...)
@@ -2444,7 +2446,7 @@
return false;
}
pre << ", ";
- } else if (builtin->Type() == sem::BuiltinType::kTextureNumLevels) {
+ } else if (builtin->Type() == builtin::Function::kTextureNumLevels) {
pre << "0, ";
}
@@ -2491,34 +2493,34 @@
uint32_t hlsl_ret_width = 4u;
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureSample:
+ case builtin::Function::kTextureSample:
out << ".Sample(";
break;
- case sem::BuiltinType::kTextureSampleBias:
+ case builtin::Function::kTextureSampleBias:
out << ".SampleBias(";
break;
- case sem::BuiltinType::kTextureSampleLevel:
+ case builtin::Function::kTextureSampleLevel:
out << ".SampleLevel(";
break;
- case sem::BuiltinType::kTextureSampleGrad:
+ case builtin::Function::kTextureSampleGrad:
out << ".SampleGrad(";
break;
- case sem::BuiltinType::kTextureSampleCompare:
+ case builtin::Function::kTextureSampleCompare:
out << ".SampleCmp(";
hlsl_ret_width = 1;
break;
- case sem::BuiltinType::kTextureSampleCompareLevel:
+ case builtin::Function::kTextureSampleCompareLevel:
out << ".SampleCmpLevelZero(";
hlsl_ret_width = 1;
break;
- case sem::BuiltinType::kTextureLoad:
+ case builtin::Function::kTextureLoad:
out << ".Load(";
// Multisampled textures do not support mip-levels.
if (!texture_type->Is<type::MultisampledTexture>()) {
pack_level_in_coords = true;
}
break;
- case sem::BuiltinType::kTextureGather:
+ case builtin::Function::kTextureGather:
out << ".Gather";
if (builtin->Parameters()[0]->Usage() == sem::ParameterUsage::kComponent) {
switch (call->Arguments()[0]->ConstantValue()->ValueAs<AInt>()) {
@@ -2538,10 +2540,10 @@
}
out << "(";
break;
- case sem::BuiltinType::kTextureGatherCompare:
+ case builtin::Function::kTextureGatherCompare:
out << ".GatherCmp(";
break;
- case sem::BuiltinType::kTextureStore:
+ case builtin::Function::kTextureStore:
out << "[";
break;
default:
@@ -2621,7 +2623,7 @@
}
}
- if (builtin->Type() == sem::BuiltinType::kTextureStore) {
+ if (builtin->Type() == builtin::Function::kTextureStore) {
out << "] = ";
if (!EmitExpression(out, arg(Usage::kValue))) {
return false;
@@ -2655,78 +2657,78 @@
std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
switch (builtin->Type()) {
- case sem::BuiltinType::kAbs:
- case sem::BuiltinType::kAcos:
- case sem::BuiltinType::kAll:
- case sem::BuiltinType::kAny:
- case sem::BuiltinType::kAsin:
- case sem::BuiltinType::kAtan:
- case sem::BuiltinType::kAtan2:
- case sem::BuiltinType::kCeil:
- case sem::BuiltinType::kClamp:
- case sem::BuiltinType::kCos:
- case sem::BuiltinType::kCosh:
- case sem::BuiltinType::kCross:
- case sem::BuiltinType::kDeterminant:
- case sem::BuiltinType::kDistance:
- case sem::BuiltinType::kDot:
- case sem::BuiltinType::kExp:
- case sem::BuiltinType::kExp2:
- case sem::BuiltinType::kFloor:
- case sem::BuiltinType::kFrexp:
- case sem::BuiltinType::kLdexp:
- case sem::BuiltinType::kLength:
- case sem::BuiltinType::kLog:
- case sem::BuiltinType::kLog2:
- case sem::BuiltinType::kMax:
- case sem::BuiltinType::kMin:
- case sem::BuiltinType::kModf:
- case sem::BuiltinType::kNormalize:
- case sem::BuiltinType::kPow:
- case sem::BuiltinType::kReflect:
- case sem::BuiltinType::kRefract:
- case sem::BuiltinType::kRound:
- case sem::BuiltinType::kSaturate:
- case sem::BuiltinType::kSin:
- case sem::BuiltinType::kSinh:
- case sem::BuiltinType::kSqrt:
- case sem::BuiltinType::kStep:
- case sem::BuiltinType::kTan:
- case sem::BuiltinType::kTanh:
- case sem::BuiltinType::kTranspose:
- case sem::BuiltinType::kTrunc:
+ case builtin::Function::kAbs:
+ case builtin::Function::kAcos:
+ case builtin::Function::kAll:
+ case builtin::Function::kAny:
+ case builtin::Function::kAsin:
+ case builtin::Function::kAtan:
+ case builtin::Function::kAtan2:
+ case builtin::Function::kCeil:
+ case builtin::Function::kClamp:
+ case builtin::Function::kCos:
+ case builtin::Function::kCosh:
+ case builtin::Function::kCross:
+ case builtin::Function::kDeterminant:
+ case builtin::Function::kDistance:
+ case builtin::Function::kDot:
+ case builtin::Function::kExp:
+ case builtin::Function::kExp2:
+ case builtin::Function::kFloor:
+ case builtin::Function::kFrexp:
+ case builtin::Function::kLdexp:
+ case builtin::Function::kLength:
+ case builtin::Function::kLog:
+ case builtin::Function::kLog2:
+ case builtin::Function::kMax:
+ case builtin::Function::kMin:
+ case builtin::Function::kModf:
+ case builtin::Function::kNormalize:
+ case builtin::Function::kPow:
+ case builtin::Function::kReflect:
+ case builtin::Function::kRefract:
+ case builtin::Function::kRound:
+ case builtin::Function::kSaturate:
+ case builtin::Function::kSin:
+ case builtin::Function::kSinh:
+ case builtin::Function::kSqrt:
+ case builtin::Function::kStep:
+ case builtin::Function::kTan:
+ case builtin::Function::kTanh:
+ case builtin::Function::kTranspose:
+ case builtin::Function::kTrunc:
return builtin->str();
- case sem::BuiltinType::kCountOneBits: // uint
+ case builtin::Function::kCountOneBits: // uint
return "countbits";
- case sem::BuiltinType::kDpdx:
+ case builtin::Function::kDpdx:
return "ddx";
- case sem::BuiltinType::kDpdxCoarse:
+ case builtin::Function::kDpdxCoarse:
return "ddx_coarse";
- case sem::BuiltinType::kDpdxFine:
+ case builtin::Function::kDpdxFine:
return "ddx_fine";
- case sem::BuiltinType::kDpdy:
+ case builtin::Function::kDpdy:
return "ddy";
- case sem::BuiltinType::kDpdyCoarse:
+ case builtin::Function::kDpdyCoarse:
return "ddy_coarse";
- case sem::BuiltinType::kDpdyFine:
+ case builtin::Function::kDpdyFine:
return "ddy_fine";
- case sem::BuiltinType::kFaceForward:
+ case builtin::Function::kFaceForward:
return "faceforward";
- case sem::BuiltinType::kFract:
+ case builtin::Function::kFract:
return "frac";
- case sem::BuiltinType::kFma:
+ case builtin::Function::kFma:
return "mad";
- case sem::BuiltinType::kFwidth:
- case sem::BuiltinType::kFwidthCoarse:
- case sem::BuiltinType::kFwidthFine:
+ case builtin::Function::kFwidth:
+ case builtin::Function::kFwidthCoarse:
+ case builtin::Function::kFwidthFine:
return "fwidth";
- case sem::BuiltinType::kInverseSqrt:
+ case builtin::Function::kInverseSqrt:
return "rsqrt";
- case sem::BuiltinType::kMix:
+ case builtin::Function::kMix:
return "lerp";
- case sem::BuiltinType::kReverseBits: // uint
+ case builtin::Function::kReverseBits: // uint
return "reversebits";
- case sem::BuiltinType::kSmoothstep:
+ case builtin::Function::kSmoothstep:
return "smoothstep";
default:
diagnostics_.add_error(diag::System::Writer,
@@ -3321,10 +3323,10 @@
return true;
},
[&](const type::Vector* v) {
- if (constant->AllEqual()) {
+ if (auto* splat = constant->As<constant::Splat>()) {
{
ScopedParen sp(out);
- if (!EmitConstant(out, constant->Index(0), is_variable_initializer)) {
+ if (!EmitConstant(out, splat->el, is_variable_initializer)) {
return false;
}
}
@@ -4346,7 +4348,7 @@
TextBuffer b;
TINT_DEFER(helpers_.Append(b));
- auto fn_name = UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
+ auto fn_name = UniqueIdentifier(std::string("tint_") + builtin::str(builtin->Type()));
std::vector<std::string> parameter_names;
{
auto decl = line(&b);
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
index 5054327..f473ac8 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
@@ -26,7 +26,6 @@
namespace tint::writer::hlsl {
namespace {
-using BuiltinType = sem::BuiltinType;
using HlslGeneratorImplTest_Builtin = TestHelper;
enum class CallParamType {
@@ -37,7 +36,7 @@
};
struct BuiltinData {
- BuiltinType builtin;
+ builtin::Function builtin;
CallParamType type;
const char* hlsl_name;
};
@@ -61,85 +60,85 @@
return out;
}
-const ast::CallExpression* GenerateCall(BuiltinType builtin,
+const ast::CallExpression* GenerateCall(builtin::Function builtin,
CallParamType type,
ProgramBuilder* builder) {
std::string name;
utils::StringStream str;
str << name << builtin;
switch (builtin) {
- case BuiltinType::kAcos:
- case BuiltinType::kAsin:
- case BuiltinType::kAtan:
- case BuiltinType::kCeil:
- case BuiltinType::kCos:
- case BuiltinType::kCosh:
- case BuiltinType::kDpdx:
- case BuiltinType::kDpdxCoarse:
- case BuiltinType::kDpdxFine:
- case BuiltinType::kDpdy:
- case BuiltinType::kDpdyCoarse:
- case BuiltinType::kDpdyFine:
- case BuiltinType::kExp:
- case BuiltinType::kExp2:
- case BuiltinType::kFloor:
- case BuiltinType::kFract:
- case BuiltinType::kFwidth:
- case BuiltinType::kFwidthCoarse:
- case BuiltinType::kFwidthFine:
- case BuiltinType::kInverseSqrt:
- case BuiltinType::kLength:
- case BuiltinType::kLog:
- case BuiltinType::kLog2:
- case BuiltinType::kNormalize:
- case BuiltinType::kRound:
- case BuiltinType::kSin:
- case BuiltinType::kSinh:
- case BuiltinType::kSqrt:
- case BuiltinType::kTan:
- case BuiltinType::kTanh:
- case BuiltinType::kTrunc:
+ case builtin::Function::kAcos:
+ case builtin::Function::kAsin:
+ case builtin::Function::kAtan:
+ case builtin::Function::kCeil:
+ case builtin::Function::kCos:
+ case builtin::Function::kCosh:
+ case builtin::Function::kDpdx:
+ case builtin::Function::kDpdxCoarse:
+ case builtin::Function::kDpdxFine:
+ case builtin::Function::kDpdy:
+ case builtin::Function::kDpdyCoarse:
+ case builtin::Function::kDpdyFine:
+ case builtin::Function::kExp:
+ case builtin::Function::kExp2:
+ case builtin::Function::kFloor:
+ case builtin::Function::kFract:
+ case builtin::Function::kFwidth:
+ case builtin::Function::kFwidthCoarse:
+ case builtin::Function::kFwidthFine:
+ case builtin::Function::kInverseSqrt:
+ case builtin::Function::kLength:
+ case builtin::Function::kLog:
+ case builtin::Function::kLog2:
+ case builtin::Function::kNormalize:
+ case builtin::Function::kRound:
+ case builtin::Function::kSin:
+ case builtin::Function::kSinh:
+ case builtin::Function::kSqrt:
+ case builtin::Function::kTan:
+ case builtin::Function::kTanh:
+ case builtin::Function::kTrunc:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2");
} else {
return builder->Call(str.str(), "f2");
}
- case BuiltinType::kLdexp:
+ case builtin::Function::kLdexp:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "i2");
} else {
return builder->Call(str.str(), "f2", "i2");
}
- case BuiltinType::kAtan2:
- case BuiltinType::kDot:
- case BuiltinType::kDistance:
- case BuiltinType::kPow:
- case BuiltinType::kReflect:
- case BuiltinType::kStep:
+ case builtin::Function::kAtan2:
+ case builtin::Function::kDot:
+ case builtin::Function::kDistance:
+ case builtin::Function::kPow:
+ case builtin::Function::kReflect:
+ case builtin::Function::kStep:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2");
} else {
return builder->Call(str.str(), "f2", "f2");
}
- case BuiltinType::kCross:
+ case builtin::Function::kCross:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h3", "h3");
} else {
return builder->Call(str.str(), "f3", "f3");
}
- case BuiltinType::kFma:
- case BuiltinType::kMix:
- case BuiltinType::kFaceForward:
- case BuiltinType::kSmoothstep:
+ case builtin::Function::kFma:
+ case builtin::Function::kMix:
+ case builtin::Function::kFaceForward:
+ case builtin::Function::kSmoothstep:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2", "h2");
} else {
return builder->Call(str.str(), "f2", "f2", "f2");
}
- case BuiltinType::kAll:
- case BuiltinType::kAny:
+ case builtin::Function::kAll:
+ case builtin::Function::kAny:
return builder->Call(str.str(), "b2");
- case BuiltinType::kAbs:
+ case builtin::Function::kAbs:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2");
} else if (type == CallParamType::kF16) {
@@ -147,11 +146,11 @@
} else {
return builder->Call(str.str(), "u2");
}
- case BuiltinType::kCountOneBits:
- case BuiltinType::kReverseBits:
+ case builtin::Function::kCountOneBits:
+ case builtin::Function::kReverseBits:
return builder->Call(str.str(), "u2");
- case BuiltinType::kMax:
- case BuiltinType::kMin:
+ case builtin::Function::kMax:
+ case builtin::Function::kMin:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2", "f2");
} else if (type == CallParamType::kF16) {
@@ -159,7 +158,7 @@
} else {
return builder->Call(str.str(), "u2", "u2");
}
- case BuiltinType::kClamp:
+ case builtin::Function::kClamp:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2", "f2", "f2");
} else if (type == CallParamType::kF16) {
@@ -167,19 +166,19 @@
} else {
return builder->Call(str.str(), "u2", "u2", "u2");
}
- case BuiltinType::kSelect:
+ case builtin::Function::kSelect:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2", "b2");
} else {
return builder->Call(str.str(), "f2", "f2", "b2");
}
- case BuiltinType::kDeterminant:
+ case builtin::Function::kDeterminant:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "hm2x2");
} else {
return builder->Call(str.str(), "m2x2");
}
- case BuiltinType::kTranspose:
+ case builtin::Function::kTranspose:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "hm3x2");
} else {
@@ -235,107 +234,112 @@
HlslGeneratorImplTest_Builtin,
HlslBuiltinTest,
testing::Values(/* Logical built-in */
- BuiltinData{BuiltinType::kAll, CallParamType::kBool, "all"},
- BuiltinData{BuiltinType::kAny, CallParamType::kBool, "any"},
+ BuiltinData{builtin::Function::kAll, CallParamType::kBool, "all"},
+ BuiltinData{builtin::Function::kAny, CallParamType::kBool, "any"},
/* Float built-in */
- BuiltinData{BuiltinType::kAbs, CallParamType::kF32, "abs"},
- BuiltinData{BuiltinType::kAbs, CallParamType::kF16, "abs"},
- BuiltinData{BuiltinType::kAcos, CallParamType::kF32, "acos"},
- BuiltinData{BuiltinType::kAcos, CallParamType::kF16, "acos"},
- BuiltinData{BuiltinType::kAsin, CallParamType::kF32, "asin"},
- BuiltinData{BuiltinType::kAsin, CallParamType::kF16, "asin"},
- BuiltinData{BuiltinType::kAtan, CallParamType::kF32, "atan"},
- BuiltinData{BuiltinType::kAtan, CallParamType::kF16, "atan"},
- BuiltinData{BuiltinType::kAtan2, CallParamType::kF32, "atan2"},
- BuiltinData{BuiltinType::kAtan2, CallParamType::kF16, "atan2"},
- BuiltinData{BuiltinType::kCeil, CallParamType::kF32, "ceil"},
- BuiltinData{BuiltinType::kCeil, CallParamType::kF16, "ceil"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kF32, "clamp"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kF16, "clamp"},
- BuiltinData{BuiltinType::kCos, CallParamType::kF32, "cos"},
- BuiltinData{BuiltinType::kCos, CallParamType::kF16, "cos"},
- BuiltinData{BuiltinType::kCosh, CallParamType::kF32, "cosh"},
- BuiltinData{BuiltinType::kCosh, CallParamType::kF16, "cosh"},
- BuiltinData{BuiltinType::kCross, CallParamType::kF32, "cross"},
- BuiltinData{BuiltinType::kCross, CallParamType::kF16, "cross"},
- BuiltinData{BuiltinType::kDistance, CallParamType::kF32, "distance"},
- BuiltinData{BuiltinType::kDistance, CallParamType::kF16, "distance"},
- BuiltinData{BuiltinType::kExp, CallParamType::kF32, "exp"},
- BuiltinData{BuiltinType::kExp, CallParamType::kF16, "exp"},
- BuiltinData{BuiltinType::kExp2, CallParamType::kF32, "exp2"},
- BuiltinData{BuiltinType::kExp2, CallParamType::kF16, "exp2"},
- BuiltinData{BuiltinType::kFaceForward, CallParamType::kF32, "faceforward"},
- BuiltinData{BuiltinType::kFaceForward, CallParamType::kF16, "faceforward"},
- BuiltinData{BuiltinType::kFloor, CallParamType::kF32, "floor"},
- BuiltinData{BuiltinType::kFloor, CallParamType::kF16, "floor"},
- BuiltinData{BuiltinType::kFma, CallParamType::kF32, "mad"},
- BuiltinData{BuiltinType::kFma, CallParamType::kF16, "mad"},
- BuiltinData{BuiltinType::kFract, CallParamType::kF32, "frac"},
- BuiltinData{BuiltinType::kFract, CallParamType::kF16, "frac"},
- BuiltinData{BuiltinType::kInverseSqrt, CallParamType::kF32, "rsqrt"},
- BuiltinData{BuiltinType::kInverseSqrt, CallParamType::kF16, "rsqrt"},
- BuiltinData{BuiltinType::kLdexp, CallParamType::kF32, "ldexp"},
- BuiltinData{BuiltinType::kLdexp, CallParamType::kF16, "ldexp"},
- BuiltinData{BuiltinType::kLength, CallParamType::kF32, "length"},
- BuiltinData{BuiltinType::kLength, CallParamType::kF16, "length"},
- BuiltinData{BuiltinType::kLog, CallParamType::kF32, "log"},
- BuiltinData{BuiltinType::kLog, CallParamType::kF16, "log"},
- BuiltinData{BuiltinType::kLog2, CallParamType::kF32, "log2"},
- BuiltinData{BuiltinType::kLog2, CallParamType::kF16, "log2"},
- BuiltinData{BuiltinType::kMax, CallParamType::kF32, "max"},
- BuiltinData{BuiltinType::kMax, CallParamType::kF16, "max"},
- BuiltinData{BuiltinType::kMin, CallParamType::kF32, "min"},
- BuiltinData{BuiltinType::kMin, CallParamType::kF16, "min"},
- BuiltinData{BuiltinType::kMix, CallParamType::kF32, "lerp"},
- BuiltinData{BuiltinType::kMix, CallParamType::kF16, "lerp"},
- BuiltinData{BuiltinType::kNormalize, CallParamType::kF32, "normalize"},
- BuiltinData{BuiltinType::kNormalize, CallParamType::kF16, "normalize"},
- BuiltinData{BuiltinType::kPow, CallParamType::kF32, "pow"},
- BuiltinData{BuiltinType::kPow, CallParamType::kF16, "pow"},
- BuiltinData{BuiltinType::kReflect, CallParamType::kF32, "reflect"},
- BuiltinData{BuiltinType::kReflect, CallParamType::kF16, "reflect"},
- BuiltinData{BuiltinType::kSin, CallParamType::kF32, "sin"},
- BuiltinData{BuiltinType::kSin, CallParamType::kF16, "sin"},
- BuiltinData{BuiltinType::kSinh, CallParamType::kF32, "sinh"},
- BuiltinData{BuiltinType::kSinh, CallParamType::kF16, "sinh"},
- BuiltinData{BuiltinType::kSmoothstep, CallParamType::kF32, "smoothstep"},
- BuiltinData{BuiltinType::kSmoothstep, CallParamType::kF16, "smoothstep"},
- BuiltinData{BuiltinType::kSqrt, CallParamType::kF32, "sqrt"},
- BuiltinData{BuiltinType::kSqrt, CallParamType::kF16, "sqrt"},
- BuiltinData{BuiltinType::kStep, CallParamType::kF32, "step"},
- BuiltinData{BuiltinType::kStep, CallParamType::kF16, "step"},
- BuiltinData{BuiltinType::kTan, CallParamType::kF32, "tan"},
- BuiltinData{BuiltinType::kTan, CallParamType::kF16, "tan"},
- BuiltinData{BuiltinType::kTanh, CallParamType::kF32, "tanh"},
- BuiltinData{BuiltinType::kTanh, CallParamType::kF16, "tanh"},
- BuiltinData{BuiltinType::kTrunc, CallParamType::kF32, "trunc"},
- BuiltinData{BuiltinType::kTrunc, CallParamType::kF16, "trunc"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kF32, "abs"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kF16, "abs"},
+ BuiltinData{builtin::Function::kAcos, CallParamType::kF32, "acos"},
+ BuiltinData{builtin::Function::kAcos, CallParamType::kF16, "acos"},
+ BuiltinData{builtin::Function::kAsin, CallParamType::kF32, "asin"},
+ BuiltinData{builtin::Function::kAsin, CallParamType::kF16, "asin"},
+ BuiltinData{builtin::Function::kAtan, CallParamType::kF32, "atan"},
+ BuiltinData{builtin::Function::kAtan, CallParamType::kF16, "atan"},
+ BuiltinData{builtin::Function::kAtan2, CallParamType::kF32, "atan2"},
+ BuiltinData{builtin::Function::kAtan2, CallParamType::kF16, "atan2"},
+ BuiltinData{builtin::Function::kCeil, CallParamType::kF32, "ceil"},
+ BuiltinData{builtin::Function::kCeil, CallParamType::kF16, "ceil"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kF32, "clamp"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kF16, "clamp"},
+ BuiltinData{builtin::Function::kCos, CallParamType::kF32, "cos"},
+ BuiltinData{builtin::Function::kCos, CallParamType::kF16, "cos"},
+ BuiltinData{builtin::Function::kCosh, CallParamType::kF32, "cosh"},
+ BuiltinData{builtin::Function::kCosh, CallParamType::kF16, "cosh"},
+ BuiltinData{builtin::Function::kCross, CallParamType::kF32, "cross"},
+ BuiltinData{builtin::Function::kCross, CallParamType::kF16, "cross"},
+ BuiltinData{builtin::Function::kDistance, CallParamType::kF32, "distance"},
+ BuiltinData{builtin::Function::kDistance, CallParamType::kF16, "distance"},
+ BuiltinData{builtin::Function::kExp, CallParamType::kF32, "exp"},
+ BuiltinData{builtin::Function::kExp, CallParamType::kF16, "exp"},
+ BuiltinData{builtin::Function::kExp2, CallParamType::kF32, "exp2"},
+ BuiltinData{builtin::Function::kExp2, CallParamType::kF16, "exp2"},
+ BuiltinData{builtin::Function::kFaceForward, CallParamType::kF32,
+ "faceforward"},
+ BuiltinData{builtin::Function::kFaceForward, CallParamType::kF16,
+ "faceforward"},
+ BuiltinData{builtin::Function::kFloor, CallParamType::kF32, "floor"},
+ BuiltinData{builtin::Function::kFloor, CallParamType::kF16, "floor"},
+ BuiltinData{builtin::Function::kFma, CallParamType::kF32, "mad"},
+ BuiltinData{builtin::Function::kFma, CallParamType::kF16, "mad"},
+ BuiltinData{builtin::Function::kFract, CallParamType::kF32, "frac"},
+ BuiltinData{builtin::Function::kFract, CallParamType::kF16, "frac"},
+ BuiltinData{builtin::Function::kInverseSqrt, CallParamType::kF32, "rsqrt"},
+ BuiltinData{builtin::Function::kInverseSqrt, CallParamType::kF16, "rsqrt"},
+ BuiltinData{builtin::Function::kLdexp, CallParamType::kF32, "ldexp"},
+ BuiltinData{builtin::Function::kLdexp, CallParamType::kF16, "ldexp"},
+ BuiltinData{builtin::Function::kLength, CallParamType::kF32, "length"},
+ BuiltinData{builtin::Function::kLength, CallParamType::kF16, "length"},
+ BuiltinData{builtin::Function::kLog, CallParamType::kF32, "log"},
+ BuiltinData{builtin::Function::kLog, CallParamType::kF16, "log"},
+ BuiltinData{builtin::Function::kLog2, CallParamType::kF32, "log2"},
+ BuiltinData{builtin::Function::kLog2, CallParamType::kF16, "log2"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kF32, "max"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kF16, "max"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kF32, "min"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kF16, "min"},
+ BuiltinData{builtin::Function::kMix, CallParamType::kF32, "lerp"},
+ BuiltinData{builtin::Function::kMix, CallParamType::kF16, "lerp"},
+ BuiltinData{builtin::Function::kNormalize, CallParamType::kF32, "normalize"},
+ BuiltinData{builtin::Function::kNormalize, CallParamType::kF16, "normalize"},
+ BuiltinData{builtin::Function::kPow, CallParamType::kF32, "pow"},
+ BuiltinData{builtin::Function::kPow, CallParamType::kF16, "pow"},
+ BuiltinData{builtin::Function::kReflect, CallParamType::kF32, "reflect"},
+ BuiltinData{builtin::Function::kReflect, CallParamType::kF16, "reflect"},
+ BuiltinData{builtin::Function::kSin, CallParamType::kF32, "sin"},
+ BuiltinData{builtin::Function::kSin, CallParamType::kF16, "sin"},
+ BuiltinData{builtin::Function::kSinh, CallParamType::kF32, "sinh"},
+ BuiltinData{builtin::Function::kSinh, CallParamType::kF16, "sinh"},
+ BuiltinData{builtin::Function::kSmoothstep, CallParamType::kF32, "smoothstep"},
+ BuiltinData{builtin::Function::kSmoothstep, CallParamType::kF16, "smoothstep"},
+ BuiltinData{builtin::Function::kSqrt, CallParamType::kF32, "sqrt"},
+ BuiltinData{builtin::Function::kSqrt, CallParamType::kF16, "sqrt"},
+ BuiltinData{builtin::Function::kStep, CallParamType::kF32, "step"},
+ BuiltinData{builtin::Function::kStep, CallParamType::kF16, "step"},
+ BuiltinData{builtin::Function::kTan, CallParamType::kF32, "tan"},
+ BuiltinData{builtin::Function::kTan, CallParamType::kF16, "tan"},
+ BuiltinData{builtin::Function::kTanh, CallParamType::kF32, "tanh"},
+ BuiltinData{builtin::Function::kTanh, CallParamType::kF16, "tanh"},
+ BuiltinData{builtin::Function::kTrunc, CallParamType::kF32, "trunc"},
+ BuiltinData{builtin::Function::kTrunc, CallParamType::kF16, "trunc"},
/* Integer built-in */
- BuiltinData{BuiltinType::kAbs, CallParamType::kU32, "abs"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kU32, "clamp"},
- BuiltinData{BuiltinType::kCountOneBits, CallParamType::kU32, "countbits"},
- BuiltinData{BuiltinType::kMax, CallParamType::kU32, "max"},
- BuiltinData{BuiltinType::kMin, CallParamType::kU32, "min"},
- BuiltinData{BuiltinType::kReverseBits, CallParamType::kU32, "reversebits"},
- BuiltinData{BuiltinType::kRound, CallParamType::kU32, "round"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kU32, "abs"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kU32, "clamp"},
+ BuiltinData{builtin::Function::kCountOneBits, CallParamType::kU32, "countbits"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kU32, "max"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kU32, "min"},
+ BuiltinData{builtin::Function::kReverseBits, CallParamType::kU32,
+ "reversebits"},
+ BuiltinData{builtin::Function::kRound, CallParamType::kU32, "round"},
/* Matrix built-in */
- BuiltinData{BuiltinType::kDeterminant, CallParamType::kF32, "determinant"},
- BuiltinData{BuiltinType::kDeterminant, CallParamType::kF16, "determinant"},
- BuiltinData{BuiltinType::kTranspose, CallParamType::kF32, "transpose"},
- BuiltinData{BuiltinType::kTranspose, CallParamType::kF16, "transpose"},
+ BuiltinData{builtin::Function::kDeterminant, CallParamType::kF32,
+ "determinant"},
+ BuiltinData{builtin::Function::kDeterminant, CallParamType::kF16,
+ "determinant"},
+ BuiltinData{builtin::Function::kTranspose, CallParamType::kF32, "transpose"},
+ BuiltinData{builtin::Function::kTranspose, CallParamType::kF16, "transpose"},
/* Vector built-in */
- BuiltinData{BuiltinType::kDot, CallParamType::kF32, "dot"},
- BuiltinData{BuiltinType::kDot, CallParamType::kF16, "dot"},
+ BuiltinData{builtin::Function::kDot, CallParamType::kF32, "dot"},
+ BuiltinData{builtin::Function::kDot, CallParamType::kF16, "dot"},
/* Derivate built-in */
- BuiltinData{BuiltinType::kDpdx, CallParamType::kF32, "ddx"},
- BuiltinData{BuiltinType::kDpdxCoarse, CallParamType::kF32, "ddx_coarse"},
- BuiltinData{BuiltinType::kDpdxFine, CallParamType::kF32, "ddx_fine"},
- BuiltinData{BuiltinType::kDpdy, CallParamType::kF32, "ddy"},
- BuiltinData{BuiltinType::kDpdyCoarse, CallParamType::kF32, "ddy_coarse"},
- BuiltinData{BuiltinType::kDpdyFine, CallParamType::kF32, "ddy_fine"},
- BuiltinData{BuiltinType::kFwidth, CallParamType::kF32, "fwidth"},
- BuiltinData{BuiltinType::kFwidthCoarse, CallParamType::kF32, "fwidth"},
- BuiltinData{BuiltinType::kFwidthFine, CallParamType::kF32, "fwidth"}));
+ BuiltinData{builtin::Function::kDpdx, CallParamType::kF32, "ddx"},
+ BuiltinData{builtin::Function::kDpdxCoarse, CallParamType::kF32, "ddx_coarse"},
+ BuiltinData{builtin::Function::kDpdxFine, CallParamType::kF32, "ddx_fine"},
+ BuiltinData{builtin::Function::kDpdy, CallParamType::kF32, "ddy"},
+ BuiltinData{builtin::Function::kDpdyCoarse, CallParamType::kF32, "ddy_coarse"},
+ BuiltinData{builtin::Function::kDpdyFine, CallParamType::kF32, "ddy_fine"},
+ BuiltinData{builtin::Function::kFwidth, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kFwidthCoarse, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kFwidthFine, CallParamType::kF32, "fwidth"}));
TEST_F(HlslGeneratorImplTest_Builtin, Builtin_Call) {
auto* call = Call("dot", "param1", "param2");
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
index 6751790..4d7165b 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
@@ -170,6 +170,8 @@
return R"(tint_symbol.GatherCmp(tint_symbol_1, float4(1.0f, 2.0f, 3.0f, float(4u)), 5.0f))";
case ValidTextureOverload::kNumLayers2dArray:
case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
case ValidTextureOverload::kNumLayersStorageWO2dArray:
return {
R"(int3 tint_tmp;
diff --git a/src/tint/writer/msl/generator.h b/src/tint/writer/msl/generator.h
index 1add259..b4e11d9 100644
--- a/src/tint/writer/msl/generator.h
+++ b/src/tint/writer/msl/generator.h
@@ -23,6 +23,7 @@
#include "src/tint/reflection.h"
#include "src/tint/writer/array_length_from_uniform_options.h"
+#include "src/tint/writer/external_texture_options.h"
#include "src/tint/writer/text.h"
// Forward declarations
@@ -62,8 +63,8 @@
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
- /// Set to 'true' to generates binding mappings for external textures
- bool generate_external_texture_bindings = false;
+ /// Options used in the binding mappings for external textures
+ ExternalTextureOptions external_texture_options = {};
/// Options used to specify a mapping of binding points to indices into a UBO
/// from which to load buffer sizes.
@@ -75,7 +76,7 @@
fixed_sample_mask,
emit_vertex_point_size,
disable_workgroup_init,
- generate_external_texture_bindings,
+ external_texture_options,
array_length_from_uniform);
};
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 5c9e11b..268736f 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -40,6 +40,7 @@
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
#include "src/tint/transform/array_length_from_uniform.h"
#include "src/tint/transform/builtin_polyfill.h"
#include "src/tint/transform/canonicalize_entry_point_io.h"
@@ -48,6 +49,7 @@
#include "src/tint/transform/expand_compound_assignment.h"
#include "src/tint/transform/manager.h"
#include "src/tint/transform/module_scope_var_to_entry_point_param.h"
+#include "src/tint/transform/multiplanar_external_texture.h"
#include "src/tint/transform/packed_vec3.h"
#include "src/tint/transform/preserve_padding.h"
#include "src/tint/transform/promote_initializers_to_let.h"
@@ -82,7 +84,6 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/check_supported_extensions.h"
#include "src/tint/writer/float_to_string.h"
-#include "src/tint/writer/generate_external_texture_bindings.h"
namespace tint::writer::msl {
namespace {
@@ -218,6 +219,7 @@
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
polyfills.bitshift_modulo = true; // crbug.com/tint/1543
polyfills.clamp_int = true;
+ polyfills.conv_f32_to_iu32 = true;
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
polyfills.first_leading_bit = true;
polyfills.first_trailing_bit = true;
@@ -230,10 +232,10 @@
manager.Add<transform::BuiltinPolyfill>();
}
- if (options.generate_external_texture_bindings) {
+ if (!options.external_texture_options.bindings_map.empty()) {
// Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
- auto new_bindings_map = GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
+ options.external_texture_options.bindings_map);
manager.Add<transform::MultiplanarExternalTexture>();
}
@@ -699,20 +701,20 @@
auto name = generate_builtin_name(builtin);
switch (builtin->Type()) {
- case sem::BuiltinType::kDot:
+ case builtin::Function::kDot:
return EmitDotCall(out, expr, builtin);
- case sem::BuiltinType::kModf:
+ case builtin::Function::kModf:
return EmitModfCall(out, expr, builtin);
- case sem::BuiltinType::kFrexp:
+ case builtin::Function::kFrexp:
return EmitFrexpCall(out, expr, builtin);
- case sem::BuiltinType::kDegrees:
+ case builtin::Function::kDegrees:
return EmitDegreesCall(out, expr, builtin);
- case sem::BuiltinType::kRadians:
+ case builtin::Function::kRadians:
return EmitRadiansCall(out, expr, builtin);
- case sem::BuiltinType::kPack2X16Float:
- case sem::BuiltinType::kUnpack2X16Float: {
- if (builtin->Type() == sem::BuiltinType::kPack2X16Float) {
+ case builtin::Function::kPack2X16Float:
+ case builtin::Function::kUnpack2X16Float: {
+ if (builtin->Type() == builtin::Function::kPack2X16Float) {
out << "as_type<uint>(half2(";
} else {
out << "float2(as_type<half2>(";
@@ -723,7 +725,7 @@
out << "))";
return true;
}
- case sem::BuiltinType::kQuantizeToF16: {
+ case builtin::Function::kQuantizeToF16: {
std::string width = "";
if (auto* vec = builtin->ReturnType()->As<type::Vector>()) {
width = std::to_string(vec->Width());
@@ -737,16 +739,16 @@
}
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction.
- case sem::BuiltinType::kStorageBarrier: {
+ case builtin::Function::kStorageBarrier: {
out << "threadgroup_barrier(mem_flags::mem_device)";
return true;
}
- case sem::BuiltinType::kWorkgroupBarrier: {
+ case builtin::Function::kWorkgroupBarrier: {
out << "threadgroup_barrier(mem_flags::mem_threadgroup)";
return true;
}
- case sem::BuiltinType::kLength: {
+ case builtin::Function::kLength: {
auto* sem = builder_.Sem().GetVal(expr->args[0]);
if (sem->Type()->UnwrapRef()->is_scalar()) {
// Emulate scalar overload using fabs(x).
@@ -755,7 +757,7 @@
break;
}
- case sem::BuiltinType::kDistance: {
+ case builtin::Function::kDistance: {
auto* sem = builder_.Sem().GetVal(expr->args[0]);
if (sem->Type()->UnwrapRef()->is_scalar()) {
// Emulate scalar overload using fabs(x - y);
@@ -896,37 +898,37 @@
};
switch (builtin->Type()) {
- case sem::BuiltinType::kAtomicLoad:
+ case builtin::Function::kAtomicLoad:
return call("atomic_load_explicit", true);
- case sem::BuiltinType::kAtomicStore:
+ case builtin::Function::kAtomicStore:
return call("atomic_store_explicit", true);
- case sem::BuiltinType::kAtomicAdd:
+ case builtin::Function::kAtomicAdd:
return call("atomic_fetch_add_explicit", true);
- case sem::BuiltinType::kAtomicSub:
+ case builtin::Function::kAtomicSub:
return call("atomic_fetch_sub_explicit", true);
- case sem::BuiltinType::kAtomicMax:
+ case builtin::Function::kAtomicMax:
return call("atomic_fetch_max_explicit", true);
- case sem::BuiltinType::kAtomicMin:
+ case builtin::Function::kAtomicMin:
return call("atomic_fetch_min_explicit", true);
- case sem::BuiltinType::kAtomicAnd:
+ case builtin::Function::kAtomicAnd:
return call("atomic_fetch_and_explicit", true);
- case sem::BuiltinType::kAtomicOr:
+ case builtin::Function::kAtomicOr:
return call("atomic_fetch_or_explicit", true);
- case sem::BuiltinType::kAtomicXor:
+ case builtin::Function::kAtomicXor:
return call("atomic_fetch_xor_explicit", true);
- case sem::BuiltinType::kAtomicExchange:
+ case builtin::Function::kAtomicExchange:
return call("atomic_exchange_explicit", true);
- case sem::BuiltinType::kAtomicCompareExchangeWeak: {
+ case builtin::Function::kAtomicCompareExchangeWeak: {
auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<type::Pointer>();
auto sc = ptr_ty->AddressSpace();
auto* str = builtin->ReturnType()->As<sem::Struct>();
@@ -1041,7 +1043,7 @@
bool level_is_constant_zero = texture_type->dim() == type::TextureDimension::k1d;
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureDimensions: {
+ case builtin::Function::kTextureDimensions: {
std::vector<const char*> dims;
switch (texture_type->dim()) {
case type::TextureDimension::kNone:
@@ -1094,21 +1096,21 @@
}
return true;
}
- case sem::BuiltinType::kTextureNumLayers: {
+ case builtin::Function::kTextureNumLayers: {
if (!texture_expr()) {
return false;
}
out << ".get_array_size()";
return true;
}
- case sem::BuiltinType::kTextureNumLevels: {
+ case builtin::Function::kTextureNumLevels: {
if (!texture_expr()) {
return false;
}
out << ".get_num_mip_levels()";
return true;
}
- case sem::BuiltinType::kTextureNumSamples: {
+ case builtin::Function::kTextureNumSamples: {
if (!texture_expr()) {
return false;
}
@@ -1126,27 +1128,27 @@
bool lod_param_is_named = true;
switch (builtin->Type()) {
- case sem::BuiltinType::kTextureSample:
- case sem::BuiltinType::kTextureSampleBias:
- case sem::BuiltinType::kTextureSampleLevel:
- case sem::BuiltinType::kTextureSampleGrad:
+ case builtin::Function::kTextureSample:
+ case builtin::Function::kTextureSampleBias:
+ case builtin::Function::kTextureSampleLevel:
+ case builtin::Function::kTextureSampleGrad:
out << ".sample(";
break;
- case sem::BuiltinType::kTextureSampleCompare:
- case sem::BuiltinType::kTextureSampleCompareLevel:
+ case builtin::Function::kTextureSampleCompare:
+ case builtin::Function::kTextureSampleCompareLevel:
out << ".sample_compare(";
break;
- case sem::BuiltinType::kTextureGather:
+ case builtin::Function::kTextureGather:
out << ".gather(";
break;
- case sem::BuiltinType::kTextureGatherCompare:
+ case builtin::Function::kTextureGatherCompare:
out << ".gather_compare(";
break;
- case sem::BuiltinType::kTextureLoad:
+ case builtin::Function::kTextureLoad:
out << ".read(";
lod_param_is_named = false;
break;
- case sem::BuiltinType::kTextureStore:
+ case builtin::Function::kTextureStore:
out << ".write(";
break;
default:
@@ -1223,7 +1225,7 @@
out << ")";
}
}
- if (builtin->Type() == sem::BuiltinType::kTextureSampleCompareLevel) {
+ if (builtin->Type() == builtin::Function::kTextureSampleCompareLevel) {
maybe_write_comma();
out << "level(0)";
}
@@ -1430,143 +1432,143 @@
std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
std::string out = "";
switch (builtin->Type()) {
- case sem::BuiltinType::kAcos:
- case sem::BuiltinType::kAcosh:
- case sem::BuiltinType::kAll:
- case sem::BuiltinType::kAny:
- case sem::BuiltinType::kAsin:
- case sem::BuiltinType::kAsinh:
- case sem::BuiltinType::kAtanh:
- case sem::BuiltinType::kAtan:
- case sem::BuiltinType::kAtan2:
- case sem::BuiltinType::kCeil:
- case sem::BuiltinType::kCos:
- case sem::BuiltinType::kCosh:
- case sem::BuiltinType::kCross:
- case sem::BuiltinType::kDeterminant:
- case sem::BuiltinType::kDistance:
- case sem::BuiltinType::kDot:
- case sem::BuiltinType::kExp:
- case sem::BuiltinType::kExp2:
- case sem::BuiltinType::kFloor:
- case sem::BuiltinType::kFma:
- case sem::BuiltinType::kFract:
- case sem::BuiltinType::kFrexp:
- case sem::BuiltinType::kLength:
- case sem::BuiltinType::kLdexp:
- case sem::BuiltinType::kLog:
- case sem::BuiltinType::kLog2:
- case sem::BuiltinType::kMix:
- case sem::BuiltinType::kModf:
- case sem::BuiltinType::kNormalize:
- case sem::BuiltinType::kPow:
- case sem::BuiltinType::kReflect:
- case sem::BuiltinType::kRefract:
- case sem::BuiltinType::kSaturate:
- case sem::BuiltinType::kSelect:
- case sem::BuiltinType::kSin:
- case sem::BuiltinType::kSinh:
- case sem::BuiltinType::kSqrt:
- case sem::BuiltinType::kStep:
- case sem::BuiltinType::kTan:
- case sem::BuiltinType::kTanh:
- case sem::BuiltinType::kTranspose:
- case sem::BuiltinType::kTrunc:
- case sem::BuiltinType::kSign:
- case sem::BuiltinType::kClamp:
+ case builtin::Function::kAcos:
+ case builtin::Function::kAcosh:
+ case builtin::Function::kAll:
+ case builtin::Function::kAny:
+ case builtin::Function::kAsin:
+ case builtin::Function::kAsinh:
+ case builtin::Function::kAtanh:
+ case builtin::Function::kAtan:
+ case builtin::Function::kAtan2:
+ case builtin::Function::kCeil:
+ case builtin::Function::kCos:
+ case builtin::Function::kCosh:
+ case builtin::Function::kCross:
+ case builtin::Function::kDeterminant:
+ case builtin::Function::kDistance:
+ case builtin::Function::kDot:
+ case builtin::Function::kExp:
+ case builtin::Function::kExp2:
+ case builtin::Function::kFloor:
+ case builtin::Function::kFma:
+ case builtin::Function::kFract:
+ case builtin::Function::kFrexp:
+ case builtin::Function::kLength:
+ case builtin::Function::kLdexp:
+ case builtin::Function::kLog:
+ case builtin::Function::kLog2:
+ case builtin::Function::kMix:
+ case builtin::Function::kModf:
+ case builtin::Function::kNormalize:
+ case builtin::Function::kPow:
+ case builtin::Function::kReflect:
+ case builtin::Function::kRefract:
+ case builtin::Function::kSaturate:
+ case builtin::Function::kSelect:
+ case builtin::Function::kSin:
+ case builtin::Function::kSinh:
+ case builtin::Function::kSqrt:
+ case builtin::Function::kStep:
+ case builtin::Function::kTan:
+ case builtin::Function::kTanh:
+ case builtin::Function::kTranspose:
+ case builtin::Function::kTrunc:
+ case builtin::Function::kSign:
+ case builtin::Function::kClamp:
out += builtin->str();
break;
- case sem::BuiltinType::kAbs:
+ case builtin::Function::kAbs:
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
out += "fabs";
} else {
out += "abs";
}
break;
- case sem::BuiltinType::kCountLeadingZeros:
+ case builtin::Function::kCountLeadingZeros:
out += "clz";
break;
- case sem::BuiltinType::kCountOneBits:
+ case builtin::Function::kCountOneBits:
out += "popcount";
break;
- case sem::BuiltinType::kCountTrailingZeros:
+ case builtin::Function::kCountTrailingZeros:
out += "ctz";
break;
- case sem::BuiltinType::kDpdx:
- case sem::BuiltinType::kDpdxCoarse:
- case sem::BuiltinType::kDpdxFine:
+ case builtin::Function::kDpdx:
+ case builtin::Function::kDpdxCoarse:
+ case builtin::Function::kDpdxFine:
out += "dfdx";
break;
- case sem::BuiltinType::kDpdy:
- case sem::BuiltinType::kDpdyCoarse:
- case sem::BuiltinType::kDpdyFine:
+ case builtin::Function::kDpdy:
+ case builtin::Function::kDpdyCoarse:
+ case builtin::Function::kDpdyFine:
out += "dfdy";
break;
- case sem::BuiltinType::kExtractBits:
+ case builtin::Function::kExtractBits:
out += "extract_bits";
break;
- case sem::BuiltinType::kInsertBits:
+ case builtin::Function::kInsertBits:
out += "insert_bits";
break;
- case sem::BuiltinType::kFwidth:
- case sem::BuiltinType::kFwidthCoarse:
- case sem::BuiltinType::kFwidthFine:
+ case builtin::Function::kFwidth:
+ case builtin::Function::kFwidthCoarse:
+ case builtin::Function::kFwidthFine:
out += "fwidth";
break;
- case sem::BuiltinType::kMax:
+ case builtin::Function::kMax:
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
out += "fmax";
} else {
out += "max";
}
break;
- case sem::BuiltinType::kMin:
+ case builtin::Function::kMin:
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
out += "fmin";
} else {
out += "min";
}
break;
- case sem::BuiltinType::kFaceForward:
+ case builtin::Function::kFaceForward:
out += "faceforward";
break;
- case sem::BuiltinType::kPack4X8Snorm:
+ case builtin::Function::kPack4X8Snorm:
out += "pack_float_to_snorm4x8";
break;
- case sem::BuiltinType::kPack4X8Unorm:
+ case builtin::Function::kPack4X8Unorm:
out += "pack_float_to_unorm4x8";
break;
- case sem::BuiltinType::kPack2X16Snorm:
+ case builtin::Function::kPack2X16Snorm:
out += "pack_float_to_snorm2x16";
break;
- case sem::BuiltinType::kPack2X16Unorm:
+ case builtin::Function::kPack2X16Unorm:
out += "pack_float_to_unorm2x16";
break;
- case sem::BuiltinType::kReverseBits:
+ case builtin::Function::kReverseBits:
out += "reverse_bits";
break;
- case sem::BuiltinType::kRound:
+ case builtin::Function::kRound:
out += "rint";
break;
- case sem::BuiltinType::kSmoothstep:
+ case builtin::Function::kSmoothstep:
out += "smoothstep";
break;
- case sem::BuiltinType::kInverseSqrt:
+ case builtin::Function::kInverseSqrt:
out += "rsqrt";
break;
- case sem::BuiltinType::kUnpack4X8Snorm:
+ case builtin::Function::kUnpack4X8Snorm:
out += "unpack_snorm4x8_to_float";
break;
- case sem::BuiltinType::kUnpack4X8Unorm:
+ case builtin::Function::kUnpack4X8Unorm:
out += "unpack_unorm4x8_to_float";
break;
- case sem::BuiltinType::kUnpack2X16Snorm:
+ case builtin::Function::kUnpack2X16Snorm:
out += "unpack_snorm2x16_to_float";
break;
- case sem::BuiltinType::kUnpack2X16Unorm:
+ case builtin::Function::kUnpack2X16Unorm:
out += "unpack_unorm2x16_to_float";
break;
- case sem::BuiltinType::kArrayLength:
+ case builtin::Function::kArrayLength:
diagnostics_.add_error(
diag::System::Writer,
"Unable to translate builtin: " + std::string(builtin->str()) +
@@ -1707,8 +1709,8 @@
ScopedParen sp(out);
- if (constant->AllEqual()) {
- if (!EmitConstant(out, constant->Index(0))) {
+ if (auto* splat = constant->As<constant::Splat>()) {
+ if (!EmitConstant(out, splat->el)) {
return false;
}
return true;
@@ -3258,7 +3260,7 @@
TextBuffer b;
TINT_DEFER(helpers_.Append(b));
- auto fn_name = UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
+ auto fn_name = UniqueIdentifier(std::string("tint_") + builtin::str(builtin->Type()));
std::vector<std::string> parameter_names;
{
auto decl = line(&b);
diff --git a/src/tint/writer/msl/generator_impl_builtin_test.cc b/src/tint/writer/msl/generator_impl_builtin_test.cc
index 08a2d25..6c70abe 100644
--- a/src/tint/writer/msl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_test.cc
@@ -22,8 +22,6 @@
namespace tint::writer::msl {
namespace {
-using BuiltinType = sem::BuiltinType;
-
using MslGeneratorImplTest = TestHelper;
enum class CallParamType {
@@ -34,7 +32,7 @@
};
struct BuiltinData {
- BuiltinType builtin;
+ builtin::Function builtin;
CallParamType type;
const char* msl_name;
};
@@ -58,88 +56,88 @@
return out;
}
-const ast::CallExpression* GenerateCall(BuiltinType builtin,
+const ast::CallExpression* GenerateCall(builtin::Function builtin,
CallParamType type,
ProgramBuilder* builder) {
std::string name;
utils::StringStream str;
str << name << builtin;
switch (builtin) {
- case BuiltinType::kAcos:
- case BuiltinType::kAsin:
- case BuiltinType::kAtan:
- case BuiltinType::kCeil:
- case BuiltinType::kCos:
- case BuiltinType::kCosh:
- case BuiltinType::kDpdx:
- case BuiltinType::kDpdxCoarse:
- case BuiltinType::kDpdxFine:
- case BuiltinType::kDpdy:
- case BuiltinType::kDpdyCoarse:
- case BuiltinType::kDpdyFine:
- case BuiltinType::kExp:
- case BuiltinType::kExp2:
- case BuiltinType::kFloor:
- case BuiltinType::kFract:
- case BuiltinType::kFwidth:
- case BuiltinType::kFwidthCoarse:
- case BuiltinType::kFwidthFine:
- case BuiltinType::kInverseSqrt:
- case BuiltinType::kLength:
- case BuiltinType::kLog:
- case BuiltinType::kLog2:
- case BuiltinType::kNormalize:
- case BuiltinType::kRound:
- case BuiltinType::kSin:
- case BuiltinType::kSinh:
- case BuiltinType::kSqrt:
- case BuiltinType::kTan:
- case BuiltinType::kTanh:
- case BuiltinType::kTrunc:
- case BuiltinType::kSign:
+ case builtin::Function::kAcos:
+ case builtin::Function::kAsin:
+ case builtin::Function::kAtan:
+ case builtin::Function::kCeil:
+ case builtin::Function::kCos:
+ case builtin::Function::kCosh:
+ case builtin::Function::kDpdx:
+ case builtin::Function::kDpdxCoarse:
+ case builtin::Function::kDpdxFine:
+ case builtin::Function::kDpdy:
+ case builtin::Function::kDpdyCoarse:
+ case builtin::Function::kDpdyFine:
+ case builtin::Function::kExp:
+ case builtin::Function::kExp2:
+ case builtin::Function::kFloor:
+ case builtin::Function::kFract:
+ case builtin::Function::kFwidth:
+ case builtin::Function::kFwidthCoarse:
+ case builtin::Function::kFwidthFine:
+ case builtin::Function::kInverseSqrt:
+ case builtin::Function::kLength:
+ case builtin::Function::kLog:
+ case builtin::Function::kLog2:
+ case builtin::Function::kNormalize:
+ case builtin::Function::kRound:
+ case builtin::Function::kSin:
+ case builtin::Function::kSinh:
+ case builtin::Function::kSqrt:
+ case builtin::Function::kTan:
+ case builtin::Function::kTanh:
+ case builtin::Function::kTrunc:
+ case builtin::Function::kSign:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2");
} else {
return builder->Call(str.str(), "f2");
}
- case BuiltinType::kLdexp:
+ case builtin::Function::kLdexp:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "i2");
} else {
return builder->Call(str.str(), "f2", "i2");
}
- case BuiltinType::kAtan2:
- case BuiltinType::kDot:
- case BuiltinType::kDistance:
- case BuiltinType::kPow:
- case BuiltinType::kReflect:
- case BuiltinType::kStep:
+ case builtin::Function::kAtan2:
+ case builtin::Function::kDot:
+ case builtin::Function::kDistance:
+ case builtin::Function::kPow:
+ case builtin::Function::kReflect:
+ case builtin::Function::kStep:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2");
} else {
return builder->Call(str.str(), "f2", "f2");
}
- case BuiltinType::kStorageBarrier:
+ case builtin::Function::kStorageBarrier:
return builder->Call(str.str());
- case BuiltinType::kCross:
+ case builtin::Function::kCross:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h3", "h3");
} else {
return builder->Call(str.str(), "f3", "f3");
}
- case BuiltinType::kFma:
- case BuiltinType::kMix:
- case BuiltinType::kFaceForward:
- case BuiltinType::kSmoothstep:
+ case builtin::Function::kFma:
+ case builtin::Function::kMix:
+ case builtin::Function::kFaceForward:
+ case builtin::Function::kSmoothstep:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2", "h2");
} else {
return builder->Call(str.str(), "f2", "f2", "f2");
}
- case BuiltinType::kAll:
- case BuiltinType::kAny:
+ case builtin::Function::kAll:
+ case builtin::Function::kAny:
return builder->Call(str.str(), "b2");
- case BuiltinType::kAbs:
+ case builtin::Function::kAbs:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2");
} else if (type == CallParamType::kF16) {
@@ -147,17 +145,17 @@
} else {
return builder->Call(str.str(), "u2");
}
- case BuiltinType::kCountLeadingZeros:
- case BuiltinType::kCountOneBits:
- case BuiltinType::kCountTrailingZeros:
- case BuiltinType::kReverseBits:
+ case builtin::Function::kCountLeadingZeros:
+ case builtin::Function::kCountOneBits:
+ case builtin::Function::kCountTrailingZeros:
+ case builtin::Function::kReverseBits:
return builder->Call(str.str(), "u2");
- case BuiltinType::kExtractBits:
+ case builtin::Function::kExtractBits:
return builder->Call(str.str(), "u2", "u1", "u1");
- case BuiltinType::kInsertBits:
+ case builtin::Function::kInsertBits:
return builder->Call(str.str(), "u2", "u2", "u1", "u1");
- case BuiltinType::kMax:
- case BuiltinType::kMin:
+ case builtin::Function::kMax:
+ case builtin::Function::kMin:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2", "f2");
} else if (type == CallParamType::kF16) {
@@ -165,7 +163,7 @@
} else {
return builder->Call(str.str(), "u2", "u2");
}
- case BuiltinType::kClamp:
+ case builtin::Function::kClamp:
if (type == CallParamType::kF32) {
return builder->Call(str.str(), "f2", "f2", "f2");
} else if (type == CallParamType::kF16) {
@@ -173,32 +171,32 @@
} else {
return builder->Call(str.str(), "u2", "u2", "u2");
}
- case BuiltinType::kSelect:
+ case builtin::Function::kSelect:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "h2", "h2", "b2");
} else {
return builder->Call(str.str(), "f2", "f2", "b2");
}
- case BuiltinType::kDeterminant:
+ case builtin::Function::kDeterminant:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "hm2x2");
} else {
return builder->Call(str.str(), "m2x2");
}
- case BuiltinType::kPack2X16Snorm:
- case BuiltinType::kPack2X16Unorm:
+ case builtin::Function::kPack2X16Snorm:
+ case builtin::Function::kPack2X16Unorm:
return builder->Call(str.str(), "f2");
- case BuiltinType::kPack4X8Snorm:
- case BuiltinType::kPack4X8Unorm:
+ case builtin::Function::kPack4X8Snorm:
+ case builtin::Function::kPack4X8Unorm:
return builder->Call(str.str(), "f4");
- case BuiltinType::kUnpack4X8Snorm:
- case BuiltinType::kUnpack4X8Unorm:
- case BuiltinType::kUnpack2X16Snorm:
- case BuiltinType::kUnpack2X16Unorm:
+ case builtin::Function::kUnpack4X8Snorm:
+ case builtin::Function::kUnpack4X8Unorm:
+ case builtin::Function::kUnpack2X16Snorm:
+ case builtin::Function::kUnpack2X16Unorm:
return builder->Call(str.str(), "u1");
- case BuiltinType::kWorkgroupBarrier:
+ case builtin::Function::kWorkgroupBarrier:
return builder->Call(str.str());
- case BuiltinType::kTranspose:
+ case builtin::Function::kTranspose:
if (type == CallParamType::kF16) {
return builder->Call(str.str(), "hm3x2");
} else {
@@ -254,120 +252,126 @@
MslBuiltinTest,
testing::Values(
/* Logical built-in */
- BuiltinData{BuiltinType::kAll, CallParamType::kBool, "all"},
- BuiltinData{BuiltinType::kAny, CallParamType::kBool, "any"},
- BuiltinData{BuiltinType::kSelect, CallParamType::kF32, "select"},
+ BuiltinData{builtin::Function::kAll, CallParamType::kBool, "all"},
+ BuiltinData{builtin::Function::kAny, CallParamType::kBool, "any"},
+ BuiltinData{builtin::Function::kSelect, CallParamType::kF32, "select"},
/* Float built-in */
- BuiltinData{BuiltinType::kAbs, CallParamType::kF32, "fabs"},
- BuiltinData{BuiltinType::kAbs, CallParamType::kF16, "fabs"},
- BuiltinData{BuiltinType::kAcos, CallParamType::kF32, "acos"},
- BuiltinData{BuiltinType::kAcos, CallParamType::kF16, "acos"},
- BuiltinData{BuiltinType::kAsin, CallParamType::kF32, "asin"},
- BuiltinData{BuiltinType::kAsin, CallParamType::kF16, "asin"},
- BuiltinData{BuiltinType::kAtan, CallParamType::kF32, "atan"},
- BuiltinData{BuiltinType::kAtan, CallParamType::kF16, "atan"},
- BuiltinData{BuiltinType::kAtan2, CallParamType::kF32, "atan2"},
- BuiltinData{BuiltinType::kAtan2, CallParamType::kF16, "atan2"},
- BuiltinData{BuiltinType::kCeil, CallParamType::kF32, "ceil"},
- BuiltinData{BuiltinType::kCeil, CallParamType::kF16, "ceil"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kF32, "clamp"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kF16, "clamp"},
- BuiltinData{BuiltinType::kCos, CallParamType::kF32, "cos"},
- BuiltinData{BuiltinType::kCos, CallParamType::kF16, "cos"},
- BuiltinData{BuiltinType::kCosh, CallParamType::kF32, "cosh"},
- BuiltinData{BuiltinType::kCosh, CallParamType::kF16, "cosh"},
- BuiltinData{BuiltinType::kCross, CallParamType::kF32, "cross"},
- BuiltinData{BuiltinType::kCross, CallParamType::kF16, "cross"},
- BuiltinData{BuiltinType::kDistance, CallParamType::kF32, "distance"},
- BuiltinData{BuiltinType::kDistance, CallParamType::kF16, "distance"},
- BuiltinData{BuiltinType::kExp, CallParamType::kF32, "exp"},
- BuiltinData{BuiltinType::kExp, CallParamType::kF16, "exp"},
- BuiltinData{BuiltinType::kExp2, CallParamType::kF32, "exp2"},
- BuiltinData{BuiltinType::kExp2, CallParamType::kF16, "exp2"},
- BuiltinData{BuiltinType::kFaceForward, CallParamType::kF32, "faceforward"},
- BuiltinData{BuiltinType::kFaceForward, CallParamType::kF16, "faceforward"},
- BuiltinData{BuiltinType::kFloor, CallParamType::kF32, "floor"},
- BuiltinData{BuiltinType::kFloor, CallParamType::kF16, "floor"},
- BuiltinData{BuiltinType::kFma, CallParamType::kF32, "fma"},
- BuiltinData{BuiltinType::kFma, CallParamType::kF16, "fma"},
- BuiltinData{BuiltinType::kFract, CallParamType::kF32, "fract"},
- BuiltinData{BuiltinType::kFract, CallParamType::kF16, "fract"},
- BuiltinData{BuiltinType::kInverseSqrt, CallParamType::kF32, "rsqrt"},
- BuiltinData{BuiltinType::kInverseSqrt, CallParamType::kF16, "rsqrt"},
- BuiltinData{BuiltinType::kLdexp, CallParamType::kF32, "ldexp"},
- BuiltinData{BuiltinType::kLdexp, CallParamType::kF16, "ldexp"},
- BuiltinData{BuiltinType::kLength, CallParamType::kF32, "length"},
- BuiltinData{BuiltinType::kLength, CallParamType::kF16, "length"},
- BuiltinData{BuiltinType::kLog, CallParamType::kF32, "log"},
- BuiltinData{BuiltinType::kLog, CallParamType::kF16, "log"},
- BuiltinData{BuiltinType::kLog2, CallParamType::kF32, "log2"},
- BuiltinData{BuiltinType::kLog2, CallParamType::kF16, "log2"},
- BuiltinData{BuiltinType::kMax, CallParamType::kF32, "fmax"},
- BuiltinData{BuiltinType::kMax, CallParamType::kF16, "fmax"},
- BuiltinData{BuiltinType::kMin, CallParamType::kF32, "fmin"},
- BuiltinData{BuiltinType::kMin, CallParamType::kF16, "fmin"},
- BuiltinData{BuiltinType::kNormalize, CallParamType::kF32, "normalize"},
- BuiltinData{BuiltinType::kNormalize, CallParamType::kF16, "normalize"},
- BuiltinData{BuiltinType::kPow, CallParamType::kF32, "pow"},
- BuiltinData{BuiltinType::kPow, CallParamType::kF16, "pow"},
- BuiltinData{BuiltinType::kReflect, CallParamType::kF32, "reflect"},
- BuiltinData{BuiltinType::kReflect, CallParamType::kF16, "reflect"},
- BuiltinData{BuiltinType::kSign, CallParamType::kF32, "sign"},
- BuiltinData{BuiltinType::kSign, CallParamType::kF16, "sign"},
- BuiltinData{BuiltinType::kSin, CallParamType::kF32, "sin"},
- BuiltinData{BuiltinType::kSin, CallParamType::kF16, "sin"},
- BuiltinData{BuiltinType::kSinh, CallParamType::kF32, "sinh"},
- BuiltinData{BuiltinType::kSinh, CallParamType::kF16, "sinh"},
- BuiltinData{BuiltinType::kSmoothstep, CallParamType::kF32, "smoothstep"},
- BuiltinData{BuiltinType::kSmoothstep, CallParamType::kF16, "smoothstep"},
- BuiltinData{BuiltinType::kSqrt, CallParamType::kF32, "sqrt"},
- BuiltinData{BuiltinType::kSqrt, CallParamType::kF16, "sqrt"},
- BuiltinData{BuiltinType::kStep, CallParamType::kF32, "step"},
- BuiltinData{BuiltinType::kStep, CallParamType::kF16, "step"},
- BuiltinData{BuiltinType::kTan, CallParamType::kF32, "tan"},
- BuiltinData{BuiltinType::kTan, CallParamType::kF16, "tan"},
- BuiltinData{BuiltinType::kTanh, CallParamType::kF32, "tanh"},
- BuiltinData{BuiltinType::kTanh, CallParamType::kF16, "tanh"},
- BuiltinData{BuiltinType::kTrunc, CallParamType::kF32, "trunc"},
- BuiltinData{BuiltinType::kTrunc, CallParamType::kF16, "trunc"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kF32, "fabs"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kF16, "fabs"},
+ BuiltinData{builtin::Function::kAcos, CallParamType::kF32, "acos"},
+ BuiltinData{builtin::Function::kAcos, CallParamType::kF16, "acos"},
+ BuiltinData{builtin::Function::kAsin, CallParamType::kF32, "asin"},
+ BuiltinData{builtin::Function::kAsin, CallParamType::kF16, "asin"},
+ BuiltinData{builtin::Function::kAtan, CallParamType::kF32, "atan"},
+ BuiltinData{builtin::Function::kAtan, CallParamType::kF16, "atan"},
+ BuiltinData{builtin::Function::kAtan2, CallParamType::kF32, "atan2"},
+ BuiltinData{builtin::Function::kAtan2, CallParamType::kF16, "atan2"},
+ BuiltinData{builtin::Function::kCeil, CallParamType::kF32, "ceil"},
+ BuiltinData{builtin::Function::kCeil, CallParamType::kF16, "ceil"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kF32, "clamp"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kF16, "clamp"},
+ BuiltinData{builtin::Function::kCos, CallParamType::kF32, "cos"},
+ BuiltinData{builtin::Function::kCos, CallParamType::kF16, "cos"},
+ BuiltinData{builtin::Function::kCosh, CallParamType::kF32, "cosh"},
+ BuiltinData{builtin::Function::kCosh, CallParamType::kF16, "cosh"},
+ BuiltinData{builtin::Function::kCross, CallParamType::kF32, "cross"},
+ BuiltinData{builtin::Function::kCross, CallParamType::kF16, "cross"},
+ BuiltinData{builtin::Function::kDistance, CallParamType::kF32, "distance"},
+ BuiltinData{builtin::Function::kDistance, CallParamType::kF16, "distance"},
+ BuiltinData{builtin::Function::kExp, CallParamType::kF32, "exp"},
+ BuiltinData{builtin::Function::kExp, CallParamType::kF16, "exp"},
+ BuiltinData{builtin::Function::kExp2, CallParamType::kF32, "exp2"},
+ BuiltinData{builtin::Function::kExp2, CallParamType::kF16, "exp2"},
+ BuiltinData{builtin::Function::kFaceForward, CallParamType::kF32, "faceforward"},
+ BuiltinData{builtin::Function::kFaceForward, CallParamType::kF16, "faceforward"},
+ BuiltinData{builtin::Function::kFloor, CallParamType::kF32, "floor"},
+ BuiltinData{builtin::Function::kFloor, CallParamType::kF16, "floor"},
+ BuiltinData{builtin::Function::kFma, CallParamType::kF32, "fma"},
+ BuiltinData{builtin::Function::kFma, CallParamType::kF16, "fma"},
+ BuiltinData{builtin::Function::kFract, CallParamType::kF32, "fract"},
+ BuiltinData{builtin::Function::kFract, CallParamType::kF16, "fract"},
+ BuiltinData{builtin::Function::kInverseSqrt, CallParamType::kF32, "rsqrt"},
+ BuiltinData{builtin::Function::kInverseSqrt, CallParamType::kF16, "rsqrt"},
+ BuiltinData{builtin::Function::kLdexp, CallParamType::kF32, "ldexp"},
+ BuiltinData{builtin::Function::kLdexp, CallParamType::kF16, "ldexp"},
+ BuiltinData{builtin::Function::kLength, CallParamType::kF32, "length"},
+ BuiltinData{builtin::Function::kLength, CallParamType::kF16, "length"},
+ BuiltinData{builtin::Function::kLog, CallParamType::kF32, "log"},
+ BuiltinData{builtin::Function::kLog, CallParamType::kF16, "log"},
+ BuiltinData{builtin::Function::kLog2, CallParamType::kF32, "log2"},
+ BuiltinData{builtin::Function::kLog2, CallParamType::kF16, "log2"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kF32, "fmax"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kF16, "fmax"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kF32, "fmin"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kF16, "fmin"},
+ BuiltinData{builtin::Function::kNormalize, CallParamType::kF32, "normalize"},
+ BuiltinData{builtin::Function::kNormalize, CallParamType::kF16, "normalize"},
+ BuiltinData{builtin::Function::kPow, CallParamType::kF32, "pow"},
+ BuiltinData{builtin::Function::kPow, CallParamType::kF16, "pow"},
+ BuiltinData{builtin::Function::kReflect, CallParamType::kF32, "reflect"},
+ BuiltinData{builtin::Function::kReflect, CallParamType::kF16, "reflect"},
+ BuiltinData{builtin::Function::kSign, CallParamType::kF32, "sign"},
+ BuiltinData{builtin::Function::kSign, CallParamType::kF16, "sign"},
+ BuiltinData{builtin::Function::kSin, CallParamType::kF32, "sin"},
+ BuiltinData{builtin::Function::kSin, CallParamType::kF16, "sin"},
+ BuiltinData{builtin::Function::kSinh, CallParamType::kF32, "sinh"},
+ BuiltinData{builtin::Function::kSinh, CallParamType::kF16, "sinh"},
+ BuiltinData{builtin::Function::kSmoothstep, CallParamType::kF32, "smoothstep"},
+ BuiltinData{builtin::Function::kSmoothstep, CallParamType::kF16, "smoothstep"},
+ BuiltinData{builtin::Function::kSqrt, CallParamType::kF32, "sqrt"},
+ BuiltinData{builtin::Function::kSqrt, CallParamType::kF16, "sqrt"},
+ BuiltinData{builtin::Function::kStep, CallParamType::kF32, "step"},
+ BuiltinData{builtin::Function::kStep, CallParamType::kF16, "step"},
+ BuiltinData{builtin::Function::kTan, CallParamType::kF32, "tan"},
+ BuiltinData{builtin::Function::kTan, CallParamType::kF16, "tan"},
+ BuiltinData{builtin::Function::kTanh, CallParamType::kF32, "tanh"},
+ BuiltinData{builtin::Function::kTanh, CallParamType::kF16, "tanh"},
+ BuiltinData{builtin::Function::kTrunc, CallParamType::kF32, "trunc"},
+ BuiltinData{builtin::Function::kTrunc, CallParamType::kF16, "trunc"},
/* Integer built-in */
- BuiltinData{BuiltinType::kAbs, CallParamType::kU32, "abs"},
- BuiltinData{BuiltinType::kClamp, CallParamType::kU32, "clamp"},
- BuiltinData{BuiltinType::kCountLeadingZeros, CallParamType::kU32, "clz"},
- BuiltinData{BuiltinType::kCountOneBits, CallParamType::kU32, "popcount"},
- BuiltinData{BuiltinType::kCountTrailingZeros, CallParamType::kU32, "ctz"},
- BuiltinData{BuiltinType::kExtractBits, CallParamType::kU32, "extract_bits"},
- BuiltinData{BuiltinType::kInsertBits, CallParamType::kU32, "insert_bits"},
- BuiltinData{BuiltinType::kMax, CallParamType::kU32, "max"},
- BuiltinData{BuiltinType::kMin, CallParamType::kU32, "min"},
- BuiltinData{BuiltinType::kReverseBits, CallParamType::kU32, "reverse_bits"},
- BuiltinData{BuiltinType::kRound, CallParamType::kU32, "rint"},
+ BuiltinData{builtin::Function::kAbs, CallParamType::kU32, "abs"},
+ BuiltinData{builtin::Function::kClamp, CallParamType::kU32, "clamp"},
+ BuiltinData{builtin::Function::kCountLeadingZeros, CallParamType::kU32, "clz"},
+ BuiltinData{builtin::Function::kCountOneBits, CallParamType::kU32, "popcount"},
+ BuiltinData{builtin::Function::kCountTrailingZeros, CallParamType::kU32, "ctz"},
+ BuiltinData{builtin::Function::kExtractBits, CallParamType::kU32, "extract_bits"},
+ BuiltinData{builtin::Function::kInsertBits, CallParamType::kU32, "insert_bits"},
+ BuiltinData{builtin::Function::kMax, CallParamType::kU32, "max"},
+ BuiltinData{builtin::Function::kMin, CallParamType::kU32, "min"},
+ BuiltinData{builtin::Function::kReverseBits, CallParamType::kU32, "reverse_bits"},
+ BuiltinData{builtin::Function::kRound, CallParamType::kU32, "rint"},
/* Matrix built-in */
- BuiltinData{BuiltinType::kDeterminant, CallParamType::kF32, "determinant"},
- BuiltinData{BuiltinType::kTranspose, CallParamType::kF32, "transpose"},
+ BuiltinData{builtin::Function::kDeterminant, CallParamType::kF32, "determinant"},
+ BuiltinData{builtin::Function::kTranspose, CallParamType::kF32, "transpose"},
/* Vector built-in */
- BuiltinData{BuiltinType::kDot, CallParamType::kF32, "dot"},
+ BuiltinData{builtin::Function::kDot, CallParamType::kF32, "dot"},
/* Derivate built-in */
- BuiltinData{BuiltinType::kDpdx, CallParamType::kF32, "dfdx"},
- BuiltinData{BuiltinType::kDpdxCoarse, CallParamType::kF32, "dfdx"},
- BuiltinData{BuiltinType::kDpdxFine, CallParamType::kF32, "dfdx"},
- BuiltinData{BuiltinType::kDpdy, CallParamType::kF32, "dfdy"},
- BuiltinData{BuiltinType::kDpdyCoarse, CallParamType::kF32, "dfdy"},
- BuiltinData{BuiltinType::kDpdyFine, CallParamType::kF32, "dfdy"},
- BuiltinData{BuiltinType::kFwidth, CallParamType::kF32, "fwidth"},
- BuiltinData{BuiltinType::kFwidthCoarse, CallParamType::kF32, "fwidth"},
- BuiltinData{BuiltinType::kFwidthFine, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kDpdx, CallParamType::kF32, "dfdx"},
+ BuiltinData{builtin::Function::kDpdxCoarse, CallParamType::kF32, "dfdx"},
+ BuiltinData{builtin::Function::kDpdxFine, CallParamType::kF32, "dfdx"},
+ BuiltinData{builtin::Function::kDpdy, CallParamType::kF32, "dfdy"},
+ BuiltinData{builtin::Function::kDpdyCoarse, CallParamType::kF32, "dfdy"},
+ BuiltinData{builtin::Function::kDpdyFine, CallParamType::kF32, "dfdy"},
+ BuiltinData{builtin::Function::kFwidth, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kFwidthCoarse, CallParamType::kF32, "fwidth"},
+ BuiltinData{builtin::Function::kFwidthFine, CallParamType::kF32, "fwidth"},
/* Data packing builtin */
- BuiltinData{BuiltinType::kPack4X8Snorm, CallParamType::kF32, "pack_float_to_snorm4x8"},
- BuiltinData{BuiltinType::kPack4X8Unorm, CallParamType::kF32, "pack_float_to_unorm4x8"},
- BuiltinData{BuiltinType::kPack2X16Snorm, CallParamType::kF32, "pack_float_to_snorm2x16"},
- BuiltinData{BuiltinType::kPack2X16Unorm, CallParamType::kF32, "pack_float_to_unorm2x16"},
+ BuiltinData{builtin::Function::kPack4X8Snorm, CallParamType::kF32,
+ "pack_float_to_snorm4x8"},
+ BuiltinData{builtin::Function::kPack4X8Unorm, CallParamType::kF32,
+ "pack_float_to_unorm4x8"},
+ BuiltinData{builtin::Function::kPack2X16Snorm, CallParamType::kF32,
+ "pack_float_to_snorm2x16"},
+ BuiltinData{builtin::Function::kPack2X16Unorm, CallParamType::kF32,
+ "pack_float_to_unorm2x16"},
/* Data unpacking builtin */
- BuiltinData{BuiltinType::kUnpack4X8Snorm, CallParamType::kU32, "unpack_snorm4x8_to_float"},
- BuiltinData{BuiltinType::kUnpack4X8Unorm, CallParamType::kU32, "unpack_unorm4x8_to_float"},
- BuiltinData{BuiltinType::kUnpack2X16Snorm, CallParamType::kU32,
+ BuiltinData{builtin::Function::kUnpack4X8Snorm, CallParamType::kU32,
+ "unpack_snorm4x8_to_float"},
+ BuiltinData{builtin::Function::kUnpack4X8Unorm, CallParamType::kU32,
+ "unpack_unorm4x8_to_float"},
+ BuiltinData{builtin::Function::kUnpack2X16Snorm, CallParamType::kU32,
"unpack_snorm2x16_to_float"},
- BuiltinData{BuiltinType::kUnpack2X16Unorm, CallParamType::kU32,
+ BuiltinData{builtin::Function::kUnpack2X16Unorm, CallParamType::kU32,
"unpack_unorm2x16_to_float"}));
TEST_F(MslGeneratorImplTest, Builtin_Call) {
diff --git a/src/tint/writer/msl/generator_impl_builtin_texture_test.cc b/src/tint/writer/msl/generator_impl_builtin_texture_test.cc
index 7beee1a..730fe99 100644
--- a/src/tint/writer/msl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_texture_test.cc
@@ -90,7 +90,9 @@
case ValidTextureOverload::kGatherCompareDepthCubeArrayF32:
return R"(Texture.gather_compare(Sampler, float3(1.0f, 2.0f, 3.0f), 4u, 5.0f))";
case ValidTextureOverload::kNumLayers2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
case ValidTextureOverload::kNumLayersStorageWO2dArray:
return R"(Texture.get_array_size())";
case ValidTextureOverload::kNumLevels2d:
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 40f98d8..ae14acd 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -56,8 +56,6 @@
namespace tint::writer::spirv {
namespace {
-using BuiltinType = sem::BuiltinType;
-
const char kGLSLstd450[] = "GLSL.std.450";
uint32_t size_of(const InstructionList& instructions) {
@@ -102,23 +100,23 @@
uint32_t builtin_to_glsl_method(const sem::Builtin* builtin) {
switch (builtin->Type()) {
- case BuiltinType::kAcos:
+ case builtin::Function::kAcos:
return GLSLstd450Acos;
- case BuiltinType::kAcosh:
+ case builtin::Function::kAcosh:
return GLSLstd450Acosh;
- case BuiltinType::kAsin:
+ case builtin::Function::kAsin:
return GLSLstd450Asin;
- case BuiltinType::kAsinh:
+ case builtin::Function::kAsinh:
return GLSLstd450Asinh;
- case BuiltinType::kAtan:
+ case builtin::Function::kAtan:
return GLSLstd450Atan;
- case BuiltinType::kAtan2:
+ case builtin::Function::kAtan2:
return GLSLstd450Atan2;
- case BuiltinType::kAtanh:
+ case builtin::Function::kAtanh:
return GLSLstd450Atanh;
- case BuiltinType::kCeil:
+ case builtin::Function::kCeil:
return GLSLstd450Ceil;
- case BuiltinType::kClamp:
+ case builtin::Function::kClamp:
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
return GLSLstd450NClamp;
} else if (builtin->ReturnType()->is_unsigned_integer_scalar_or_vector()) {
@@ -126,43 +124,43 @@
} else {
return GLSLstd450SClamp;
}
- case BuiltinType::kCos:
+ case builtin::Function::kCos:
return GLSLstd450Cos;
- case BuiltinType::kCosh:
+ case builtin::Function::kCosh:
return GLSLstd450Cosh;
- case BuiltinType::kCross:
+ case builtin::Function::kCross:
return GLSLstd450Cross;
- case BuiltinType::kDegrees:
+ case builtin::Function::kDegrees:
return GLSLstd450Degrees;
- case BuiltinType::kDeterminant:
+ case builtin::Function::kDeterminant:
return GLSLstd450Determinant;
- case BuiltinType::kDistance:
+ case builtin::Function::kDistance:
return GLSLstd450Distance;
- case BuiltinType::kExp:
+ case builtin::Function::kExp:
return GLSLstd450Exp;
- case BuiltinType::kExp2:
+ case builtin::Function::kExp2:
return GLSLstd450Exp2;
- case BuiltinType::kFaceForward:
+ case builtin::Function::kFaceForward:
return GLSLstd450FaceForward;
- case BuiltinType::kFloor:
+ case builtin::Function::kFloor:
return GLSLstd450Floor;
- case BuiltinType::kFma:
+ case builtin::Function::kFma:
return GLSLstd450Fma;
- case BuiltinType::kFract:
+ case builtin::Function::kFract:
return GLSLstd450Fract;
- case BuiltinType::kFrexp:
+ case builtin::Function::kFrexp:
return GLSLstd450FrexpStruct;
- case BuiltinType::kInverseSqrt:
+ case builtin::Function::kInverseSqrt:
return GLSLstd450InverseSqrt;
- case BuiltinType::kLdexp:
+ case builtin::Function::kLdexp:
return GLSLstd450Ldexp;
- case BuiltinType::kLength:
+ case builtin::Function::kLength:
return GLSLstd450Length;
- case BuiltinType::kLog:
+ case builtin::Function::kLog:
return GLSLstd450Log;
- case BuiltinType::kLog2:
+ case builtin::Function::kLog2:
return GLSLstd450Log2;
- case BuiltinType::kMax:
+ case builtin::Function::kMax:
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
return GLSLstd450NMax;
} else if (builtin->ReturnType()->is_unsigned_integer_scalar_or_vector()) {
@@ -170,7 +168,7 @@
} else {
return GLSLstd450SMax;
}
- case BuiltinType::kMin:
+ case builtin::Function::kMin:
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
return GLSLstd450NMin;
} else if (builtin->ReturnType()->is_unsigned_integer_scalar_or_vector()) {
@@ -178,63 +176,63 @@
} else {
return GLSLstd450SMin;
}
- case BuiltinType::kMix:
+ case builtin::Function::kMix:
return GLSLstd450FMix;
- case BuiltinType::kModf:
+ case builtin::Function::kModf:
return GLSLstd450ModfStruct;
- case BuiltinType::kNormalize:
+ case builtin::Function::kNormalize:
return GLSLstd450Normalize;
- case BuiltinType::kPack4X8Snorm:
+ case builtin::Function::kPack4X8Snorm:
return GLSLstd450PackSnorm4x8;
- case BuiltinType::kPack4X8Unorm:
+ case builtin::Function::kPack4X8Unorm:
return GLSLstd450PackUnorm4x8;
- case BuiltinType::kPack2X16Snorm:
+ case builtin::Function::kPack2X16Snorm:
return GLSLstd450PackSnorm2x16;
- case BuiltinType::kPack2X16Unorm:
+ case builtin::Function::kPack2X16Unorm:
return GLSLstd450PackUnorm2x16;
- case BuiltinType::kPack2X16Float:
+ case builtin::Function::kPack2X16Float:
return GLSLstd450PackHalf2x16;
- case BuiltinType::kPow:
+ case builtin::Function::kPow:
return GLSLstd450Pow;
- case BuiltinType::kRadians:
+ case builtin::Function::kRadians:
return GLSLstd450Radians;
- case BuiltinType::kReflect:
+ case builtin::Function::kReflect:
return GLSLstd450Reflect;
- case BuiltinType::kRefract:
+ case builtin::Function::kRefract:
return GLSLstd450Refract;
- case BuiltinType::kRound:
+ case builtin::Function::kRound:
return GLSLstd450RoundEven;
- case BuiltinType::kSign:
+ case builtin::Function::kSign:
if (builtin->ReturnType()->is_signed_integer_scalar_or_vector()) {
return GLSLstd450SSign;
} else {
return GLSLstd450FSign;
}
- case BuiltinType::kSin:
+ case builtin::Function::kSin:
return GLSLstd450Sin;
- case BuiltinType::kSinh:
+ case builtin::Function::kSinh:
return GLSLstd450Sinh;
- case BuiltinType::kSmoothstep:
+ case builtin::Function::kSmoothstep:
return GLSLstd450SmoothStep;
- case BuiltinType::kSqrt:
+ case builtin::Function::kSqrt:
return GLSLstd450Sqrt;
- case BuiltinType::kStep:
+ case builtin::Function::kStep:
return GLSLstd450Step;
- case BuiltinType::kTan:
+ case builtin::Function::kTan:
return GLSLstd450Tan;
- case BuiltinType::kTanh:
+ case builtin::Function::kTanh:
return GLSLstd450Tanh;
- case BuiltinType::kTrunc:
+ case builtin::Function::kTrunc:
return GLSLstd450Trunc;
- case BuiltinType::kUnpack4X8Snorm:
+ case builtin::Function::kUnpack4X8Snorm:
return GLSLstd450UnpackSnorm4x8;
- case BuiltinType::kUnpack4X8Unorm:
+ case builtin::Function::kUnpack4X8Unorm:
return GLSLstd450UnpackUnorm4x8;
- case BuiltinType::kUnpack2X16Snorm:
+ case builtin::Function::kUnpack2X16Snorm:
return GLSLstd450UnpackSnorm2x16;
- case BuiltinType::kUnpack2X16Unorm:
+ case builtin::Function::kUnpack2X16Unorm:
return GLSLstd450UnpackUnorm2x16;
- case BuiltinType::kUnpack2X16Float:
+ case builtin::Function::kUnpack2X16Float:
return GLSLstd450UnpackHalf2x16;
default:
break;
@@ -2363,21 +2361,21 @@
};
switch (builtin->Type()) {
- case BuiltinType::kAny:
+ case builtin::Function::kAny:
if (builtin->Parameters()[0]->Type()->Is<type::Bool>()) {
// any(v: bool) just resolves to v.
return get_arg_as_value_id(0);
}
op = spv::Op::OpAny;
break;
- case BuiltinType::kAll:
+ case builtin::Function::kAll:
if (builtin->Parameters()[0]->Type()->Is<type::Bool>()) {
// all(v: bool) just resolves to v.
return get_arg_as_value_id(0);
}
op = spv::Op::OpAll;
break;
- case BuiltinType::kArrayLength: {
+ case builtin::Function::kArrayLength: {
auto* address_of = call->Arguments()[0]->Declaration()->As<ast::UnaryOpExpression>();
if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
error_ = "arrayLength() expected pointer to member access, got " +
@@ -2414,10 +2412,10 @@
}
return result_id;
}
- case BuiltinType::kCountOneBits:
+ case builtin::Function::kCountOneBits:
op = spv::Op::OpBitCount;
break;
- case BuiltinType::kDot: {
+ case builtin::Function::kDot: {
op = spv::Op::OpDot;
auto* vec_ty = builtin->Parameters()[0]->Type()->As<type::Vector>();
if (vec_ty->type()->is_integer_scalar()) {
@@ -2458,42 +2456,42 @@
}
break;
}
- case BuiltinType::kDpdx:
+ case builtin::Function::kDpdx:
op = spv::Op::OpDPdx;
break;
- case BuiltinType::kDpdxCoarse:
+ case builtin::Function::kDpdxCoarse:
op = spv::Op::OpDPdxCoarse;
break;
- case BuiltinType::kDpdxFine:
+ case builtin::Function::kDpdxFine:
op = spv::Op::OpDPdxFine;
break;
- case BuiltinType::kDpdy:
+ case builtin::Function::kDpdy:
op = spv::Op::OpDPdy;
break;
- case BuiltinType::kDpdyCoarse:
+ case builtin::Function::kDpdyCoarse:
op = spv::Op::OpDPdyCoarse;
break;
- case BuiltinType::kDpdyFine:
+ case builtin::Function::kDpdyFine:
op = spv::Op::OpDPdyFine;
break;
- case BuiltinType::kExtractBits:
+ case builtin::Function::kExtractBits:
op = builtin->Parameters()[0]->Type()->is_unsigned_integer_scalar_or_vector()
? spv::Op::OpBitFieldUExtract
: spv::Op::OpBitFieldSExtract;
break;
- case BuiltinType::kFwidth:
+ case builtin::Function::kFwidth:
op = spv::Op::OpFwidth;
break;
- case BuiltinType::kFwidthCoarse:
+ case builtin::Function::kFwidthCoarse:
op = spv::Op::OpFwidthCoarse;
break;
- case BuiltinType::kFwidthFine:
+ case builtin::Function::kFwidthFine:
op = spv::Op::OpFwidthFine;
break;
- case BuiltinType::kInsertBits:
+ case builtin::Function::kInsertBits:
op = spv::Op::OpBitFieldInsert;
break;
- case BuiltinType::kMix: {
+ case builtin::Function::kMix: {
auto std450 = Operand(GetGLSLstd450Import());
auto a_id = get_arg_as_value_id(0);
@@ -2520,13 +2518,13 @@
}
return result_id;
}
- case BuiltinType::kQuantizeToF16:
+ case builtin::Function::kQuantizeToF16:
op = spv::Op::OpQuantizeToF16;
break;
- case BuiltinType::kReverseBits:
+ case builtin::Function::kReverseBits:
op = spv::Op::OpBitReverse;
break;
- case BuiltinType::kSelect: {
+ case builtin::Function::kSelect: {
// Note: Argument order is different in WGSL and SPIR-V
auto cond_id = get_arg_as_value_id(2);
auto true_id = get_arg_as_value_id(1);
@@ -2558,10 +2556,10 @@
}
return result_id;
}
- case BuiltinType::kTranspose:
+ case builtin::Function::kTranspose:
op = spv::Op::OpTranspose;
break;
- case BuiltinType::kAbs:
+ case builtin::Function::kAbs:
if (builtin->ReturnType()->is_unsigned_integer_scalar_or_vector()) {
// abs() only operates on *signed* integers.
// This is a no-op for unsigned integers.
@@ -2573,7 +2571,7 @@
glsl_std450(GLSLstd450SAbs);
}
break;
- case BuiltinType::kDot4I8Packed: {
+ case builtin::Function::kDot4I8Packed: {
auto first_param_id = get_arg_as_value_id(0);
auto second_param_id = get_arg_as_value_id(1);
if (!push_function_inst(spv::Op::OpSDotKHR,
@@ -2585,7 +2583,7 @@
}
return result_id;
}
- case BuiltinType::kDot4U8Packed: {
+ case builtin::Function::kDot4U8Packed: {
auto first_param_id = get_arg_as_value_id(0);
auto second_param_id = get_arg_as_value_id(1);
if (!push_function_inst(spv::Op::OpUDotKHR,
@@ -2788,7 +2786,7 @@
};
switch (builtin->Type()) {
- case BuiltinType::kTextureDimensions: {
+ case builtin::Function::kTextureDimensions: {
// Number of returned elements from OpImageQuerySize[Lod] may not match
// those of textureDimensions().
// This might be due to an extra vector scalar describing the number of
@@ -2833,7 +2831,7 @@
}
break;
}
- case BuiltinType::kTextureNumLayers: {
+ case builtin::Function::kTextureNumLayers: {
uint32_t spirv_dims = 0;
switch (texture_type->dim()) {
default:
@@ -2863,19 +2861,19 @@
}
break;
}
- case BuiltinType::kTextureNumLevels: {
+ case builtin::Function::kTextureNumLevels: {
op = spv::Op::OpImageQueryLevels;
append_result_type_and_id_to_spirv_params();
spirv_params.emplace_back(gen_arg(Usage::kTexture));
break;
}
- case BuiltinType::kTextureNumSamples: {
+ case builtin::Function::kTextureNumSamples: {
op = spv::Op::OpImageQuerySamples;
append_result_type_and_id_to_spirv_params();
spirv_params.emplace_back(gen_arg(Usage::kTexture));
break;
}
- case BuiltinType::kTextureLoad: {
+ case builtin::Function::kTextureLoad: {
op = texture_type->Is<type::StorageTexture>() ? spv::Op::OpImageRead
: spv::Op::OpImageFetch;
append_result_type_and_id_to_spirv_params_for_read();
@@ -2895,7 +2893,7 @@
break;
}
- case BuiltinType::kTextureStore: {
+ case builtin::Function::kTextureStore: {
op = spv::Op::OpImageWrite;
spirv_params.emplace_back(gen_arg(Usage::kTexture));
if (!append_coords_to_spirv_params()) {
@@ -2904,7 +2902,7 @@
spirv_params.emplace_back(gen_arg(Usage::kValue));
break;
}
- case BuiltinType::kTextureGather: {
+ case builtin::Function::kTextureGather: {
op = spv::Op::OpImageGather;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2918,7 +2916,7 @@
}
break;
}
- case BuiltinType::kTextureGatherCompare: {
+ case builtin::Function::kTextureGatherCompare: {
op = spv::Op::OpImageDrefGather;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2927,7 +2925,7 @@
spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
break;
}
- case BuiltinType::kTextureSample: {
+ case builtin::Function::kTextureSample: {
op = spv::Op::OpImageSampleImplicitLod;
append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2935,7 +2933,7 @@
}
break;
}
- case BuiltinType::kTextureSampleBias: {
+ case builtin::Function::kTextureSampleBias: {
op = spv::Op::OpImageSampleImplicitLod;
append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2945,7 +2943,7 @@
ImageOperand{SpvImageOperandsBiasMask, gen_arg(Usage::kBias)});
break;
}
- case BuiltinType::kTextureSampleLevel: {
+ case builtin::Function::kTextureSampleLevel: {
op = spv::Op::OpImageSampleExplicitLod;
append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2970,7 +2968,7 @@
image_operands.emplace_back(ImageOperand{SpvImageOperandsLodMask, level});
break;
}
- case BuiltinType::kTextureSampleGrad: {
+ case builtin::Function::kTextureSampleGrad: {
op = spv::Op::OpImageSampleExplicitLod;
append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2982,7 +2980,7 @@
ImageOperand{SpvImageOperandsGradMask, gen_arg(Usage::kDdy)});
break;
}
- case BuiltinType::kTextureSampleCompare: {
+ case builtin::Function::kTextureSampleCompare: {
op = spv::Op::OpImageSampleDrefImplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
@@ -2991,7 +2989,7 @@
spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
break;
}
- case BuiltinType::kTextureSampleCompareLevel: {
+ case builtin::Function::kTextureSampleCompareLevel: {
op = spv::Op::OpImageSampleDrefExplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
@@ -3046,19 +3044,19 @@
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction.
- if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
+ if (builtin->Type() == builtin::Function::kWorkgroupBarrier) {
execution = static_cast<uint32_t>(spv::Scope::Workgroup);
memory = static_cast<uint32_t>(spv::Scope::Workgroup);
semantics = static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
static_cast<uint32_t>(spv::MemorySemanticsMask::WorkgroupMemory);
- } else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
+ } else if (builtin->Type() == builtin::Function::kStorageBarrier) {
execution = static_cast<uint32_t>(spv::Scope::Workgroup);
memory = static_cast<uint32_t>(spv::Scope::Workgroup);
semantics = static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
static_cast<uint32_t>(spv::MemorySemanticsMask::UniformMemory);
} else {
error_ = "unexpected barrier builtin type ";
- error_ += sem::str(builtin->Type());
+ error_ += builtin::str(builtin->Type());
return false;
}
@@ -3128,7 +3126,7 @@
Operand semantics = Operand(semantics_id);
switch (builtin->Type()) {
- case sem::BuiltinType::kAtomicLoad:
+ case builtin::Function::kAtomicLoad:
return push_function_inst(spv::Op::OpAtomicLoad, {
result_type,
result_id,
@@ -3136,14 +3134,14 @@
memory,
semantics,
});
- case sem::BuiltinType::kAtomicStore:
+ case builtin::Function::kAtomicStore:
return push_function_inst(spv::Op::OpAtomicStore, {
pointer,
memory,
semantics,
value,
});
- case sem::BuiltinType::kAtomicAdd:
+ case builtin::Function::kAtomicAdd:
return push_function_inst(spv::Op::OpAtomicIAdd, {
result_type,
result_id,
@@ -3152,7 +3150,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicSub:
+ case builtin::Function::kAtomicSub:
return push_function_inst(spv::Op::OpAtomicISub, {
result_type,
result_id,
@@ -3161,7 +3159,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicMax:
+ case builtin::Function::kAtomicMax:
return push_function_inst(
is_value_signed() ? spv::Op::OpAtomicSMax : spv::Op::OpAtomicUMax, {
result_type,
@@ -3171,7 +3169,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicMin:
+ case builtin::Function::kAtomicMin:
return push_function_inst(
is_value_signed() ? spv::Op::OpAtomicSMin : spv::Op::OpAtomicUMin, {
result_type,
@@ -3181,7 +3179,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicAnd:
+ case builtin::Function::kAtomicAnd:
return push_function_inst(spv::Op::OpAtomicAnd, {
result_type,
result_id,
@@ -3190,7 +3188,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicOr:
+ case builtin::Function::kAtomicOr:
return push_function_inst(spv::Op::OpAtomicOr, {
result_type,
result_id,
@@ -3199,7 +3197,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicXor:
+ case builtin::Function::kAtomicXor:
return push_function_inst(spv::Op::OpAtomicXor, {
result_type,
result_id,
@@ -3208,7 +3206,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicExchange:
+ case builtin::Function::kAtomicExchange:
return push_function_inst(spv::Op::OpAtomicExchange, {
result_type,
result_id,
@@ -3217,7 +3215,7 @@
semantics,
value,
});
- case sem::BuiltinType::kAtomicCompareExchangeWeak: {
+ case builtin::Function::kAtomicCompareExchangeWeak: {
auto comparator = GenerateExpression(call->Arguments()[1]);
if (comparator == 0) {
return false;
diff --git a/src/tint/writer/spirv/builder_builtin_test.cc b/src/tint/writer/spirv/builder_builtin_test.cc
index 5db867a..280b878 100644
--- a/src/tint/writer/spirv/builder_builtin_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_test.cc
@@ -4154,10 +4154,7 @@
namespace DP4A_builtin_tests {
TEST_F(BuiltinBuilderTest, Call_Dot4I8Packed) {
- auto* ext =
- create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
- builtin::Extension::kChromiumExperimentalDp4A);
- AST().AddEnable(ext);
+ Enable(builtin::Extension::kChromiumExperimentalDp4A);
auto* val1 = Var("val1", ty.u32());
auto* val2 = Var("val2", ty.u32());
@@ -4194,10 +4191,7 @@
}
TEST_F(BuiltinBuilderTest, Call_Dot4U8Packed) {
- auto* ext =
- create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
- builtin::Extension::kChromiumExperimentalDp4A);
- AST().AddEnable(ext);
+ Enable(builtin::Extension::kChromiumExperimentalDp4A);
auto* val1 = Var("val1", ty.u32());
auto* val2 = Var("val2", ty.u32());
diff --git a/src/tint/writer/spirv/builder_builtin_texture_test.cc b/src/tint/writer/spirv/builder_builtin_texture_test.cc
index 766b78b..4697582 100644
--- a/src/tint/writer/spirv/builder_builtin_texture_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_texture_test.cc
@@ -1132,6 +1132,29 @@
R"(
OpCapability ImageQuery
)"};
+ case ValidTextureOverload::kNumLayersCubeArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 0
+%11 = OpTypeVector %9 3
+%13 = OpTypeInt 32 1
+%14 = OpConstant %13 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %14
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability SampledCubeArray
+OpCapability ImageQuery
+)"};
case ValidTextureOverload::kNumLayersDepth2dArray:
return {R"(
%4 = OpTypeFloat 32
@@ -1154,6 +1177,29 @@
R"(
OpCapability ImageQuery
)"};
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 0
+%11 = OpTypeVector %9 3
+%13 = OpTypeInt 32 1
+%14 = OpConstant %13 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %14
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability SampledCubeArray
+OpCapability ImageQuery
+)"};
case ValidTextureOverload::kNumLayersStorageWO2dArray:
return {R"(
%4 = OpTypeFloat 32
diff --git a/src/tint/writer/spirv/generator.h b/src/tint/writer/spirv/generator.h
index 8b34032..f6d2268 100644
--- a/src/tint/writer/spirv/generator.h
+++ b/src/tint/writer/spirv/generator.h
@@ -20,6 +20,7 @@
#include <vector>
#include "src/tint/reflection.h"
+#include "src/tint/writer/external_texture_options.h"
#include "src/tint/writer/writer.h"
// Forward declarations
@@ -45,8 +46,11 @@
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
- /// Set to 'true' to generates binding mappings for external textures
- bool generate_external_texture_bindings = false;
+ /// Set to `true` to clamp frag depth
+ bool clamp_frag_depth = false;
+
+ /// Options used in the binding mappings for external textures
+ ExternalTextureOptions external_texture_options = {};
/// Set to `true` to initialize workgroup memory with OpConstantNull when
/// VK_KHR_zero_initialize_workgroup_memory is enabled.
@@ -56,7 +60,7 @@
TINT_REFLECT(disable_robustness,
emit_vertex_point_size,
disable_workgroup_init,
- generate_external_texture_bindings,
+ external_texture_options,
use_zero_initialize_workgroup_memory_extension);
};
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index 72a3629..1986f83 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -21,6 +21,7 @@
#include "src/tint/transform/add_empty_entry_point.h"
#include "src/tint/transform/builtin_polyfill.h"
#include "src/tint/transform/canonicalize_entry_point_io.h"
+#include "src/tint/transform/clamp_frag_depth.h"
#include "src/tint/transform/demote_to_helper.h"
#include "src/tint/transform/direct_variable_access.h"
#include "src/tint/transform/disable_uniformity_analysis.h"
@@ -28,6 +29,7 @@
#include "src/tint/transform/for_loop_to_loop.h"
#include "src/tint/transform/manager.h"
#include "src/tint/transform/merge_return.h"
+#include "src/tint/transform/multiplanar_external_texture.h"
#include "src/tint/transform/preserve_padding.h"
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_phonies.h"
@@ -41,7 +43,6 @@
#include "src/tint/transform/vectorize_scalar_matrix_initializers.h"
#include "src/tint/transform/while_to_loop.h"
#include "src/tint/transform/zero_init_workgroup_memory.h"
-#include "src/tint/writer/generate_external_texture_bindings.h"
namespace tint::writer::spirv {
@@ -49,6 +50,10 @@
transform::Manager manager;
transform::DataMap data;
+ if (options.clamp_frag_depth) {
+ manager.Add<tint::transform::ClampFragDepth>();
+ }
+
manager.Add<transform::DisableUniformityAnalysis>();
// ExpandCompoundAssignment must come before BuiltinPolyfill
@@ -73,10 +78,10 @@
manager.Add<transform::Robustness>();
}
- if (options.generate_external_texture_bindings) {
+ if (!options.external_texture_options.bindings_map.empty()) {
// Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
- auto new_bindings_map = GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
+ options.external_texture_options.bindings_map);
manager.Add<transform::MultiplanarExternalTexture>();
}
@@ -89,6 +94,7 @@
polyfills.bgra8unorm = true;
polyfills.bitshift_modulo = true;
polyfills.clamp_int = true;
+ polyfills.conv_f32_to_iu32 = true;
polyfills.count_leading_zeros = true;
polyfills.count_trailing_zeros = true;
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
diff --git a/src/tint/writer/syntax_tree/generator.cc b/src/tint/writer/syntax_tree/generator.cc
new file mode 100644
index 0000000..6919d24
--- /dev/null
+++ b/src/tint/writer/syntax_tree/generator.cc
@@ -0,0 +1,36 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/syntax_tree/generator.h"
+#include "src/tint/writer/syntax_tree/generator_impl.h"
+
+namespace tint::writer::syntax_tree {
+
+Result::Result() = default;
+Result::~Result() = default;
+Result::Result(const Result&) = default;
+
+Result Generate(const Program* program, const Options&) {
+ Result result;
+
+ // Generate the AST dump.
+ auto impl = std::make_unique<GeneratorImpl>(program);
+ result.success = impl->Generate();
+ result.error = impl->error();
+ result.ast = impl->result();
+
+ return result;
+}
+
+} // namespace tint::writer::syntax_tree
diff --git a/src/tint/writer/syntax_tree/generator.h b/src/tint/writer/syntax_tree/generator.h
new file mode 100644
index 0000000..ce81c3f
--- /dev/null
+++ b/src/tint/writer/syntax_tree/generator.h
@@ -0,0 +1,65 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_H_
+#define SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_H_
+
+#include <memory>
+#include <string>
+
+#include "src/tint/writer/text.h"
+
+// Forward declarations
+namespace tint {
+class Program;
+} // namespace tint
+
+namespace tint::writer::syntax_tree {
+
+class GeneratorImpl;
+
+/// Configuration options used for generating AST.
+struct Options {};
+
+/// The result produced when generating AST.
+struct Result {
+ /// Constructor
+ Result();
+
+ /// Destructor
+ ~Result();
+
+ /// Copy constructor
+ Result(const Result&);
+
+ /// True if generation was successful.
+ bool success = false;
+
+ /// The errors generated during code generation, if any.
+ std::string error;
+
+ /// The generated AST.
+ std::string ast = "";
+};
+
+/// Generate an AST dump for a program, according to a set of configuration options.
+/// The result will contain the AST, as well as success status and diagnostic information.
+/// @param program the program to dump
+/// @param options the configuration options to use when dumping
+/// @returns the resulting AST dump and supplementary information
+Result Generate(const Program* program, const Options& options);
+
+} // namespace tint::writer::syntax_tree
+
+#endif // SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_H_
diff --git a/src/tint/writer/syntax_tree/generator_impl.cc b/src/tint/writer/syntax_tree/generator_impl.cc
new file mode 100644
index 0000000..02e6ff7
--- /dev/null
+++ b/src/tint/writer/syntax_tree/generator_impl.cc
@@ -0,0 +1,1358 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/syntax_tree/generator_impl.h"
+
+#include <algorithm>
+
+#include "src/tint/ast/alias.h"
+#include "src/tint/ast/bool_literal_expression.h"
+#include "src/tint/ast/call_statement.h"
+#include "src/tint/ast/float_literal_expression.h"
+#include "src/tint/ast/id_attribute.h"
+#include "src/tint/ast/internal_attribute.h"
+#include "src/tint/ast/interpolate_attribute.h"
+#include "src/tint/ast/invariant_attribute.h"
+#include "src/tint/ast/module.h"
+#include "src/tint/ast/stage_attribute.h"
+#include "src/tint/ast/stride_attribute.h"
+#include "src/tint/ast/struct_member_align_attribute.h"
+#include "src/tint/ast/struct_member_offset_attribute.h"
+#include "src/tint/ast/struct_member_size_attribute.h"
+#include "src/tint/ast/variable_decl_statement.h"
+#include "src/tint/ast/workgroup_attribute.h"
+#include "src/tint/sem/struct.h"
+#include "src/tint/sem/switch_statement.h"
+#include "src/tint/switch.h"
+#include "src/tint/utils/math.h"
+#include "src/tint/utils/scoped_assignment.h"
+#include "src/tint/writer/float_to_string.h"
+
+namespace tint::writer::syntax_tree {
+
+GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
+
+GeneratorImpl::~GeneratorImpl() = default;
+
+bool GeneratorImpl::Generate() {
+ // Generate global declarations in the order they appear in the module.
+ for (auto* decl : program_->AST().GlobalDeclarations()) {
+ if (!Switch(
+ decl, //
+ [&](const ast::DiagnosticDirective* dd) {
+ return EmitDiagnosticControl(dd->control);
+ },
+ [&](const ast::Enable* e) { return EmitEnable(e); },
+ [&](const ast::TypeDecl* td) { return EmitTypeDecl(td); },
+ [&](const ast::Function* func) { return EmitFunction(func); },
+ [&](const ast::Variable* var) { return EmitVariable(var); },
+ [&](const ast::ConstAssert* ca) { return EmitConstAssert(ca); },
+ [&](Default) {
+ TINT_UNREACHABLE(Writer, diagnostics_);
+ return false;
+ })) {
+ return false;
+ }
+ if (decl != program_->AST().GlobalDeclarations().Back()) {
+ line();
+ }
+ }
+
+ return true;
+}
+
+bool GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic) {
+ line() << "DiagnosticControl [severity: " << diagnostic.severity
+ << ", rule: " << program_->Symbols().NameFor(diagnostic.rule_name->symbol) << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitEnable(const ast::Enable* enable) {
+ auto l = line();
+ l << "Enable [";
+ for (auto* ext : enable->extensions) {
+ if (ext != enable->extensions.Front()) {
+ l << ", ";
+ }
+ l << ext->name;
+ }
+ l << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitTypeDecl(const ast::TypeDecl* ty) {
+ return Switch(
+ ty,
+ [&](const ast::Alias* alias) { //
+ line() << "Alias [";
+ {
+ ScopedIndent ai(this);
+
+ line() << "name: " << program_->Symbols().NameFor(alias->name->symbol);
+ line() << "expr: ";
+ {
+ ScopedIndent ex(this);
+ if (!EmitExpression(alias->type)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::Struct* str) { //
+ return EmitStructType(str);
+ },
+ [&](Default) { //
+ diagnostics_.add_error(diag::System::Writer,
+ "unknown declared type: " + std::string(ty->TypeInfo().name));
+ return false;
+ });
+}
+
+bool GeneratorImpl::EmitExpression(const ast::Expression* expr) {
+ return Switch(
+ expr,
+ [&](const ast::IndexAccessorExpression* a) { //
+ return EmitIndexAccessor(a);
+ },
+ [&](const ast::BinaryExpression* b) { //
+ return EmitBinary(b);
+ },
+ [&](const ast::BitcastExpression* b) { //
+ return EmitBitcast(b);
+ },
+ [&](const ast::CallExpression* c) { //
+ return EmitCall(c);
+ },
+ [&](const ast::IdentifierExpression* i) { //
+ return EmitIdentifier(i);
+ },
+ [&](const ast::LiteralExpression* l) { //
+ return EmitLiteral(l);
+ },
+ [&](const ast::MemberAccessorExpression* m) { //
+ return EmitMemberAccessor(m);
+ },
+ [&](const ast::PhonyExpression*) { //
+ line() << "[PhonyExpression]";
+ return true;
+ },
+ [&](const ast::UnaryOpExpression* u) { //
+ return EmitUnaryOp(u);
+ },
+ [&](Default) {
+ diagnostics_.add_error(diag::System::Writer, "unknown expression type");
+ return false;
+ });
+}
+
+bool GeneratorImpl::EmitIndexAccessor(const ast::IndexAccessorExpression* expr) {
+ line() << "IndexAccessorExpression [";
+ {
+ ScopedIndent iae(this);
+ line() << "object: ";
+ {
+ ScopedIndent obj(this);
+ if (!EmitExpression(expr->object)) {
+ return false;
+ }
+ }
+
+ line() << "index: ";
+ {
+ ScopedIndent idx(this);
+ if (!EmitExpression(expr->index)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+
+ return true;
+}
+
+bool GeneratorImpl::EmitMemberAccessor(const ast::MemberAccessorExpression* expr) {
+ line() << "MemberAccessorExpression [";
+ {
+ ScopedIndent mae(this);
+
+ line() << "object: ";
+ {
+ ScopedIndent obj(this);
+ if (!EmitExpression(expr->object)) {
+ return false;
+ }
+ }
+ line() << "member: " << program_->Symbols().NameFor(expr->member->symbol);
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitBitcast(const ast::BitcastExpression* expr) {
+ line() << "BitcastExpression [";
+ {
+ ScopedIndent bc(this);
+ {
+ line() << "type: ";
+ ScopedIndent ty(this);
+ if (!EmitExpression(expr->type)) {
+ return false;
+ }
+ }
+ {
+ line() << "expr: ";
+ ScopedIndent exp(this);
+ if (!EmitExpression(expr->expr)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitCall(const ast::CallExpression* expr) {
+ line() << "Call [";
+ {
+ ScopedIndent cl(this);
+
+ line() << "target: [";
+ {
+ ScopedIndent tgt(this);
+ if (!EmitExpression(expr->target)) {
+ return false;
+ }
+ }
+ line() << "]";
+
+ if (!expr->args.IsEmpty()) {
+ line() << "args: [";
+ {
+ ScopedIndent args(this);
+ for (auto* arg : expr->args) {
+ line() << "arg: [";
+ {
+ ScopedIndent arg_val(this);
+ if (!EmitExpression(arg)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitLiteral(const ast::LiteralExpression* lit) {
+ bool ret = false;
+ line() << "LiteralExpression [";
+ {
+ ScopedIndent le(this);
+ ret = Switch(
+ lit,
+ [&](const ast::BoolLiteralExpression* l) { //
+ line() << (l->value ? "true" : "false");
+ return true;
+ },
+ [&](const ast::FloatLiteralExpression* l) { //
+ // f16 literals are also emitted as float value with suffix "h".
+ // Note that all normal and subnormal f16 values are normal f32 values, and since
+ // NaN and Inf are not allowed to be spelled in literal, it should be fine to emit
+ // f16 literals in this way.
+ if (l->suffix == ast::FloatLiteralExpression::Suffix::kNone) {
+ line() << DoubleToBitPreservingString(l->value);
+ } else {
+ line() << FloatToBitPreservingString(static_cast<float>(l->value)) << l->suffix;
+ }
+ return true;
+ },
+ [&](const ast::IntLiteralExpression* l) { //
+ line() << l->value << l->suffix;
+ return true;
+ },
+ [&](Default) { //
+ diagnostics_.add_error(diag::System::Writer, "unknown literal type");
+ return false;
+ });
+ }
+ line() << "]";
+ return ret;
+}
+
+bool GeneratorImpl::EmitIdentifier(const ast::IdentifierExpression* expr) {
+ bool ret = false;
+ line() << "IdentifierExpression [";
+ {
+ ScopedIndent ie(this);
+ ret = EmitIdentifier(expr->identifier);
+ }
+ line() << "]";
+ return ret;
+}
+
+bool GeneratorImpl::EmitIdentifier(const ast::Identifier* ident) {
+ line() << "Identifier [";
+ {
+ ScopedIndent id(this);
+ if (auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>()) {
+ line() << "Templated [";
+ {
+ ScopedIndent tmpl(this);
+ if (!tmpl_ident->attributes.IsEmpty()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ EmitAttributes(tmpl_ident->attributes);
+ }
+ line() << "]";
+ }
+ line() << "name: " << program_->Symbols().NameFor(ident->symbol);
+ if (!tmpl_ident->arguments.IsEmpty()) {
+ line() << "args: [";
+ {
+ ScopedIndent args(this);
+ for (auto* expr : tmpl_ident->arguments) {
+ if (!EmitExpression(expr)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ } else {
+ line() << program_->Symbols().NameFor(ident->symbol);
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitFunction(const ast::Function* func) {
+ line() << "Function [";
+ {
+ ScopedIndent funct(this);
+
+ if (func->attributes.Length()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ if (!EmitAttributes(func->attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "name: " << program_->Symbols().NameFor(func->name->symbol);
+
+ if (!func->params.IsEmpty()) {
+ line() << "params: [";
+ {
+ ScopedIndent args(this);
+ for (auto* v : func->params) {
+ line() << "param: [";
+ {
+ ScopedIndent param(this);
+ line() << "name: " << program_->Symbols().NameFor(v->name->symbol);
+ if (!v->attributes.IsEmpty()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ if (!EmitAttributes(v->attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "type: [";
+ {
+ ScopedIndent ty(this);
+ if (!EmitExpression(v->type)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ }
+
+ line() << "return: [";
+ {
+ ScopedIndent ret(this);
+
+ if (func->return_type || !func->return_type_attributes.IsEmpty()) {
+ if (!func->return_type_attributes.IsEmpty()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ if (!EmitAttributes(func->return_type_attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+
+ line() << "type: [";
+ {
+ ScopedIndent ty(this);
+ if (!EmitExpression(func->return_type)) {
+ return false;
+ }
+ }
+ line() << "]";
+ } else {
+ line() << "void";
+ }
+ }
+ line() << "]";
+ line() << "body: [";
+ {
+ ScopedIndent bdy(this);
+ if (func->body) {
+ if (!EmitBlockHeader(func->body)) {
+ return false;
+ }
+ if (!EmitStatementsWithIndent(func->body->statements)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitImageFormat(const builtin::TexelFormat fmt) {
+ line() << "builtin::TexelFormat [" << fmt << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitStructType(const ast::Struct* str) {
+ line() << "Struct [";
+ {
+ ScopedIndent strct(this);
+
+ if (str->attributes.Length()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ if (!EmitAttributes(str->attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "name: " << program_->Symbols().NameFor(str->name->symbol);
+ line() << "members: [";
+ {
+ ScopedIndent membs(this);
+
+ for (auto* mem : str->members) {
+ line() << "StructMember[";
+ {
+ ScopedIndent m(this);
+ if (!mem->attributes.IsEmpty()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ if (!EmitAttributes(mem->attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+
+ line() << "name: " << program_->Symbols().NameFor(mem->name->symbol);
+ line() << "type: [";
+ {
+ ScopedIndent ty(this);
+ if (!EmitExpression(mem->type)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ }
+ line() << "]";
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitVariable(const ast::Variable* v) {
+ line() << "Variable [";
+ {
+ ScopedIndent variable(this);
+ if (!v->attributes.IsEmpty()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attr(this);
+ if (!EmitAttributes(v->attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+
+ bool ok = Switch(
+ v, //
+ [&](const ast::Var* var) {
+ if (var->declared_address_space || var->declared_access) {
+ line() << "Var [";
+ {
+ ScopedIndent vr(this);
+ line() << "address_space: [";
+ {
+ ScopedIndent addr(this);
+ if (!EmitExpression(var->declared_address_space)) {
+ return false;
+ }
+ }
+ line() << "]";
+ if (var->declared_access) {
+ line() << "access: [";
+ {
+ ScopedIndent acs(this);
+ if (!EmitExpression(var->declared_access)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ } else {
+ line() << "Var []";
+ }
+ return true;
+ },
+ [&](const ast::Let*) {
+ line() << "Let []";
+ return true;
+ },
+ [&](const ast::Override*) {
+ line() << "Override []";
+ return true;
+ },
+ [&](const ast::Const*) {
+ line() << "Const []";
+ return true;
+ },
+ [&](Default) {
+ TINT_ICE(Writer, diagnostics_) << "unhandled variable type " << v->TypeInfo().name;
+ return false;
+ });
+ if (!ok) {
+ return false;
+ }
+
+ line() << "name: " << program_->Symbols().NameFor(v->name->symbol);
+
+ if (auto ty = v->type) {
+ line() << "type: [";
+ {
+ ScopedIndent vty(this);
+ if (!EmitExpression(ty)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+
+ if (v->initializer != nullptr) {
+ line() << "initializer: [";
+ {
+ ScopedIndent init(this);
+ if (!EmitExpression(v->initializer)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs) {
+ for (auto* attr : attrs) {
+ bool ok = Switch(
+ attr,
+ [&](const ast::WorkgroupAttribute* workgroup) {
+ auto values = workgroup->Values();
+ line() << "WorkgroupAttribute [";
+ {
+ ScopedIndent wg(this);
+ for (size_t i = 0; i < 3; i++) {
+ if (values[i]) {
+ if (!EmitExpression(values[i])) {
+ return false;
+ }
+ }
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::StageAttribute* stage) {
+ line() << "StageAttribute [" << stage->stage << "]";
+ return true;
+ },
+ [&](const ast::BindingAttribute* binding) {
+ line() << "BindingAttribute [";
+ {
+ ScopedIndent ba(this);
+ if (!EmitExpression(binding->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::GroupAttribute* group) {
+ line() << "GroupAttribute [";
+ {
+ ScopedIndent ga(this);
+ if (!EmitExpression(group->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::LocationAttribute* location) {
+ line() << "LocationAttribute [";
+ {
+ ScopedIndent la(this);
+ if (!EmitExpression(location->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::BuiltinAttribute* builtin) {
+ line() << "BuiltinAttribute [";
+ {
+ ScopedIndent ba(this);
+ if (!EmitExpression(builtin->builtin)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::DiagnosticAttribute* diagnostic) {
+ return EmitDiagnosticControl(diagnostic->control);
+ },
+ [&](const ast::InterpolateAttribute* interpolate) {
+ line() << "InterpolateAttribute [";
+ {
+ ScopedIndent ia(this);
+ line() << "type: [";
+ {
+ ScopedIndent ty(this);
+ if (!EmitExpression(interpolate->type)) {
+ return false;
+ }
+ }
+ line() << "]";
+ if (interpolate->sampling) {
+ line() << "sampling: [";
+ {
+ ScopedIndent sa(this);
+ if (!EmitExpression(interpolate->sampling)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::InvariantAttribute*) {
+ line() << "InvariantAttribute []";
+ return true;
+ },
+ [&](const ast::IdAttribute* override_deco) {
+ line() << "IdAttribute [";
+ {
+ ScopedIndent id(this);
+ if (!EmitExpression(override_deco->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::MustUseAttribute*) {
+ line() << "MustUseAttribute []";
+ return true;
+ },
+ [&](const ast::StructMemberOffsetAttribute* offset) {
+ line() << "StructMemberOffsetAttribute [";
+ {
+ ScopedIndent smoa(this);
+ if (!EmitExpression(offset->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::StructMemberSizeAttribute* size) {
+ line() << "StructMemberSizeAttribute [";
+ {
+ ScopedIndent smsa(this);
+ if (!EmitExpression(size->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::StructMemberAlignAttribute* align) {
+ line() << "StructMemberAlignAttribute [";
+ {
+ ScopedIndent smaa(this);
+ if (!EmitExpression(align->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+ },
+ [&](const ast::StrideAttribute* stride) {
+ line() << "StrideAttribute [" << stride->stride << "]";
+ return true;
+ },
+ [&](const ast::InternalAttribute* internal) {
+ line() << "InternalAttribute [" << internal->InternalName() << "]";
+ return true;
+ },
+ [&](Default) {
+ TINT_ICE(Writer, diagnostics_)
+ << "Unsupported attribute '" << attr->TypeInfo().name << "'";
+ return false;
+ });
+
+ if (!ok) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GeneratorImpl::EmitBinary(const ast::BinaryExpression* expr) {
+ line() << "BinaryExpression [";
+ {
+ ScopedIndent be(this);
+ line() << "lhs: [";
+ {
+ ScopedIndent lhs(this);
+
+ if (!EmitExpression(expr->lhs)) {
+ return false;
+ }
+ }
+ line() << "]";
+ line() << "op: [";
+ {
+ ScopedIndent op(this);
+ if (!EmitBinaryOp(expr->op)) {
+ return false;
+ }
+ }
+ line() << "]";
+ line() << "rhs: [";
+ {
+ ScopedIndent rhs(this);
+ if (!EmitExpression(expr->rhs)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitBinaryOp(const ast::BinaryOp op) {
+ switch (op) {
+ case ast::BinaryOp::kAnd:
+ line() << "&";
+ break;
+ case ast::BinaryOp::kOr:
+ line() << "|";
+ break;
+ case ast::BinaryOp::kXor:
+ line() << "^";
+ break;
+ case ast::BinaryOp::kLogicalAnd:
+ line() << "&&";
+ break;
+ case ast::BinaryOp::kLogicalOr:
+ line() << "||";
+ break;
+ case ast::BinaryOp::kEqual:
+ line() << "==";
+ break;
+ case ast::BinaryOp::kNotEqual:
+ line() << "!=";
+ break;
+ case ast::BinaryOp::kLessThan:
+ line() << "<";
+ break;
+ case ast::BinaryOp::kGreaterThan:
+ line() << ">";
+ break;
+ case ast::BinaryOp::kLessThanEqual:
+ line() << "<=";
+ break;
+ case ast::BinaryOp::kGreaterThanEqual:
+ line() << ">=";
+ break;
+ case ast::BinaryOp::kShiftLeft:
+ line() << "<<";
+ break;
+ case ast::BinaryOp::kShiftRight:
+ line() << ">>";
+ break;
+ case ast::BinaryOp::kAdd:
+ line() << "+";
+ break;
+ case ast::BinaryOp::kSubtract:
+ line() << "-";
+ break;
+ case ast::BinaryOp::kMultiply:
+ line() << "*";
+ break;
+ case ast::BinaryOp::kDivide:
+ line() << "/";
+ break;
+ case ast::BinaryOp::kModulo:
+ line() << "%";
+ break;
+ case ast::BinaryOp::kNone:
+ diagnostics_.add_error(diag::System::Writer, "missing binary operation type");
+ return false;
+ }
+ return true;
+}
+
+bool GeneratorImpl::EmitUnaryOp(const ast::UnaryOpExpression* expr) {
+ line() << "UnaryOpExpression [";
+ {
+ ScopedIndent uoe(this);
+ line() << "op: [";
+ {
+ ScopedIndent op(this);
+ switch (expr->op) {
+ case ast::UnaryOp::kAddressOf:
+ line() << "&";
+ break;
+ case ast::UnaryOp::kComplement:
+ line() << "~";
+ break;
+ case ast::UnaryOp::kIndirection:
+ line() << "*";
+ break;
+ case ast::UnaryOp::kNot:
+ line() << "!";
+ break;
+ case ast::UnaryOp::kNegation:
+ line() << "-";
+ break;
+ }
+ }
+ line() << "]";
+ line() << "expr: [";
+ {
+ ScopedIndent ex(this);
+ if (!EmitExpression(expr->expr)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "]";
+
+ return true;
+}
+
+bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
+ {
+ if (!EmitBlockHeader(stmt)) {
+ return false;
+ }
+ }
+ if (!EmitStatementsWithIndent(stmt->statements)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool GeneratorImpl::EmitBlockHeader(const ast::BlockStatement* stmt) {
+ if (!stmt->attributes.IsEmpty()) {
+ line() << "attrs: [";
+ {
+ ScopedIndent attrs(this);
+ if (!EmitAttributes(stmt->attributes)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ return true;
+}
+
+bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
+ return Switch(
+ stmt, //
+ [&](const ast::AssignmentStatement* a) { return EmitAssign(a); },
+ [&](const ast::BlockStatement* b) { return EmitBlock(b); },
+ [&](const ast::BreakStatement* b) { return EmitBreak(b); },
+ [&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); },
+ [&](const ast::CallStatement* c) { return EmitCall(c->expr); },
+ [&](const ast::CompoundAssignmentStatement* c) { return EmitCompoundAssign(c); },
+ [&](const ast::ContinueStatement* c) { return EmitContinue(c); },
+ [&](const ast::DiscardStatement* d) { return EmitDiscard(d); },
+ [&](const ast::IfStatement* i) { return EmitIf(i); },
+ [&](const ast::IncrementDecrementStatement* l) { return EmitIncrementDecrement(l); },
+ [&](const ast::LoopStatement* l) { return EmitLoop(l); },
+ [&](const ast::ForLoopStatement* l) { return EmitForLoop(l); },
+ [&](const ast::WhileStatement* l) { return EmitWhile(l); },
+ [&](const ast::ReturnStatement* r) { return EmitReturn(r); },
+ [&](const ast::ConstAssert* c) { return EmitConstAssert(c); },
+ [&](const ast::SwitchStatement* s) { return EmitSwitch(s); },
+ [&](const ast::VariableDeclStatement* v) { return EmitVariable(v->variable); },
+ [&](Default) {
+ diagnostics_.add_error(diag::System::Writer,
+ "unknown statement type: " + std::string(stmt->TypeInfo().name));
+ return false;
+ });
+}
+
+bool GeneratorImpl::EmitStatements(utils::VectorRef<const ast::Statement*> stmts) {
+ for (auto* s : stmts) {
+ if (!EmitStatement(s)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GeneratorImpl::EmitStatementsWithIndent(utils::VectorRef<const ast::Statement*> stmts) {
+ ScopedIndent si(this);
+ return EmitStatements(stmts);
+}
+
+bool GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
+ line() << "AssignmentStatement [";
+ {
+ ScopedIndent as(this);
+ line() << "lhs: [";
+ {
+ ScopedIndent lhs(this);
+ if (!EmitExpression(stmt->lhs)) {
+ return false;
+ }
+ }
+ line() << "]";
+ line() << "rhs: [";
+ {
+ ScopedIndent rhs(this);
+ if (!EmitExpression(stmt->rhs)) {
+ return false;
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+
+ return true;
+}
+
+bool GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
+ line() << "BreakStatement []";
+ return true;
+}
+
+bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
+ line() << "BreakIfStatement [";
+ {
+ ScopedIndent bis(this);
+ if (!EmitExpression(b->condition)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
+ line() << "CaseStatement [";
+ {
+ ScopedIndent cs(this);
+ if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
+ line() << "selector: default";
+ if (!EmitBlockHeader(stmt->body)) {
+ return false;
+ }
+ } else {
+ line() << "selectors: [";
+ {
+ ScopedIndent sels(this);
+ for (auto* sel : stmt->selectors) {
+ if (sel->IsDefault()) {
+ line() << "default []";
+ } else if (!EmitExpression(sel->expr)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+ if (!EmitBlockHeader(stmt->body)) {
+ return false;
+ }
+ }
+ if (!EmitStatementsWithIndent(stmt->body->statements)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt) {
+ line() << "CompoundAssignmentStatement [";
+ {
+ ScopedIndent cas(this);
+ line() << "lhs: [";
+ {
+ ScopedIndent lhs(this);
+ if (!EmitExpression(stmt->lhs)) {
+ return false;
+ }
+ }
+ line() << "]";
+
+ line() << "op: [";
+ {
+ ScopedIndent op(this);
+ if (!EmitBinaryOp(stmt->op)) {
+ return false;
+ }
+ }
+ line() << "]";
+ line() << "rhs: [";
+ {
+ ScopedIndent rhs(this);
+
+ if (!EmitExpression(stmt->rhs)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
+ line() << "ContinueStatement []";
+ return true;
+}
+
+bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
+ {
+ line() << "IfStatement [";
+ {
+ ScopedIndent ifs(this);
+ line() << "condition: [";
+ {
+ ScopedIndent cond(this);
+ if (!EmitExpression(stmt->condition)) {
+ return false;
+ }
+ }
+ line() << "]";
+ if (!EmitBlockHeader(stmt->body)) {
+ return false;
+ }
+ }
+ line() << "] ";
+ }
+ if (!EmitStatementsWithIndent(stmt->body->statements)) {
+ return false;
+ }
+
+ const ast::Statement* e = stmt->else_statement;
+ while (e) {
+ if (auto* elseif = e->As<ast::IfStatement>()) {
+ {
+ line() << "Else IfStatement [";
+ {
+ ScopedIndent ifs(this);
+ line() << "condition: [";
+ if (!EmitExpression(elseif->condition)) {
+ return false;
+ }
+ }
+ line() << "]";
+ if (!EmitBlockHeader(elseif->body)) {
+ return false;
+ }
+ }
+ line() << "]";
+ if (!EmitStatementsWithIndent(elseif->body->statements)) {
+ return false;
+ }
+ e = elseif->else_statement;
+ } else {
+ auto* body = e->As<ast::BlockStatement>();
+ {
+ line() << "Else [";
+ {
+ ScopedIndent els(this);
+ if (!EmitBlockHeader(body)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ if (!EmitStatementsWithIndent(body->statements)) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+bool GeneratorImpl::EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) {
+ line() << "IncrementDecrementStatement [";
+ {
+ ScopedIndent ids(this);
+ line() << "expr: [";
+ if (!EmitExpression(stmt->lhs)) {
+ return false;
+ }
+ line() << "]";
+ line() << "dir: " << (stmt->increment ? "++" : "--");
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
+ line() << "DiscardStatement []";
+ return true;
+}
+
+bool GeneratorImpl::EmitLoop(const ast::LoopStatement* stmt) {
+ line() << "LoopStatement [";
+ {
+ ScopedIndent ls(this);
+ if (!EmitStatements(stmt->body->statements)) {
+ return false;
+ }
+
+ if (stmt->continuing && !stmt->continuing->Empty()) {
+ line() << "Continuing [";
+ {
+ ScopedIndent cont(this);
+ if (!EmitStatementsWithIndent(stmt->continuing->statements)) {
+ return false;
+ }
+ }
+ line() << "]";
+ }
+ }
+ line() << "]";
+
+ return true;
+}
+
+bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
+ TextBuffer init_buf;
+ if (auto* init = stmt->initializer) {
+ TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
+ if (!EmitStatement(init)) {
+ return false;
+ }
+ }
+
+ TextBuffer cont_buf;
+ if (auto* cont = stmt->continuing) {
+ TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
+ if (!EmitStatement(cont)) {
+ return false;
+ }
+ }
+
+ line() << "ForLoopStatement [";
+ {
+ ScopedIndent fs(this);
+
+ line() << "initializer: [";
+ {
+ ScopedIndent init(this);
+ switch (init_buf.lines.size()) {
+ case 0: // No initializer
+ break;
+ case 1: // Single line initializer statement
+ line() << TrimSuffix(init_buf.lines[0].content, ";");
+ break;
+ default: // Block initializer statement
+ for (size_t i = 1; i < init_buf.lines.size(); i++) {
+ // Indent all by the first line
+ init_buf.lines[i].indent += current_buffer_->current_indent;
+ }
+ line() << TrimSuffix(init_buf.String(), "\n");
+ break;
+ }
+ }
+ line() << "]";
+ line() << "condition: [";
+ {
+ ScopedIndent con(this);
+ if (auto* cond = stmt->condition) {
+ if (!EmitExpression(cond)) {
+ return false;
+ }
+ }
+ }
+
+ line() << "]";
+ line() << "continuing: [";
+ {
+ ScopedIndent cont(this);
+ switch (cont_buf.lines.size()) {
+ case 0: // No continuing
+ break;
+ case 1: // Single line continuing statement
+ line() << TrimSuffix(cont_buf.lines[0].content, ";");
+ break;
+ default: // Block continuing statement
+ for (size_t i = 1; i < cont_buf.lines.size(); i++) {
+ // Indent all by the first line
+ cont_buf.lines[i].indent += current_buffer_->current_indent;
+ }
+ line() << TrimSuffix(cont_buf.String(), "\n");
+ break;
+ }
+ }
+ if (!EmitBlockHeader(stmt->body)) {
+ return false;
+ }
+
+ if (!EmitStatementsWithIndent(stmt->body->statements)) {
+ return false;
+ }
+ }
+ line() << "]";
+
+ return true;
+}
+
+bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
+ line() << "WhileStatement [";
+ {
+ ScopedIndent ws(this);
+ {
+ auto* cond = stmt->condition;
+ if (!EmitExpression(cond)) {
+ return false;
+ }
+ }
+ if (!EmitBlockHeader(stmt->body)) {
+ return false;
+ }
+ if (!EmitStatementsWithIndent(stmt->body->statements)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
+ line() << "ReturnStatement [";
+ {
+ ScopedIndent ret(this);
+ if (stmt->value) {
+ if (!EmitExpression(stmt->value)) {
+ return false;
+ }
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitConstAssert(const ast::ConstAssert* stmt) {
+ line() << "ConstAssert [";
+ {
+ ScopedIndent ca(this);
+ if (!EmitExpression(stmt->condition)) {
+ return false;
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
+ line() << "SwitchStatement [";
+ {
+ ScopedIndent ss(this);
+ line() << "condition: [";
+ {
+ ScopedIndent cond(this);
+ if (!EmitExpression(stmt->condition)) {
+ return false;
+ }
+ }
+ line() << "]";
+
+ {
+ ScopedIndent si(this);
+ for (auto* s : stmt->body) {
+ if (!EmitCase(s)) {
+ return false;
+ }
+ }
+ }
+ }
+ line() << "]";
+ return true;
+}
+
+} // namespace tint::writer::syntax_tree
diff --git a/src/tint/writer/syntax_tree/generator_impl.h b/src/tint/writer/syntax_tree/generator_impl.h
new file mode 100644
index 0000000..8b9a187
--- /dev/null
+++ b/src/tint/writer/syntax_tree/generator_impl.h
@@ -0,0 +1,215 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_IMPL_H_
+#define SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_IMPL_H_
+
+#include <string>
+
+#include "src/tint/ast/assignment_statement.h"
+#include "src/tint/ast/binary_expression.h"
+#include "src/tint/ast/bitcast_expression.h"
+#include "src/tint/ast/break_if_statement.h"
+#include "src/tint/ast/break_statement.h"
+#include "src/tint/ast/compound_assignment_statement.h"
+#include "src/tint/ast/continue_statement.h"
+#include "src/tint/ast/discard_statement.h"
+#include "src/tint/ast/for_loop_statement.h"
+#include "src/tint/ast/if_statement.h"
+#include "src/tint/ast/index_accessor_expression.h"
+#include "src/tint/ast/loop_statement.h"
+#include "src/tint/ast/member_accessor_expression.h"
+#include "src/tint/ast/return_statement.h"
+#include "src/tint/ast/switch_statement.h"
+#include "src/tint/ast/unary_op_expression.h"
+#include "src/tint/program.h"
+#include "src/tint/sem/struct.h"
+#include "src/tint/utils/string_stream.h"
+#include "src/tint/writer/text_generator.h"
+
+namespace tint::writer::syntax_tree {
+
+/// Implementation class for AST generator
+class GeneratorImpl : public TextGenerator {
+ public:
+ /// Constructor
+ /// @param program the program
+ explicit GeneratorImpl(const Program* program);
+ ~GeneratorImpl();
+
+ /// Generates the result data
+ /// @returns true on successful generation; false otherwise
+ bool Generate();
+
+ /// Handles generating a diagnostic control
+ /// @param diagnostic the diagnostic control node
+ /// @returns true if the diagnostic control was emitted
+ bool EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic);
+ /// Handles generating an enable directive
+ /// @param enable the enable node
+ /// @returns true if the enable directive was emitted
+ bool EmitEnable(const ast::Enable* enable);
+ /// Handles generating a declared type
+ /// @param ty the declared type to generate
+ /// @returns true if the declared type was emitted
+ bool EmitTypeDecl(const ast::TypeDecl* ty);
+ /// Handles an index accessor expression
+ /// @param expr the expression to emit
+ /// @returns true if the index accessor was emitted
+ bool EmitIndexAccessor(const ast::IndexAccessorExpression* expr);
+ /// Handles an assignment statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted successfully
+ bool EmitAssign(const ast::AssignmentStatement* stmt);
+ /// Handles generating a binary expression
+ /// @param expr the binary expression
+ /// @returns true if the expression was emitted, false otherwise
+ bool EmitBinary(const ast::BinaryExpression* expr);
+ /// Handles generating a binary operator
+ /// @param op the binary operator
+ /// @returns true if the operator was emitted, false otherwise
+ bool EmitBinaryOp(const ast::BinaryOp op);
+ /// Handles generating a bitcast expression
+ /// @param expr the bitcast expression
+ /// @returns true if the bitcast was emitted
+ bool EmitBitcast(const ast::BitcastExpression* expr);
+ /// Handles a block statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted successfully
+ bool EmitBlock(const ast::BlockStatement* stmt);
+ /// Handles emitting the start of a block statement (including attributes)
+ /// @param stmt the block statement to emit the header for
+ /// @returns true if the statement was emitted successfully
+ bool EmitBlockHeader(const ast::BlockStatement* stmt);
+ /// Handles a break statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted successfully
+ bool EmitBreak(const ast::BreakStatement* stmt);
+ /// Handles a break-if statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted successfully
+ bool EmitBreakIf(const ast::BreakIfStatement* stmt);
+ /// Handles generating a call expression
+ /// @param expr the call expression
+ /// @returns true if the call expression is emitted
+ bool EmitCall(const ast::CallExpression* expr);
+ /// Handles a case statement
+ /// @param stmt the statement
+ /// @returns true if the statment was emitted successfully
+ bool EmitCase(const ast::CaseStatement* stmt);
+ /// Handles a compound assignment statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted successfully
+ bool EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt);
+ /// Handles generating a literal expression
+ /// @param expr the literal expression expression
+ /// @returns true if the literal expression is emitted
+ bool EmitLiteral(const ast::LiteralExpression* expr);
+ /// Handles a continue statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted successfully
+ bool EmitContinue(const ast::ContinueStatement* stmt);
+ /// Handles generate an Expression
+ /// @param expr the expression
+ /// @returns true if the expression was emitted
+ bool EmitExpression(const ast::Expression* expr);
+ /// Handles generating a function
+ /// @param func the function to generate
+ /// @returns true if the function was emitted
+ bool EmitFunction(const ast::Function* func);
+ /// Handles generating an identifier expression
+ /// @param expr the identifier expression
+ /// @returns true if the identifier was emitted
+ bool EmitIdentifier(const ast::IdentifierExpression* expr);
+ /// Handles generating an identifier
+ /// @param ident the identifier
+ /// @returns true if the identifier was emitted
+ bool EmitIdentifier(const ast::Identifier* ident);
+ /// Handles an if statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was successfully emitted
+ bool EmitIf(const ast::IfStatement* stmt);
+ /// Handles an increment/decrement statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was successfully emitted
+ bool EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt);
+ /// Handles generating a discard statement
+ /// @param stmt the discard statement
+ /// @returns true if the statement was successfully emitted
+ bool EmitDiscard(const ast::DiscardStatement* stmt);
+ /// Handles a loop statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emtited
+ bool EmitLoop(const ast::LoopStatement* stmt);
+ /// Handles a for-loop statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emtited
+ bool EmitForLoop(const ast::ForLoopStatement* stmt);
+ /// Handles a while statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emtited
+ bool EmitWhile(const ast::WhileStatement* stmt);
+ /// Handles a member accessor expression
+ /// @param expr the member accessor expression
+ /// @returns true if the member accessor was emitted
+ bool EmitMemberAccessor(const ast::MemberAccessorExpression* expr);
+ /// Handles return statements
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was successfully emitted
+ bool EmitReturn(const ast::ReturnStatement* stmt);
+ /// Handles const assertion statements
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was successfully emitted
+ bool EmitConstAssert(const ast::ConstAssert* stmt);
+ /// Handles statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted
+ bool EmitStatement(const ast::Statement* stmt);
+ /// Handles a statement list
+ /// @param stmts the statements to emit
+ /// @returns true if the statements were emitted
+ bool EmitStatements(utils::VectorRef<const ast::Statement*> stmts);
+ /// Handles a statement list with an increased indentation
+ /// @param stmts the statements to emit
+ /// @returns true if the statements were emitted
+ bool EmitStatementsWithIndent(utils::VectorRef<const ast::Statement*> stmts);
+ /// Handles generating a switch statement
+ /// @param stmt the statement to emit
+ /// @returns true if the statement was emitted
+ bool EmitSwitch(const ast::SwitchStatement* stmt);
+ /// Handles generating a struct declaration
+ /// @param str the struct
+ /// @returns true if the struct is emitted
+ bool EmitStructType(const ast::Struct* str);
+ /// Handles emitting an image format
+ /// @param fmt the format to generate
+ /// @returns true if the format is emitted
+ bool EmitImageFormat(const builtin::TexelFormat fmt);
+ /// Handles a unary op expression
+ /// @param expr the expression to emit
+ /// @returns true if the expression was emitted
+ bool EmitUnaryOp(const ast::UnaryOpExpression* expr);
+ /// Handles generating a variable
+ /// @param var the variable to generate
+ /// @returns true if the variable was emitted
+ bool EmitVariable(const ast::Variable* var);
+ /// Handles generating a attribute list
+ /// @param attrs the attribute list
+ /// @returns true if the attributes were emitted
+ bool EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs);
+};
+
+} // namespace tint::writer::syntax_tree
+
+#endif // SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_IMPL_H_
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index 69aaabd..2b5f474 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -34,6 +34,8 @@
#include "src/tint/ast/workgroup_attribute.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/switch_statement.h"
+#include "src/tint/switch.h"
+#include "src/tint/utils/defer.h"
#include "src/tint/utils/math.h"
#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/writer/float_to_string.h"
@@ -98,7 +100,14 @@
bool GeneratorImpl::EmitEnable(const ast::Enable* enable) {
auto out = line();
- out << "enable " << enable->extension << ";";
+ out << "enable ";
+ for (auto* ext : enable->extensions) {
+ if (ext != enable->extensions.Front()) {
+ out << ", ";
+ }
+ out << ext->name;
+ }
+ out << ";";
return true;
}
@@ -940,6 +949,14 @@
bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
{
auto out = line();
+
+ if (!stmt->attributes.IsEmpty()) {
+ if (!EmitAttributes(out, stmt->attributes)) {
+ return false;
+ }
+ out << " ";
+ }
+
out << "if (";
if (!EmitExpression(out, stmt->condition)) {
return false;
@@ -1049,6 +1066,14 @@
{
auto out = line();
+
+ if (!stmt->attributes.IsEmpty()) {
+ if (!EmitAttributes(out, stmt->attributes)) {
+ return false;
+ }
+ out << " ";
+ }
+
out << "for";
{
ScopedParen sp(out);
@@ -1110,6 +1135,14 @@
bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
{
auto out = line();
+
+ if (!stmt->attributes.IsEmpty()) {
+ if (!EmitAttributes(out, stmt->attributes)) {
+ return false;
+ }
+ out << " ";
+ }
+
out << "while";
{
ScopedParen sp(out);
@@ -1160,6 +1193,14 @@
bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
{
auto out = line();
+
+ if (!stmt->attributes.IsEmpty()) {
+ if (!EmitAttributes(out, stmt->attributes)) {
+ return false;
+ }
+ out << " ";
+ }
+
out << "switch(";
if (!EmitExpression(out, stmt->condition)) {
return false;
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index bf1542c..3ee0d99 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -51,3 +51,18 @@
add_subdirectory("${TINT_THIRD_PARTY_DIR}/vulkan-deps/glslang/src" "${CMAKE_BINARY_DIR}/third_party/glslang" EXCLUDE_FROM_ALL)
endif()
endif()
+
+if (NOT TARGET libabsl)
+ if (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") OR
+ ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang"))
+ add_compile_options(
+ -Wno-array-parameter
+ -Wno-deprecated-builtins
+ -Wno-unknown-warning-option
+ )
+ endif()
+
+ # Recommended setting for compability with future abseil releases.
+ set(ABSL_PROPAGATE_CXX_STD ON)
+ add_subdirectory("${TINT_THIRD_PARTY_DIR}/abseil-cpp" "${CMAKE_CURRENT_BINARY_DIR}/abseil")
+endif()
diff --git a/third_party/gn/abseil-cpp/BUILD.gn b/third_party/gn/abseil-cpp/BUILD.gn
new file mode 100644
index 0000000..60c9406
--- /dev/null
+++ b/third_party/gn/abseil-cpp/BUILD.gn
@@ -0,0 +1,168 @@
+# Copyright 2021 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../scripts/dawn_overrides_with_defaults.gni")
+
+config("absl_config") {
+ if (is_clang) {
+ cflags = [
+ # Allow the use of enable_if()
+ "-Wno-gcc-compat",
+ ]
+ }
+
+ include_dirs = [ "${dawn_abseil_dir}" ]
+}
+
+template("absl_source_set") {
+ source_set(target_name) {
+ forward_variables_from(invoker, "*")
+
+ if (!defined(public_configs)) {
+ public_configs = []
+ }
+ public_configs += [ ":absl_config" ]
+ }
+}
+
+#
+# absl/base
+#
+
+absl_source_set("log_severity") {
+ sources = [ "${dawn_abseil_dir}/absl/base/log_severity.cc" ]
+ public = [ "${dawn_abseil_dir}/absl/base/log_severity.h" ]
+}
+
+absl_source_set("raw_logging_internal") {
+ sources = [ "${dawn_abseil_dir}/absl/base/internal/raw_logging.cc" ]
+ public = [ "${dawn_abseil_dir}/absl/base/internal/raw_logging.h" ]
+ public_deps = [ ":log_severity" ]
+ visibility = [ ":*" ]
+}
+
+absl_source_set("throw_delegate") {
+ sources = [ "${dawn_abseil_dir}/absl/base/internal/throw_delegate.cc" ]
+ public = [ "${dawn_abseil_dir}/absl/base/internal/throw_delegate.h" ]
+ public_deps = [ ":raw_logging_internal" ]
+ visibility = [ ":*" ]
+}
+
+#
+# absl/numeric
+#
+
+absl_source_set("int128") {
+ sources = [
+ "${dawn_abseil_dir}/absl/numeric/int128.cc",
+ "${dawn_abseil_dir}/absl/numeric/int128_have_intrinsic.inc",
+ "${dawn_abseil_dir}/absl/numeric/int128_no_intrinsic.inc",
+ ]
+ public = [ "${dawn_abseil_dir}/absl/numeric/int128.h" ]
+}
+
+#
+# absl/strings
+#
+
+absl_source_set("strings") {
+ sources = [
+ "${dawn_abseil_dir}/absl/strings/ascii.cc",
+ "${dawn_abseil_dir}/absl/strings/charconv.cc",
+ "${dawn_abseil_dir}/absl/strings/escaping.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/charconv_bigint.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/charconv_bigint.h",
+ "${dawn_abseil_dir}/absl/strings/internal/charconv_parse.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/charconv_parse.h",
+ "${dawn_abseil_dir}/absl/strings/internal/memutil.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/memutil.h",
+ "${dawn_abseil_dir}/absl/strings/internal/stl_type_traits.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_join_internal.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_split_internal.h",
+ "${dawn_abseil_dir}/absl/strings/match.cc",
+ "${dawn_abseil_dir}/absl/strings/numbers.cc",
+ "${dawn_abseil_dir}/absl/strings/str_cat.cc",
+ "${dawn_abseil_dir}/absl/strings/str_replace.cc",
+ "${dawn_abseil_dir}/absl/strings/str_split.cc",
+ "${dawn_abseil_dir}/absl/strings/string_view.cc",
+ "${dawn_abseil_dir}/absl/strings/substitute.cc",
+ ]
+ public = [
+ "${dawn_abseil_dir}/absl/strings/ascii.h",
+ "${dawn_abseil_dir}/absl/strings/charconv.h",
+ "${dawn_abseil_dir}/absl/strings/escaping.h",
+ "${dawn_abseil_dir}/absl/strings/internal/string_constant.h",
+ "${dawn_abseil_dir}/absl/strings/match.h",
+ "${dawn_abseil_dir}/absl/strings/numbers.h",
+ "${dawn_abseil_dir}/absl/strings/str_cat.h",
+ "${dawn_abseil_dir}/absl/strings/str_join.h",
+ "${dawn_abseil_dir}/absl/strings/str_replace.h",
+ "${dawn_abseil_dir}/absl/strings/str_split.h",
+ "${dawn_abseil_dir}/absl/strings/string_view.h",
+ "${dawn_abseil_dir}/absl/strings/strip.h",
+ "${dawn_abseil_dir}/absl/strings/substitute.h",
+ ]
+ deps = [
+ ":int128",
+ ":raw_logging_internal",
+ ":strings_internal",
+ ":throw_delegate",
+ ]
+}
+
+absl_source_set("strings_internal") {
+ sources = [
+ "${dawn_abseil_dir}/absl/strings/internal/escaping.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/ostringstream.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/utf8.cc",
+ ]
+ public = [
+ "${dawn_abseil_dir}/absl/strings/internal/char_map.h",
+ "${dawn_abseil_dir}/absl/strings/internal/escaping.h",
+ "${dawn_abseil_dir}/absl/strings/internal/ostringstream.h",
+ "${dawn_abseil_dir}/absl/strings/internal/resize_uninitialized.h",
+ "${dawn_abseil_dir}/absl/strings/internal/utf8.h",
+ ]
+ deps = [ ":raw_logging_internal" ]
+}
+
+absl_source_set("str_format") {
+ public = [ "${dawn_abseil_dir}/absl/strings/str_format.h" ]
+ deps = [ ":str_format_internal" ]
+}
+
+absl_source_set("str_format_internal") {
+ sources = [
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/arg.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/bind.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/extension.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/float_conversion.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/output.cc",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/parser.cc",
+ ]
+ public = [
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/arg.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/bind.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/checker.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/extension.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/float_conversion.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/output.h",
+ "${dawn_abseil_dir}/absl/strings/internal/str_format/parser.h",
+ ]
+ visibility = [ ":*" ]
+ deps = [
+ ":int128",
+ ":strings",
+ ]
+}
diff --git a/tint_overrides_with_defaults.gni b/tint_overrides_with_defaults.gni
index 9e39248..c54915d 100644
--- a/tint_overrides_with_defaults.gni
+++ b/tint_overrides_with_defaults.gni
@@ -72,6 +72,11 @@
tint_build_glsl_writer = true
}
+ # Build the Syntax Tree writer
+ if (!defined(tint_build_syntax_tree_writer)) {
+ tint_build_syntax_tree_writer = false
+ }
+
# Build unittests
if (!defined(tint_build_unittests)) {
tint_build_unittests = true