Import Tint changes from Dawn
Contains manual fixes for:
* BUILD.gn
* CMakeLists.txt
* DEPS
* Doxyfile
* build_overrides/build.gni
* kokoro/linux/docker.sh
* scripts/tint_overrides_with_defaults.gni
* third_party/CMakeLists.txt
And two new files:
* third_party/google_benchmark/BUILD.gn
* third_party/google_benchmark/README.chromium
Changes: - 5784a4bd7a0ca25ff2ec57a2b9759a34621ba51c [tint][utils] Add support for large allocations by Ben Clayton <bclayton@google.com>
- 48a4eabdad4985dff82e2dc897d8245a2df4a36f Fix Combine Sampler transform on function with unused tex... by Shrek Shao <shrekshao@google.com>
- 6d370e591b68d9abb68eb25bf1638476fbe98f15 [ir] Process uncalled functions in DemoteToHelper by James Price <jrprice@google.com>
- d037b6031f0b0e5b4a5122f660ac24bc454f5a55 [tint][gn] Fix cmd generation by Ben Clayton <bclayton@google.com>
- 0c7be2d6360c30922096e3a1bc7e37610dc3013d [spirv-reader] Avoid nested struct deduplication by James Price <jrprice@google.com>
- f1b8a01f97c5567d9f93feb7b276e567849240bb [tint][glsl] Put GLSL validation behind a build flag. by Ben Clayton <bclayton@google.com>
- 49a564c40dd569b29fe9e569cd1ace173a170844 [tint][gn] Only build 'cmd' targets when 'tint_standalone' by Ben Clayton <bclayton@google.com>
- fc9b2c489785c4154d4b8988f25a11ec3f349bc9 [tint][resolver] Error if ptr store type is not storable by Ben Clayton <bclayton@google.com>
- 80b987eccbcb17fe679db6e5801cf956d17fcd36 [tint][build] Guard WGSL reader with tint_build_wgsl_reader by Ben Clayton <bclayton@google.com>
- ddd2f5905b1d725a865e5b558ddf681f7d88ef7d [tint][resolver] Move handling of incomplete types by Ben Clayton <bclayton@google.com>
- 8886d0b3bdb7b3f79d4899d1d9930d17a5d31865 [tint][resolver] Convert abstract-numerics for array() by Ben Clayton <bclayton@google.com>
- 2550b49be0b0f59612e668db92c40dccab108cc4 [tint][build] Guard WGSL writer with tint_build_wgsl_writer by Ben Clayton <bclayton@google.com>
- fe9e9d8c69c02df82bd75f376b8350c337dfa989 Support larger maxInterStageShader limits on D3D and Vulkan by Jiawei Shao <jiawei.shao@intel.com>
- 9bbb27a1c5b945b3815c2f867564c20f34997957 [tint] Add missing build guards by Ben Clayton <bclayton@google.com>
- 3a533674ffa6881844516706307a965cd967da89 [tint][utils] Assert vectors aren't mutated while iterating by Ben Clayton <bclayton@google.com>
- 3cd439bfaf464c0ea5ab2d669febda4bc5651e0a [tint] Resolve types without recursion by Ben Clayton <bclayton@google.com>
- d283e95ad3bfe7c307ede27c6593d5d0b4bfb091 [gn] Add new groups() for various targets, grouped by tar... by Ben Clayton <bclayton@google.com>
- 535535bf1b3de33fa7fb146761afe14f352c256c [tint] Move override tracking into sem objects by Ben Clayton <bclayton@google.com>
- b8ff13ee7e41f9e9d3a8480457c8eef350619b5b [tint] Add sem::Array, derives from core::type::Array by Ben Clayton <bclayton@google.com>
- c3a47ef072710d83dcc6f313d3d96d2f8d65a6f0 [tint][resolver] Add UnresolvedIdentifier, IncompleteType by Ben Clayton <bclayton@google.com>
- 0b4efc53e94e2199a0fc688a14e5f2ce764bec24 [tint] Add setters to sem variable types by Ben Clayton <bclayton@google.com>
- ac72499c0a8a154fdfdc13a6442ef440d69f0ed0 Wrap fuzzer generation in GN tint_has_fuzzers check by Jim Van Verth <jvanverth@google.com>
- 23f3c347a2ea07b88b41657178cd2ed36163f244 [spirv-writer] Clean up some obsolete TODOs by James Price <jrprice@google.com>
- 01c15776a2e8e0b319f157d1e9670ae70a3a96d2 [spirv-writer] Move LiteralOperand to spirv::ir by James Price <jrprice@google.com>
- dc5e5196a03c79fbd4490b58c72dcd8577125bfb [spirv-writer] Add pass-matrix-by-pointer option by James Price <jrprice@google.com>
- ac001956d8395e7ec907b883aed0a9a3c7da023b [tint][IrToProgram] Reconstruct workgroupUniformLoad by Ben Clayton <bclayton@google.com>
- abfb8e09a03b72d8fb03dc105f053336d399cae1 [spirv-writer] Fix ftoi conversion polyfill by James Price <jrprice@google.com>
- 6f071847315a18825f6c217f784d672e75b5bf47 [spirv-writer] Don't hash `const char*` by Austin Eng <enga@chromium.org>
- 5294cb0e9e7f4ca373b7638a92c44f2ed97fb045 Using binding information for SPIR-V/Tint interface by dan sinclair <dsinclair@chromium.org>
- 66b75667e70724cef9912e78c50c25e164163a00 [gn] Disable fuzzers when '[dawn|tint]_has_build' is false by Ben Clayton <bclayton@google.com>
- 99bc3e8ab7b60cad7909571b925d0ed48c75552a [tint][resolver] Rename builder_ to b and make a reference by Ben Clayton <bclayton@google.com>
- c00c569fca7d3e1d40a179e340177815f3292733 [ir] Check for orphaned instructions in validator by James Price <jrprice@google.com>
- 68c25b86e5e2ac299a4c84efa6ac75df31f9b545 [tint][resolver] Move lambdas to methods by Ben Clayton <bclayton@google.com>
- 0eec270d3e1451cec2ffd712b00d3c28b3e47d92 [tint][utils] Add VectorIterator class by Ben Clayton <bclayton@google.com>
- 7d95661d5b198f322edb31a507afecf54d74123a [kokoro] Update GCC to 13 by Ben Clayton <bclayton@google.com>
- e82fe98bd900efceca25ee39099315c2ad8468e0 [tint][ir] Add Disassemble() free function by Ben Clayton <bclayton@google.com>
- 89f9d6d4c49643b5d2d23ee3765d1f183ce38cf9 [tint][ir] Various fixes to IR -> Program by Ben Clayton <bclayton@google.com>
- 1a1da4576f273526876d1b8e4fecfbcf619a9518 [spirv-writer] Combine access instruction chains by James Price <jrprice@google.com>
- 6ab5462857c27c5f08f70a90c9a974d4bfc90b61 [tint][fuzzers] Add tint_wgsl_fuzzer executable by Ben Clayton <bclayton@google.com>
- 415f1bed2988cdb6ae539093f1b86347c6861de6 [ir] Fix use-after-free in MultiplanarExternalTexture by James Price <jrprice@google.com>
- 1d1205c77ca96f18be2cb77fe6278bac0223af77 [fuzzers] Skip *.expected.ir.spvasm files by James Price <jrprice@google.com>
- 089347a5062e47e2761f8f262a21eafe14f7142a [tint] Don't link 'benchmark_main' target by Ben Clayton <bclayton@google.com>
- ef3f5dc888e81edfdddd059b8a1ec06fb913890b [tint] Change signature of ApplySubstituteOverrides() by Ben Clayton <bclayton@google.com>
- a9cc4c1ceb544d3e23e15ec70ee82b1a4b7c7e39 [tint] Add fuzzer target support to 'gen build' by Ben Clayton <bclayton@google.com>
- a324e1a5e0e2a7c1b5e76247a783217c6c71cb65 [ir] Add polyfill for ftoi conversions by James Price <jrprice@google.com>
- ddd6d24e437a54548ac446d009dcfeadf77dc6ad [wgsl][ir] Polyfill workgroupUniformLoad on lower by James Price <jrprice@google.com>
- dcf6c42bed367b79377cdb335e29a6b849e351bb [spirv-writer] Use OpConstantNull for composites by James Price <jrprice@google.com>
- fcda9f809f4d1092372379381c8f32f862fa8238 [tint][bench] Fix linker errors for certain build by Ben Clayton <bclayton@google.com>
- 9d05868b851a00feb884b902f1756f0ed887019e [tint][gn] Remove `testonly = true` from emitted BUILD.gn... by Ben Clayton <bclayton@google.com>
- d09eb2406339e8c4608b425fae3c7a78450b4cb3 [tint][utils] Use [[maybe_unused]] on TINT_STATIC_INIT by Ben Clayton <bclayton@google.com>
- 997c2cbe94dd6a4bb5878d702926b0ef9b2a11ee [tint][utils] Add a TINT_STATIC_INIT() helper by Ben Clayton <bclayton@google.com>
- 9d1b610d7666f3b8081fd83004c7376e8725790b [tint][build] Generate benchmarks for GN and Bazel by Ben Clayton <bclayton@google.com>
- 77a51263418907750a14e1a6b55d31c2c57690c5 [tint] Move ApplySubstitueOverrides() fuzzers -> wgsl/hel... by Ben Clayton <bclayton@google.com>
- 6f2ede60bf320ce42315de35eb257c289e1215f0 [tint] Remove blankline before copyright by Ben Clayton <bclayton@google.com>
- 77350e94b50beb8366b0cfd06fc5afca228387f7 [tint] Support iteration while adding to BlockAllocator by Ben Clayton <bclayton@google.com>
- ffcb82acc65d2c740ddf5ce463c2b52fead00d38 [tint][cmake] Rework targets for fuzzers by Ben Clayton <bclayton@google.com>
- 8c71a15d9019dcfa98454c7dd76f5277ff341a05 [tint] Remove tint_spirv_tools_fuzzers by Ben Clayton <bclayton@google.com>
- b099a8fc31eb4788bc144789c13dc6981055f389 [ir] Add PreservePadding transform by James Price <jrprice@google.com>
- 9ff85267afccef5a8dbd86aea57a4da417fc8d6d [ir] Fix let instructions in BlockDecoratedStructs by James Price <jrprice@google.com>
- c0476283ff86f358c76346d7f014330e5206bf76 [tint] Remove tint_black_box_fuzz_target by Ben Clayton <bclayton@google.com>
- d5fcc3dd1751834721d2bd4b89b2e511f27b2a6b Add support for unorm10-10-10-2 vertex format by François Beaufort <beaufort.francois@gmail.com>
- f744cf4a265f07aab17ad2605a46ec078afdacd6 [ir] Do not automatically add cloned functions by James Price <jrprice@google.com>
- b1c7464f22074e923f90c3fc474cd16c19513ba0 [ir] Use Builder::LoopRange helper by James Price <jrprice@google.com>
- a2bf4bdc476986228397d9584f6c78d08e606cd6 [ir] Fix use-after-free in ShaderIO transform by James Price <jrprice@google.com>
- 8f403335073f241870c4bd9176146c4f20325331 [wgsl][lower] Destroy converted call instructions by James Price <jrprice@google.com>
- d66eeb775802fcf92ddc9995ffd53096f13f9e96 [ir][spirv-writer] Add index to IO output names by James Price <jrprice@google.com>
- 57d9ec4f87f22a562d4221d1e1ed15ecbabf18e3 [tint][fuzzers] Disable concurrency fuzzer for pixel-loca... by Ben Clayton <bclayton@google.com>
- 1ec4835ca75d777a294587d50cb6640dcc6bd740 [ir] Change ir::BindingRemapper to take a set of options. by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: 5784a4bd7a0ca25ff2ec57a2b9759a34621ba51c
Change-Id: Id46f334e607067a4b8bb341bd214dc2b33aa0b05
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/155921
Commit-Queue: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 1a1b671..685e9fe 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -14,14 +14,50 @@
import("scripts/tint_overrides_with_defaults.gni")
+group("benchmarks") {
+ testonly = true
+ deps = [ "src/tint:benchmarks" ]
+}
+
+group("fuzzers") {
+ testonly = true
+ deps = [
+ "src/tint:fuzzers",
+ ]
+}
+
+group("libs") {
+ deps = [
+ "src/tint:libs",
+ ]
+}
+
+group("tests") {
+ testonly = true
+ deps = [
+ "src/tint:tests",
+ ]
+}
+
+group("cmds") {
+ deps = [
+ "src/tint:cmds",
+ ]
+}
+
+group("all") {
+ testonly = true
+ deps = [
+ ":benchmarks",
+ ":cmds",
+ ":fuzzers",
+ ":libs",
+ ":tests",
+ ]
+}
+
# This target is built when no specific target is specified on the command line.
group("default") {
testonly = true
- deps = [
- "src/tint/api",
- "src/tint/fuzzers",
- ]
- if (tint_build_unittests) {
- deps += [ "src/tint/cmd/test" ]
- }
+ deps = [ ":all" ]
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e92ed63..fc95d64 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -285,6 +285,10 @@
set(COMPILER_IS_CLANG TRUE)
endif()
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(COMPILER_IS_GNU TRUE)
+endif()
+
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR COMPILER_IS_CLANG)
set(COMPILER_IS_LIKE_GNU TRUE)
endif()
diff --git a/DEPS b/DEPS
index 84ca13f..4138b73 100644
--- a/DEPS
+++ b/DEPS
@@ -38,15 +38,15 @@
# Dependencies required to use GN/Clang in standalone
'build': {
- 'url': '{chromium_git}/chromium/src/build@8cbb95464bb7f05b442f3ece4951efbe0825a131',
+ 'url': '{chromium_git}/chromium/src/build@5885d3c24833ad72845a52a1b913a2b8bc651b56',
},
'buildtools': {
- 'url': '{chromium_git}/chromium/src/buildtools@70e9f44cbc8bc4c3dff18800ba5d962154a4f2a6',
+ 'url': '{chromium_git}/chromium/src/buildtools@a9a6f0c49d0e8fa0cda37337430b4736ab3dc944',
},
'tools/clang': {
- 'url': '{chromium_git}/chromium/src/tools/clang@fff7f04d30a0687029ddc7e174d5548a525ddf0b',
+ 'url': '{chromium_git}/chromium/src/tools/clang@8f75392b4aa947fb55c7c206b36804229595e4da',
},
'buildtools/clang_format/script': {
@@ -78,7 +78,7 @@
'condition': 'host_os == "win"',
},
- 'buildtools/reclient': {
+ 'buildtools/reclient': {
'packages': [
{
'package': Var('reclient_package') + '${{platform}}',
@@ -88,12 +88,12 @@
'dep_type': 'cipd',
},
- 'buildtools/third_party/libc++/trunk': {
- 'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxx.git@035440c7077237787869cb08ab99bcc8b5ddc97e',
+ 'third_party/libc++/src': {
+ 'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxx.git@84fb809dd6dae36d556dc0bb702c6cc2ce9d4b80',
},
- 'buildtools/third_party/libc++abi/trunk': {
- 'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxxabi.git@b74d7716111d7eda5c03cb8f5dfc940e1c2c0030',
+ 'third_party/libc++abi/src': {
+ 'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxxabi.git@d4760c0af99ccc9bce077960d5ddde4d66146c05',
},
'third_party/ninja': {
@@ -113,14 +113,14 @@
# Dependencies required for testing
'testing': {
- 'url': '{chromium_git}/chromium/src/testing@d5ea1bf4b64781cfe38f207f56f264eb080d06b2',
+ 'url': '{chromium_git}/chromium/src/testing@035a9b18047370df7403758b006e6c9696d6b84d',
},
'third_party/catapult': {
'url': '{chromium_git}/catapult.git@37e879a7d13cbaa4925e09fc02b0f9276e060f0a',
},
- 'third_party/benchmark': {
+ 'third_party/google_benchmark/src': {
'url': '{chromium_git}/external/github.com/google/benchmark.git@efc89f0b524780b1994d5dddd83a92718e5be492',
},
diff --git a/Doxyfile b/Doxyfile
index 8f1bd7d..2cc7f05 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -786,11 +786,8 @@
# Note: If this tag is empty the current directory is searched.
INPUT = CODE_OF_CONDUCT.md \
- src/tint/fuzzers/tint_spirv_tools_fuzzer \
src \
- tools/src \
- src/tint/fuzzers/tint_spirv_tools_fuzzer \
- src/tint/fuzzers/tint_ast_fuzzer
+ tools/src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 11ce9f4..8070462 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -25,6 +25,9 @@
ignore_elf32_limitations = false
}
+# Enables assertions on safety checks in libc++.
+enable_safe_libcxx = true
+
# Detect whether we can use the hermetic XCode like in Chromium and do so if
# possible.
if (host_os == "mac" && use_system_xcode == "") {
diff --git a/kokoro/linux/docker.sh b/kokoro/linux/docker.sh
index bea2fd9..a15ff37 100755
--- a/kokoro/linux/docker.sh
+++ b/kokoro/linux/docker.sh
@@ -105,7 +105,7 @@
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_AST_FUZZER=1"
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_REGEX_FUZZER=1"
elif [ "$BUILD_TOOLCHAIN" == "gcc" ]; then
- using gcc-10
+ using gcc-13
fi
if [ "$BUILD_SANITIZER" == "asan" ]; then
diff --git a/scripts/tint_overrides_with_defaults.gni b/scripts/tint_overrides_with_defaults.gni
index dca626e..0edfb87 100644
--- a/scripts/tint_overrides_with_defaults.gni
+++ b/scripts/tint_overrides_with_defaults.gni
@@ -16,6 +16,16 @@
# This file contains Tint-related build flags.
+if (!defined(tint_standalone)) {
+ tint_standalone = false
+}
+
+if (!defined(tint_has_build)) {
+ tint_has_build = true
+}
+
+tint_has_fuzzers = tint_has_build
+
declare_args() {
# Path to tint checkout
if (!defined(tint_root_dir)) {
@@ -42,6 +52,10 @@
tint_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src"
}
+ if (!defined(tint_build_cmds)) {
+ tint_build_cmds = tint_standalone
+ }
+
# Build the SPIR-V input reader
if (!defined(tint_build_spv_reader)) {
tint_build_spv_reader = true
@@ -77,20 +91,25 @@
tint_build_glsl_writer = true
}
+ # Build the GLSL output validator
+ if (!defined(tint_build_glsl_validator)) {
+ tint_build_glsl_validator = true
+ }
+
# Build the Syntax Tree writer
if (!defined(tint_build_syntax_tree_writer)) {
tint_build_syntax_tree_writer = false
}
- # Build the Tint IR
- if (!defined(tint_build_ir)) {
- tint_build_ir = false
- }
-
# Build unittests
if (!defined(tint_build_unittests)) {
tint_build_unittests = true
}
+
+ # Build benchmarks
+ if (!defined(tint_build_benchmarks)) {
+ tint_build_benchmarks = true
+ }
}
declare_args() {
diff --git a/src/tint/BUILD.bazel b/src/tint/BUILD.bazel
index ca63402..d9b2f7e 100644
--- a/src/tint/BUILD.bazel
+++ b/src/tint/BUILD.bazel
@@ -17,14 +17,15 @@
load(":flags.bzl", "declare_bool_flag", "declare_os_flag")
# Declares the 'tint_build_*' flags that control what parts of Tint get built
-declare_bool_flag(name = "tint_build_glsl_writer", default = False)
-declare_bool_flag(name = "tint_build_hlsl_writer", default = True)
-declare_bool_flag(name = "tint_build_ir", default = True)
-declare_bool_flag(name = "tint_build_msl_writer", default = True)
-declare_bool_flag(name = "tint_build_spv_reader", default = True)
-declare_bool_flag(name = "tint_build_spv_writer", default = True)
-declare_bool_flag(name = "tint_build_wgsl_reader", default = True)
-declare_bool_flag(name = "tint_build_wgsl_writer", default = True)
+declare_bool_flag(name = "tint_build_glsl_writer", default = False)
+declare_bool_flag(name = "tint_build_glsl_validator", default = False)
+declare_bool_flag(name = "tint_build_hlsl_writer", default = True)
+declare_bool_flag(name = "tint_build_ir", default = True)
+declare_bool_flag(name = "tint_build_msl_writer", default = True)
+declare_bool_flag(name = "tint_build_spv_reader", default = True)
+declare_bool_flag(name = "tint_build_spv_writer", default = True)
+declare_bool_flag(name = "tint_build_wgsl_reader", default = True)
+declare_bool_flag(name = "tint_build_wgsl_writer", default = True)
# Declares the 'os' flag that control what OS-specific Tint code gets built
declare_os_flag()
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index d6570a1..1bcdbee 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -83,6 +83,12 @@
defines += [ "TINT_BUILD_GLSL_WRITER=0" ]
}
+ if (tint_build_glsl_validator) {
+ defines += [ "TINT_BUILD_GLSL_VALIDATOR=1" ]
+ } else {
+ defines += [ "TINT_BUILD_GLSL_VALIDATOR=0" ]
+ }
+
if (tint_build_syntax_tree_writer) {
defines += [ "TINT_BUILD_SYNTAX_TREE_WRITER=1" ]
} else {
@@ -194,6 +200,13 @@
}
}
+if (tint_build_benchmarks) {
+ group("google_benchmark") {
+ testonly = true
+ public_deps = [ "//third_party/google_benchmark" ]
+ }
+}
+
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
@@ -210,11 +223,69 @@
}
###############################################################################
-# Aliases.
+# Fuzzers
###############################################################################
-if (tint_build_unittests) {
- group("tint_unittests") {
- testonly = true
- public_deps = [ "${tint_src_dir}/cmd/test" ]
+if (tint_has_fuzzers) {
+ action("tint_generate_wgsl_corpus") {
+ script = "${tint_src_dir}/cmd/fuzz/wgsl/generate_wgsl_corpus.py"
+ sources = [ "${tint_src_dir}/cmd/fuzz/wgsl/generate_wgsl_corpus.py" ]
+ args = [
+ "--stamp=" + rebase_path(fuzzer_corpus_wgsl_stamp, root_build_dir),
+ rebase_path("${tint_root_dir}/test", root_build_dir),
+ rebase_path(fuzzer_corpus_wgsl_dir, root_build_dir),
+ ]
+ outputs = [ fuzzer_corpus_wgsl_stamp ]
}
}
+
+###############################################################################
+# Groups
+###############################################################################
+group("libs") {
+ deps = [ "${tint_src_dir}/api" ]
+}
+
+group("cmds") {
+ deps = []
+ if (tint_build_cmds) {
+ deps += [
+ "${tint_src_dir}/cmd/remote_compile",
+ "${tint_src_dir}/cmd/tint",
+ ]
+ }
+}
+
+group("fuzzers") {
+ testonly = true
+ deps = []
+ if (tint_has_fuzzers) {
+ deps += [
+ "${tint_src_dir}/cmd/fuzz/wgsl",
+ "${tint_src_dir}/fuzzers",
+ ]
+ }
+}
+
+group("tests") {
+ testonly = true
+ deps = []
+ if (tint_build_unittests) {
+ deps += [ "${tint_src_dir}/cmd/test:test_cmd" ]
+ }
+}
+
+group("benchmarks") {
+ testonly = true
+ deps = []
+ if (tint_build_benchmarks) {
+ deps += [ "${tint_src_dir}/cmd/bench:bench_cmd" ]
+ }
+}
+
+###############################################################################
+# Aliases
+###############################################################################
+group("tint_unittests") {
+ testonly = true
+ public_deps = [ ":tests" ]
+}
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 2f3e893..d674fde 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -37,12 +37,17 @@
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_SPV_READER=$<BOOL:${TINT_BUILD_SPV_READER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_WGSL_READER=$<BOOL:${TINT_BUILD_WGSL_READER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_GLSL_WRITER=$<BOOL:${TINT_BUILD_GLSL_WRITER}>)
+ target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_GLSL_VALIDATOR=$<BOOL:${TINT_BUILD_GLSL_VALIDATOR}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_HLSL_WRITER=$<BOOL:${TINT_BUILD_HLSL_WRITER}>)
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}>)
+ if(TINT_BUILD_FUZZERS)
+ target_compile_options(${TARGET} PRIVATE "-fsanitize=fuzzer")
+ endif()
+
common_compile_options(${TARGET})
endfunction()
@@ -74,6 +79,12 @@
-Weverything
)
+ if(COMPILER_IS_GNU)
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
+ # Despite the bug being closed, false-positives still seen in GCC-13.
+ target_compile_options(${TARGET} PRIVATE -Wno-maybe-uninitialized)
+ endif(COMPILER_IS_GNU)
+
if(COMPILER_IS_LIKE_GNU)
target_compile_options(${TARGET} PRIVATE
-pedantic-errors
@@ -82,13 +93,9 @@
if(COMPILER_IS_CLANG)
if(IS_DEBUG_BUILD)
- target_compile_options(${TARGET} PRIVATE
- -fstandalone-debug
- )
+ target_compile_options(${TARGET} PRIVATE -fstandalone-debug)
endif()
- target_compile_options(${TARGET} PRIVATE
- ${COMMON_CLANG_OPTIONS}
- )
+ target_compile_options(${TARGET} PRIVATE ${COMMON_CLANG_OPTIONS})
endif()
endif(COMPILER_IS_LIKE_GNU)
@@ -171,13 +178,11 @@
function(tint_bench_compile_options TARGET)
tint_core_compile_options(${TARGET})
- set_target_properties(${TARGET} PROPERTIES FOLDER "Benchmarks")
- target_link_libraries(${TARGET} PRIVATE benchmark::benchmark)
- if(TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER)
- target_compile_definitions(${TARGET} PRIVATE
- "TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER=\"${TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER}\""
- )
- endif()
+endfunction()
+
+function(tint_fuzz_compile_options TARGET)
+ tint_core_compile_options(${TARGET})
+ set_target_properties(${TARGET} PROPERTIES FOLDER "Fuzzers")
endfunction()
function(tint_test_cmd_compile_options TARGET)
@@ -201,20 +206,28 @@
target_link_libraries(${TARGET} PRIVATE benchmark::benchmark)
endfunction()
-function(tint_fuzzer_compile_options TARGET)
- tint_default_compile_options(${TARGET})
- target_link_libraries(${TARGET} PRIVATE "tint_api${TINT_FUZZ_SUFFIX}")
+function(tint_fuzz_cmd_compile_options TARGET)
+ tint_fuzz_compile_options(${TARGET})
if(NOT "${TINT_LIB_FUZZING_ENGINE_LINK_OPTIONS}" STREQUAL "")
- # This is set when the fuzzers are being built by OSS${TINT_FUZZ_SUFFIX}. In this case the
- # variable provides the necessary linker flags, and OSS${TINT_FUZZ_SUFFIX} will take care
+ # This is set when the fuzzers are being built by OSS-Fuzz. In this case the
+ # variable provides the necessary linker flags, and OSS-Fuzz will take care
# of passing suitable compiler flags.
target_link_options(${TARGET} PUBLIC ${TINT_LIB_FUZZING_ENGINE_LINK_OPTIONS})
else()
- # When the fuzzers are being built outside of OSS${TINT_FUZZ_SUFFIX}, specific libFuzzer
+ # When the fuzzers are being built outside of OSS-Fuzz, specific libFuzzer
# arguments to enable fuzzing are used.
target_link_options(${TARGET} PUBLIC -fsanitize=fuzzer -fsanitize-coverage=trace-cmp)
endif()
+
+ # Link the version of tint_api with -sanitize=fuzzer enabled
+ target_link_libraries(${TARGET} PRIVATE "tint_api_sanitize_fuzzer")
+endfunction()
+
+# TODO(bclayton): Remove this when fuzzers fully migrated to gen build
+function(tint_fuzzer_compile_options TARGET)
+ tint_fuzz_cmd_compile_options(${TARGET})
+ target_link_libraries(${TARGET} PRIVATE "tint_api_sanitize_fuzzer")
endfunction()
if(TINT_ENABLE_BREAK_IN_DEBUGGER)
@@ -223,17 +236,6 @@
endif()
################################################################################
-# Fuzzers
-################################################################################
-if(TINT_BUILD_FUZZERS)
- if(NOT COMPILER_IS_CLANG)
- message(FATAL_ERROR "TINT_BUILD_FUZZERS can only be enabled with the Clang toolchain")
- endif()
- add_subdirectory(fuzzers)
- set(TINT_FUZZ_SUFFIX "_fuzz")
-endif()
-
-################################################################################
# Benchmarks
################################################################################
if(TINT_BUILD_BENCHMARKS AND TINT_EXTERNAL_BENCHMARK_CORPUS_DIR)
@@ -282,17 +284,16 @@
# Functions used by BUILD.cmake files
# The CMake build handles the target kinds in different ways:
# 'cmd' - Translates to a CMake executable target.
-# 'lib' - Translates to CMake static library.
-# If TINT_BUILD_FUZZERS is enabled, then a second static library with
-# the ${TINT_FUZZ_SUFFIX} suffix is also created. This is done because
-# the fuzzer build requires compilation with the '-fsanitize=fuzzer'
-# flag, which results in a separate set of compilation units.
+# 'lib' - Translates to a CMake static library.
# 'test' - Translates to a CMake object library, configured for compiling and
# linking against google-test.
# 'bench' - Translates to a CMake object library, configured for compiling and
# linking against google-benchmark.
+# 'fuzz' - Translates to a CMake object library, configured for compiling and
+# linking against libfuzzer.
# 'test_cmd' - Translates to a CMake executable target linked against google-test.
# 'bench_cmd' - Translates to a CMake executable target linked against google-benchmark.
+# 'fuzz_cmd' - Translates to a CMake executable target linked against libfuzz.
# See also: docs/tint/gen.md
################################################################################
@@ -310,24 +311,20 @@
if(TINT_BUILD_CMD_TOOLS)
set(IS_ENABLED TRUE PARENT_SCOPE)
endif()
- elseif(${KIND} STREQUAL test_cmd)
- if(TINT_BUILD_TESTS)
- set(IS_ENABLED TRUE PARENT_SCOPE)
- endif()
- elseif(${KIND} STREQUAL bench_cmd)
- if(TINT_BUILD_BENCHMARKS)
- set(IS_ENABLED TRUE PARENT_SCOPE)
- endif()
- elseif(${KIND} STREQUAL test)
- if(TINT_BUILD_TESTS)
- set(IS_ENABLED TRUE PARENT_SCOPE)
- endif()
- elseif(${KIND} STREQUAL bench)
- if(TINT_BUILD_BENCHMARKS)
- set(IS_ENABLED TRUE PARENT_SCOPE)
- endif()
elseif(${KIND} STREQUAL lib)
set(IS_ENABLED TRUE PARENT_SCOPE)
+ elseif((${KIND} STREQUAL test) OR (${KIND} STREQUAL test_cmd))
+ if(TINT_BUILD_TESTS)
+ set(IS_ENABLED TRUE PARENT_SCOPE)
+ endif()
+ elseif((${KIND} STREQUAL bench) OR (${KIND} STREQUAL bench_cmd))
+ if(TINT_BUILD_BENCHMARKS)
+ set(IS_ENABLED TRUE PARENT_SCOPE)
+ endif()
+ elseif((${KIND} STREQUAL fuzz) OR (${KIND} STREQUAL fuzz_cmd))
+ if(TINT_BUILD_FUZZERS)
+ set(IS_ENABLED TRUE PARENT_SCOPE)
+ endif()
else()
message(FATAL_ERROR "unhandled target kind ${KIND}")
endif()
@@ -343,6 +340,7 @@
# KIND - The target kind
# SOURCES - a list of source files, relative to this directory
function(tint_add_target TARGET KIND)
+ set(TARGET "${TARGET}${TINT_TARGET_SUFFIX}") # Apply suffix
set(SOURCES ${ARGN})
tint_check_target_is_enabled(IS_ENABLED ${KIND})
@@ -359,21 +357,6 @@
)
endif()
tint_default_compile_options(${TARGET})
-
- if(TINT_BUILD_FUZZERS)
- # Create a second library target for use of the fuzzers, with the
- # ${TINT_FUZZ_SUFFIX} suffix
- set(FUZZ_TARGET "${TARGET}${TINT_FUZZ_SUFFIX}")
- add_library(${FUZZ_TARGET} STATIC EXCLUDE_FROM_ALL)
- target_sources(${FUZZ_TARGET} PRIVATE ${SOURCES})
- if (TINT_ENABLE_INSTALL)
- install(TARGETS ${FUZZ_TARGET}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- )
- endif()
- tint_default_compile_options(${FUZZ_TARGET})
- endif()
elseif(${KIND} STREQUAL cmd)
add_executable(${TARGET})
tint_default_compile_options(${TARGET})
@@ -383,12 +366,18 @@
elseif(${KIND} STREQUAL bench_cmd)
add_executable(${TARGET})
tint_bench_cmd_compile_options(${TARGET})
+ elseif(${KIND} STREQUAL fuzz_cmd)
+ add_executable(${TARGET})
+ tint_fuzz_cmd_compile_options(${TARGET})
elseif(${KIND} STREQUAL test)
add_library(${TARGET} OBJECT EXCLUDE_FROM_ALL)
tint_test_compile_options(${TARGET})
elseif(${KIND} STREQUAL bench)
add_library(${TARGET} OBJECT EXCLUDE_FROM_ALL)
tint_bench_compile_options(${TARGET})
+ elseif(${KIND} STREQUAL fuzz)
+ add_library(${TARGET} OBJECT EXCLUDE_FROM_ALL)
+ tint_fuzz_compile_options(${TARGET})
else()
message(FATAL_ERROR "unhandled target kind ${KIND}")
endif()
@@ -406,6 +395,7 @@
# KIND - The target kind
# SOURCES - a list of source files, relative to this directory
function(tint_target_add_sources TARGET KIND)
+ set(TARGET "${TARGET}${TINT_TARGET_SUFFIX}") # Apply suffix
set(SOURCES ${ARGN})
tint_check_target_is_enabled(IS_ENABLED ${KIND})
@@ -414,12 +404,6 @@
endif()
target_sources(${TARGET} PRIVATE ${SOURCES})
-
- # If there's a corresponding fuzz target for this target, also append the files to that target
- set(FUZZ_TARGET "${TARGET}${TINT_FUZZ_SUFFIX}")
- if(TARGET "${FUZZ_TARGET}")
- target_sources("${FUZZ_TARGET}" PRIVATE ${SOURCES})
- endif()
endfunction()
# tint_target_add_dependencies(TARGET DEPENDENCIES...)
@@ -431,6 +415,7 @@
# KIND - The target kind
# DEPENDENCIES - a list of target names
function(tint_target_add_dependencies TARGET KIND)
+ set(TARGET "${TARGET}${TINT_TARGET_SUFFIX}") # Apply suffix
set(DEPENDENCIES ${ARGN})
tint_check_target_is_enabled(IS_ENABLED ${KIND})
@@ -438,21 +423,14 @@
return() # Target is disabled via build flags
endif()
+ # Apply target suffix
+ set(SUFFIXED_DEPENDENCIES "")
+ foreach(DEPENDENCY ${DEPENDENCIES})
+ list(APPEND SUFFIXED_DEPENDENCIES "${DEPENDENCY}${TINT_TARGET_SUFFIX}")
+ endforeach()
+
# Register the dependencies
- target_link_libraries(${TARGET} PRIVATE ${DEPENDENCIES})
-
- # If there's a corresponding fuzz target for this target, add the corresponding fuzz dependencies
- # to the fuzz target.
- set(FUZZ_TARGET "${TARGET}${TINT_FUZZ_SUFFIX}")
- if(TARGET "${FUZZ_TARGET}")
- set(FUZZ_DEPENDENCIES "")
-
- foreach(TARGET ${DEPENDENCIES})
- list(APPEND FUZZ_DEPENDENCIES "${TARGET}${TINT_FUZZ_SUFFIX}")
- endforeach()
-
- target_link_libraries("${FUZZ_TARGET}" PRIVATE ${FUZZ_DEPENDENCIES})
- endif()
+ target_link_libraries(${TARGET} PRIVATE ${SUFFIXED_DEPENDENCIES})
endfunction()
# tint_target_add_external_dependencies(TARGET KIND DEPENDENCIES...)
@@ -465,7 +443,8 @@
# DEPENDENCIES - a list of external target names
#
# See src/tint/externals.json for the list of external dependencies.
-function(tint_target_add_external_dependencies UNSUFFIXED_TARGET KIND)
+function(tint_target_add_external_dependencies TARGET KIND)
+ set(TARGET "${TARGET}${TINT_TARGET_SUFFIX}") # Apply suffix
set(DEPENDENCIES ${ARGN})
tint_check_target_is_enabled(IS_ENABLED ${KIND})
@@ -473,67 +452,67 @@
return() # Target is disabled via build flags
endif()
- # Build a list of targets that we're going to operate on
- set(TARGETS ${UNSUFFIXED_TARGET})
- if(TARGET "${UNSUFFIXED_TARGET}${TINT_FUZZ_SUFFIX}")
- list(APPEND TARGETS "${UNSUFFIXED_TARGET}${TINT_FUZZ_SUFFIX}")
- endif()
-
- foreach(TARGET ${TARGETS})
- foreach(DEPENDENCY ${DEPENDENCIES}) # Each external dependency requires special handling...
- if(${DEPENDENCY} STREQUAL "abseil")
- target_link_libraries(${TARGET} PRIVATE
- absl_strings
+ foreach(DEPENDENCY ${DEPENDENCIES}) # Each external dependency requires special handling...
+ if(${DEPENDENCY} STREQUAL "abseil")
+ target_link_libraries(${TARGET} PRIVATE
+ absl_strings
+ )
+ elseif(${DEPENDENCY} STREQUAL "glslang")
+ target_link_libraries(${TARGET} PRIVATE glslang)
+ if(NOT MSVC)
+ target_compile_options(${TARGET} PRIVATE
+ -Wno-reserved-id-macro
+ -Wno-shadow-field-in-constructor
+ -Wno-shadow
+ -Wno-weak-vtables
)
- elseif(${DEPENDENCY} STREQUAL "glslang")
- target_link_libraries(${TARGET} PRIVATE glslang)
- if(NOT MSVC)
- target_compile_options(${TARGET} PRIVATE
- -Wno-reserved-id-macro
- -Wno-shadow-field-in-constructor
- -Wno-shadow
- -Wno-weak-vtables
- )
- endif()
- elseif(${DEPENDENCY} STREQUAL "glslang-res-limits")
- target_link_libraries(${TARGET} PRIVATE
- glslang-default-resource-limits
- )
- elseif(${DEPENDENCY} STREQUAL "gtest")
- target_include_directories(${TARGET} PRIVATE ${gmock_SOURCE_DIR}/include)
- target_link_libraries(${TARGET} PRIVATE gmock)
- elseif(${DEPENDENCY} STREQUAL "metal")
- find_library(CoreGraphicsFramework CoreGraphics REQUIRED)
- find_library(FoundationFramework Foundation REQUIRED)
- find_library(MetalFramework Metal REQUIRED)
- target_link_libraries(${TARGET} PRIVATE
- ${CoreGraphicsFramework}
- ${FoundationFramework}
- ${MetalFramework}
- )
- elseif(${DEPENDENCY} STREQUAL "spirv-headers")
- tint_spvheaders_compile_options(${TARGET})
- elseif(${DEPENDENCY} STREQUAL "spirv-tools")
- tint_spvtools_compile_options(${TARGET})
- elseif(${DEPENDENCY} STREQUAL "spirv-opt-internal")
- target_link_libraries(${TARGET} PRIVATE
- SPIRV-Tools-opt
- )
- target_include_directories(${TARGET} PRIVATE
- "${TINT_SPIRV_TOOLS_DIR}"
- "${TINT_SPIRV_TOOLS_DIR}/include"
- "${TINT_SPIRV_TOOLS_DIR}/source"
- "${spirv-tools_BINARY_DIR}"
- )
- elseif(${DEPENDENCY} STREQUAL "thread")
- find_package(Threads REQUIRED)
- target_link_libraries(${TARGET} PRIVATE Threads::Threads)
- elseif(${DEPENDENCY} STREQUAL "winsock")
- target_link_libraries(${TARGET} PRIVATE ws2_32)
- else()
- message(FATAL_ERROR "unhandled external dependency ${DEPENDENCY}")
endif()
- endforeach()
+ elseif(${DEPENDENCY} STREQUAL "glslang-res-limits")
+ target_link_libraries(${TARGET} PRIVATE
+ glslang-default-resource-limits
+ )
+ elseif(${DEPENDENCY} STREQUAL "google-benchmark")
+ set_target_properties(${TARGET} PROPERTIES FOLDER "Benchmarks")
+ target_link_libraries(${TARGET} PRIVATE benchmark::benchmark)
+ if(TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER)
+ target_compile_definitions(${TARGET} PRIVATE
+ "TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER=\"${TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER}\""
+ )
+ endif()
+ elseif(${DEPENDENCY} STREQUAL "gtest")
+ target_include_directories(${TARGET} PRIVATE ${gmock_SOURCE_DIR}/include)
+ target_link_libraries(${TARGET} PRIVATE gmock)
+ elseif(${DEPENDENCY} STREQUAL "metal")
+ find_library(CoreGraphicsFramework CoreGraphics REQUIRED)
+ find_library(FoundationFramework Foundation REQUIRED)
+ find_library(MetalFramework Metal REQUIRED)
+ target_link_libraries(${TARGET} PRIVATE
+ ${CoreGraphicsFramework}
+ ${FoundationFramework}
+ ${MetalFramework}
+ )
+ elseif(${DEPENDENCY} STREQUAL "spirv-headers")
+ tint_spvheaders_compile_options(${TARGET})
+ elseif(${DEPENDENCY} STREQUAL "spirv-tools")
+ tint_spvtools_compile_options(${TARGET})
+ elseif(${DEPENDENCY} STREQUAL "spirv-opt-internal")
+ target_link_libraries(${TARGET} PRIVATE
+ SPIRV-Tools-opt
+ )
+ target_include_directories(${TARGET} PRIVATE
+ "${TINT_SPIRV_TOOLS_DIR}"
+ "${TINT_SPIRV_TOOLS_DIR}/include"
+ "${TINT_SPIRV_TOOLS_DIR}/source"
+ "${spirv-tools_BINARY_DIR}"
+ )
+ elseif(${DEPENDENCY} STREQUAL "thread")
+ find_package(Threads REQUIRED)
+ target_link_libraries(${TARGET} PRIVATE Threads::Threads)
+ elseif(${DEPENDENCY} STREQUAL "winsock")
+ target_link_libraries(${TARGET} PRIVATE ws2_32)
+ else()
+ message(FATAL_ERROR "unhandled external dependency ${DEPENDENCY}")
+ endif()
endforeach()
endfunction()
@@ -546,6 +525,7 @@
# KIND - The target kind
# OUTPUT_NAME - the new name for the target output
function(tint_target_set_output_name TARGET KIND OUTPUT_NAME)
+ set(TARGET "${TARGET}${TINT_TARGET_SUFFIX}") # Apply suffix
tint_check_target_is_enabled(IS_ENABLED ${KIND})
if(NOT IS_ENABLED)
return() # Target is disabled via build flags
@@ -558,12 +538,18 @@
add_library(${OUTPUT_NAME} ALIAS ${TARGET})
elseif(${KIND} STREQUAL test)
add_library(${OUTPUT_NAME} ALIAS ${TARGET})
+ elseif(${KIND} STREQUAL bench)
+ add_library(${OUTPUT_NAME} ALIAS ${TARGET})
+ elseif(${KIND} STREQUAL fuzz)
+ add_library(${OUTPUT_NAME} ALIAS ${TARGET})
elseif(${KIND} STREQUAL cmd)
add_executable(${OUTPUT_NAME} ALIAS ${TARGET})
elseif(${KIND} STREQUAL test_cmd)
add_executable(${OUTPUT_NAME} ALIAS ${TARGET})
elseif(${KIND} STREQUAL bench_cmd)
add_executable(${OUTPUT_NAME} ALIAS ${TARGET})
+ elseif(${KIND} STREQUAL fuzz_cmd)
+ add_executable(${OUTPUT_NAME} ALIAS ${TARGET})
else()
message(FATAL_ERROR "unhandled target kind ${KIND}")
endif()
@@ -572,7 +558,44 @@
################################################################################
# Include the generated build files
################################################################################
-include("BUILD.cmake")
+if(TINT_BUILD_FUZZERS)
+ if(NOT COMPILER_IS_CLANG)
+ message(FATAL_ERROR "TINT_BUILD_FUZZERS can only be enabled with the Clang toolchain")
+ endif()
+
+ # Save the current build flags
+ set(SAVE_TINT_BUILD_CMD_TOOLS ${TINT_BUILD_CMD_TOOLS})
+ set(SAVE_TINT_BUILD_TESTS ${TINT_BUILD_TESTS})
+ set(SAVE_TINT_BUILD_BENCHMARKS ${TINT_BUILD_BENCHMARKS})
+ set(SAVE_TINT_BUILD_FUZZERS ${TINT_BUILD_FUZZERS})
+ set(SAVE_TINT_TARGET_SUFFIX ${TINT_TARGET_SUFFIX})
+
+ # Declare the targets with fuzzers disabled
+ set(TINT_BUILD_FUZZERS FALSE)
+ include("BUILD.cmake")
+
+ # Now redeclare the fuzzers targets with a '_sanitize_fuzzer' target suffix
+ # Enabling TINT_BUILD_FUZZERS will enable the -fsanitize=fuzzer compilation flag for these
+ # targets.
+ set(TINT_TARGET_SUFFIX "_sanitize_fuzzer")
+ set(TINT_BUILD_FUZZERS TRUE)
+ set(TINT_BUILD_CMD_TOOLS FALSE)
+ set(TINT_BUILD_TESTS FALSE)
+ set(TINT_BUILD_BENCHMARKS FALSE)
+ include("BUILD.cmake")
+ add_subdirectory(fuzzers)
+
+ # Restore the build flags
+ set(TINT_BUILD_CMD_TOOLS ${SAVE_TINT_BUILD_CMD_TOOLS})
+ set(TINT_BUILD_TESTS ${SAVE_TINT_BUILD_TESTS})
+ set(TINT_BUILD_BENCHMARKS ${SAVE_TINT_BUILD_BENCHMARKS})
+ set(TINT_BUILD_FUZZERS ${SAVE_TINT_BUILD_FUZZERS})
+ set(TINT_TARGET_SUFFIX ${SAVE_TINT_TARGET_SUFFIX})
+else()
+ # Fuzzers not enabled. Just include BUILD.cmake with the current flags.
+ include("BUILD.cmake")
+endif(TINT_BUILD_FUZZERS)
+
################################################################################
# Bespoke target settings
diff --git a/src/tint/api/BUILD.bazel b/src/tint/api/BUILD.bazel
index 885b21d..534fd1b 100644
--- a/src/tint/api/BUILD.bazel
+++ b/src/tint/api/BUILD.bazel
@@ -43,9 +43,7 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -87,6 +85,16 @@
"//src/tint/lang/spirv/writer/common",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -117,3 +125,13 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
diff --git a/src/tint/api/BUILD.cmake b/src/tint/api/BUILD.cmake
index 697a9f0..14e5cda 100644
--- a/src/tint/api/BUILD.cmake
+++ b/src/tint/api/BUILD.cmake
@@ -45,9 +45,7 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -95,3 +93,15 @@
tint_lang_spirv_writer_common
)
endif(TINT_BUILD_SPV_WRITER)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_api lib
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_api lib
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
diff --git a/src/tint/api/BUILD.gn b/src/tint/api/BUILD.gn
index b1e798a..8e20ff6 100644
--- a/src/tint/api/BUILD.gn
+++ b/src/tint/api/BUILD.gn
@@ -42,9 +42,7 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -88,4 +86,12 @@
"${tint_src_dir}/lang/spirv/writer/common",
]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
diff --git a/src/tint/cmd/BUILD.cmake b/src/tint/cmd/BUILD.cmake
index 2315cbe..889a33e 100644
--- a/src/tint/cmd/BUILD.cmake
+++ b/src/tint/cmd/BUILD.cmake
@@ -23,6 +23,7 @@
include(cmd/bench/BUILD.cmake)
include(cmd/common/BUILD.cmake)
+include(cmd/fuzz/BUILD.cmake)
include(cmd/info/BUILD.cmake)
include(cmd/loopy/BUILD.cmake)
include(cmd/remote_compile/BUILD.cmake)
diff --git a/src/tint/cmd/bench/BUILD.bazel b/src/tint/cmd/bench/BUILD.bazel
index 62a4335..950f723 100644
--- a/src/tint/cmd/bench/BUILD.bazel
+++ b/src/tint/cmd/bench/BUILD.bazel
@@ -25,59 +25,22 @@
load("@bazel_skylib//lib:selects.bzl", "selects")
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
- "benchmark.cc",
- ],
- hdrs = [
+ "bench.cc",
"bench.h",
],
deps = [
- "//src/tint/lang/core",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/sem",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/id",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "//src/tint/utils/traits",
- ],
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-cc_binary(
- name = "bench_cmd",
- srcs = [
- "main_bench.cc",
- ],
- deps = [
"//src/tint/api/common",
- "//src/tint/cmd/bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/ir",
"//src/tint/lang/core/type",
- "//src/tint/lang/core:bench",
"//src/tint/lang/spirv/reader/common",
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
- "//src/tint/lang/wgsl/reader:bench",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
- "//src/tint/lang/wgsl/writer:bench",
- "//src/tint/lang/wgsl:bench",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -88,10 +51,59 @@
"//src/tint/utils/reflection",
"//src/tint/utils/result",
"//src/tint/utils/rtti",
+ "//src/tint/utils/symbol",
+ "//src/tint/utils/text",
+ "//src/tint/utils/traits",
+ "@benchmark",
+ ] + select({
+ ":tint_build_spv_reader": [
+ "//src/tint/lang/spirv/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
+ copts = COPTS,
+ visibility = ["//visibility:public"],
+)
+cc_binary(
+ name = "bench_cmd",
+ srcs = [
+ "main_bench.cc",
+ ],
+ deps = [
+ "//src/tint/cmd/bench:bench",
+ "//src/tint/lang/core",
+ "//src/tint/lang/core/constant",
+ "//src/tint/lang/core/type",
+ "//src/tint/lang/core:bench",
+ "//src/tint/lang/wgsl",
+ "//src/tint/lang/wgsl/ast",
+ "//src/tint/lang/wgsl/program",
+ "//src/tint/lang/wgsl/sem",
+ "//src/tint/lang/wgsl:bench",
+ "//src/tint/utils/containers",
+ "//src/tint/utils/diagnostic",
+ "//src/tint/utils/ice",
+ "//src/tint/utils/id",
+ "//src/tint/utils/macros",
+ "//src/tint/utils/math",
+ "//src/tint/utils/memory",
+ "//src/tint/utils/result",
+ "//src/tint/utils/rtti",
"//src/tint/utils/rtti:bench",
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
+ "@benchmark",
] + select({
":tint_build_glsl_writer": [
"//src/tint/lang/glsl/writer:bench",
@@ -108,13 +120,18 @@
],
"//conditions:default": [],
}) + select({
- ":tint_build_spv_reader": [
- "//src/tint/lang/spirv/reader",
+ ":tint_build_spv_writer": [
+ "//src/tint/lang/spirv/writer:bench",
],
"//conditions:default": [],
}) + select({
- ":tint_build_spv_writer": [
- "//src/tint/lang/spirv/writer:bench",
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader:bench",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer:bench",
],
"//conditions:default": [],
}),
@@ -147,3 +164,13 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
diff --git a/src/tint/cmd/bench/BUILD.cmake b/src/tint/cmd/bench/BUILD.cmake
index a6da553..03d6c47 100644
--- a/src/tint/cmd/bench/BUILD.cmake
+++ b/src/tint/cmd/bench/BUILD.cmake
@@ -22,37 +22,6 @@
################################################################################
################################################################################
-# Target: tint_cmd_bench
-# Kind: lib
-################################################################################
-tint_add_target(tint_cmd_bench lib
- cmd/bench/bench.h
- cmd/bench/benchmark.cc
-)
-
-tint_target_add_dependencies(tint_cmd_bench lib
- tint_lang_core
- tint_lang_core_constant
- tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_program
- tint_lang_wgsl_sem
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_id
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
- tint_utils_traits
-)
-
-################################################################################
# Target: tint_cmd_bench_bench_cmd
# Kind: bench_cmd
################################################################################
@@ -61,22 +30,15 @@
)
tint_target_add_dependencies(tint_cmd_bench_bench_cmd bench_cmd
- tint_api_common
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
- tint_lang_core_ir
tint_lang_core_type
tint_lang_core_bench
- tint_lang_spirv_reader_common
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_program
- tint_lang_wgsl_reader
- tint_lang_wgsl_reader_bench
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
- tint_lang_wgsl_writer_bench
tint_lang_wgsl_bench
tint_utils_containers
tint_utils_diagnostic
@@ -85,7 +47,6 @@
tint_utils_macros
tint_utils_math
tint_utils_memory
- tint_utils_reflection
tint_utils_result
tint_utils_rtti
tint_utils_rtti_bench
@@ -94,6 +55,10 @@
tint_utils_traits
)
+tint_target_add_external_dependencies(tint_cmd_bench_bench_cmd bench_cmd
+ "google-benchmark"
+)
+
if(TINT_BUILD_GLSL_WRITER)
tint_target_add_dependencies(tint_cmd_bench_bench_cmd bench_cmd
tint_lang_glsl_writer_bench
@@ -112,16 +77,79 @@
)
endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_SPV_READER)
- tint_target_add_dependencies(tint_cmd_bench_bench_cmd bench_cmd
- tint_lang_spirv_reader
- )
-endif(TINT_BUILD_SPV_READER)
-
if(TINT_BUILD_SPV_WRITER)
tint_target_add_dependencies(tint_cmd_bench_bench_cmd bench_cmd
tint_lang_spirv_writer_bench
)
endif(TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_bench_bench_cmd bench_cmd
+ tint_lang_wgsl_reader_bench
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_bench_bench_cmd bench_cmd
+ tint_lang_wgsl_writer_bench
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
tint_target_set_output_name(tint_cmd_bench_bench_cmd bench_cmd "tint_benchmark")
+
+################################################################################
+# Target: tint_cmd_bench_bench
+# Kind: bench
+################################################################################
+tint_add_target(tint_cmd_bench_bench bench
+ cmd/bench/bench.cc
+ cmd/bench/bench.h
+)
+
+tint_target_add_dependencies(tint_cmd_bench_bench bench
+ tint_api_common
+ tint_lang_core
+ tint_lang_core_constant
+ tint_lang_core_ir
+ tint_lang_core_type
+ tint_lang_spirv_reader_common
+ tint_lang_wgsl
+ tint_lang_wgsl_ast
+ tint_lang_wgsl_program
+ tint_lang_wgsl_sem
+ tint_utils_containers
+ tint_utils_diagnostic
+ tint_utils_ice
+ tint_utils_id
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_reflection
+ tint_utils_result
+ tint_utils_rtti
+ tint_utils_symbol
+ tint_utils_text
+ tint_utils_traits
+)
+
+tint_target_add_external_dependencies(tint_cmd_bench_bench bench
+ "google-benchmark"
+)
+
+if(TINT_BUILD_SPV_READER)
+ tint_target_add_dependencies(tint_cmd_bench_bench bench
+ tint_lang_spirv_reader
+ )
+endif(TINT_BUILD_SPV_READER)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_bench_bench bench
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_bench_bench bench
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
diff --git a/src/tint/cmd/bench/BUILD.gn b/src/tint/cmd/bench/BUILD.gn
index e17e2de..49a79f4 100644
--- a/src/tint/cmd/bench/BUILD.gn
+++ b/src/tint/cmd/bench/BUILD.gn
@@ -25,30 +25,109 @@
import("${tint_src_dir}/tint.gni")
-libtint_source_set("bench") {
- sources = [
- "bench.h",
- "benchmark.cc",
- ]
- deps = [
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
+if (tint_build_benchmarks) {
+ tint_unittests_source_set("bench") {
+ sources = [
+ "bench.cc",
+ "bench.h",
+ ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/spirv/reader/common",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_spv_reader) {
+ deps += [ "${tint_src_dir}/lang/spirv/reader" ]
+ }
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
+ }
+}
+if (tint_build_benchmarks) {
+ test("bench_cmd") {
+ testonly = true
+ output_name = "tint_benchmark"
+ sources = [ "main_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core:bench",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl:bench",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/rtti:bench",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_glsl_writer) {
+ deps += [ "${tint_src_dir}/lang/glsl/writer:bench" ]
+ }
+
+ if (tint_build_hlsl_writer) {
+ deps += [ "${tint_src_dir}/lang/hlsl/writer:bench" ]
+ }
+
+ if (tint_build_msl_writer) {
+ deps += [ "${tint_src_dir}/lang/msl/writer:bench" ]
+ }
+
+ if (tint_build_spv_writer) {
+ deps += [ "${tint_src_dir}/lang/spirv/writer:bench" ]
+ }
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader:bench" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer:bench" ]
+ }
+ }
}
diff --git a/src/tint/cmd/bench/bench.cc b/src/tint/cmd/bench/bench.cc
new file mode 100644
index 0000000..f36a404
--- /dev/null
+++ b/src/tint/cmd/bench/bench.cc
@@ -0,0 +1,163 @@
+// 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 <filesystem>
+#include <iostream>
+#include <utility>
+#include <vector>
+
+#include "src/tint/cmd/bench/bench.h"
+
+#if TINT_BUILD_SPV_READER
+#include "src/tint/lang/spirv/reader/reader.h"
+#endif
+
+#if TINT_BUILD_WGSL_WRITER
+#include "src/tint/lang/wgsl/writer/writer.h"
+#endif
+
+#if TINT_BUILD_WGSL_READER
+#include "src/tint/lang/wgsl/reader/reader.h"
+#endif
+
+#include "src/tint/utils/text/string.h"
+#include "src/tint/utils/text/string_stream.h"
+
+namespace tint::bench {
+namespace {
+
+std::filesystem::path kInputFileDir;
+
+/// Copies the content from the file named `input_file` to `buffer`,
+/// assuming each element in the file is of type `T`. If any error occurs,
+/// writes error messages to the standard error stream and returns false.
+/// Assumes the size of a `T` object is divisible by its required alignment.
+/// @returns true if we successfully read the file.
+template <typename T>
+Result<std::vector<T>> ReadFile(const std::string& input_file) {
+ FILE* file = nullptr;
+#if defined(_MSC_VER)
+ fopen_s(&file, input_file.c_str(), "rb");
+#else
+ file = fopen(input_file.c_str(), "rb");
+#endif
+ if (!file) {
+ return Failure{"Failed to open " + input_file};
+ }
+
+ fseek(file, 0, SEEK_END);
+ const auto file_size = static_cast<size_t>(ftell(file));
+ if (0 != (file_size % sizeof(T))) {
+ StringStream err;
+ err << "File " << input_file
+ << " does not contain an integral number of objects: " << file_size
+ << " bytes in the file, require " << sizeof(T) << " bytes per object";
+ fclose(file);
+ return Failure{err.str()};
+ }
+ fseek(file, 0, SEEK_SET);
+
+ std::vector<T> buffer;
+ buffer.resize(file_size / sizeof(T));
+
+ size_t bytes_read = fread(buffer.data(), 1, file_size, file);
+ fclose(file);
+ if (bytes_read != file_size) {
+ return Failure{"Failed to read " + input_file};
+ }
+
+ return buffer;
+}
+
+bool FindBenchmarkInputDir() {
+ // Attempt to find the benchmark input files by searching up from the current
+ // working directory.
+ auto path = std::filesystem::current_path();
+ while (std::filesystem::is_directory(path)) {
+ auto test = path / "test" / "tint" / "benchmark";
+ if (std::filesystem::is_directory(test)) {
+ kInputFileDir = test;
+ return true;
+ }
+ auto parent = path.parent_path();
+ if (path == parent) {
+ break;
+ }
+ path = parent;
+ }
+ return false;
+}
+
+} // namespace
+
+bool Initialize() {
+ if (!FindBenchmarkInputDir()) {
+ std::cerr << "failed to locate benchmark input files" << std::endl;
+ return false;
+ }
+ return true;
+}
+
+Result<Source::File> LoadInputFile(std::string name) {
+ auto path = std::filesystem::path(name).is_absolute() ? name : (kInputFileDir / name).string();
+ if (tint::HasSuffix(path, ".wgsl")) {
+#if TINT_BUILD_WGSL_READER
+ auto data = ReadFile<uint8_t>(path);
+ if (!data) {
+ return data.Failure();
+ }
+ return tint::Source::File(path, std::string(data->begin(), data->end()));
+#else
+ return Failure{"cannot load " + path + " file as TINT_BUILD_WGSL_READER is not enabled"};
+#endif
+ }
+ if (tint::HasSuffix(path, ".spv")) {
+#if !TINT_BUILD_SPV_READER
+ return Failure{"cannot load " + path + " as TINT_BUILD_SPV_READER is not enabled"};
+#elif !TINT_BUILD_WGSL_WRITER
+ return Failure{"cannot load " + path + " as TINT_BUILD_WGSL_WRITER is not enabled"};
+#else
+
+ auto spirv = ReadFile<uint32_t>(path);
+ if (spirv) {
+ auto program = tint::spirv::reader::Read(spirv.Get(), {});
+ if (!program.IsValid()) {
+ return Failure{program.Diagnostics()};
+ }
+ auto result = tint::wgsl::writer::Generate(program, {});
+ if (!result) {
+ return result.Failure();
+ }
+ return tint::Source::File(path, result->wgsl);
+ }
+ return spirv.Failure();
+#endif
+ }
+ return Failure{"unsupported file extension: '" + name + "'"};
+}
+
+Result<ProgramAndFile> LoadProgram(std::string name) {
+ auto res = bench::LoadInputFile(name);
+ if (!res) {
+ return res.Failure();
+ }
+ auto file = std::make_unique<Source::File>(res.Get());
+ auto program = wgsl::reader::Parse(file.get());
+ if (!program.IsValid()) {
+ return Failure{program.Diagnostics()};
+ }
+ return ProgramAndFile{std::move(program), std::move(file)};
+}
+
+} // namespace tint::bench
diff --git a/src/tint/cmd/bench/bench.h b/src/tint/cmd/bench/bench.h
index e813c4a..fc15e20 100644
--- a/src/tint/cmd/bench/bench.h
+++ b/src/tint/cmd/bench/bench.h
@@ -21,16 +21,12 @@
#include "benchmark/benchmark.h"
#include "src/tint/lang/wgsl/program/program.h"
+#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/macros/concat.h"
+#include "src/tint/utils/result/result.h"
namespace tint::bench {
-/// Error indicates an operation did not complete successfully.
-struct Error {
- /// The error message.
- std::string msg;
-};
-
/// ProgramAndFile holds a Program and a Source::File.
struct ProgramAndFile {
/// The tint program parsed from file.
@@ -39,18 +35,23 @@
std::unique_ptr<Source::File> file;
};
+/// Initializes the internal state for benchmarking.
+/// Must be called once by the benchmark executable entry point.
+/// @returns true on success, false of failure
+bool Initialize();
+
/// LoadInputFile attempts to load a benchmark input file with the given file
/// name. Accepts files with the .wgsl and .spv extension.
/// SPIR-V files are automatically converted to WGSL.
/// @param name the file name
-/// @returns either the loaded Source::File or an Error
-std::variant<Source::File, Error> LoadInputFile(std::string name);
+/// @returns the loaded Source::File
+Result<Source::File> LoadInputFile(std::string name);
/// LoadInputFile attempts to load a benchmark input program with the given file
/// name.
/// @param name the file name
-/// @returns either the loaded Program or an Error
-std::variant<ProgramAndFile, Error> LoadProgram(std::string name);
+/// @returns the loaded Program
+Result<ProgramAndFile> LoadProgram(std::string name);
// If TINT_BENCHMARK_EXTERNAL_SHADERS_HEADER is defined, include that to
// declare the TINT_BENCHMARK_EXTERNAL_WGSL_PROGRAMS() and TINT_BENCHMARK_EXTERNAL_SPV_PROGRAMS()
@@ -64,7 +65,7 @@
#endif
/// Declares a benchmark with the given function and WGSL file name
-#define TINT_BENCHMARK_WGSL_PROGRAM(FUNC, WGSL_NAME) BENCHMARK_CAPTURE(FUNC, WGSL_NAME, WGSL_NAME);
+#define TINT_BENCHMARK_WGSL_PROGRAM(FUNC, WGSL_NAME) BENCHMARK_CAPTURE(FUNC, WGSL_NAME, WGSL_NAME)
/// Declares a set of benchmarks for the given function using a list of WGSL files.
#define TINT_BENCHMARK_WGSL_PROGRAMS(FUNC) \
@@ -83,7 +84,8 @@
/// Declares a set of benchmarks for the given function using a list of WGSL and SPIR-V files.
#define TINT_BENCHMARK_PROGRAMS(FUNC) \
TINT_BENCHMARK_WGSL_PROGRAMS(FUNC) \
- TINT_BENCHMARK_SPV_PROGRAMS(FUNC)
+ TINT_BENCHMARK_SPV_PROGRAMS(FUNC) \
+ TINT_REQUIRE_SEMICOLON
} // namespace tint::bench
diff --git a/src/tint/cmd/bench/main_bench.cc b/src/tint/cmd/bench/main_bench.cc
index e04dc38..99d6c48 100644
--- a/src/tint/cmd/bench/main_bench.cc
+++ b/src/tint/cmd/bench/main_bench.cc
@@ -12,134 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <filesystem>
-#include <iostream>
-#include <utility>
-#include <vector>
-
#include "src/tint/cmd/bench/bench.h"
-#include "src/tint/lang/spirv/reader/reader.h"
-#include "src/tint/lang/wgsl/reader/reader.h"
-#include "src/tint/lang/wgsl/writer/writer.h"
-#include "src/tint/utils/text/string.h"
-#include "src/tint/utils/text/string_stream.h"
-
-namespace tint::bench {
-namespace {
-
-std::filesystem::path kInputFileDir;
-
-/// Copies the content from the file named `input_file` to `buffer`,
-/// assuming each element in the file is of type `T`. If any error occurs,
-/// writes error messages to the standard error stream and returns false.
-/// Assumes the size of a `T` object is divisible by its required alignment.
-/// @returns true if we successfully read the file.
-template <typename T>
-std::variant<std::vector<T>, Error> ReadFile(const std::string& input_file) {
- FILE* file = nullptr;
-#if defined(_MSC_VER)
- fopen_s(&file, input_file.c_str(), "rb");
-#else
- file = fopen(input_file.c_str(), "rb");
-#endif
- if (!file) {
- return Error{"Failed to open " + input_file};
- }
-
- fseek(file, 0, SEEK_END);
- const auto file_size = static_cast<size_t>(ftell(file));
- if (0 != (file_size % sizeof(T))) {
- StringStream err;
- err << "File " << input_file
- << " does not contain an integral number of objects: " << file_size
- << " bytes in the file, require " << sizeof(T) << " bytes per object";
- fclose(file);
- return Error{err.str()};
- }
- fseek(file, 0, SEEK_SET);
-
- std::vector<T> buffer;
- buffer.resize(file_size / sizeof(T));
-
- size_t bytes_read = fread(buffer.data(), 1, file_size, file);
- fclose(file);
- if (bytes_read != file_size) {
- return Error{"Failed to read " + input_file};
- }
-
- return buffer;
-}
-
-bool FindBenchmarkInputDir() {
- // Attempt to find the benchmark input files by searching up from the current
- // working directory.
- auto path = std::filesystem::current_path();
- while (std::filesystem::is_directory(path)) {
- auto test = path / "test" / "tint" / "benchmark";
- if (std::filesystem::is_directory(test)) {
- kInputFileDir = test;
- return true;
- }
- auto parent = path.parent_path();
- if (path == parent) {
- break;
- }
- path = parent;
- }
- return false;
-}
-
-} // namespace
-
-std::variant<tint::Source::File, Error> LoadInputFile(std::string name) {
- auto path = std::filesystem::path(name).is_absolute() ? name : (kInputFileDir / name).string();
- if (tint::HasSuffix(path, ".wgsl")) {
- auto data = ReadFile<uint8_t>(path);
- if (auto* buf = std::get_if<std::vector<uint8_t>>(&data)) {
- return tint::Source::File(path, std::string(buf->begin(), buf->end()));
- }
- return std::get<Error>(data);
- }
- if (tint::HasSuffix(path, ".spv")) {
- auto spirv = ReadFile<uint32_t>(path);
- if (auto* buf = std::get_if<std::vector<uint32_t>>(&spirv)) {
- auto program = tint::spirv::reader::Read(*buf, {});
- if (!program.IsValid()) {
- return Error{program.Diagnostics().str()};
- }
- auto result = tint::wgsl::writer::Generate(program, {});
- if (!result) {
- return Error{result.Failure().reason.str()};
- }
- return tint::Source::File(path, result->wgsl);
- }
- return std::get<Error>(spirv);
- }
- return Error{"unsupported file extension: '" + name + "'"};
-}
-
-std::variant<ProgramAndFile, Error> LoadProgram(std::string name) {
- auto res = bench::LoadInputFile(name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- return *err;
- }
- auto file = std::make_unique<Source::File>(std::move(std::get<Source::File>(res)));
- auto program = wgsl::reader::Parse(file.get());
- if (program.Diagnostics().contains_errors()) {
- return Error{program.Diagnostics().str()};
- }
- return ProgramAndFile{std::move(program), std::move(file)};
-}
-
-} // namespace tint::bench
int main(int argc, char** argv) {
benchmark::Initialize(&argc, argv);
if (benchmark::ReportUnrecognizedArguments(argc, argv)) {
return 1;
}
- if (!tint::bench::FindBenchmarkInputDir()) {
- std::cerr << "failed to locate benchmark input files" << std::endl;
+ if (!tint::bench::Initialize()) {
return 1;
}
benchmark::RunSpecifiedBenchmarks();
diff --git a/src/tint/cmd/common/BUILD.bazel b/src/tint/cmd/common/BUILD.bazel
index 5ff1ba3..8f0fa38 100644
--- a/src/tint/cmd/common/BUILD.bazel
+++ b/src/tint/cmd/common/BUILD.bazel
@@ -45,9 +45,7 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/inspector",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -71,6 +69,16 @@
"@spirv_tools",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -122,6 +130,16 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
selects.config_setting_group(
name = "tint_build_spv_reader_or_tint_build_spv_writer",
match_any = [
diff --git a/src/tint/cmd/common/BUILD.cmake b/src/tint/cmd/common/BUILD.cmake
index 7bd7799..dd7a96f 100644
--- a/src/tint/cmd/common/BUILD.cmake
+++ b/src/tint/cmd/common/BUILD.cmake
@@ -44,9 +44,7 @@
tint_lang_wgsl_ast
tint_lang_wgsl_inspector
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -74,6 +72,18 @@
)
endif(TINT_BUILD_SPV_READER OR TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_common lib
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_common lib
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
################################################################################
# Target: tint_cmd_common_test
# Kind: test
diff --git a/src/tint/cmd/common/BUILD.gn b/src/tint/cmd/common/BUILD.gn
index 5bca6c4..d4d0ea3 100644
--- a/src/tint/cmd/common/BUILD.gn
+++ b/src/tint/cmd/common/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -48,9 +48,7 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/inspector",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -76,10 +74,17 @@
"${tint_spirv_tools_dir}:spvtools_val",
]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "generate_external_texture_bindings_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/cmd/fuzz/BUILD.bazel b/src/tint/cmd/fuzz/BUILD.bazel
new file mode 100644
index 0000000..9f81589
--- /dev/null
+++ b/src/tint/cmd/fuzz/BUILD.bazel
@@ -0,0 +1,26 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
diff --git a/src/tint/cmd/fuzz/BUILD.cmake b/src/tint/cmd/fuzz/BUILD.cmake
new file mode 100644
index 0000000..2f0dfdf
--- /dev/null
+++ b/src/tint/cmd/fuzz/BUILD.cmake
@@ -0,0 +1,24 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+include(cmd/fuzz/wgsl/BUILD.cmake)
diff --git a/src/tint/cmd/fuzz/BUILD.gn b/src/tint/cmd/fuzz/BUILD.gn
new file mode 100644
index 0000000..b8a448e
--- /dev/null
+++ b/src/tint/cmd/fuzz/BUILD.gn
@@ -0,0 +1,26 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+import("../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.bazel b/src/tint/cmd/fuzz/wgsl/BUILD.bazel
new file mode 100644
index 0000000..1b32106
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.bazel
@@ -0,0 +1,31 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.cfg b/src/tint/cmd/fuzz/wgsl/BUILD.cfg
new file mode 100644
index 0000000..de92f71
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.cfg
@@ -0,0 +1,12 @@
+{
+ "condition": "tint_build_wgsl_reader",
+ "fuzz_cmd": {
+ /* The Tint fuzzer executable for WGSL-input. */
+ "OutputName": "tint_wgsl_fuzzer",
+ "AdditionalDependencies": {
+ /* Depend on all the fuzz targets to pull them all together. */
+ "Internal": [ "**:fuzz" ]
+ }
+ }
+}
+
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.cmake b/src/tint/cmd/fuzz/wgsl/BUILD.cmake
new file mode 100644
index 0000000..8b294e9
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.cmake
@@ -0,0 +1,107 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+if(TINT_BUILD_WGSL_READER)
+################################################################################
+# Target: tint_cmd_fuzz_wgsl_fuzz_cmd
+# Kind: fuzz_cmd
+# Condition: TINT_BUILD_WGSL_READER
+################################################################################
+tint_add_target(tint_cmd_fuzz_wgsl_fuzz_cmd fuzz_cmd
+ cmd/fuzz/wgsl/main_fuzz.cc
+)
+
+tint_target_add_dependencies(tint_cmd_fuzz_wgsl_fuzz_cmd fuzz_cmd
+ tint_lang_core
+ tint_lang_core_constant
+ tint_lang_core_type
+ tint_lang_wgsl
+ tint_lang_wgsl_ast
+ tint_lang_wgsl_program
+ tint_lang_wgsl_sem
+ tint_utils_containers
+ tint_utils_diagnostic
+ tint_utils_ice
+ tint_utils_id
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_result
+ tint_utils_rtti
+ tint_utils_symbol
+ tint_utils_text
+ tint_utils_traits
+)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_fuzz_wgsl_fuzz_cmd fuzz_cmd
+ tint_cmd_fuzz_wgsl_fuzz
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+tint_target_set_output_name(tint_cmd_fuzz_wgsl_fuzz_cmd fuzz_cmd "tint_wgsl_fuzzer")
+
+endif(TINT_BUILD_WGSL_READER)
+if(TINT_BUILD_WGSL_READER)
+################################################################################
+# Target: tint_cmd_fuzz_wgsl_fuzz
+# Kind: fuzz
+# Condition: TINT_BUILD_WGSL_READER
+################################################################################
+tint_add_target(tint_cmd_fuzz_wgsl_fuzz fuzz
+ cmd/fuzz/wgsl/wgsl_fuzz.cc
+ cmd/fuzz/wgsl/wgsl_fuzz.h
+)
+
+tint_target_add_dependencies(tint_cmd_fuzz_wgsl_fuzz fuzz
+ tint_api_common
+ tint_lang_core
+ tint_lang_core_constant
+ tint_lang_core_ir
+ tint_lang_core_type
+ tint_lang_wgsl
+ tint_lang_wgsl_ast
+ tint_lang_wgsl_program
+ tint_lang_wgsl_sem
+ tint_utils_containers
+ tint_utils_diagnostic
+ tint_utils_ice
+ tint_utils_id
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_reflection
+ tint_utils_result
+ tint_utils_rtti
+ tint_utils_symbol
+ tint_utils_text
+ tint_utils_traits
+)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_fuzz_wgsl_fuzz fuzz
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+endif(TINT_BUILD_WGSL_READER)
\ No newline at end of file
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.gn b/src/tint/cmd/fuzz/wgsl/BUILD.gn
new file mode 100644
index 0000000..cbf6274
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.gn
@@ -0,0 +1,93 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+import("../../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+if (tint_build_wgsl_reader) {
+ tint_fuzz_source_set("fuzz") {
+ sources = [
+ "wgsl_fuzz.cc",
+ "wgsl_fuzz.h",
+ ]
+ deps = [
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+ }
+}
+if (tint_build_wgsl_reader) {
+ tint_fuzzer_test("wgsl") {
+ output_name = "tint_wgsl_fuzzer"
+ sources = [ "main_fuzz.cc" ]
+ deps = [
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/cmd/fuzz/wgsl:fuzz" ]
+ }
+ }
+}
diff --git a/src/tint/cmd/fuzz/wgsl/dictionary.txt b/src/tint/cmd/fuzz/wgsl/dictionary.txt
new file mode 100644
index 0000000..59742d7
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/dictionary.txt
@@ -0,0 +1,296 @@
+"!"
+"!="
+"%"
+"%="
+"&"
+"&&"
+"&="
+"("
+")"
+"*"
+"*="
+"+"
+"++"
+"+="
+","
+"-"
+"--"
+"-="
+"->"
+"."
+"/"
+"/="
+":"
+";"
+"<"
+"<<"
+"<<="
+"<="
+"="
+"=="
+">"
+">="
+">>"
+">>="
+"@"
+"["
+"]"
+"^"
+"^="
+"_"
+"{"
+"|"
+"|="
+"||"
+"}"
+"~"
+"a"
+"abs"
+"acos"
+"acosh"
+"@align"
+"all"
+"any"
+"array"
+"arrayLength"
+"asin"
+"asinh"
+"atan"
+"atan2"
+"atanh"
+"atomic"
+"atomicAdd"
+"atomicAnd"
+"atomicLoad"
+"atomicMax"
+"atomicMin"
+"atomicOr"
+"atomicStore"
+"atomicSub"
+"atomicXor"
+"b"
+"@binding"
+"bitcast"
+"bool"
+"break"
+"@builtin"
+"@builtin(frag_depth)"
+"@builtin(front_facing)"
+"@builtin(global_invocation_id)"
+"@builtin(instance_index)"
+"@builtin(local_invocation_id)"
+"@builtin(local_invocation_index)"
+"@builtin(num_workgroups)"
+"@builtin(position)"
+"@builtin(sample_index)"
+"@builtin(sample_mask)"
+"@builtin(vertex_index)"
+"@builtin(workgroup_id)"
+"case"
+"ceil"
+"center"
+"centroid"
+"clamp"
+"@compute"
+"@const"
+"const"
+"continue"
+"continuing"
+"cos"
+"cosh"
+"countLeadingZeros"
+"countOneBits"
+"countTrailingZeros"
+"cross"
+"default"
+"degrees"
+"determinant"
+"discard"
+"distance"
+"dot"
+"dot4I8Packed"
+"dot4U8Packed"
+"dpdx"
+"dpdxCoarse"
+"dpdxFine"
+"dpdy"
+"dpdyCoarse"
+"dpdyFine"
+"else"
+"enable"
+"exp"
+"exp2"
+"extractBits"
+"f16"
+"f32"
+"faceForward"
+"fallthrough"
+"false"
+"firstLeadingBit"
+"firstTrailingBit"
+"flat"
+"floor"
+"fma"
+"fn"
+"for"
+"fract"
+"frag_depth"
+"@fragment"
+"frexp"
+"front_facing"
+"function"
+"fwidth"
+"fwidthCoarse"
+"fwidthFine"
+"g"
+"global_invocation_id"
+"@group"
+"i32"
+"@id"
+"if"
+"insertBits"
+"instance_index"
+"@interpolate"
+"@invariant"
+"inverseSqrt"
+"ldexp"
+"length"
+"let"
+"linear"
+"local_invocation_id"
+"local_invocation_index"
+"@location"
+"log"
+"log2"
+"loop"
+"mat2x2"
+"mat2x3"
+"mat2x4"
+"mat3x2"
+"mat3x3"
+"mat3x4"
+"mat4x2"
+"mat4x3"
+"mat4x4"
+"max"
+"min"
+"mix"
+"modf"
+"normalize"
+"num_workgroups"
+"override"
+"pack2x16float"
+"pack2x16snorm"
+"pack2x16unorm"
+"pack4x8snorm"
+"pack4x8unorm"
+"perspective"
+"position"
+"pow"
+"private"
+"ptr"
+"quantizeToF16"
+"r"
+"r32float"
+"r32sint"
+"r32uint"
+"radians"
+"read"
+"read_write"
+"reflect"
+"refract"
+"return"
+"reverseBits"
+"rg32float"
+"rg32sint"
+"rg32uint"
+"rgba16float"
+"rgba16sint"
+"rgba16uint"
+"rgba32float"
+"rgba32sint"
+"rgba32uint"
+"rgba8sint"
+"rgba8snorm"
+"rgba8uint"
+"rgba8unorm"
+"round"
+"sample"
+"sample_index"
+"sample_mask"
+"sampler"
+"sampler_comparison"
+"saturate"
+"select"
+"sign"
+"sin"
+"sinh"
+"@size"
+"smoothstep"
+"sqrt"
+"staticAssert"
+"step"
+"storage"
+"storageBarrier"
+"struct"
+"switch"
+"tan"
+"tanh"
+"texture_1d"
+"texture_2d"
+"texture_2d_array"
+"texture_3d"
+"texture_cube"
+"texture_cube_array"
+"texture_depth_2d"
+"texture_depth_2d_array"
+"texture_depth_cube"
+"texture_depth_cube_array"
+"texture_depth_multisampled_2d"
+"textureDimensions"
+"textureGather"
+"textureGatherCompare"
+"textureLoad"
+"texture_multisampled_2d"
+"textureNumLayers"
+"textureNumLevels"
+"textureNumSamples"
+"textureSample"
+"textureSampleBias"
+"textureSampleCompare"
+"textureSampleCompareLevel"
+"textureSampleGrad"
+"textureSampleLevel"
+"texture_storage_1d"
+"texture_storage_2d"
+"texture_storage_2d_array"
+"texture_storage_3d"
+"textureStore"
+"transpose"
+"true"
+"trunc"
+"type"
+"u32"
+"uniform"
+"unpack2x16float"
+"unpack2x16snorm"
+"unpack2x16unorm"
+"unpack4x8snorm"
+"unpack4x8unorm"
+"var"
+"vec2"
+"vec3"
+"vec4"
+"@vertex"
+"vertex_index"
+"w"
+"while"
+"workgroup"
+"workgroupBarrier"
+"workgroupUniformLoad"
+"workgroup_id"
+"@workgroup_size"
+"write"
+"x"
+"y"
+"z"
diff --git a/src/tint/cmd/fuzz/wgsl/generate_wgsl_corpus.py b/src/tint/cmd/fuzz/wgsl/generate_wgsl_corpus.py
new file mode 100644
index 0000000..983acd9
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/generate_wgsl_corpus.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+
+# 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.
+
+# Collect all .wgsl files under a given directory and copy them to a given
+# corpus directory, flattening their file names by replacing path
+# separators with underscores. If the output directory already exists, it
+# will be deleted and re-created. Files ending with ".expected.spvasm" are
+# skipped.
+#
+# The intended use of this script is to generate a corpus of WGSL shaders
+# for fuzzing.
+#
+# Usage:
+# generate_wgsl_corpus.py <input_dir> <corpus_dir>
+
+import optparse
+import os
+import pathlib
+import shutil
+import sys
+
+
+def list_wgsl_files(root_search_dir):
+ for root, folders, files in os.walk(root_search_dir):
+ for filename in folders + files:
+ if pathlib.Path(filename).suffix == '.wgsl':
+ yield os.path.join(root, filename)
+
+
+def main():
+ parser = optparse.OptionParser(
+ usage="usage: %prog [option] input-dir output-dir")
+ parser.add_option('--stamp', dest='stamp', help='stamp file')
+ options, args = parser.parse_args(sys.argv[1:])
+ if len(args) != 2:
+ parser.error("incorrect number of arguments")
+ input_dir: str = os.path.abspath(args[0].rstrip(os.sep))
+ corpus_dir: str = os.path.abspath(args[1])
+ if os.path.exists(corpus_dir):
+ shutil.rmtree(corpus_dir)
+ os.makedirs(corpus_dir)
+ for in_file in list_wgsl_files(input_dir):
+ if in_file.endswith(".expected.wgsl"):
+ continue
+ out_file = in_file[len(input_dir) + 1:].replace(os.sep, '_')
+ shutil.copy(in_file, corpus_dir + os.sep + out_file)
+ if options.stamp:
+ pathlib.Path(options.stamp).touch(mode=0o644, exist_ok=True)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/src/tint/cmd/bench/benchmark.cc b/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
similarity index 68%
rename from src/tint/cmd/bench/benchmark.cc
rename to src/tint/cmd/fuzz/wgsl/main_fuzz.cc
index ad8658b..8f3c3ab 100644
--- a/src/tint/cmd/bench/benchmark.cc
+++ b/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
-#endif
+#include "src/tint/cmd/fuzz/wgsl/wgsl_fuzz.h"
-// A placeholder symbol used to emit a symbol for this lib target.
-int tint_cmd_bench_symbol = 1;
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size > 0) {
+ std::string_view wgsl(reinterpret_cast<const char*>(data), size);
+ tint::fuzz::wgsl::Run(wgsl);
+ }
+ return 0;
+}
diff --git a/src/tint/cmd/fuzz/wgsl/wgsl_fuzz.cc b/src/tint/cmd/fuzz/wgsl/wgsl_fuzz.cc
new file mode 100644
index 0000000..50907f6
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/wgsl_fuzz.cc
@@ -0,0 +1,66 @@
+// 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/cmd/fuzz/wgsl/wgsl_fuzz.h"
+
+#include <iostream>
+
+#include "src/tint/lang/wgsl/reader/reader.h"
+#include "src/tint/utils/containers/vector.h"
+#include "src/tint/utils/macros/defer.h"
+#include "src/tint/utils/macros/static_init.h"
+
+namespace tint::fuzz::wgsl {
+namespace {
+
+Vector<ProgramFuzzer, 32> fuzzers;
+std::string_view currently_running;
+
+[[noreturn]] void TintInternalCompilerErrorReporter(const tint::InternalCompilerError& err) {
+ std::cerr << "ICE while running fuzzer: '" << currently_running << "'" << std::endl;
+ std::cerr << err.Error() << std::endl;
+ __builtin_trap();
+}
+
+} // namespace
+
+void Register(const ProgramFuzzer& fuzzer) {
+ fuzzers.Push(fuzzer);
+}
+
+void Run(std::string_view wgsl) {
+ tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);
+
+ // Ensure that fuzzers are sorted. Without this, the fuzzers may be registered in any order,
+ // leading to non-determinism, which we must avoid.
+ TINT_STATIC_INIT(fuzzers.Sort([](auto& a, auto& b) { return a.name < b.name; }));
+
+ // Create a Source::File to hand to the parser.
+ tint::Source::File file("test.wgsl", wgsl);
+
+ // Parse the WGSL program.
+ auto program = tint::wgsl::reader::Parse(&file);
+ if (!program.IsValid()) {
+ return;
+ }
+
+ // Run each of the program fuzzer functions
+ TINT_DEFER(currently_running = "");
+ for (auto& fuzzer : fuzzers) {
+ currently_running = fuzzer.name;
+ fuzzer.fn(program);
+ }
+}
+
+} // namespace tint::fuzz::wgsl
diff --git a/src/tint/cmd/fuzz/wgsl/wgsl_fuzz.h b/src/tint/cmd/fuzz/wgsl/wgsl_fuzz.h
new file mode 100644
index 0000000..9fb5fd4
--- /dev/null
+++ b/src/tint/cmd/fuzz/wgsl/wgsl_fuzz.h
@@ -0,0 +1,51 @@
+// 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_CMD_FUZZ_WGSL_WGSL_FUZZ_H_
+#define SRC_TINT_CMD_FUZZ_WGSL_WGSL_FUZZ_H_
+
+#include <string>
+
+#include "src/tint/lang/wgsl/program/program.h"
+#include "src/tint/utils/containers/slice.h"
+#include "src/tint/utils/macros/static_init.h"
+
+namespace tint::fuzz::wgsl {
+
+/// ProgramFuzzer describes a fuzzer function that takes a WGSL program as input
+struct ProgramFuzzer {
+ /// The function signature
+ using Fn = void(const Program&);
+
+ /// Name of the fuzzer function
+ std::string_view name;
+ /// The fuzzer function pointer
+ Fn* fn = nullptr;
+};
+
+/// Runs all the registered WGSL fuzzers with the supplied WGSL
+/// @param wgsl the input WGSL
+void Run(std::string_view wgsl);
+
+/// Registers the fuzzer function with the WGSL fuzzer executable.
+/// @param fuzzer the fuzzer
+void Register(const ProgramFuzzer& fuzzer);
+
+/// TINT_WGSL_PROGRAM_FUZZER registers the fuzzer function to run as part of `tint_wgsl_fuzzer`
+#define TINT_WGSL_PROGRAM_FUZZER(FUNCTION) \
+ TINT_STATIC_INIT(::tint::fuzz::wgsl::Register({#FUNCTION, FUNCTION}))
+
+} // namespace tint::fuzz::wgsl
+
+#endif // SRC_TINT_CMD_FUZZ_WGSL_WGSL_FUZZ_H_
diff --git a/src/tint/cmd/info/BUILD.gn b/src/tint/cmd/info/BUILD.gn
index e9d84ce..79018c2 100644
--- a/src/tint/cmd/info/BUILD.gn
+++ b/src/tint/cmd/info/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-executable("info") {
+tint_executable("info") {
output_name = "tint_info"
sources = [ "main.cc" ]
deps = [
diff --git a/src/tint/cmd/loopy/BUILD.bazel b/src/tint/cmd/loopy/BUILD.bazel
index 194e728..2725298 100644
--- a/src/tint/cmd/loopy/BUILD.bazel
+++ b/src/tint/cmd/loopy/BUILD.bazel
@@ -44,10 +44,7 @@
"//src/tint/lang/wgsl/helpers",
"//src/tint/lang/wgsl/inspector",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -87,6 +84,18 @@
":tint_build_spv_writer": [
"//src/tint/lang/spirv/writer",
"//src/tint/lang/spirv/writer/common",
+ "//src/tint/lang/spirv/writer/helpers",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
],
"//conditions:default": [],
}),
@@ -119,3 +128,13 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
diff --git a/src/tint/cmd/loopy/BUILD.cmake b/src/tint/cmd/loopy/BUILD.cmake
index 86eee38..3e559b7 100644
--- a/src/tint/cmd/loopy/BUILD.cmake
+++ b/src/tint/cmd/loopy/BUILD.cmake
@@ -45,10 +45,7 @@
tint_lang_wgsl_helpers
tint_lang_wgsl_inspector
tint_lang_wgsl_program
- tint_lang_wgsl_reader
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -94,7 +91,21 @@
tint_target_add_dependencies(tint_cmd_loopy_cmd cmd
tint_lang_spirv_writer
tint_lang_spirv_writer_common
+ tint_lang_spirv_writer_helpers
)
endif(TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_loopy_cmd cmd
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_loopy_cmd cmd
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
tint_target_set_output_name(tint_cmd_loopy_cmd cmd "tint_loopy")
diff --git a/src/tint/cmd/loopy/BUILD.gn b/src/tint/cmd/loopy/BUILD.gn
index 4c54f72..f8b76c9 100644
--- a/src/tint/cmd/loopy/BUILD.gn
+++ b/src/tint/cmd/loopy/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-executable("loopy") {
+tint_executable("loopy") {
output_name = "tint_loopy"
sources = [ "main.cc" ]
deps = [
@@ -44,10 +44,7 @@
"${tint_src_dir}/lang/wgsl/helpers",
"${tint_src_dir}/lang/wgsl/inspector",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -89,6 +86,18 @@
deps += [
"${tint_src_dir}/lang/spirv/writer",
"${tint_src_dir}/lang/spirv/writer/common",
+ "${tint_src_dir}/lang/spirv/writer/helpers",
]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
diff --git a/src/tint/cmd/loopy/main.cc b/src/tint/cmd/loopy/main.cc
index e488fad..31cd2dc 100644
--- a/src/tint/cmd/loopy/main.cc
+++ b/src/tint/cmd/loopy/main.cc
@@ -18,7 +18,6 @@
#include "src/tint/cmd/common/generate_external_texture_bindings.h"
#include "src/tint/cmd/common/helper.h"
#include "src/tint/lang/core/ir/module.h"
-#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
#if TINT_BUILD_GLSL_WRITER
#include "src/tint/lang/glsl/writer/writer.h"
@@ -37,10 +36,12 @@
#endif // TINT_BUILD_SPV_READER
#if TINT_BUILD_SPV_WRITER
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
#include "src/tint/lang/spirv/writer/writer.h"
#endif // TINT_BUILD_SPV_WRITER
#if TINT_BUILD_WGSL_READER
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
#include "src/tint/lang/wgsl/reader/reader.h"
#endif // TINT_BUILD_WGSL_READER
@@ -192,8 +193,7 @@
bool GenerateSpirv(const tint::Program& program) {
#if TINT_BUILD_SPV_WRITER
tint::spirv::writer::Options gen_options;
- gen_options.external_texture_options.bindings_map =
- tint::cmd::GenerateExternalTextureBindings(program);
+ gen_options.bindings = tint::spirv::writer::GenerateBindings(program);
auto result = tint::spirv::writer::Generate(program, gen_options);
if (!result) {
tint::cmd::PrintWGSL(std::cerr, program);
@@ -231,12 +231,15 @@
/// Generate MSL code for a program.
/// @param program the program to generate
/// @returns true on success
-bool GenerateMsl(const tint::Program& program) {
-#if TINT_BUILD_MSL_WRITER
+bool GenerateMsl([[maybe_unused]] const tint::Program& program) {
+#if !TINT_BUILD_MSL_WRITER
+ std::cerr << "MSL writer not enabled in tint build" << std::endl;
+ return false;
+#else
// Remap resource numbers to a flat namespace.
// TODO(crbug.com/tint/1501): Do this via Options::BindingMap.
const tint::Program* input_program = &program;
- auto flattened = tint::writer::FlattenBindings(program);
+ auto flattened = tint::wgsl::FlattenBindings(program);
if (flattened) {
input_program = &*flattened;
}
@@ -257,11 +260,7 @@
}
return true;
-#else
- (void)program;
- std::cerr << "MSL writer not enabled in tint build" << std::endl;
- return false;
-#endif // TINT_BUILD_MSL_WRITER
+#endif
}
/// Generate HLSL code for a program.
@@ -381,6 +380,7 @@
opts.filename = options.input_filename;
auto info = tint::cmd::LoadProgramInfo(opts);
+#if TINT_BUILD_WGSL_READER
{
uint32_t loop_count = 1;
if (options.loop == Looper::kIRGenerate) {
@@ -393,6 +393,7 @@
}
}
}
+#endif // TINT_BUILD_WGSL_READER
bool success = false;
{
diff --git a/src/tint/cmd/remote_compile/BUILD.gn b/src/tint/cmd/remote_compile/BUILD.gn
index 6d5be7d..58dfd2e 100644
--- a/src/tint/cmd/remote_compile/BUILD.gn
+++ b/src/tint/cmd/remote_compile/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-executable("remote_compile") {
+tint_executable("remote_compile") {
output_name = "tint_remote_compile"
sources = [ "main.cc" ]
deps = [
diff --git a/src/tint/cmd/remote_compile/main.cc b/src/tint/cmd/remote_compile/main.cc
index 95e2c48..12611af 100644
--- a/src/tint/cmd/remote_compile/main.cc
+++ b/src/tint/cmd/remote_compile/main.cc
@@ -23,7 +23,10 @@
#include <type_traits>
#include <vector>
+#if TINT_BUILD_MSL_WRITER
#include "src/tint/lang/msl/validate/val.h"
+#endif
+
#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/socket/socket.h"
@@ -421,7 +424,7 @@
DEBUG("%s\n", stream.error.c_str());
return;
}
-#ifdef __APPLE__
+#if TINT_BUILD_MSL_WRITER && defined(__APPLE__)
if (req.language == SourceLanguage::MSL) {
auto version = tint::msl::validate::MslVersion::kMsl_1_2;
if (req.version_major == 2 && req.version_minor == 1) {
diff --git a/src/tint/cmd/test/BUILD.bazel b/src/tint/cmd/test/BUILD.bazel
index 60aebb2..81c6552 100644
--- a/src/tint/cmd/test/BUILD.bazel
+++ b/src/tint/cmd/test/BUILD.bazel
@@ -38,17 +38,12 @@
"//src/tint/lang/core/type:test",
"//src/tint/lang/core:test",
"//src/tint/lang/spirv/ir:test",
- "//src/tint/lang/wgsl/ast/transform:test",
"//src/tint/lang/wgsl/ast:test",
"//src/tint/lang/wgsl/helpers:test",
- "//src/tint/lang/wgsl/inspector:test",
"//src/tint/lang/wgsl/program:test",
"//src/tint/lang/wgsl/reader/lower:test",
- "//src/tint/lang/wgsl/reader/parser:test",
- "//src/tint/lang/wgsl/reader/program_to_ir:test",
"//src/tint/lang/wgsl/resolver:test",
"//src/tint/lang/wgsl/sem:test",
- "//src/tint/lang/wgsl/writer/ast_printer:test",
"//src/tint/lang/wgsl/writer/ir_to_program:test",
"//src/tint/lang/wgsl/writer/raise:test",
"//src/tint/lang/wgsl:test",
@@ -74,38 +69,75 @@
] + select({
":tint_build_glsl_writer": [
"//src/tint/lang/glsl/writer/ast_printer:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_glsl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
"//src/tint/lang/glsl/writer/ast_raise:test",
],
"//conditions:default": [],
}) + select({
":tint_build_hlsl_writer": [
"//src/tint/lang/hlsl/writer/ast_printer:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_hlsl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
"//src/tint/lang/hlsl/writer/ast_raise:test",
],
"//conditions:default": [],
}) + select({
":tint_build_msl_writer": [
"//src/tint/lang/msl/writer/ast_printer:test",
- "//src/tint/lang/msl/writer/ast_raise:test",
"//src/tint/lang/msl/writer/common:test",
"//src/tint/lang/msl/writer/printer:test",
],
"//conditions:default": [],
}) + select({
- ":tint_build_spv_reader": [
+ ":tint_build_msl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/msl/writer/ast_raise:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_spv_reader_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
"//src/tint/lang/spirv/reader/ast_lower:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_spv_reader_and_tint_build_wgsl_writer": [
"//src/tint/lang/spirv/reader/ast_parser:test",
],
"//conditions:default": [],
}) + select({
":tint_build_spv_writer": [
"//src/tint/lang/spirv/writer/ast_printer:test",
- "//src/tint/lang/spirv/writer/ast_raise:test",
"//src/tint/lang/spirv/writer/common:test",
"//src/tint/lang/spirv/writer/raise:test",
"//src/tint/lang/spirv/writer:test",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_spv_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/spirv/writer/ast_raise:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/inspector:test",
+ "//src/tint/lang/wgsl/reader/parser:test",
+ "//src/tint/lang/wgsl/reader/program_to_ir:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/ast/transform:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer/ast_printer:test",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -136,3 +168,68 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_glsl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_glsl_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_hlsl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_hlsl_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_msl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_msl_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_spv_reader_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_spv_reader",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_spv_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_spv_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_spv_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_spv_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/cmd/test/BUILD.cmake b/src/tint/cmd/test/BUILD.cmake
index 108f7af..e0f6550 100644
--- a/src/tint/cmd/test/BUILD.cmake
+++ b/src/tint/cmd/test/BUILD.cmake
@@ -39,17 +39,12 @@
tint_lang_core_type_test
tint_lang_core_test
tint_lang_spirv_ir_test
- tint_lang_wgsl_ast_transform_test
tint_lang_wgsl_ast_test
tint_lang_wgsl_helpers_test
- tint_lang_wgsl_inspector_test
tint_lang_wgsl_program_test
tint_lang_wgsl_reader_lower_test
- tint_lang_wgsl_reader_parser_test
- tint_lang_wgsl_reader_program_to_ir_test
tint_lang_wgsl_resolver_test
tint_lang_wgsl_sem_test
- tint_lang_wgsl_writer_ast_printer_test
tint_lang_wgsl_writer_ir_to_program_test
tint_lang_wgsl_writer_raise_test
tint_lang_wgsl_test
@@ -80,41 +75,86 @@
if(TINT_BUILD_GLSL_WRITER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_glsl_writer_ast_printer_test
- tint_lang_glsl_writer_ast_raise_test
)
endif(TINT_BUILD_GLSL_WRITER)
+if(TINT_BUILD_GLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_glsl_writer_ast_raise_test
+ )
+endif(TINT_BUILD_GLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
if(TINT_BUILD_HLSL_WRITER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_hlsl_writer_ast_printer_test
- tint_lang_hlsl_writer_ast_raise_test
)
endif(TINT_BUILD_HLSL_WRITER)
+if(TINT_BUILD_HLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_hlsl_writer_ast_raise_test
+ )
+endif(TINT_BUILD_HLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
if(TINT_BUILD_MSL_WRITER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_msl_writer_ast_printer_test
- tint_lang_msl_writer_ast_raise_test
tint_lang_msl_writer_common_test
tint_lang_msl_writer_printer_test
)
endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_SPV_READER)
+if(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_msl_writer_ast_raise_test
+ )
+endif(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_spirv_reader_ast_lower_test
+ )
+endif(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_spirv_reader_ast_parser_test
)
-endif(TINT_BUILD_SPV_READER)
+endif(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_WRITER)
if(TINT_BUILD_SPV_WRITER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_spirv_writer_ast_printer_test
- tint_lang_spirv_writer_ast_raise_test
tint_lang_spirv_writer_common_test
tint_lang_spirv_writer_raise_test
tint_lang_spirv_writer_test
)
endif(TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_SPV_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_spirv_writer_ast_raise_test
+ )
+endif(TINT_BUILD_SPV_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_wgsl_inspector_test
+ tint_lang_wgsl_reader_parser_test
+ tint_lang_wgsl_reader_program_to_ir_test
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_wgsl_ast_transform_test
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
+ tint_lang_wgsl_writer_ast_printer_test
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
tint_target_set_output_name(tint_cmd_test_test_cmd test_cmd "tint_unittests")
diff --git a/src/tint/cmd/test/BUILD.gn b/src/tint/cmd/test/BUILD.gn
index 5461cfb..09acee9 100644
--- a/src/tint/cmd/test/BUILD.gn
+++ b/src/tint/cmd/test/BUILD.gn
@@ -25,11 +25,12 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_unittests) {
- test("test") {
+ test("test_cmd") {
+ testonly = true
output_name = "tint_unittests"
sources = [ "main_test.cc" ]
deps = [
@@ -45,16 +46,11 @@
"${tint_src_dir}/lang/spirv/ir:unittests",
"${tint_src_dir}/lang/wgsl:unittests",
"${tint_src_dir}/lang/wgsl/ast:unittests",
- "${tint_src_dir}/lang/wgsl/ast/transform:unittests",
"${tint_src_dir}/lang/wgsl/helpers:unittests",
- "${tint_src_dir}/lang/wgsl/inspector:unittests",
"${tint_src_dir}/lang/wgsl/program:unittests",
"${tint_src_dir}/lang/wgsl/reader/lower:unittests",
- "${tint_src_dir}/lang/wgsl/reader/parser:unittests",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir:unittests",
"${tint_src_dir}/lang/wgsl/resolver:unittests",
"${tint_src_dir}/lang/wgsl/sem:unittests",
- "${tint_src_dir}/lang/wgsl/writer/ast_printer:unittests",
"${tint_src_dir}/lang/wgsl/writer/ir_to_program:unittests",
"${tint_src_dir}/lang/wgsl/writer/raise:unittests",
"${tint_src_dir}/utils/cli:unittests",
@@ -78,45 +74,74 @@
]
if (tint_build_glsl_writer) {
- deps += [
- "${tint_src_dir}/lang/glsl/writer/ast_printer:unittests",
- "${tint_src_dir}/lang/glsl/writer/ast_raise:unittests",
- ]
+ deps += [ "${tint_src_dir}/lang/glsl/writer/ast_printer:unittests" ]
+ }
+
+ if (tint_build_glsl_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/glsl/writer/ast_raise:unittests" ]
}
if (tint_build_hlsl_writer) {
- deps += [
- "${tint_src_dir}/lang/hlsl/writer/ast_printer:unittests",
- "${tint_src_dir}/lang/hlsl/writer/ast_raise:unittests",
- ]
+ deps += [ "${tint_src_dir}/lang/hlsl/writer/ast_printer:unittests" ]
+ }
+
+ if (tint_build_hlsl_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/hlsl/writer/ast_raise:unittests" ]
}
if (tint_build_msl_writer) {
deps += [
"${tint_src_dir}/lang/msl/writer/ast_printer:unittests",
- "${tint_src_dir}/lang/msl/writer/ast_raise:unittests",
"${tint_src_dir}/lang/msl/writer/common:unittests",
"${tint_src_dir}/lang/msl/writer/printer:unittests",
]
}
- if (tint_build_spv_reader) {
- deps += [
- "${tint_src_dir}/lang/spirv/reader/ast_lower:unittests",
- "${tint_src_dir}/lang/spirv/reader/ast_parser:unittests",
- ]
+ if (tint_build_msl_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/msl/writer/ast_raise:unittests" ]
+ }
+
+ if (tint_build_spv_reader && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/spirv/reader/ast_lower:unittests" ]
+ }
+
+ if (tint_build_spv_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/spirv/reader/ast_parser:unittests" ]
}
if (tint_build_spv_writer) {
deps += [
"${tint_src_dir}/lang/spirv/writer:unittests",
"${tint_src_dir}/lang/spirv/writer/ast_printer:unittests",
- "${tint_src_dir}/lang/spirv/writer/ast_raise:unittests",
"${tint_src_dir}/lang/spirv/writer/common:unittests",
"${tint_src_dir}/lang/spirv/writer/raise:unittests",
]
}
- testonly = true
+
+ if (tint_build_spv_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/spirv/writer/ast_raise:unittests" ]
+ }
+
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/inspector:unittests",
+ "${tint_src_dir}/lang/wgsl/reader/parser:unittests",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir:unittests",
+ ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer/ast_printer:unittests" ]
+ }
configs += [ "${tint_src_dir}:tint_unittests_config" ]
if (build_with_chromium) {
diff --git a/src/tint/cmd/tint/BUILD.bazel b/src/tint/cmd/tint/BUILD.bazel
index 321c15e..e333aea 100644
--- a/src/tint/cmd/tint/BUILD.bazel
+++ b/src/tint/cmd/tint/BUILD.bazel
@@ -45,10 +45,7 @@
"//src/tint/lang/wgsl/helpers",
"//src/tint/lang/wgsl/inspector",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/cli",
"//src/tint/utils/command",
"//src/tint/utils/containers",
@@ -66,11 +63,14 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
] + select({
+ ":tint_build_glsl_validator": [
+ "//src/tint/lang/glsl/validate",
+ ],
+ "//conditions:default": [],
+ }) + select({
":tint_build_glsl_writer": [
"//src/tint/lang/glsl/writer",
"//src/tint/lang/glsl/writer/common",
-
-
],
"//conditions:default": [],
}) + select({
@@ -100,6 +100,18 @@
":tint_build_spv_writer": [
"//src/tint/lang/spirv/writer",
"//src/tint/lang/spirv/writer/common",
+ "//src/tint/lang/spirv/writer/helpers",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
],
"//conditions:default": [],
}),
@@ -108,6 +120,11 @@
)
alias(
+ name = "tint_build_glsl_validator",
+ actual = "//src/tint:tint_build_glsl_validator_true",
+)
+
+alias(
name = "tint_build_glsl_writer",
actual = "//src/tint:tint_build_glsl_writer_true",
)
@@ -132,6 +149,16 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
selects.config_setting_group(
name = "tint_build_spv_reader_or_tint_build_spv_writer",
match_any = [
diff --git a/src/tint/cmd/tint/BUILD.cmake b/src/tint/cmd/tint/BUILD.cmake
index 1d500ac..b70b52b 100644
--- a/src/tint/cmd/tint/BUILD.cmake
+++ b/src/tint/cmd/tint/BUILD.cmake
@@ -46,10 +46,7 @@
tint_lang_wgsl_helpers
tint_lang_wgsl_inspector
tint_lang_wgsl_program
- tint_lang_wgsl_reader
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_cli
tint_utils_command
tint_utils_containers
@@ -68,15 +65,17 @@
tint_utils_traits
)
+if(TINT_BUILD_GLSL_VALIDATOR)
+ tint_target_add_dependencies(tint_cmd_tint_cmd cmd
+ tint_lang_glsl_validate
+ )
+endif(TINT_BUILD_GLSL_VALIDATOR)
+
if(TINT_BUILD_GLSL_WRITER)
tint_target_add_dependencies(tint_cmd_tint_cmd cmd
tint_lang_glsl_writer
tint_lang_glsl_writer_common
)
- tint_target_add_external_dependencies(tint_cmd_tint_cmd cmd
- "glslang"
- "glslang-res-limits"
- )
endif(TINT_BUILD_GLSL_WRITER)
if(TINT_BUILD_HLSL_WRITER)
@@ -110,7 +109,21 @@
tint_target_add_dependencies(tint_cmd_tint_cmd cmd
tint_lang_spirv_writer
tint_lang_spirv_writer_common
+ tint_lang_spirv_writer_helpers
)
endif(TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_cmd_tint_cmd cmd
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_cmd_tint_cmd cmd
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
tint_target_set_output_name(tint_cmd_tint_cmd cmd "tint")
diff --git a/src/tint/cmd/tint/BUILD.gn b/src/tint/cmd/tint/BUILD.gn
index e6c897c..50a05f7 100644
--- a/src/tint/cmd/tint/BUILD.gn
+++ b/src/tint/cmd/tint/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-executable("tint") {
+tint_executable("tint") {
output_name = "tint"
sources = [ "main.cc" ]
deps = [
@@ -45,10 +45,7 @@
"${tint_src_dir}/lang/wgsl/helpers",
"${tint_src_dir}/lang/wgsl/inspector",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/cli",
"${tint_src_dir}/utils/command",
"${tint_src_dir}/utils/containers",
@@ -67,10 +64,12 @@
"${tint_src_dir}/utils/traits",
]
+ if (tint_build_glsl_validator) {
+ deps += [ "${tint_src_dir}/lang/glsl/validate" ]
+ }
+
if (tint_build_glsl_writer) {
deps += [
- "${tint_glslang_dir}:glslang_default_resource_limits_sources",
- "${tint_glslang_dir}:glslang_lib_sources",
"${tint_src_dir}/lang/glsl/writer",
"${tint_src_dir}/lang/glsl/writer/common",
]
@@ -106,6 +105,18 @@
deps += [
"${tint_src_dir}/lang/spirv/writer",
"${tint_src_dir}/lang/spirv/writer/common",
+ "${tint_src_dir}/lang/spirv/writer/helpers",
]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 1a48a8d..31e4522 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -24,11 +24,6 @@
#include <unordered_map>
#include <vector>
-#if TINT_BUILD_GLSL_WRITER
-#include "glslang/Public/ResourceLimits.h"
-#include "glslang/Public/ShaderLang.h"
-#endif // TINT_BUILD_GLSL_WRITER
-
#if TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER
#include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER
@@ -46,7 +41,6 @@
#include "src/tint/lang/wgsl/ast/transform/single_entry_point.h"
#include "src/tint/lang/wgsl/ast/transform/substitute_override.h"
#include "src/tint/lang/wgsl/helpers/flatten_bindings.h"
-#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
#include "src/tint/utils/cli/cli.h"
#include "src/tint/utils/command/command.h"
#include "src/tint/utils/containers/transform.h"
@@ -61,10 +55,12 @@
#endif // TINT_BUILD_SPV_READER
#if TINT_BUILD_WGSL_READER
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
#include "src/tint/lang/wgsl/reader/reader.h"
#endif // TINT_BUILD_WGSL_READER
#if TINT_BUILD_SPV_WRITER
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
#include "src/tint/lang/spirv/writer/writer.h"
#endif // TINT_BUILD_SPV_WRITER
@@ -86,6 +82,10 @@
#include "src/tint/lang/glsl/writer/writer.h"
#endif // TINT_BUILD_GLSL_WRITER
+#if TINT_BUILD_GLSL_VALIDATOR
+#include "src/tint/lang/glsl/validate/validate.h"
+#endif // TINT_BUILD_GLSL_VALIDATOR
+
#if TINT_BUILD_SPV_WRITER
#define SPV_WRITER_ONLY(x) x
#else
@@ -495,7 +495,9 @@
/// like `std::string` and `std::vector` do.
/// @returns true on success
template <typename ContainerT>
-bool WriteFile(const std::string& output_file, const std::string mode, const ContainerT& buffer) {
+[[maybe_unused]] bool WriteFile(const std::string& output_file,
+ const std::string mode,
+ const ContainerT& buffer) {
const bool use_stdout = output_file.empty() || output_file == "-";
FILE* file = stdout;
@@ -579,8 +581,7 @@
tint::spirv::writer::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
- gen_options.external_texture_options.bindings_map =
- tint::cmd::GenerateExternalTextureBindings(program);
+ gen_options.bindings = tint::spirv::writer::GenerateBindings(program);
gen_options.use_tint_ir = options.use_ir;
auto result = tint::spirv::writer::Generate(program, gen_options);
@@ -631,7 +632,8 @@
/// @param program the program to generate
/// @param options the options that Tint was invoked with
/// @returns true on success
-bool GenerateWgsl(const tint::Program& program, const Options& options) {
+bool GenerateWgsl([[maybe_unused]] const tint::Program& program,
+ [[maybe_unused]] const Options& options) {
#if TINT_BUILD_WGSL_WRITER
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::wgsl::writer::Options gen_options;
@@ -650,6 +652,7 @@
PrintHash(hash);
}
+#if TINT_BUILD_WGSL_READER
if (options.validate && options.skip_hash.count(hash) == 0) {
// Attempt to re-parse the output program with Tint's WGSL reader.
auto source = std::make_unique<tint::Source::File>(options.input_filename, result->wgsl);
@@ -661,11 +664,10 @@
return false;
}
}
+#endif // TINT_BUILD_WGSL_READER
return true;
#else
- (void)program;
- (void)options;
std::cerr << "WGSL writer not enabled in tint build" << std::endl;
return false;
#endif // TINT_BUILD_WGSL_WRITER
@@ -675,12 +677,16 @@
/// @param program the program to generate
/// @param options the options that Tint was invoked with
/// @returns true on success
-bool GenerateMsl(const tint::Program& program, const Options& options) {
-#if TINT_BUILD_MSL_WRITER
+bool GenerateMsl([[maybe_unused]] const tint::Program& program,
+ [[maybe_unused]] const Options& options) {
+#if !TINT_BUILD_MSL_WRITER
+ std::cerr << "MSL writer not enabled in tint build" << std::endl;
+ return false;
+#else
// Remap resource numbers to a flat namespace.
// TODO(crbug.com/tint/1501): Do this via Options::BindingMap.
const tint::Program* input_program = &program;
- auto flattened = tint::writer::FlattenBindings(program);
+ auto flattened = tint::wgsl::FlattenBindings(program);
if (flattened) {
input_program = &*flattened;
}
@@ -752,11 +758,6 @@
}
return true;
-#else
- (void)program;
- (void)options;
- std::cerr << "MSL writer not enabled in tint build" << std::endl;
- return false;
#endif // TINT_BUILD_MSL_WRITER
}
@@ -883,32 +884,16 @@
#endif // TINT_BUILD_HLSL_WRITER
}
-#if TINT_BUILD_GLSL_WRITER
-EShLanguage pipeline_stage_to_esh_language(tint::ast::PipelineStage stage) {
- switch (stage) {
- case tint::ast::PipelineStage::kFragment:
- return EShLangFragment;
- case tint::ast::PipelineStage::kVertex:
- return EShLangVertex;
- case tint::ast::PipelineStage::kCompute:
- return EShLangCompute;
- default:
- TINT_UNREACHABLE();
- return EShLangVertex;
- }
-}
-#endif
-
/// Generate GLSL code for a program.
/// @param program the program to generate
/// @param options the options that Tint was invoked with
/// @returns true on success
-bool GenerateGlsl(const tint::Program& program, const Options& options) {
-#if TINT_BUILD_GLSL_WRITER
- if (options.validate) {
- glslang::InitializeProcess();
- }
-
+bool GenerateGlsl([[maybe_unused]] const tint::Program& program,
+ [[maybe_unused]] const Options& options) {
+#if !TINT_BUILD_GLSL_WRITER
+ std::cerr << "GLSL writer not enabled in tint build" << std::endl;
+ return false;
+#else
auto generate = [&](const tint::Program& prg, const std::string entry_point_name) -> bool {
tint::glsl::writer::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
@@ -935,22 +920,16 @@
}
if (options.validate && options.skip_hash.count(hash) == 0) {
- for (auto entry_pt : result->entry_points) {
- EShLanguage lang = pipeline_stage_to_esh_language(entry_pt.second);
- glslang::TShader shader(lang);
- const char* strings[1] = {result->glsl.c_str()};
- int lengths[1] = {static_cast<int>(result->glsl.length())};
- shader.setStringsWithLengths(strings, lengths, 1);
- shader.setEntryPoint("main");
- bool glslang_result = shader.parse(GetDefaultResources(), 310, EEsProfile, false,
- false, EShMsgDefault);
- if (!glslang_result) {
- std::cerr << "Error parsing GLSL shader:\n"
- << shader.getInfoLog() << "\n"
- << shader.getInfoDebugLog() << "\n";
- return false;
- }
+#if !TINT_BUILD_GLSL_VALIDATOR
+ std::cerr << "GLSL validator not enabled in tint build" << std::endl;
+ return false;
+#else
+ auto val = tint::glsl::validate::Validate(result->glsl, result->entry_points);
+ if (!val) {
+ std::cerr << "Error parsing GLSL shader:\n" << val.Failure();
+ return false;
}
+#endif
}
return true;
};
@@ -968,11 +947,6 @@
success &= generate(program, entry_point.name);
}
return success;
-#else
- (void)program;
- (void)options;
- std::cerr << "GLSL writer not enabled in tint build" << std::endl;
- return false;
#endif // TINT_BUILD_GLSL_WRITER
}
@@ -1116,8 +1090,7 @@
} else {
auto mod = result.Move();
if (options.dump_ir) {
- tint::core::ir::Disassembler d(mod);
- std::cout << d.Disassemble() << std::endl;
+ std::cout << tint::core::ir::Disassemble(mod) << std::endl;
}
}
}
diff --git a/src/tint/externals.json b/src/tint/externals.json
index 649a650..6cdd1b2 100644
--- a/src/tint/externals.json
+++ b/src/tint/externals.json
@@ -8,6 +8,11 @@
"absl/**"
],
},
+ "google-benchmark": {
+ "IncludePatterns": [
+ "benchmark/benchmark.h"
+ ]
+ },
"metal": {
"IncludePatterns": [
"Metal/Metal.h"
diff --git a/src/tint/fuzzers/BUILD.gn b/src/tint/fuzzers/BUILD.gn
index f15436a..1f576ad 100644
--- a/src/tint/fuzzers/BUILD.gn
+++ b/src/tint/fuzzers/BUILD.gn
@@ -18,7 +18,7 @@
# Fuzzers - Libfuzzer based fuzzing targets for Chromium
# To run the fuzzers outside of Chromium, use the CMake based builds.
-if (build_with_chromium) {
+if (tint_has_fuzzers) {
import("//testing/libfuzzer/fuzzer_test.gni")
import("../../../scripts/dawn_overrides_with_defaults.gni")
@@ -40,13 +40,15 @@
"max_len=10000",
]
- tint_ast_fuzzer_common_libfuzzer_options =
- tint_fuzzer_common_libfuzzer_options + [
- "cross_over=0",
- "mutate_depth=1",
- "tint_enable_all_mutations=false",
- "tint_mutation_batch_size=5",
- ]
+ if (build_with_chromium) {
+ tint_ast_fuzzer_common_libfuzzer_options =
+ tint_fuzzer_common_libfuzzer_options + [
+ "cross_over=0",
+ "mutate_depth=1",
+ "tint_enable_all_mutations=false",
+ "tint_mutation_batch_size=5",
+ ]
+ }
tint_regex_fuzzer_common_libfuzzer_options =
tint_fuzzer_common_libfuzzer_options + [
@@ -72,6 +74,7 @@
"${tint_src_dir}/lang/hlsl/writer",
"${tint_src_dir}/lang/msl/writer",
"${tint_src_dir}/lang/spirv/writer",
+ "${tint_src_dir}/lang/spirv/writer/helpers",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
"${tint_src_dir}/lang/wgsl/helpers",
@@ -86,8 +89,6 @@
]
sources = [
- "apply_substitute_overrides.cc",
- "apply_substitute_overrides.h",
"data_builder.h",
"mersenne_twister_engine.cc",
"mersenne_twister_engine.h",
@@ -134,12 +135,14 @@
seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
}
- fuzzer_test("tint_ast_wgsl_writer_fuzzer") {
- sources = [ "tint_ast_fuzzer/tint_ast_wgsl_writer_fuzzer.cc" ]
- deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
- libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
- seed_corpus = fuzzer_corpus_wgsl_dir
- seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ if (build_with_chromium) {
+ fuzzer_test("tint_ast_wgsl_writer_fuzzer") {
+ sources = [ "tint_ast_fuzzer/tint_ast_wgsl_writer_fuzzer.cc" ]
+ deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
+ libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
+ seed_corpus = fuzzer_corpus_wgsl_dir
+ seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ }
}
fuzzer_test("tint_regex_wgsl_writer_fuzzer") {
@@ -170,12 +173,14 @@
seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
}
- fuzzer_test("tint_ast_spv_writer_fuzzer") {
- sources = [ "tint_ast_fuzzer/tint_ast_spv_writer_fuzzer.cc" ]
- deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
- libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
- seed_corpus = fuzzer_corpus_wgsl_dir
- seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ if (build_with_chromium) {
+ fuzzer_test("tint_ast_spv_writer_fuzzer") {
+ sources = [ "tint_ast_fuzzer/tint_ast_spv_writer_fuzzer.cc" ]
+ deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
+ libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
+ seed_corpus = fuzzer_corpus_wgsl_dir
+ seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ }
}
fuzzer_test("tint_binding_remapper_fuzzer") {
@@ -263,12 +268,14 @@
}
if (tint_build_wgsl_reader && tint_build_hlsl_writer) {
- fuzzer_test("tint_ast_hlsl_writer_fuzzer") {
- sources = [ "tint_ast_fuzzer/tint_ast_hlsl_writer_fuzzer.cc" ]
- deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
- libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
- seed_corpus = fuzzer_corpus_wgsl_dir
- seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ if (build_with_chromium) {
+ fuzzer_test("tint_ast_hlsl_writer_fuzzer") {
+ sources = [ "tint_ast_fuzzer/tint_ast_hlsl_writer_fuzzer.cc" ]
+ deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
+ libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
+ seed_corpus = fuzzer_corpus_wgsl_dir
+ seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ }
}
fuzzer_test("tint_regex_hlsl_writer_fuzzer") {
@@ -290,12 +297,14 @@
}
if (tint_build_wgsl_reader && tint_build_msl_writer) {
- fuzzer_test("tint_ast_msl_writer_fuzzer") {
- sources = [ "tint_ast_fuzzer/tint_ast_msl_writer_fuzzer.cc" ]
- deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
- libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
- seed_corpus = fuzzer_corpus_wgsl_dir
- seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ if (build_with_chromium) {
+ fuzzer_test("tint_ast_msl_writer_fuzzer") {
+ sources = [ "tint_ast_fuzzer/tint_ast_msl_writer_fuzzer.cc" ]
+ deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
+ libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options
+ seed_corpus = fuzzer_corpus_wgsl_dir
+ seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
+ }
}
fuzzer_test("tint_regex_msl_writer_fuzzer") {
@@ -316,15 +325,6 @@
}
}
- if (tint_build_wgsl_reader && tint_build_hlsl_writer &&
- tint_build_msl_writer && tint_build_spv_writer &&
- tint_build_wgsl_writer) {
- executable("tint_black_box_fuzz_target") {
- sources = [ "tint_black_box_fuzz_target.cc" ]
- deps = [ ":tint_fuzzer_common_src" ]
- }
- }
-
group("fuzzers") {
testonly = true
deps = []
@@ -332,15 +332,16 @@
if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
deps += [
":tint_ast_clone_fuzzer",
- ":tint_ast_wgsl_writer_fuzzer",
":tint_regex_wgsl_writer_fuzzer",
":tint_wgsl_reader_wgsl_writer_fuzzer",
]
+ if (build_with_chromium) {
+ deps += [ ":tint_ast_wgsl_writer_fuzzer" ]
+ }
}
if (tint_build_wgsl_reader && tint_build_spv_writer) {
deps += [
":tint_all_transforms_fuzzer",
- ":tint_ast_spv_writer_fuzzer",
":tint_binding_remapper_fuzzer",
":tint_first_index_offset_fuzzer",
":tint_regex_spv_writer_fuzzer",
@@ -350,25 +351,27 @@
":tint_vertex_pulling_fuzzer",
":tint_wgsl_reader_spv_writer_fuzzer",
]
+ if (build_with_chromium) {
+ deps += [ ":tint_ast_spv_writer_fuzzer" ]
+ }
}
if (tint_build_wgsl_reader && tint_build_hlsl_writer) {
deps += [
- ":tint_ast_hlsl_writer_fuzzer",
":tint_regex_hlsl_writer_fuzzer",
":tint_wgsl_reader_hlsl_writer_fuzzer",
]
+ if (build_with_chromium) {
+ deps += [ ":tint_ast_hlsl_writer_fuzzer" ]
+ }
}
if (tint_build_wgsl_reader && tint_build_msl_writer) {
deps += [
- ":tint_ast_msl_writer_fuzzer",
":tint_regex_msl_writer_fuzzer",
":tint_wgsl_reader_msl_writer_fuzzer",
]
- }
- if (tint_build_wgsl_reader && tint_build_hlsl_writer &&
- tint_build_msl_writer && tint_build_spv_writer &&
- tint_build_wgsl_writer) {
- deps += [ ":tint_black_box_fuzz_target" ]
+ if (build_with_chromium) {
+ deps += [ ":tint_ast_msl_writer_fuzzer" ]
+ }
}
}
} else {
diff --git a/src/tint/fuzzers/CMakeLists.txt b/src/tint/fuzzers/CMakeLists.txt
index 6fb5e6e..97674f2 100644
--- a/src/tint/fuzzers/CMakeLists.txt
+++ b/src/tint/fuzzers/CMakeLists.txt
@@ -15,8 +15,6 @@
function(add_tint_fuzzer NAME)
add_executable(${NAME}
${NAME}.cc
- apply_substitute_overrides.cc
- apply_substitute_overrides.h
cli.cc
cli.h
data_builder.h
@@ -40,6 +38,7 @@
tint_spvheaders_compile_options(${NAME})
tint_spvtools_compile_options(${NAME})
endif()
+ target_link_libraries(${NAME} PRIVATE tint_lang_spirv_writer_helpers)
target_compile_options(${NAME} PRIVATE -Wno-missing-prototypes)
endfunction()
@@ -92,10 +91,6 @@
add_tint_fuzzer(tint_ast_clone_fuzzer)
endif()
-if (${TINT_BUILD_SPIRV_TOOLS_FUZZER})
- add_subdirectory(tint_spirv_tools_fuzzer)
-endif()
-
if (${TINT_BUILD_AST_FUZZER})
add_subdirectory(tint_ast_fuzzer)
endif()
@@ -103,26 +98,3 @@
if (${TINT_BUILD_REGEX_FUZZER})
add_subdirectory(tint_regex_fuzzer)
endif()
-
-if (${TINT_BUILD_WGSL_READER}
- AND ${TINT_BUILD_HLSL_WRITER}
- AND ${TINT_BUILD_MSL_WRITER}
- AND ${TINT_BUILD_SPV_WRITER}
- AND ${TINT_BUILD_WGSL_WRITER})
- add_executable(tint_black_box_fuzz_target
- apply_substitute_overrides.cc
- apply_substitute_overrides.h
- mersenne_twister_engine.cc
- mersenne_twister_engine.h
- random_generator.cc
- random_generator.h
- random_generator_engine.cc
- random_generator_engine.h
- tint_black_box_fuzz_target.cc
- tint_common_fuzzer.cc
- tint_common_fuzzer.h
- )
- target_link_libraries(tint_black_box_fuzz_target PRIVATE libtint)
- tint_default_compile_options(tint_black_box_fuzz_target)
- tint_spvtools_compile_options(tint_black_box_fuzz_target)
-endif()
diff --git a/src/tint/fuzzers/generate_spirv_corpus.py b/src/tint/fuzzers/generate_spirv_corpus.py
index 6a865e0..53d5ae3 100644
--- a/src/tint/fuzzers/generate_spirv_corpus.py
+++ b/src/tint/fuzzers/generate_spirv_corpus.py
@@ -62,7 +62,7 @@
logged_errors = ""
for in_file in list_spvasm_files(input_dir):
- if in_file.endswith(".expected.spvasm"):
+ if ".expected." in in_file:
continue
out_file = os.path.splitext(
corpus_dir + os.sep +
diff --git a/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
index 1cb440a..85881e4 100644
--- a/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
@@ -14,7 +14,7 @@
function(add_tint_ast_fuzzer NAME)
add_executable(${NAME} ${NAME}.cc ${AST_FUZZER_SOURCES})
- target_link_libraries(${NAME} PRIVATE libtint_ast_fuzzer)
+ target_link_libraries(${NAME} PRIVATE libtint_ast_fuzzer tint_lang_spirv_writer_helpers)
tint_fuzzer_compile_options(${NAME})
if(TINT_BUILD_SPV_READER OR TINT_BUILD_SPV_WRITER)
tint_spvheaders_compile_options(${NAME})
@@ -96,7 +96,7 @@
# Add static library target.
add_library(libtint_ast_fuzzer STATIC ${LIBTINT_AST_FUZZER_SOURCES})
-target_link_libraries(libtint_ast_fuzzer protobuf::libprotobuf libtint)
+target_link_libraries(libtint_ast_fuzzer protobuf::libprotobuf tint_api_sanitize_fuzzer)
tint_default_compile_options(libtint_ast_fuzzer)
target_include_directories(libtint_ast_fuzzer PRIVATE ${CMAKE_BINARY_DIR})
target_compile_options(libtint_ast_fuzzer PRIVATE
@@ -111,8 +111,6 @@
cli.h
fuzzer.cc
override_cli_params.h
- ../apply_substitute_overrides.cc
- ../apply_substitute_overrides.h
../tint_common_fuzzer.cc
../tint_common_fuzzer.h)
diff --git a/src/tint/fuzzers/tint_black_box_fuzz_target.cc b/src/tint/fuzzers/tint_black_box_fuzz_target.cc
deleted file mode 100644
index 1f0877a..0000000
--- a/src/tint/fuzzers/tint_black_box_fuzz_target.cc
+++ /dev/null
@@ -1,156 +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.
-
-#include <cassert>
-#include <cstdio>
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "src/tint/fuzzers/tint_common_fuzzer.h"
-
-namespace {
-
-/// Controls the target language in which code will be generated.
-enum class TargetLanguage {
- kHlsl,
- kMsl,
- kSpv,
- kWgsl,
- kTargetLanguageMax,
-};
-
-/// Copies the content from the file named `input_file` to `buffer`,
-/// assuming each element in the file is of type `T`. If any error occurs,
-/// writes error messages to the standard error stream and returns false.
-/// Assumes the size of a `T` object is divisible by its required alignment.
-/// @returns true if we successfully read the file.
-template <typename T>
-bool ReadFile(const std::string& input_file, std::vector<T>* buffer) {
- if (!buffer) {
- std::cerr << "The buffer pointer was null" << std::endl;
- return false;
- }
-
- FILE* file = nullptr;
-#if defined(_MSC_VER)
- fopen_s(&file, input_file.c_str(), "rb");
-#else
- file = fopen(input_file.c_str(), "rb");
-#endif
- if (!file) {
- std::cerr << "Failed to open " << input_file << std::endl;
- return false;
- }
-
- fseek(file, 0, SEEK_END);
- const auto file_size = static_cast<size_t>(ftell(file));
- if (0 != (file_size % sizeof(T))) {
- std::cerr << "File " << input_file
- << " does not contain an integral number of objects: " << file_size
- << " bytes in the file, require " << sizeof(T) << " bytes per object"
- << std::endl;
- fclose(file);
- return false;
- }
- fseek(file, 0, SEEK_SET);
-
- buffer->clear();
- buffer->resize(file_size / sizeof(T));
-
- size_t bytes_read = fread(buffer->data(), 1, file_size, file);
- fclose(file);
- if (bytes_read != file_size) {
- std::cerr << "Failed to read " << input_file << std::endl;
- return false;
- }
-
- return true;
-}
-
-} // namespace
-
-int main(int argc, const char** argv) {
- if (argc < 2 || argc > 3) {
- std::cerr << "Usage: " << argv[0] << " <input file> [hlsl|msl|spv|wgsl]" << std::endl;
- return 1;
- }
-
- std::string input_filename(argv[1]);
-
- std::vector<uint8_t> data;
- if (!ReadFile<uint8_t>(input_filename, &data)) {
- return 1;
- }
-
- if (data.empty()) {
- return 0;
- }
-
- tint::fuzzers::DataBuilder builder(data.data(), data.size());
-
- TargetLanguage target_language;
-
- if (argc == 3) {
- std::string target_language_string = argv[2];
- if (target_language_string == "hlsl") {
- target_language = TargetLanguage::kHlsl;
- } else if (target_language_string == "msl") {
- target_language = TargetLanguage::kMsl;
- } else if (target_language_string == "spv") {
- target_language = TargetLanguage::kSpv;
- } else {
- assert(target_language_string == "wgsl" && "Unknown target language.");
- target_language = TargetLanguage::kWgsl;
- }
- } else {
- target_language = builder.enum_class<TargetLanguage>(
- static_cast<uint32_t>(TargetLanguage::kTargetLanguageMax));
- }
-
- switch (target_language) {
- case TargetLanguage::kHlsl: {
- tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
- tint::fuzzers::OutputFormat::kHLSL);
- return fuzzer.Run(data.data(), data.size());
- }
- case TargetLanguage::kMsl: {
- tint::msl::writer::Options options;
- GenerateMslOptions(&builder, &options);
- tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
- tint::fuzzers::OutputFormat::kMSL);
- fuzzer.SetOptionsMsl(options);
- return fuzzer.Run(data.data(), data.size());
- }
- case TargetLanguage::kSpv: {
- tint::spirv::writer::Options options;
- GenerateSpirvOptions(&builder, &options);
- tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
- tint::fuzzers::OutputFormat::kSpv);
- fuzzer.SetOptionsSpirv(options);
- return fuzzer.Run(data.data(), data.size());
- }
- case TargetLanguage::kWgsl: {
- tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
- tint::fuzzers::OutputFormat::kWGSL);
- return fuzzer.Run(data.data(), data.size());
- }
- default:
- std::cerr << "Aborting due to unknown target language; fuzzer must be "
- "misconfigured."
- << std::endl;
- abort();
- }
-}
diff --git a/src/tint/fuzzers/tint_common_fuzzer.cc b/src/tint/fuzzers/tint_common_fuzzer.cc
index a9e2e83..07df07b 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.cc
+++ b/src/tint/fuzzers/tint_common_fuzzer.cc
@@ -31,9 +31,9 @@
#endif // TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER
#include "src/tint/api/common/binding_point.h"
-#include "src/tint/fuzzers/apply_substitute_overrides.h"
#include "src/tint/lang/core/type/external_texture.h"
#include "src/tint/lang/wgsl/ast/module.h"
+#include "src/tint/lang/wgsl/helpers/apply_substitute_overrides.h"
#include "src/tint/lang/wgsl/helpers/flatten_bindings.h"
#include "src/tint/lang/wgsl/program/program.h"
#include "src/tint/lang/wgsl/sem/variable.h"
@@ -41,6 +41,10 @@
#include "src/tint/utils/diagnostic/printer.h"
#include "src/tint/utils/math/hash.h"
+#if TINT_BUILD_SPV_WRITER
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
+#endif // TINT_BUILD_SPV_WRITER
+
namespace tint::fuzzers {
namespace {
@@ -237,15 +241,30 @@
}
// Run SubstituteOverride if required
- program = ApplySubstituteOverrides(std::move(program));
- if (!program.IsValid()) {
- return 0;
+ if (auto transformed = tint::wgsl::ApplySubstituteOverrides(program)) {
+ program = std::move(*transformed);
+ if (!program.IsValid()) {
+ return 0;
+ }
+ }
+
+ switch (output_) {
+ case OutputFormat::kMSL:
+ break;
+ case OutputFormat::kHLSL:
+ break;
+ case OutputFormat::kSpv:
+#if TINT_BUILD_SPV_WRITER
+ options_spirv_.bindings = tint::spirv::writer::GenerateBindings(program);
+#endif // TINT_BUILD_SPV_WRITER
+ break;
+ case OutputFormat::kWGSL:
+ break;
}
// For the generates which use MultiPlanar, make sure the configuration options are provided so
// that the transformer will execute.
- if (output_ == OutputFormat::kMSL || output_ == OutputFormat::kHLSL ||
- output_ == OutputFormat::kSpv) {
+ if (output_ == OutputFormat::kMSL || output_ == OutputFormat::kHLSL) {
// Gather external texture binding information
// Collect next valid binding number per group
std::unordered_map<uint32_t, uint32_t> group_to_next_binding_number;
@@ -282,7 +301,6 @@
break;
}
case OutputFormat::kSpv: {
- options_spirv_.external_texture_options.bindings_map = new_bindings_map;
break;
}
default:
@@ -335,7 +353,7 @@
// Remap resource numbers to a flat namespace.
// TODO(crbug.com/tint/1501): Do this via Options::BindingMap.
- if (auto flattened = tint::writer::FlattenBindings(program)) {
+ if (auto flattened = tint::wgsl::FlattenBindings(program)) {
program = std::move(*flattened);
}
diff --git a/src/tint/fuzzers/tint_concurrency_fuzzer.cc b/src/tint/fuzzers/tint_concurrency_fuzzer.cc
index 9301399..c09ab46 100644
--- a/src/tint/fuzzers/tint_concurrency_fuzzer.cc
+++ b/src/tint/fuzzers/tint_concurrency_fuzzer.cc
@@ -19,14 +19,15 @@
#include <thread>
-#include "src/tint/fuzzers/apply_substitute_overrides.h"
#include "src/tint/lang/glsl/writer/writer.h"
#include "src/tint/lang/hlsl/writer/writer.h"
#include "src/tint/lang/msl/writer/writer.h"
#include "src/tint/lang/spirv/writer/writer.h"
+#include "src/tint/lang/wgsl/helpers/apply_substitute_overrides.h"
#include "src/tint/lang/wgsl/helpers/flatten_bindings.h"
#include "src/tint/lang/wgsl/inspector/inspector.h"
#include "src/tint/lang/wgsl/reader/reader.h"
+#include "src/tint/lang/wgsl/sem/module.h"
#include "src/tint/lang/wgsl/writer/writer.h"
#include "src/tint/utils/math/hash.h"
@@ -47,9 +48,16 @@
return 0;
}
- program = tint::fuzzers::ApplySubstituteOverrides(std::move(program));
- if (!program.IsValid()) {
- return 0;
+ if (program.Sem().Module()->Extensions().Contains(
+ tint::wgsl::Extension::kChromiumExperimentalPixelLocal)) {
+ return 0; // Not supported
+ }
+
+ if (auto transformed = tint::wgsl::ApplySubstituteOverrides(program)) {
+ program = std::move(*transformed);
+ if (!program.IsValid()) {
+ return 0;
+ }
}
tint::inspector::Inspector inspector(program);
@@ -110,7 +118,7 @@
#if TINT_BUILD_MSL_WRITER
case Writer::kMSL: {
// Remap resource numbers to a flat namespace.
- if (auto flattened = tint::writer::FlattenBindings(program)) {
+ if (auto flattened = tint::wgsl::FlattenBindings(program)) {
(void)tint::msl::writer::Generate(flattened.value(), {});
}
break;
diff --git a/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc b/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
index 0f1cc86..47fb9ea 100644
--- a/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
+++ b/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
@@ -16,7 +16,7 @@
#include <string>
#include <unordered_set>
-#include "src/tint/fuzzers/apply_substitute_overrides.h"
+#include "src/tint/lang/wgsl/helpers/apply_substitute_overrides.h"
#include "src/tint/lang/wgsl/reader/lower/lower.h"
#include "src/tint/lang/wgsl/reader/parser/parser.h"
#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
@@ -68,9 +68,11 @@
return 0;
}
- src = tint::fuzzers::ApplySubstituteOverrides(std::move(src));
- if (!src.IsValid()) {
- return 0;
+ if (auto transformed = tint::wgsl::ApplySubstituteOverrides(src)) {
+ src = std::move(*transformed);
+ if (!src.IsValid()) {
+ return 0;
+ }
}
auto ir = tint::wgsl::reader::ProgramToIR(src);
diff --git a/src/tint/fuzzers/tint_regex_fuzzer/BUILD.gn b/src/tint/fuzzers/tint_regex_fuzzer/BUILD.gn
index 78a3623..cddb936 100644
--- a/src/tint/fuzzers/tint_regex_fuzzer/BUILD.gn
+++ b/src/tint/fuzzers/tint_regex_fuzzer/BUILD.gn
@@ -15,7 +15,7 @@
import("//build_overrides/build.gni")
import("../../../../scripts/tint_overrides_with_defaults.gni")
-if (build_with_chromium) {
+if (tint_has_fuzzers) {
source_set("tint_regex_fuzzer") {
public_configs = [
"${tint_src_dir}:tint_config",
diff --git a/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
index 45802cd..90e7e21 100644
--- a/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
@@ -14,7 +14,7 @@
function(add_tint_regex_fuzzer NAME)
add_executable(${NAME} ${NAME}.cc ${REGEX_FUZZER_SOURCES})
- target_link_libraries(${NAME} PRIVATE libtint_regex_fuzzer)
+ target_link_libraries(${NAME} PRIVATE libtint_regex_fuzzer tint_lang_spirv_writer_helpers)
tint_fuzzer_compile_options(${NAME})
tint_spvtools_compile_options(${NAME})
target_compile_definitions(${NAME} PRIVATE CUSTOM_MUTATOR)
@@ -40,8 +40,6 @@
cli.h
fuzzer.cc
override_cli_params.h
- ../apply_substitute_overrides.cc
- ../apply_substitute_overrides.h
../tint_common_fuzzer.cc
../tint_common_fuzzer.h)
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/BUILD.gn b/src/tint/fuzzers/tint_spirv_tools_fuzzer/BUILD.gn
deleted file mode 100644
index a42c2d5..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/BUILD.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2022 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")
-
-# Target aliases to ease merging Tint->Dawn
-
-group("tint_spirv_tools_fuzzer") {
- deps = [ "${dawn_tint_dir}/src/tint/fuzzers/tint_spirv_tools_fuzzer:tint_spirv_tools_fuzzer" ]
- testonly = true
-}
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt
deleted file mode 100644
index 0e2f98f..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt
+++ /dev/null
@@ -1,115 +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.
-
-set(FUZZER_SOURCES
- ../mersenne_twister_engine.cc
- ../random_generator.cc
- ../random_generator_engine.cc
- cli.cc
- fuzzer.cc
- mutator.cc
- mutator_cache.cc
- spirv_fuzz_mutator.cc
- spirv_opt_mutator.cc
- spirv_reduce_mutator.cc
- util.cc)
-
-set(FUZZER_SOURCES ${FUZZER_SOURCES}
- ../mersenne_twister_engine.h
- ../random_generator.h
- ../random_generator_engine.h
- cli.h
- mutator.h
- mutator_cache.h
- override_cli_params.h
- spirv_fuzz_mutator.h
- spirv_opt_mutator.h
- spirv_reduce_mutator.h
- util.h)
-
-set(FUZZER_SOURCES ${FUZZER_SOURCES}
- ../apply_substitute_overrides.cc
- ../apply_substitute_overrides.h
- ../tint_common_fuzzer.cc
- ../tint_common_fuzzer.h)
-
-function(configure_spirv_tools_fuzzer_target NAME SOURCES)
- add_executable(${NAME} ${SOURCES})
- target_link_libraries(${NAME} PRIVATE
- SPIRV-Tools
- SPIRV-Tools-opt
- SPIRV-Tools-fuzz
- SPIRV-Tools-reduce
- )
- tint_default_compile_options(${NAME})
- target_compile_options(${NAME} PRIVATE
- -Wno-conditional-uninitialized
- -Wno-covered-switch-default
- -Wno-missing-prototypes
- -Wno-zero-as-null-pointer-constant
- -Wno-reserved-id-macro
- -Wno-sign-conversion
- -Wno-extra-semi-stmt
- -Wno-inconsistent-missing-destructor-override
- -Wno-newline-eof
- -Wno-old-style-cast
- -Wno-weak-vtables
- -Wno-undef)
- target_include_directories(${NAME} PRIVATE
- ${spirv-tools_SOURCE_DIR}
- ${spirv-tools_BINARY_DIR})
-endfunction()
-
-function(add_tint_spirv_tools_fuzzer NAME)
- set(FUZZER_TARGET_SOURCES ${NAME}.cc ${FUZZER_SOURCES})
- configure_spirv_tools_fuzzer_target(${NAME} "${FUZZER_TARGET_SOURCES}")
- tint_fuzzer_compile_options(${NAME})
- target_compile_definitions(tint_spirv_tools_fuzzer PUBLIC CUSTOM_MUTATOR)
- target_compile_definitions(tint_spirv_tools_fuzzer PRIVATE TARGET_FUZZER)
-endfunction()
-
-# Add libfuzzer targets.
-# Targets back-ends according to command line arguments.
-add_tint_spirv_tools_fuzzer(tint_spirv_tools_fuzzer)
-# Targets back-ends individually.
-add_tint_spirv_tools_fuzzer(tint_spirv_tools_hlsl_writer_fuzzer)
-add_tint_spirv_tools_fuzzer(tint_spirv_tools_msl_writer_fuzzer)
-add_tint_spirv_tools_fuzzer(tint_spirv_tools_spv_writer_fuzzer)
-add_tint_spirv_tools_fuzzer(tint_spirv_tools_wgsl_writer_fuzzer)
-
-set(DEBUGGER_SOURCES
- ../mersenne_twister_engine.cc
- ../random_generator.cc
- ../random_generator_engine.cc
- cli.cc
- mutator.cc
- mutator_debugger.cc
- spirv_fuzz_mutator.cc
- spirv_opt_mutator.cc
- spirv_reduce_mutator.cc
- util.cc)
-
-set(DEBUGGER_SOURCES ${DEBUGGER_SOURCES}
- ../mersenne_twister_engine.h
- ../random_generator.h
- ../random_generator_engine.h
- cli.h
- mutator.h
- spirv_fuzz_mutator.h
- spirv_opt_mutator.h
- spirv_reduce_mutator.h
- util.h)
-
-configure_spirv_tools_fuzzer_target(tint_spirv_tools_mutator_debugger "${DEBUGGER_SOURCES}")
-target_compile_definitions(tint_spirv_tools_mutator_debugger PRIVATE TARGET_DEBUGGER)
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.cc
deleted file mode 100644
index 9e7c973..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.cc
+++ /dev/null
@@ -1,470 +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.
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-
-#include <fstream>
-#include <limits>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "source/opt/build_module.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-namespace {
-
-const char* const kMutatorParameters = R"(
-Mutators' parameters:
-
- -tint_donors=
- A path to the text file with a list of paths to the
- SPIR-V donor files. Check out the doc for the spirv-fuzz
- to learn more about donor binaries. Donors are not used
- by default.
-
- -tint_enable_all_fuzzer_passes=
- Whether to use all fuzzer passes or a randomly selected subset
- of them. This must be one of `true` or `false` (without `).
- By default it's `false`.
-
- -tint_enable_all_reduce_passes=
- Whether to use all reduction passes or a randomly selected subset
- of them. This must be one of `true` or `false` (without `).
- By default it's `false`.
-
- -tint_opt_batch_size=
- The maximum number of spirv-opt optimizations that
- will be applied in a single mutation session (i.e.
- a call to LLVMFuzzerCustomMutator). This must fit in
- uint32_t. By default it's 6.
-
- -tint_reduction_batch_size=
- The maximum number of spirv-reduce reductions that
- will be applied in a single mutation session (i.e.
- a call to LLVMFuzzerCustomMutator). This must fit in
- uint32_t. By default it's 3.
-
- -tint_repeated_pass_strategy=
- The strategy that will be used to recommend the next fuzzer
- pass. This must be one of `simple`, `looped` or `random`
- (without `). By default it's `simple`. Check out the doc for
- spirv-fuzz to learn more.
-
- -tint_transformation_batch_size=
- The maximum number of spirv-fuzz transformations
- that will be applied during a single mutation
- session (i.e. a call to LLVMFuzzerCustomMutator).
- This must fit in uint32_t. By default it's 3.
-
- -tint_validate_after_each_fuzzer_pass=
- Whether to validate SPIR-V binary after each fuzzer pass.
- This must be one of `true` or `false` (without `).
- By default it's `true`. Switch this to `false` if you experience
- bad performance.
-
- -tint_validate_after_each_opt_pass=
- Whether to validate SPIR-V binary after each optimization pass.
- This must be one of `true` or `false` (without `).
- By default it's `true`. Switch this to `false` if you experience
- bad performance.
-
- -tint_validate_after_each_reduce_pass=
- Whether to validate SPIR-V binary after each reduction pass.
- This must be one of `true` or `false` (without `).
- By default it's `true`. Switch this to `false` if you experience
- bad performance.
-)";
-
-const char* const kFuzzerHelpMessage = R"(
-This fuzzer uses SPIR-V binaries to fuzz the Tint compiler. It uses SPIRV-Tools
-to mutate those binaries. The fuzzer works on a corpus of SPIR-V shaders.
-For each shader from the corpus it uses one of `spirv-fuzz`, `spirv-reduce` or
-`spirv-opt` to mutate it and then runs the shader through the Tint compiler in
-two steps:
-- Converts the mutated shader to WGSL.
-- Converts WGSL to some target language specified in the CLI arguments.
-
-Below is a list of all supported parameters for this fuzzer. You may want to
-run it with -help=1 to check out libfuzzer parameters.
-
-Fuzzer parameters:
-
- -tint_error_dir
- The directory that will be used to output invalid SPIR-V
- binaries to. This is especially useful during debugging
- mutators. The directory must have the following subdirectories:
- - spv/ - will be used to output errors, produced during
- the conversion from the SPIR-V to WGSL.
- - wgsl/ - will be used to output errors, produced during
- the conversion from the WGSL to `--fuzzing_target`.
- - mutator/ - will be used to output errors, produced by
- the mutators.
- By default invalid files are not printed out.
-
- -tint_fuzzing_target
- The type of backend to target during fuzzing. This must
- be one or a combination of `wgsl`, `spv`, `msl` or `hlsl`
- (without `) separated by commas. By default it's
- `wgsl,spv,msl,hlsl`.
-
- -tint_help
- Show this message. Note that there is also a -help=1
- parameter that will display libfuzzer's help message.
-
- -tint_mutator_cache_size=
- The maximum size of the cache that stores
- mutation sessions. This must fit in uint32_t.
- By default it's 20.
-
- -tint_mutator_type=
- Determines types of the mutators to run. This must be one or
- a combination of `fuzz`, `opt`, `reduce` (without `) separated by
- comma. If a combination is specified, each element in the
- combination will have an equal chance of mutating a SPIR-V
- binary during a mutation session (i.e. if no mutator exists
- for that binary in the mutator cache). By default, the
- parameter's value is `fuzz,opt,reduce`.
-)";
-
-const char* const kMutatorDebuggerHelpMessage = R"(
-This tool is used to debug *mutators*. It uses CLI arguments similar to the
-ones used by the fuzzer. To debug some mutator you just need to specify the
-mutator type, the seed and the path to the SPIR-V binary that triggered the
-error. This tool will run the mutator on the binary until the error is
-produced or the mutator returns `kLimitReached`.
-
-Note that this is different from debugging the fuzzer by specifying input
-files to test. The difference is that the latter will not execute any
-mutator (it will only run the LLVMFuzzerTestOneInput function) whereas this
-tool is useful when one of the SPIRV-Tools mutators crashes or produces an
-invalid binary in LLVMFuzzerCustomMutator.
-
-Debugger parameters:
-
- --help
- Show this message.
-
- --mutator_type=
- Determines the type of the mutator to debug. This must be
- one of `fuzz`, `reduce` or `opt` (without `). This parameter
- is REQUIRED.
-
- --original_binary=
- The path to the SPIR-V binary that the faulty mutator was
- initialized with. This will be dumped on errors by the fuzzer
- if `--error_dir` is specified. This parameter is REQUIRED.
-
- --seed=
- The seed for the random number generator that was used to
- initialize the mutator. This value is usually printed to
- the console when the mutator produces an invalid binary.
- It is also dumped into the log file if `--error_dir` is
- specified. This must fit in uint32_t. This parameter is
- REQUIRED.
-)";
-
-void PrintHelpMessage(const char* help_message) {
- std::cout << help_message << std::endl << kMutatorParameters << std::endl;
-}
-
-[[noreturn]] void InvalidParameter(const char* help_message, const char* param) {
- std::cout << "Invalid value for " << param << std::endl;
- PrintHelpMessage(help_message);
- exit(1);
-}
-
-bool ParseUint32(const char* param, uint32_t* out) {
- uint64_t value = static_cast<uint64_t>(strtoul(param, nullptr, 10));
- if (value > static_cast<uint64_t>(std::numeric_limits<uint32_t>::max())) {
- return false;
- }
- *out = static_cast<uint32_t>(value);
- return true;
-}
-
-std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier> ParseDonors(const char* file_name) {
- std::ifstream fin(file_name);
- if (!fin) {
- std::cout << "Can't open donors list file: " << file_name << std::endl;
- exit(1);
- }
-
- std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier> result;
- for (std::string donor_file_name; fin >> donor_file_name;) {
- if (!std::ifstream(donor_file_name)) {
- std::cout << "Can't open donor file: " << donor_file_name << std::endl;
- exit(1);
- }
-
- result.emplace_back([donor_file_name] {
- std::vector<uint32_t> binary;
- if (!util::ReadBinary(donor_file_name, &binary)) {
- std::cout << "Failed to read donor from: " << donor_file_name << std::endl;
- exit(1);
- }
- return spvtools::BuildModule(kDefaultTargetEnv,
- spvtools::fuzz::fuzzerutil::kSilentMessageConsumer,
- binary.data(), binary.size());
- });
- }
-
- return result;
-}
-
-bool ParseRepeatedPassStrategy(const char* param, spvtools::fuzz::RepeatedPassStrategy* out) {
- if (!strcmp(param, "simple")) {
- *out = spvtools::fuzz::RepeatedPassStrategy::kSimple;
- } else if (!strcmp(param, "looped")) {
- *out = spvtools::fuzz::RepeatedPassStrategy::kLoopedWithRecommendations;
- } else if (!strcmp(param, "random")) {
- *out = spvtools::fuzz::RepeatedPassStrategy::kRandomWithRecommendations;
- } else {
- return false;
- }
- return true;
-}
-
-bool ParseBool(const char* param, bool* out) {
- if (!strcmp(param, "true")) {
- *out = true;
- } else if (!strcmp(param, "false")) {
- *out = false;
- } else {
- return false;
- }
- return true;
-}
-
-bool ParseMutatorType(const char* param, MutatorType* out) {
- if (!strcmp(param, "fuzz")) {
- *out = MutatorType::kFuzz;
- } else if (!strcmp(param, "opt")) {
- *out = MutatorType::kOpt;
- } else if (!strcmp(param, "reduce")) {
- *out = MutatorType::kReduce;
- } else {
- return false;
- }
- return true;
-}
-
-bool ParseFuzzingTarget(const char* param, FuzzingTarget* out) {
- if (!strcmp(param, "wgsl")) {
- *out = FuzzingTarget::kWgsl;
- } else if (!strcmp(param, "spv")) {
- *out = FuzzingTarget::kSpv;
- } else if (!strcmp(param, "msl")) {
- *out = FuzzingTarget::kMsl;
- } else if (!strcmp(param, "hlsl")) {
- *out = FuzzingTarget::kHlsl;
- } else {
- return false;
- }
- return true;
-}
-
-bool HasPrefix(const char* str, const char* prefix) {
- return strncmp(str, prefix, strlen(prefix)) == 0;
-}
-
-bool ParseMutatorCliParam(const char* param, const char* help_message, MutatorCliParams* out) {
- if (HasPrefix(param, "-tint_transformation_batch_size=")) {
- if (!ParseUint32(param + sizeof("-tint_transformation_batch_size=") - 1,
- &out->transformation_batch_size)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_reduction_batch_size=")) {
- if (!ParseUint32(param + sizeof("-tint_reduction_batch_size=") - 1,
- &out->reduction_batch_size)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_opt_batch_size=")) {
- if (!ParseUint32(param + sizeof("-tint_opt_batch_size=") - 1, &out->opt_batch_size)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_donors=")) {
- out->donors = ParseDonors(param + sizeof("-tint_donors=") - 1);
- } else if (HasPrefix(param, "-tint_repeated_pass_strategy=")) {
- if (!ParseRepeatedPassStrategy(param + sizeof("-tint_repeated_pass_strategy=") - 1,
- &out->repeated_pass_strategy)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_enable_all_fuzzer_passes=")) {
- if (!ParseBool(param + sizeof("-tint_enable_all_fuzzer_passes=") - 1,
- &out->enable_all_fuzzer_passes)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_enable_all_reduce_passes=")) {
- if (!ParseBool(param + sizeof("-tint_enable_all_reduce_passes=") - 1,
- &out->enable_all_reduce_passes)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_validate_after_each_opt_pass=")) {
- if (!ParseBool(param + sizeof("-tint_validate_after_each_opt_pass=") - 1,
- &out->validate_after_each_opt_pass)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_validate_after_each_fuzzer_pass=")) {
- if (!ParseBool(param + sizeof("-tint_validate_after_each_fuzzer_pass=") - 1,
- &out->validate_after_each_fuzzer_pass)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_validate_after_each_reduce_pass=")) {
- if (!ParseBool(param + sizeof("-tint_validate_after_each_reduce_pass=") - 1,
- &out->validate_after_each_reduce_pass)) {
- InvalidParameter(help_message, param);
- }
- } else {
- return false;
- }
- return true;
-}
-
-} // namespace
-
-FuzzerCliParams ParseFuzzerCliParams(int* argc, char** argv) {
- FuzzerCliParams cli_params;
- const auto* help_message = kFuzzerHelpMessage;
- auto help = false;
-
- for (int i = *argc - 1; i > 0; --i) {
- auto param = argv[i];
- auto recognized_param = true;
-
- if (HasPrefix(param, "-tint_mutator_cache_size=")) {
- if (!ParseUint32(param + sizeof("-tint_mutator_cache_size=") - 1,
- &cli_params.mutator_cache_size)) {
- InvalidParameter(help_message, param);
- }
- } else if (HasPrefix(param, "-tint_mutator_type=")) {
- auto result = MutatorType::kNone;
-
- std::stringstream ss(param + sizeof("-tint_mutator_type=") - 1);
- for (std::string value; std::getline(ss, value, ',');) {
- auto out = MutatorType::kNone;
- if (!ParseMutatorType(value.c_str(), &out)) {
- InvalidParameter(help_message, param);
- }
- result = result | out;
- }
-
- if (result == MutatorType::kNone) {
- InvalidParameter(help_message, param);
- }
-
- cli_params.mutator_type = result;
- } else if (HasPrefix(param, "-tint_fuzzing_target=")) {
- auto result = FuzzingTarget::kNone;
-
- std::stringstream ss(param + sizeof("-tint_fuzzing_target=") - 1);
- for (std::string value; std::getline(ss, value, ',');) {
- auto tmp = FuzzingTarget::kNone;
- if (!ParseFuzzingTarget(value.c_str(), &tmp)) {
- InvalidParameter(help_message, param);
- }
- result = result | tmp;
- }
-
- if (result == FuzzingTarget::kNone) {
- InvalidParameter(help_message, param);
- }
-
- cli_params.fuzzing_target = result;
- } else if (HasPrefix(param, "-tint_error_dir=")) {
- cli_params.error_dir = param + sizeof("-tint_error_dir=") - 1;
- } else if (!strcmp(param, "-tint_help")) {
- help = true;
- } else {
- recognized_param =
- ParseMutatorCliParam(param, help_message, &cli_params.mutator_params);
- }
-
- if (recognized_param) {
- // Remove the recognized parameter from the list of all parameters by
- // swapping it with the last one. This will suppress warnings in the
- // libFuzzer about unrecognized parameters. By default, libFuzzer thinks
- // that all user-defined parameters start with two dashes. However, we are
- // forced to use a single one to make the fuzzer compatible with the
- // ClusterFuzz.
- std::swap(argv[i], argv[*argc - 1]);
- *argc -= 1;
- }
- }
-
- if (help) {
- PrintHelpMessage(help_message);
- exit(0);
- }
-
- return cli_params;
-}
-
-MutatorDebuggerCliParams ParseMutatorDebuggerCliParams(int argc, const char* const* argv) {
- MutatorDebuggerCliParams cli_params;
- bool seed_param_present = false;
- bool original_binary_param_present = false;
- bool mutator_type_param_present = false;
- const auto* help_message = kMutatorDebuggerHelpMessage;
- auto help = false;
-
- for (int i = 0; i < argc; ++i) {
- auto param = argv[i];
- ParseMutatorCliParam(param, help_message, &cli_params.mutator_params);
-
- if (HasPrefix(param, "--mutator_type=")) {
- if (!ParseMutatorType(param + sizeof("--mutator_type=") - 1,
- &cli_params.mutator_type)) {
- InvalidParameter(help_message, param);
- }
- mutator_type_param_present = true;
- } else if (HasPrefix(param, "--original_binary=")) {
- if (!util::ReadBinary(param + sizeof("--original_binary=") - 1,
- &cli_params.original_binary)) {
- InvalidParameter(help_message, param);
- }
- original_binary_param_present = true;
- } else if (HasPrefix(param, "--seed=")) {
- if (!ParseUint32(param + sizeof("--seed=") - 1, &cli_params.seed)) {
- InvalidParameter(help_message, param);
- }
- seed_param_present = true;
- } else if (!strcmp(param, "--help")) {
- help = true;
- }
- }
-
- if (help) {
- PrintHelpMessage(help_message);
- exit(0);
- }
-
- std::pair<bool, const char*> required_params[] = {
- {seed_param_present, "--seed"},
- {original_binary_param_present, "--original_binary"},
- {mutator_type_param_present, "--mutator_type"}};
-
- for (auto required_param : required_params) {
- if (!required_param.first) {
- std::cout << required_param.second << " is missing" << std::endl;
- exit(1);
- }
- }
-
- return cli_params;
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h
deleted file mode 100644
index c10c1a7..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h
+++ /dev/null
@@ -1,162 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_CLI_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_CLI_H_
-
-#include <string>
-#include <vector>
-
-#include "source/fuzz/fuzzer.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// Default SPIR-V environment that will be used during fuzzing.
-const auto kDefaultTargetEnv = SPV_ENV_VULKAN_1_1;
-
-/// The type of the mutator to run.
-enum class MutatorType {
- kNone = 0,
- kFuzz = 1 << 0,
- kReduce = 1 << 1,
- kOpt = 1 << 2,
- kAll = kFuzz | kReduce | kOpt
-};
-
-inline MutatorType operator|(MutatorType a, MutatorType b) {
- return static_cast<MutatorType>(static_cast<int>(a) | static_cast<int>(b));
-}
-
-inline MutatorType operator&(MutatorType a, MutatorType b) {
- return static_cast<MutatorType>(static_cast<int>(a) & static_cast<int>(b));
-}
-
-/// Shading language to target during fuzzing.
-enum class FuzzingTarget {
- kNone = 0,
- kHlsl = 1 << 0,
- kMsl = 1 << 1,
- kSpv = 1 << 2,
- kWgsl = 1 << 3,
- kAll = kHlsl | kMsl | kSpv | kWgsl
-};
-
-inline FuzzingTarget operator|(FuzzingTarget a, FuzzingTarget b) {
- return static_cast<FuzzingTarget>(static_cast<int>(a) | static_cast<int>(b));
-}
-
-inline FuzzingTarget operator&(FuzzingTarget a, FuzzingTarget b) {
- return static_cast<FuzzingTarget>(static_cast<int>(a) & static_cast<int>(b));
-}
-
-/// These parameters are accepted by various mutators and thus they are accepted
-/// by both the fuzzer and the mutator debugger.
-struct MutatorCliParams {
- /// SPIR-V target environment for fuzzing.
- spv_target_env target_env = kDefaultTargetEnv;
-
- /// The number of spirv-fuzz transformations to apply at a time.
- uint32_t transformation_batch_size = 3;
-
- /// The number of spirv-reduce reductions to apply at a time.
- uint32_t reduction_batch_size = 3;
-
- /// The number of spirv-opt optimizations to apply at a time.
- uint32_t opt_batch_size = 6;
-
- /// The vector of donors to use in spirv-fuzz (see the doc for spirv-fuzz to
- /// learn more).
- std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier> donors = {};
-
- /// The strategy to use during fuzzing in spirv-fuzz (see the doc for
- /// spirv-fuzz to learn more).
- spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy =
- spvtools::fuzz::RepeatedPassStrategy::kSimple;
-
- /// Whether to use all fuzzer passes or a randomly selected subset of them.
- bool enable_all_fuzzer_passes = false;
-
- /// Whether to use all reduction passes or a randomly selected subset of them.
- bool enable_all_reduce_passes = false;
-
- /// Whether to validate the SPIR-V binary after each optimization pass.
- bool validate_after_each_opt_pass = true;
-
- /// Whether to validate the SPIR-V binary after each fuzzer pass.
- bool validate_after_each_fuzzer_pass = true;
-
- /// Whether to validate the SPIR-V binary after each reduction pass.
- bool validate_after_each_reduce_pass = true;
-};
-
-/// Parameters specific to the fuzzer. Type `-tint_help` in the CLI to learn
-/// more.
-struct FuzzerCliParams {
- /// The size of the cache that records ongoing mutation sessions.
- uint32_t mutator_cache_size = 20;
-
- /// The type of the mutator to run.
- MutatorType mutator_type = MutatorType::kAll;
-
- /// Tint backend to fuzz.
- FuzzingTarget fuzzing_target = FuzzingTarget::kAll;
-
- /// The path to the directory, that will be used to output buggy shaders.
- std::string error_dir = "";
-
- /// Parameters for various mutators.
- MutatorCliParams mutator_params;
-};
-
-/// Parameters specific to the mutator debugger. Type `--help` in the CLI to
-/// learn more.
-struct MutatorDebuggerCliParams {
- /// The type of the mutator to debug.
- MutatorType mutator_type = MutatorType::kNone;
-
- /// The seed that was used to initialize the mutator.
- uint32_t seed = 0;
-
- /// The binary that triggered a bug in the mutator.
- std::vector<uint32_t> original_binary;
-
- /// Parameters for various mutators.
- MutatorCliParams mutator_params;
-};
-
-/// Parses CLI parameters for the fuzzer. This function exits with an error code
-/// and a message is printed to the console if some parameter has invalid
-/// format. You can pass `-tint_help` to check out all available parameters.
-/// This function will remove recognized parameters from the `argv` and adjust
-/// the `argc` accordingly.
-///
-/// @param argc - the number of parameters (identical to the `argc` in `main`
-/// function).
-/// @param argv - array of C strings of parameters.
-/// @return the parsed parameters.
-FuzzerCliParams ParseFuzzerCliParams(int* argc, char** argv);
-
-/// Parses CLI parameters for the mutator debugger. This function exits with an
-/// error code and a message is printed to the console if some parameter has
-/// invalid format. You can pass `--help` to check out all available parameters.
-///
-/// @param argc - the number of parameters (identical to the `argc` in `main`
-/// function).
-/// @param argv - array of C strings of parameters.
-/// @return the parsed parameters.
-MutatorDebuggerCliParams ParseMutatorDebuggerCliParams(int argc, const char* const* argv);
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_CLI_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc
deleted file mode 100644
index 41e417b..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc
+++ /dev/null
@@ -1,249 +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.
-
-#include <cassert>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "spirv-tools/libspirv.hpp"
-#include "src/tint/fuzzers/random_generator.h"
-#include "src/tint/fuzzers/tint_common_fuzzer.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-#include "testing/libfuzzer/libfuzzer_exports.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-namespace {
-
-struct Context {
- FuzzerCliParams params;
- std::unique_ptr<MutatorCache> mutator_cache;
-};
-
-Context* context = nullptr;
-
-extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
- auto params = ParseFuzzerCliParams(argc, *argv);
- auto mutator_cache = params.mutator_cache_size
- ? std::make_unique<MutatorCache>(params.mutator_cache_size)
- : nullptr;
- context = new Context{std::move(params), std::move(mutator_cache)};
- OverrideCliParams(context->params);
- return 0;
-}
-
-std::unique_ptr<Mutator> CreateMutator(const std::vector<uint32_t>& binary, unsigned seed) {
- std::vector<MutatorType> types;
- types.reserve(3);
-
- // Determine which mutator we will be using for `binary` at random.
- auto cli_mutator_type = context->params.mutator_type;
- if ((MutatorType::kFuzz & cli_mutator_type) == MutatorType::kFuzz) {
- types.push_back(MutatorType::kFuzz);
- }
- if ((MutatorType::kReduce & cli_mutator_type) == MutatorType::kReduce) {
- types.push_back(MutatorType::kReduce);
- }
- if ((MutatorType::kOpt & cli_mutator_type) == MutatorType::kOpt) {
- types.push_back(MutatorType::kOpt);
- }
-
- assert(!types.empty() && "At least one mutator type must be specified");
- RandomGenerator generator(seed);
- auto mutator_type = types[generator.GetUInt32(static_cast<uint32_t>(types.size()))];
-
- const auto& mutator_params = context->params.mutator_params;
- switch (mutator_type) {
- case MutatorType::kFuzz:
- return std::make_unique<SpirvFuzzMutator>(
- mutator_params.target_env, binary, seed, mutator_params.donors,
- mutator_params.enable_all_fuzzer_passes, mutator_params.repeated_pass_strategy,
- mutator_params.validate_after_each_fuzzer_pass,
- mutator_params.transformation_batch_size);
- case MutatorType::kReduce:
- return std::make_unique<SpirvReduceMutator>(
- mutator_params.target_env, binary, seed, mutator_params.reduction_batch_size,
- mutator_params.enable_all_reduce_passes,
- mutator_params.validate_after_each_reduce_pass);
- case MutatorType::kOpt:
- return std::make_unique<SpirvOptMutator>(mutator_params.target_env, seed, binary,
- mutator_params.validate_after_each_opt_pass,
- mutator_params.opt_batch_size);
- default:
- assert(false && "All mutator types must be handled above");
- return nullptr;
- }
-}
-
-void CLIMessageConsumer(spv_message_level_t level,
- const char*,
- const spv_position_t& position,
- const char* message) {
- switch (level) {
- case SPV_MSG_FATAL:
- case SPV_MSG_INTERNAL_ERROR:
- case SPV_MSG_ERROR:
- std::cerr << "error: line " << position.index << ": " << message << std::endl;
- break;
- case SPV_MSG_WARNING:
- std::cout << "warning: line " << position.index << ": " << message << std::endl;
- break;
- case SPV_MSG_INFO:
- std::cout << "info: line " << position.index << ": " << message << std::endl;
- break;
- default:
- break;
- }
-}
-
-bool IsValid(const std::vector<uint32_t>& binary) {
- spvtools::SpirvTools tools(context->params.mutator_params.target_env);
- tools.SetMessageConsumer(CLIMessageConsumer);
- return tools.IsValid() &&
- tools.Validate(binary.data(), binary.size(), spvtools::ValidatorOptions());
-}
-
-extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data,
- size_t size,
- size_t max_size,
- unsigned seed) {
- if ((size % sizeof(uint32_t)) != 0) {
- // A valid SPIR-V binary's size must be a multiple of the size of a 32-bit
- // word, and the SPIR-V Tools fuzzer is only designed to work with valid
- // binaries.
- return 0;
- }
-
- std::vector<uint32_t> binary(size / sizeof(uint32_t));
- std::memcpy(binary.data(), data, size);
-
- MutatorCache placeholder_cache(1);
- auto* mutator_cache = context->mutator_cache.get();
- if (!mutator_cache) {
- // Use a placeholder cache if the user has decided not to use a real cache.
- // The placeholder cache will be destroyed when we return from this function
- // but it will save us from writing all the `if (mutator_cache)` below.
- mutator_cache = &placeholder_cache;
- }
-
- if (!mutator_cache->Get(binary)) {
- // This is an unknown binary, so its validity must be checked before
- // proceeding.
- if (!IsValid(binary)) {
- return 0;
- }
- // Assign a mutator to the binary if it doesn't have one yet.
- mutator_cache->Put(binary, CreateMutator(binary, seed));
- }
-
- auto* mutator = mutator_cache->Get(binary);
- assert(mutator && "Mutator must be present in the cache");
-
- auto result = mutator->Mutate();
-
- if (result.GetStatus() == Mutator::Status::kInvalid) {
- // The binary is invalid - log the error and remove the mutator from the
- // cache.
- util::LogMutatorError(*mutator, context->params.error_dir);
- mutator_cache->Remove(binary);
- return 0;
- }
-
- if (!result.IsChanged()) {
- // The mutator didn't change the binary this time. This could be due to the
- // fact that we've reached the number of mutations we can apply (e.g. the
- // number of transformations in spirv-fuzz) or the mutator was just unlucky.
- // Either way, there is no harm in destroying mutator and maybe trying again
- // later (i.e. if libfuzzer decides to do so).
- mutator_cache->Remove(binary);
- return 0;
- }
-
- // At this point the binary is valid and was changed by the mutator.
-
- auto mutated = mutator->GetBinary();
- auto mutated_bytes_size = mutated.size() * sizeof(uint32_t);
- if (mutated_bytes_size > max_size) {
- // The binary is too big. It's unlikely that we'll reduce its size by
- // applying the mutator one more time.
- mutator_cache->Remove(binary);
- return 0;
- }
-
- if (result.GetStatus() == Mutator::Status::kComplete) {
- // Reassign the mutator to the mutated binary in the cache so that we can
- // access later.
- mutator_cache->Put(mutated, mutator_cache->Remove(binary));
- } else {
- // If the binary is valid and was changed but is not `kComplete`, then the
- // mutator has reached some limit on the number of mutations.
- mutator_cache->Remove(binary);
- }
-
- std::memcpy(data, mutated.data(), mutated_bytes_size);
- return mutated_bytes_size;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (size == 0) {
- return 0;
- }
-
- if ((size % sizeof(uint32_t)) != 0) {
- // The SPIR-V Tools fuzzer has been designed to work with valid
- // SPIR-V binaries, whose sizes should be multiples of the size of a 32-bit
- // word.
- return 0;
- }
-
- CommonFuzzer spv_to_wgsl(InputFormat::kSpv, OutputFormat::kWGSL);
- spv_to_wgsl.Run(data, size);
- if (spv_to_wgsl.HasErrors()) {
- auto error = spv_to_wgsl.Diagnostics().str();
- util::LogSpvError(error, data, size, context ? context->params.error_dir : "");
- return 0;
- }
-
- const auto& wgsl = spv_to_wgsl.GetGeneratedWgsl();
-
- std::pair<FuzzingTarget, OutputFormat> targets[] = {
- {FuzzingTarget::kHlsl, OutputFormat::kHLSL},
- {FuzzingTarget::kMsl, OutputFormat::kMSL},
- {FuzzingTarget::kSpv, OutputFormat::kSpv},
- {FuzzingTarget::kWgsl, OutputFormat::kWGSL}};
-
- for (auto target : targets) {
- if ((target.first & context->params.fuzzing_target) != target.first) {
- continue;
- }
-
- CommonFuzzer fuzzer(InputFormat::kWGSL, target.second);
- fuzzer.Run(reinterpret_cast<const uint8_t*>(wgsl.data()), wgsl.size());
- if (fuzzer.HasErrors()) {
- auto error = spv_to_wgsl.Diagnostics().str();
- util::LogWgslError(error, data, size, wgsl, target.second, context->params.error_dir);
- }
- }
-
- return 0;
-}
-
-} // namespace
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.cc
deleted file mode 100644
index 6bb7809..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.cc
+++ /dev/null
@@ -1,28 +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.
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-// We need to define destructor here so that vtable is produced in this
-// translation unit (see -Wweak-vtables clang flag).
-Mutator::~Mutator() = default;
-
-Mutator::Result::Result(Status status, bool is_changed) : status_(status), is_changed_(is_changed) {
- assert((is_changed || status == Status::kStuck || status == Status::kLimitReached) &&
- "Returning invalid result state");
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h
deleted file mode 100644
index 1e81dff..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h
+++ /dev/null
@@ -1,104 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_MUTATOR_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_MUTATOR_H_
-
-#include <cassert>
-#include <cstdint>
-#include <string>
-#include <vector>
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// This is an interface that is used to define custom mutators based on the
-/// SPIR-V tools.
-class Mutator {
- public:
- /// The status of the mutation.
- enum class Status {
- /// Binary is valid, the limit is not reached - can mutate further.
- kComplete,
-
- /// The binary is valid, the limit of mutations has been reached -
- /// can't mutate further.
- kLimitReached,
-
- /// The binary is valid, the limit is not reached but the mutator has spent
- /// too much time without mutating anything - better to restart to make sure
- /// we can make any progress.
- kStuck,
-
- /// The binary is invalid - this is likely a bug in the mutator - must
- /// abort.
- kInvalid
- };
-
- /// Represents the result of the mutation. The following states are possible:
- /// - if `IsChanged() == false`, then `GetStatus()` can be either
- /// `kLimitReached` or `kStuck`.
- /// - otherwise, any value of `Status` is possible.
- class Result {
- public:
- /// Constructor.
- /// @param status - the status of the mutation.
- /// @param is_changed - whether the module was changed during mutation.
- Result(Status status, bool is_changed);
-
- /// @return the status of the mutation.
- Status GetStatus() const { return status_; }
-
- /// @return whether the module was changed during mutation.
- bool IsChanged() const { return is_changed_; }
-
- private:
- Status status_;
- bool is_changed_;
- };
-
- /// Virtual destructor.
- virtual ~Mutator();
-
- /// Causes the mutator to apply a mutation. This method can be called
- /// multiple times as long as the previous call didn't return
- /// `Status::kInvalid`.
- ///
- /// @return the status of the mutation (e.g. success, error etc) and whether
- /// the binary was changed during mutation.
- virtual Result Mutate() = 0;
-
- /// Returns the mutated binary. The returned binary is guaranteed to be valid
- /// iff the previous call to the `Mutate` method returned didn't return
- /// `Status::kInvalid`.
- ///
- /// @return the mutated SPIR-V binary. It might be identical to the original
- /// binary if `Result::IsChanged` returns `false`.
- virtual std::vector<uint32_t> GetBinary() const = 0;
-
- /// Returns errors, produced by the mutator.
- ///
- /// @param path - the directory to which the errors are printed to. No files
- /// are created if the `path` is nullptr.
- /// @param count - the number of the error. Files for this error will be
- /// prefixed with `count`.
- virtual void LogErrors(const std::string* path, uint32_t count) const = 0;
-
- /// @return errors encountered during the mutation. The returned string is
- /// if there were no errors during mutation.
- virtual std::string GetErrors() const = 0;
-};
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_MUTATOR_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.cc
deleted file mode 100644
index b85bdc1..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.cc
+++ /dev/null
@@ -1,72 +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.
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-MutatorCache::MutatorCache(size_t max_size) : map_(), entries_(), max_size_(max_size) {
- assert(max_size && "`max_size` may not be 0");
-}
-
-MutatorCache::Value::pointer MutatorCache::Get(const Key& key) {
- auto it = map_.find(key);
- if (it == map_.end()) {
- return nullptr;
- }
- UpdateUsage(it);
- return entries_.front().second.get();
-}
-
-void MutatorCache::Put(const Key& key, Value value) {
- assert(value && "Mutator cache can't have nullptr unique_ptr");
- auto it = map_.find(key);
- if (it != map_.end()) {
- it->second->second = std::move(value);
- UpdateUsage(it);
- } else {
- if (map_.size() == max_size_) {
- Remove(*entries_.back().first);
- }
-
- entries_.emplace_front(nullptr, std::move(value));
- auto pair = map_.emplace(key, entries_.begin());
- assert(pair.second && "The key must be unique");
- entries_.front().first = &pair.first->first;
- }
-}
-
-MutatorCache::Value MutatorCache::Remove(const Key& key) {
- auto it = map_.find(key);
- if (it == map_.end()) {
- return nullptr;
- }
- auto result = std::move(it->second->second);
- entries_.erase(it->second);
- map_.erase(it);
- return result;
-}
-
-size_t MutatorCache::KeyHash::operator()(const std::vector<uint32_t>& vec) const {
- return std::hash<std::u32string>()({vec.begin(), vec.end()});
-}
-
-void MutatorCache::UpdateUsage(Map::iterator it) {
- auto entry = std::move(*it->second);
- entries_.erase(it->second);
- entries_.push_front(std::move(entry));
- it->second = entries_.begin();
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h
deleted file mode 100644
index cf9b148..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h
+++ /dev/null
@@ -1,95 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_MUTATOR_CACHE_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_MUTATOR_CACHE_H_
-
-#include <cassert>
-#include <list>
-#include <memory>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// Implementation of a fixed size LRU cache. That is, when the number of
-/// elements reaches a certain threshold, the element that wasn't used for the
-/// longest period of time is removed from the cache when a new element is
-/// inserted. All operations have amortized constant time complexity.
-class MutatorCache {
- public:
- /// SPIR-V binary that is being mutated.
- using Key = std::vector<uint32_t>;
-
- /// Mutator that is used to mutate the `Key`.
- using Value = std::unique_ptr<Mutator>;
-
- /// Constructor.
- /// @param max_size - the maximum number of elements the cache can store. May
- /// not be equal to 0.
- explicit MutatorCache(size_t max_size);
-
- /// Retrieves a pointer to a value, associated with a given `key`.
- ///
- /// If the key is present in the cache, its usage is updated and the
- /// (non-null) pointer to the value is returned. Otherwise, `nullptr` is
- /// returned.
- ///
- /// @param key - may not exist in this cache.
- /// @return non-`nullptr` pointer to a value if `key` exists in the cache.
- /// @return `nullptr` if `key` doesn't exist in this cache.
- Value::pointer Get(const Key& key);
-
- /// Inserts a `key`-`value` pair into the cache.
- ///
- /// If the `key` is already present, the `value` replaces the old value and
- /// the usage of `key` is updated. If the `key` is not present, then:
- /// - if the number of elements in the cache is equal to `max_size`, the
- /// key-value pair, where the usage of the key wasn't updated for the
- /// longest period of time, is removed from the cache.
- /// - a new `key`-`value` pair is inserted into the cache.
- ///
- /// @param key - a key.
- /// @param value - may not be a `nullptr`.
- void Put(const Key& key, Value value);
-
- /// Removes `key` and an associated value from the cache.
- ///
- /// @param key - a key.
- /// @return a non-`nullptr` pointer to the removed value, associated with
- /// `key`.
- /// @return `nullptr` if `key` is not present in the cache.
- Value Remove(const Key& key);
-
- private:
- struct KeyHash {
- size_t operator()(const std::vector<uint32_t>& vec) const;
- };
-
- using Entry = std::pair<const Key*, Value>;
- using Map = std::unordered_map<Key, std::list<Entry>::iterator, KeyHash>;
-
- void UpdateUsage(Map::iterator it);
-
- Map map_;
- std::list<Entry> entries_;
- const size_t max_size_;
-};
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_MUTATOR_CACHE_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_debugger.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_debugger.cc
deleted file mode 100644
index d8d6550..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator_debugger.cc
+++ /dev/null
@@ -1,76 +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.
-
-#include <memory>
-#include <string>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-
-/// This tool is used to debug *mutators*. It uses CLI arguments similar to the
-/// ones used by the fuzzer. To debug some mutator you just need to specify the
-/// mutator type, the seed and the path to the SPIR-V binary that triggered the
-/// error. This tool will run the mutator on the binary until the error is
-/// produced or the mutator returns `kLimitReached`.
-///
-/// Note that this is different from debugging the fuzzer by specifying input
-/// files to test. The difference is that the latter will not execute any
-/// mutator (it will only run the LLVMFuzzerTestOneInput function) whereas this
-/// tool is useful when one of the spirv-tools mutators crashes or produces an
-/// invalid binary in LLVMFuzzerCustomMutator.
-int main(int argc, const char** argv) {
- auto params = tint::fuzzers::spvtools_fuzzer::ParseMutatorDebuggerCliParams(argc, argv);
-
- std::unique_ptr<tint::fuzzers::spvtools_fuzzer::Mutator> mutator;
- const auto& mutator_params = params.mutator_params;
- switch (params.mutator_type) {
- case tint::fuzzers::spvtools_fuzzer::MutatorType::kFuzz:
- mutator = std::make_unique<tint::fuzzers::spvtools_fuzzer::SpirvFuzzMutator>(
- mutator_params.target_env, params.original_binary, params.seed,
- mutator_params.donors, mutator_params.enable_all_fuzzer_passes,
- mutator_params.repeated_pass_strategy,
- mutator_params.validate_after_each_fuzzer_pass,
- mutator_params.transformation_batch_size);
- break;
- case tint::fuzzers::spvtools_fuzzer::MutatorType::kReduce:
- mutator = std::make_unique<tint::fuzzers::spvtools_fuzzer::SpirvReduceMutator>(
- mutator_params.target_env, params.original_binary, params.seed,
- mutator_params.reduction_batch_size, mutator_params.enable_all_reduce_passes,
- mutator_params.validate_after_each_reduce_pass);
- break;
- case tint::fuzzers::spvtools_fuzzer::MutatorType::kOpt:
- mutator = std::make_unique<tint::fuzzers::spvtools_fuzzer::SpirvOptMutator>(
- mutator_params.target_env, params.seed, params.original_binary,
- mutator_params.validate_after_each_opt_pass, mutator_params.opt_batch_size);
- break;
- default:
- assert(false && "All mutator types must've been handled");
- return 1;
- }
-
- while (true) {
- auto result = mutator->Mutate();
- if (result.GetStatus() == tint::fuzzers::spvtools_fuzzer::Mutator::Status::kInvalid) {
- std::cerr << mutator->GetErrors() << std::endl;
- return 0;
- }
- if (result.GetStatus() == tint::fuzzers::spvtools_fuzzer::Mutator::Status::kLimitReached) {
- break;
- }
- }
-}
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h
deleted file mode 100644
index da05a4d..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h
+++ /dev/null
@@ -1,32 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_OVERRIDE_CLI_PARAMS_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_OVERRIDE_CLI_PARAMS_H_
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// @brief Allows CLI parameters to be overridden.
-///
-/// This function allows fuzz targets to override particular CLI parameters,
-/// for example forcing a particular back-end to be targeted.
-///
-/// @param cli_params - the parsed CLI parameters to be updated.
-void OverrideCliParams(FuzzerCliParams& cli_params);
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_OVERRIDE_CLI_PARAMS_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.cc
deleted file mode 100644
index b726ec3..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.cc
+++ /dev/null
@@ -1,116 +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.
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h"
-
-#include <fstream>
-#include <utility>
-
-#include "source/opt/build_module.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-SpirvFuzzMutator::SpirvFuzzMutator(
- spv_target_env target_env,
- std::vector<uint32_t> binary,
- unsigned seed,
- const std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier>& donors,
- bool enable_all_passes,
- spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy,
- bool validate_after_each_pass,
- uint32_t transformation_batch_size)
- : transformation_batch_size_(transformation_batch_size),
- errors_(std::make_unique<std::stringstream>()),
- fuzzer_(nullptr),
- validator_options_(),
- original_binary_(std::move(binary)),
- seed_(seed) {
- auto ir_context =
- spvtools::BuildModule(target_env, spvtools::fuzz::fuzzerutil::kSilentMessageConsumer,
- original_binary_.data(), original_binary_.size());
- assert(ir_context && "|binary| is invalid");
-
- auto transformation_context = std::make_unique<spvtools::fuzz::TransformationContext>(
- std::make_unique<spvtools::fuzz::FactManager>(ir_context.get()), validator_options_);
-
- auto fuzzer_context = std::make_unique<spvtools::fuzz::FuzzerContext>(
- std::make_unique<spvtools::fuzz::PseudoRandomGenerator>(seed),
- spvtools::fuzz::FuzzerContext::GetMinFreshId(ir_context.get()), false);
- fuzzer_ = std::make_unique<spvtools::fuzz::Fuzzer>(
- std::move(ir_context), std::move(transformation_context), std::move(fuzzer_context),
- util::GetBufferMessageConsumer(errors_.get()), donors, enable_all_passes,
- repeated_pass_strategy, validate_after_each_pass, validator_options_);
-}
-
-Mutator::Result SpirvFuzzMutator::Mutate() {
- // The assertion will fail in |fuzzer_->Run| if the previous fuzzing led to
- // invalid module.
- auto result = fuzzer_->Run(transformation_batch_size_);
- switch (result.status) {
- case spvtools::fuzz::Fuzzer::Status::kComplete:
- return {Mutator::Status::kComplete, result.is_changed};
- case spvtools::fuzz::Fuzzer::Status::kModuleTooBig:
- case spvtools::fuzz::Fuzzer::Status::kTransformationLimitReached:
- return {Mutator::Status::kLimitReached, result.is_changed};
- case spvtools::fuzz::Fuzzer::Status::kFuzzerStuck:
- return {Mutator::Status::kStuck, result.is_changed};
- case spvtools::fuzz::Fuzzer::Status::kFuzzerPassLedToInvalidModule:
- return {Mutator::Status::kInvalid, result.is_changed};
- }
-}
-
-std::vector<uint32_t> SpirvFuzzMutator::GetBinary() const {
- std::vector<uint32_t> result;
- fuzzer_->GetIRContext()->module()->ToBinary(&result, true);
- return result;
-}
-
-std::string SpirvFuzzMutator::GetErrors() const {
- return errors_->str();
-}
-
-void SpirvFuzzMutator::LogErrors(const std::string* path, uint32_t count) const {
- auto message = GetErrors();
- std::cout << count << " | SpirvFuzzMutator (seed: " << seed_ << ")" << std::endl;
- std::cout << message << std::endl;
-
- if (path) {
- auto prefix = *path + std::to_string(count);
-
- // Write errors to file.
- std::ofstream(prefix + ".fuzzer.log") << "seed: " << seed_ << std::endl
- << message << std::endl;
-
- // Write the invalid SPIR-V binary.
- util::WriteBinary(prefix + ".fuzzer.invalid.spv", GetBinary());
-
- // Write the original SPIR-V binary.
- util::WriteBinary(prefix + ".fuzzer.original.spv", original_binary_);
-
- // Write transformations.
- google::protobuf::util::JsonOptions options;
- options.add_whitespace = true;
- std::string json;
- google::protobuf::util::MessageToJsonString(fuzzer_->GetTransformationSequence(), &json,
- options);
- std::ofstream(prefix + ".fuzzer.transformations.json") << json << std::endl;
-
- std::ofstream binary_transformations(prefix + ".fuzzer.transformations.binary",
- std::ios::binary | std::ios::out);
- fuzzer_->GetTransformationSequence().SerializeToOstream(&binary_transformations);
- }
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h
deleted file mode 100644
index 1f94111..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h
+++ /dev/null
@@ -1,90 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_FUZZ_MUTATOR_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_FUZZ_MUTATOR_H_
-
-#include <memory>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-
-#include "source/fuzz/fuzzer.h"
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/fuzz/pseudo_random_generator.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// The mutator that uses spirv-fuzz to mutate SPIR-V.
-///
-/// The initial `binary` must be valid according to `target_env`. All other
-/// parameters (except for the `seed` which just initializes the RNG) are from
-/// the `spvtools::fuzz::Fuzzer` class.
-class SpirvFuzzMutator : public Mutator {
- public:
- /// Constructor.
- /// @param target_env - the target environment for the `binary`.
- /// @param binary - the SPIR-V binary. Must be valid.
- /// @param seed - seed for the RNG.
- /// @param donors - vector of donor suppliers.
- /// @param enable_all_passes - whether to use all fuzzer passes.
- /// @param repeated_pass_strategy - the strategy to use when selecting the
- /// next fuzzer pass.
- /// @param validate_after_each_pass - whether to validate the binary after
- /// each fuzzer pass.
- /// @param transformation_batch_size - the maximum number of transformations
- /// that will be applied during a single call to `Mutate`. It it's equal
- /// to 0 then we apply as much transformations as we can until the
- /// threshold in the spvtools::fuzz::Fuzzer is reached (see the doc for
- /// that class for more info).
- SpirvFuzzMutator(spv_target_env target_env,
- std::vector<uint32_t> binary,
- uint32_t seed,
- const std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier>& donors,
- bool enable_all_passes,
- spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy,
- bool validate_after_each_pass,
- uint32_t transformation_batch_size);
-
- Result Mutate() override;
- std::vector<uint32_t> GetBinary() const override;
- void LogErrors(const std::string* path, uint32_t count) const override;
- std::string GetErrors() const override;
-
- private:
- // The number of transformations that will be applied during a single call to
- // the `Mutate` method. Is this only a lower bound since transformations are
- // applied in batches by fuzzer passes (see docs for the
- // `spvtools::fuzz::Fuzzer` for more info).
- const uint32_t transformation_batch_size_;
-
- // The errors produced by the `spvtools::fuzz::Fuzzer`.
- std::unique_ptr<std::stringstream> errors_;
- std::unique_ptr<spvtools::fuzz::Fuzzer> fuzzer_;
- spvtools::ValidatorOptions validator_options_;
-
- // The following fields are useful for debugging.
-
- // The binary that the mutator is constructed with.
- const std::vector<uint32_t> original_binary_;
-
- // The seed that the mutator is constructed with.
- const uint32_t seed_;
-};
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_FUZZ_MUTATOR_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.cc
deleted file mode 100644
index 22fc517..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.cc
+++ /dev/null
@@ -1,153 +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.
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.h"
-
-#include <fstream>
-#include <iostream>
-#include <unordered_set>
-#include <utility>
-
-#include "spirv-tools/optimizer.hpp"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-SpirvOptMutator::SpirvOptMutator(spv_target_env target_env,
- uint32_t seed,
- std::vector<uint32_t> binary,
- bool validate_after_each_opt,
- uint32_t opt_batch_size)
- : num_executions_(0),
- is_valid_(true),
- target_env_(target_env),
- original_binary_(std::move(binary)),
- seed_(seed),
- opt_passes_({"--combine-access-chains",
- "--loop-unroll",
- "--merge-blocks",
- "--cfg-cleanup",
- "--eliminate-dead-functions",
- "--merge-return",
- "--wrap-opkill",
- "--eliminate-dead-code-aggressive",
- "--if-conversion",
- "--eliminate-local-single-store",
- "--eliminate-local-single-block",
- "--eliminate-dead-branches",
- "--scalar-replacement=0",
- "--eliminate-dead-inserts",
- "--eliminate-dead-members",
- "--simplify-instructions",
- "--private-to-local",
- "--ssa-rewrite",
- "--ccp",
- "--reduce-load-size",
- "--vector-dce",
- "--scalar-replacement=100",
- "--inline-entry-points-exhaustive",
- "--redundancy-elimination",
- "--convert-local-access-chains",
- "--copy-propagate-arrays",
- "--fix-storage-class"}),
- optimized_binary_(),
- validate_after_each_opt_(validate_after_each_opt),
- opt_batch_size_(opt_batch_size),
- generator_(seed) {
- assert(spvtools::SpirvTools(target_env).Validate(original_binary_) &&
- "Initial binary is invalid");
- assert(!opt_passes_.empty() && "Must be at least one pass");
-}
-
-SpirvOptMutator::Result SpirvOptMutator::Mutate() {
- assert(is_valid_ && "The optimizer is not longer valid");
-
- const uint32_t kMaxNumExecutions = 100;
- const uint32_t kMaxNumStuck = 10;
-
- if (num_executions_ == kMaxNumExecutions) {
- // We've applied this mutator many times already. Indicate to the user that
- // it might be better to try a different mutator.
- return {Status::kLimitReached, false};
- }
-
- num_executions_++;
-
- // Get the input binary. If this is the first time we run this mutator, use
- // the `original_binary_`. Otherwise, one of the following will be true:
- // - the `optimized_binary_` is not empty.
- // - the previous call to the `Mutate` method returned `kStuck`.
- auto binary = num_executions_ == 1 ? original_binary_ : optimized_binary_;
- optimized_binary_.clear();
-
- assert(!binary.empty() && "Can't run the optimizer on an empty binary");
-
- // Number of times spirv-opt wasn't able to produce any new result.
- uint32_t num_stuck = 0;
- do {
- // Randomly select `opt_batch_size` optimization passes. If `opt_batch_size`
- // is equal to 0, we will use the number of passes equal to the number of
- // all available passes.
- auto num_of_passes = opt_batch_size_ ? opt_batch_size_ : opt_passes_.size();
- std::vector<std::string> passes;
-
- while (passes.size() < num_of_passes) {
- auto idx = generator_.GetUInt32(static_cast<uint32_t>(opt_passes_.size()));
- passes.push_back(opt_passes_[idx]);
- }
-
- // Run the `binary` into the `optimized_binary_`.
- spvtools::Optimizer optimizer(target_env_);
- optimizer.SetMessageConsumer(util::GetBufferMessageConsumer(&errors_));
- optimizer.SetValidateAfterAll(validate_after_each_opt_);
- optimizer.RegisterPassesFromFlags(passes);
- if (!optimizer.Run(binary.data(), binary.size(), &optimized_binary_)) {
- is_valid_ = false;
- return {Status::kInvalid, true};
- }
- } while (optimized_binary_.empty() && ++num_stuck < kMaxNumStuck);
-
- return {optimized_binary_.empty() ? Status::kStuck : Status::kComplete,
- !optimized_binary_.empty()};
-}
-
-std::vector<uint32_t> SpirvOptMutator::GetBinary() const {
- return optimized_binary_;
-}
-
-std::string SpirvOptMutator::GetErrors() const {
- return errors_.str();
-}
-
-void SpirvOptMutator::LogErrors(const std::string* path, uint32_t count) const {
- auto message = GetErrors();
- std::cout << count << " | SpirvOptMutator (seed: " << seed_ << ")" << std::endl;
- std::cout << message << std::endl;
-
- if (path) {
- auto prefix = *path + std::to_string(count);
-
- // Write errors to file.
- std::ofstream(prefix + ".opt.log") << "seed: " << seed_ << std::endl
- << message << std::endl;
-
- // Write the invalid SPIR-V binary.
- util::WriteBinary(prefix + ".opt.invalid.spv", optimized_binary_);
-
- // Write the original SPIR-V binary.
- util::WriteBinary(prefix + ".opt.original.spv", original_binary_);
- }
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.h
deleted file mode 100644
index b8e15f0..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_opt_mutator.h
+++ /dev/null
@@ -1,92 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_OPT_MUTATOR_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_OPT_MUTATOR_H_
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "spirv-tools/libspirv.h"
-#include "src/tint/fuzzers/random_generator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// Mutates the SPIR-V module using the spirv-opt tool.
-///
-/// The initial `binary` must be valid according to `target_env`. On each call
-/// to the `Mutate` method the mutator selects `opt_batch_size` random
-/// optimization passes (with substitutions) and applies them to the binary.
-class SpirvOptMutator : public Mutator {
- public:
- /// Constructor.
- /// @param target_env - target environment for the `binary`.
- /// @param seed - seed for the RNG.
- /// @param binary - SPIR-V binary. Must be valid.
- /// @param validate_after_each_opt - whether to validate the binary after each
- /// optimization pass.
- /// @param opt_batch_size - the maximum number of optimization passes that
- /// will be applied in a single call to `Mutate`. If it's equal to 0 then
- /// all available optimization passes are applied.
- SpirvOptMutator(spv_target_env target_env,
- uint32_t seed,
- std::vector<uint32_t> binary,
- bool validate_after_each_opt,
- uint32_t opt_batch_size);
-
- Result Mutate() override;
- std::vector<uint32_t> GetBinary() const override;
- void LogErrors(const std::string* path, uint32_t count) const override;
- std::string GetErrors() const override;
-
- private:
- // Number of times this mutator was executed.
- uint32_t num_executions_;
-
- // Whether the last execution left it in a valid state.
- bool is_valid_;
-
- // Target environment for the SPIR-V binary.
- const spv_target_env target_env_;
-
- // The original SPIR-V binary. Useful for debugging.
- const std::vector<uint32_t> original_binary_;
-
- // The seed for the RNG. Useful for debugging.
- const uint32_t seed_;
-
- // All the optimization passes available.
- const std::vector<std::string> opt_passes_;
-
- // The result of the optimization.
- std::vector<uint32_t> optimized_binary_;
-
- // Whether we need to validate the binary after each optimization pass.
- const bool validate_after_each_opt_;
-
- // The number of optimization passes to apply at once.
- const uint32_t opt_batch_size_;
-
- // All the errors produced by the optimizer.
- std::stringstream errors_;
-
- // The random number generator initialized with `seed_`.
- RandomGenerator generator_;
-};
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_OPT_MUTATOR_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.cc
deleted file mode 100644
index 221799c..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.cc
+++ /dev/null
@@ -1,170 +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.
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.h"
-
-#include <fstream>
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/opt/build_module.h"
-#include "source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.h"
-#include "source/reduce/merge_blocks_reduction_opportunity_finder.h"
-#include "source/reduce/operand_to_const_reduction_opportunity_finder.h"
-#include "source/reduce/operand_to_dominating_id_reduction_opportunity_finder.h"
-#include "source/reduce/operand_to_undef_reduction_opportunity_finder.h"
-#include "source/reduce/remove_block_reduction_opportunity_finder.h"
-#include "source/reduce/remove_function_reduction_opportunity_finder.h"
-#include "source/reduce/remove_selection_reduction_opportunity_finder.h"
-#include "source/reduce/remove_unused_instruction_reduction_opportunity_finder.h"
-#include "source/reduce/remove_unused_struct_member_reduction_opportunity_finder.h"
-#include "source/reduce/simple_conditional_branch_to_branch_opportunity_finder.h"
-#include "source/reduce/structured_loop_to_selection_reduction_opportunity_finder.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-SpirvReduceMutator::SpirvReduceMutator(spv_target_env target_env,
- std::vector<uint32_t> binary,
- uint32_t seed,
- uint32_t reductions_batch_size,
- bool enable_all_reductions,
- bool validate_after_each_reduction)
- : ir_context_(nullptr),
- finders_(),
- generator_(seed),
- errors_(),
- is_valid_(true),
- reductions_batch_size_(reductions_batch_size),
- total_applied_reductions_(0),
- enable_all_reductions_(enable_all_reductions),
- validate_after_each_reduction_(validate_after_each_reduction),
- original_binary_(std::move(binary)),
- seed_(seed) {
- ir_context_ =
- spvtools::BuildModule(target_env, spvtools::fuzz::fuzzerutil::kSilentMessageConsumer,
- original_binary_.data(), original_binary_.size());
- assert(ir_context_ && "|binary| is invalid");
-
- do {
- MaybeAddFinder<
- spvtools::reduce::ConditionalBranchToSimpleConditionalBranchOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::MergeBlocksReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::OperandToConstReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::OperandToDominatingIdReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::OperandToUndefReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::RemoveBlockReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::RemoveFunctionReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::RemoveSelectionReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::RemoveUnusedInstructionReductionOpportunityFinder>(true);
- MaybeAddFinder<spvtools::reduce::RemoveUnusedStructMemberReductionOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::SimpleConditionalBranchToBranchOpportunityFinder>();
- MaybeAddFinder<spvtools::reduce::StructuredLoopToSelectionReductionOpportunityFinder>();
- } while (finders_.empty());
-}
-
-Mutator::Result SpirvReduceMutator::Mutate() {
- assert(is_valid_ && "Can't mutate invalid module");
-
- // The upper limit on the number of applied reduction passes.
- const uint32_t kMaxAppliedReductions = 500;
- const auto old_applied_reductions = total_applied_reductions_;
-
- // The upper limit on the number of failed attempts to apply reductions (i.e.
- // when no reduction was returned by the reduction finder).
- const uint32_t kMaxConsecutiveFailures = 10;
- uint32_t num_consecutive_failures = 0;
-
- // Iterate while we haven't exceeded the limit on the total number of applied
- // reductions, the limit on the number of reductions applied at once and limit
- // on the number of consecutive failed attempts.
- while (total_applied_reductions_ < kMaxAppliedReductions &&
- (reductions_batch_size_ == 0 ||
- total_applied_reductions_ - old_applied_reductions < reductions_batch_size_) &&
- num_consecutive_failures < kMaxConsecutiveFailures) {
- // Select an opportunity finder and get some reduction opportunities from
- // it.
- auto finder = GetRandomElement(&finders_);
- auto reduction_opportunities = finder->GetAvailableOpportunities(ir_context_.get(), 0);
-
- if (reduction_opportunities.empty()) {
- // There is nothing to reduce. We increase the counter to make sure we
- // don't stuck in this situation.
- num_consecutive_failures++;
- } else {
- // Apply a random reduction opportunity. The latter should be applicable.
- auto opportunity = GetRandomElement(&reduction_opportunities);
- assert(opportunity->PreconditionHolds() && "Preconditions should hold");
- total_applied_reductions_++;
- num_consecutive_failures = 0;
- if (!ApplyReduction(opportunity)) {
- // The module became invalid as a result of the applied reduction.
- is_valid_ = false;
- return {Mutator::Status::kInvalid,
- total_applied_reductions_ != old_applied_reductions};
- }
- }
- }
-
- auto is_changed = total_applied_reductions_ != old_applied_reductions;
- if (total_applied_reductions_ == kMaxAppliedReductions) {
- return {Mutator::Status::kLimitReached, is_changed};
- }
-
- if (num_consecutive_failures == kMaxConsecutiveFailures) {
- return {Mutator::Status::kStuck, is_changed};
- }
-
- assert(is_changed && "This is the only way left to break the loop");
- return {Mutator::Status::kComplete, is_changed};
-}
-
-bool SpirvReduceMutator::ApplyReduction(
- spvtools::reduce::ReductionOpportunity* reduction_opportunity) {
- reduction_opportunity->TryToApply();
- return !validate_after_each_reduction_ || spvtools::fuzz::fuzzerutil::IsValidAndWellFormed(
- ir_context_.get(), spvtools::ValidatorOptions(),
- util::GetBufferMessageConsumer(&errors_));
-}
-
-std::vector<uint32_t> SpirvReduceMutator::GetBinary() const {
- std::vector<uint32_t> result;
- ir_context_->module()->ToBinary(&result, true);
- return result;
-}
-
-std::string SpirvReduceMutator::GetErrors() const {
- return errors_.str();
-}
-
-void SpirvReduceMutator::LogErrors(const std::string* path, uint32_t count) const {
- auto message = GetErrors();
- std::cout << count << " | SpirvReduceMutator (seed: " << seed_ << ")" << std::endl;
- std::cout << message << std::endl;
-
- if (path) {
- auto prefix = *path + std::to_string(count);
-
- // Write errors to file.
- std::ofstream(prefix + ".reducer.log") << "seed: " << seed_ << std::endl
- << message << std::endl;
-
- // Write the invalid SPIR-V binary.
- util::WriteBinary(prefix + ".reducer.invalid.spv", GetBinary());
-
- // Write the original SPIR-V binary.
- util::WriteBinary(prefix + ".reducer.original.spv", original_binary_);
- }
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.h
deleted file mode 100644
index ba7bef4..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/spirv_reduce_mutator.h
+++ /dev/null
@@ -1,126 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_REDUCE_MUTATOR_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_REDUCE_MUTATOR_H_
-
-#include <memory>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "src/tint/fuzzers/random_generator.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-
-#include "source/reduce/reduction_opportunity_finder.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-/// Mutates SPIR-V binary by running spirv-reduce tool.
-///
-/// The initial `binary` must be valid according to `target_env`. Applies at
-/// most `reductions_batch_size` reductions at a time. This parameter is ignored
-/// if its value is 0. Uses a random subset of reduction opportunity finders by
-/// default. This can be overridden with the `enable_all_reductions` parameter.
-class SpirvReduceMutator : public Mutator {
- public:
- /// Constructor.
- /// @param target_env - the target environment for the `binary`.
- /// @param binary - SPIR-V binary. Must be valid.
- /// @param seed - the seed for the RNG.
- /// @param reductions_batch_size - the number of reduction passes that will be
- /// applied during a single call to `Mutate`. If it's equal to 0 then we
- /// apply the passes until we reach the threshold for the total number of
- /// applied passes.
- /// @param enable_all_reductions - whether to use all reduction passes or only
- /// a randomly selected subset of them.
- /// @param validate_after_each_reduction - whether to validate after each
- /// applied reduction.
- SpirvReduceMutator(spv_target_env target_env,
- std::vector<uint32_t> binary,
- uint32_t seed,
- uint32_t reductions_batch_size,
- bool enable_all_reductions,
- bool validate_after_each_reduction);
-
- Result Mutate() override;
- std::vector<uint32_t> GetBinary() const override;
- void LogErrors(const std::string* path, uint32_t count) const override;
- std::string GetErrors() const override;
-
- private:
- template <typename T, typename... Args>
- void MaybeAddFinder(Args&&... args) {
- if (enable_all_reductions_ || generator_.GetBool()) {
- finders_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
- }
- }
-
- template <typename T>
- T* GetRandomElement(std::vector<T>* arr) {
- assert(!arr->empty() && "Can't get random element from an empty vector");
- auto index = generator_.GetUInt32(static_cast<uint32_t>(arr->size()));
- return &(*arr)[index];
- }
-
- template <typename T>
- T* GetRandomElement(std::vector<std::unique_ptr<T>>* arr) {
- assert(!arr->empty() && "Can't get random element from an empty vector");
- auto index = generator_.GetUInt32(static_cast<uint32_t>(arr->size()));
- return (*arr)[index].get();
- }
-
- bool ApplyReduction(spvtools::reduce::ReductionOpportunity* reduction_opportunity);
-
- // The SPIR-V binary that is being reduced.
- std::unique_ptr<spvtools::opt::IRContext> ir_context_;
-
- // The selected subset of reduction opportunity finders.
- std::vector<std::unique_ptr<spvtools::reduce::ReductionOpportunityFinder>> finders_;
-
- // Random number generator initialized with `seed_`.
- RandomGenerator generator_;
-
- // All the errors produced by the reducer.
- std::stringstream errors_;
-
- // Whether the last call to the `Mutate` method produced the valid binary.
- bool is_valid_;
-
- // The number of reductions to apply on a single call to `Mutate`.
- const uint32_t reductions_batch_size_;
-
- // The total number of applied reductions.
- uint32_t total_applied_reductions_;
-
- // Whether we want to use all the reduction opportunity finders and not just a
- // subset of them.
- const bool enable_all_reductions_;
-
- // Whether we want to validate all the binary after each reduction.
- const bool validate_after_each_reduction_;
-
- // The original binary that was used to initialize this mutator.
- // Useful for debugging.
- const std::vector<uint32_t> original_binary_;
-
- // The seed that was used to initialize the random number generator.
- // Useful for debugging.
- const uint32_t seed_;
-};
-
-} // namespace tint::fuzzers::spvtools_fuzzer
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_REDUCE_MUTATOR_H_
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_fuzzer.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_fuzzer.cc
deleted file mode 100644
index 6ba973a..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_fuzzer.cc
+++ /dev/null
@@ -1,26 +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.
-
-#include <cassert>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-void OverrideCliParams(FuzzerCliParams& /*unused*/) {
- // Leave the CLI parameters unchanged.
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_hlsl_writer_fuzzer.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_hlsl_writer_fuzzer.cc
deleted file mode 100644
index 2c76157..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_hlsl_writer_fuzzer.cc
+++ /dev/null
@@ -1,29 +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.
-
-#include <cassert>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-void OverrideCliParams(FuzzerCliParams& cli_params) {
- assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
- "The fuzzing target should not have been set by a CLI parameter: it "
- "should have its default value.");
- cli_params.fuzzing_target = FuzzingTarget::kHlsl;
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_msl_writer_fuzzer.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_msl_writer_fuzzer.cc
deleted file mode 100644
index 5d70ad3..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_msl_writer_fuzzer.cc
+++ /dev/null
@@ -1,29 +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.
-
-#include <cassert>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-void OverrideCliParams(FuzzerCliParams& cli_params) {
- assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
- "The fuzzing target should not have been set by a CLI parameter: it "
- "should have its default value.");
- cli_params.fuzzing_target = FuzzingTarget::kMsl;
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_spv_writer_fuzzer.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_spv_writer_fuzzer.cc
deleted file mode 100644
index 53b4e45..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_spv_writer_fuzzer.cc
+++ /dev/null
@@ -1,29 +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.
-
-#include <cassert>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-void OverrideCliParams(FuzzerCliParams& cli_params) {
- assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
- "The fuzzing target should not have been set by a CLI parameter: it "
- "should have its default value.");
- cli_params.fuzzing_target = FuzzingTarget::kSpv;
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_wgsl_writer_fuzzer.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_wgsl_writer_fuzzer.cc
deleted file mode 100644
index 0593f6e..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/tint_spirv_tools_wgsl_writer_fuzzer.cc
+++ /dev/null
@@ -1,29 +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.
-
-#include <cassert>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/cli.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/override_cli_params.h"
-
-namespace tint::fuzzers::spvtools_fuzzer {
-
-void OverrideCliParams(FuzzerCliParams& cli_params) {
- assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
- "The fuzzing target should not have been set by a CLI parameter: it "
- "should have its default value.");
- cli_params.fuzzing_target = FuzzingTarget::kWgsl;
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/util.cc b/src/tint/fuzzers/tint_spirv_tools_fuzzer/util.cc
deleted file mode 100644
index a9e9e2b..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/util.cc
+++ /dev/null
@@ -1,151 +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.
-
-#include <fstream>
-#include <iostream>
-
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h"
-
-namespace tint::fuzzers::spvtools_fuzzer::util {
-namespace {
-
-bool WriteBinary(const std::string& path, const uint8_t* data, size_t size) {
- std::ofstream spv(path, std::ios::binary);
- return spv &&
- spv.write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(size));
-}
-
-void LogError(uint32_t index,
- const std::string& type,
- const std::string& message,
- const std::string* path,
- const uint8_t* data,
- size_t size,
- const std::string* wgsl) {
- std::cout << index << " | " << type << ": " << message << std::endl;
-
- if (path) {
- auto prefix = *path + std::to_string(index);
- std::ofstream(prefix + ".log") << message << std::endl;
-
- WriteBinary(prefix + ".spv", data, size);
-
- if (wgsl) {
- std::ofstream(prefix + ".wgsl") << *wgsl << std::endl;
- }
- }
-}
-
-} // namespace
-
-spvtools::MessageConsumer GetBufferMessageConsumer(std::stringstream* buffer) {
- return [buffer](spv_message_level_t level, const char*, const spv_position_t& position,
- const char* message) {
- std::string status;
- switch (level) {
- case SPV_MSG_FATAL:
- case SPV_MSG_INTERNAL_ERROR:
- case SPV_MSG_ERROR:
- status = "ERROR";
- break;
- case SPV_MSG_WARNING:
- case SPV_MSG_INFO:
- case SPV_MSG_DEBUG:
- status = "INFO";
- break;
- }
- *buffer << status << " " << position.line << ":" << position.column << ":" << position.index
- << ": " << message << std::endl;
- };
-}
-
-void LogMutatorError(const Mutator& mutator, const std::string& error_dir) {
- static uint32_t mutator_count = 0;
- auto error_path = error_dir.empty() ? error_dir : error_dir + "/mutator/";
- mutator.LogErrors(error_dir.empty() ? nullptr : &error_path, mutator_count++);
-}
-
-void LogWgslError(const std::string& message,
- const uint8_t* data,
- size_t size,
- const std::string& wgsl,
- OutputFormat output_format,
- const std::string& error_dir) {
- static uint32_t wgsl_count = 0;
- std::string error_type;
- switch (output_format) {
- case OutputFormat::kSpv:
- error_type = "WGSL -> SPV";
- break;
- case OutputFormat::kMSL:
- error_type = "WGSL -> MSL";
- break;
- case OutputFormat::kHLSL:
- error_type = "WGSL -> HLSL";
- break;
- case OutputFormat::kWGSL:
- error_type = "WGSL -> WGSL";
- break;
- }
- auto error_path = error_dir.empty() ? error_dir : error_dir + "/wgsl/";
- LogError(wgsl_count++, error_type, message, error_dir.empty() ? nullptr : &error_path, data,
- size, &wgsl);
-}
-
-void LogSpvError(const std::string& message,
- const uint8_t* data,
- size_t size,
- const std::string& error_dir) {
- static uint32_t spv_count = 0;
- auto error_path = error_dir.empty() ? error_dir : error_dir + "/spv/";
- LogError(spv_count++, "SPV -> WGSL", message, error_dir.empty() ? nullptr : &error_path, data,
- size, nullptr);
-}
-
-bool ReadBinary(const std::string& path, std::vector<uint32_t>* out) {
- if (!out) {
- return false;
- }
-
- std::ifstream file(path, std::ios::binary | std::ios::ate);
- if (!file) {
- return false;
- }
-
- size_t size = static_cast<size_t>(file.tellg());
- if (!file) {
- return false;
- }
-
- file.seekg(0);
- if (!file) {
- return false;
- }
-
- std::vector<char> binary(size);
- if (!file.read(binary.data(), size)) {
- return false;
- }
-
- out->resize(binary.size() / sizeof(uint32_t));
- std::memcpy(out->data(), binary.data(), binary.size());
- return true;
-}
-
-bool WriteBinary(const std::string& path, const std::vector<uint32_t>& binary) {
- return WriteBinary(path, reinterpret_cast<const uint8_t*>(binary.data()),
- binary.size() * sizeof(uint32_t));
-}
-
-} // namespace tint::fuzzers::spvtools_fuzzer::util
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h b/src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h
deleted file mode 100644
index 28b1774..0000000
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/util.h
+++ /dev/null
@@ -1,90 +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.
-
-#ifndef SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_UTIL_H_
-#define SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_UTIL_H_
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "src/tint/fuzzers/tint_common_fuzzer.h"
-#include "src/tint/fuzzers/tint_spirv_tools_fuzzer/mutator.h"
-
-#include "spirv-tools/libspirv.hpp"
-
-namespace tint::fuzzers::spvtools_fuzzer::util {
-
-/// @param buffer will be used to output errors by the returned message
-/// consumer. Must remain in scope as long as the returned consumer is in
-/// scope.
-/// @return the message consumer that will print errors to the `buffer`.
-spvtools::MessageConsumer GetBufferMessageConsumer(std::stringstream* buffer);
-
-/// Output errors from the SPV -> WGSL conversion.
-///
-/// @param message - the error message.
-/// @param data - invalid SPIR-V binary.
-/// @param size - the size of `data`.
-/// @param error_dir - the directory, to which the binary will be printed to.
-/// If it's empty, the invalid binary and supplemental files will not be
-/// printed. Otherwise, it must have a `spv/` subdirectory.
-void LogSpvError(const std::string& message,
- const uint8_t* data,
- size_t size,
- const std::string& error_dir);
-
-/// Output errors from the WGSL -> `output_format` conversion.
-///
-/// @param message - the error message.
-/// @param data - the SPIR-V binary that generated the WGSL binary.
-/// @param size - the size of `data`.
-/// @param wgsl - the invalid WGSL binary.
-/// @param output_format - the format which we attempted to convert `wgsl` to.
-/// @param error_dir - the directory, to which the binary will be printed out.
-/// If it's empty, the invalid binary and supplemental files will not be
-/// printed. Otherwise, it must have a `wgsl/` subdirectory.
-void LogWgslError(const std::string& message,
- const uint8_t* data,
- size_t size,
- const std::string& wgsl,
- OutputFormat output_format,
- const std::string& error_dir);
-
-/// Output errors produced by the mutator.
-///
-/// @param mutator - the mutator with invalid state.
-/// @param error_dir - the directory, to which invalid files will be printed to.
-/// If it's empty, the invalid binary and supplemental files will not be
-/// printed. Otherwise, it must have a `mutator/` subdirectory.
-void LogMutatorError(const Mutator& mutator, const std::string& error_dir);
-
-/// Reads SPIR-V binary from `path` into `out`. Returns `true` if successful and
-/// `false` otherwise (in this case, `out` is unchanged).
-///
-/// @param path - the path to the SPIR-V binary.
-/// @param out - may be a `nullptr`. In this case, `false` is returned.
-/// @return `true` if successful and `false` otherwise.
-bool ReadBinary(const std::string& path, std::vector<uint32_t>* out);
-
-/// Writes `binary` into `path`.
-///
-/// @param path - the path to write `binary` to.
-/// @param binary - SPIR-V binary.
-/// @return whether the operation was successful.
-bool WriteBinary(const std::string& path, const std::vector<uint32_t>& binary);
-
-} // namespace tint::fuzzers::spvtools_fuzzer::util
-
-#endif // SRC_TINT_FUZZERS_TINT_SPIRV_TOOLS_FUZZER_UTIL_H_
diff --git a/src/tint/lang/core/BUILD.bazel b/src/tint/lang/core/BUILD.bazel
index 8b4f3e9..f3b42a9 100644
--- a/src/tint/lang/core/BUILD.bazel
+++ b/src/tint/lang/core/BUILD.bazel
@@ -116,6 +116,7 @@
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"access_bench.cc",
"address_space_bench.cc",
@@ -129,6 +130,7 @@
deps = [
"//src/tint/lang/core",
"//src/tint/utils/traits",
+ "@benchmark",
],
copts = COPTS,
visibility = ["//visibility:public"],
diff --git a/src/tint/lang/core/BUILD.cmake b/src/tint/lang/core/BUILD.cmake
index ec43104..3bc86ee 100644
--- a/src/tint/lang/core/BUILD.cmake
+++ b/src/tint/lang/core/BUILD.cmake
@@ -138,3 +138,7 @@
tint_lang_core
tint_utils_traits
)
+
+tint_target_add_external_dependencies(tint_lang_core_bench bench
+ "google-benchmark"
+)
diff --git a/src/tint/lang/core/BUILD.gn b/src/tint/lang/core/BUILD.gn
index 78c9e73..ba5a75c 100644
--- a/src/tint/lang/core/BUILD.gn
+++ b/src/tint/lang/core/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -76,7 +76,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"access_test.cc",
"address_space_test.cc",
@@ -114,3 +113,22 @@
]
}
}
+if (tint_build_benchmarks) {
+ tint_unittests_source_set("bench") {
+ sources = [
+ "access_bench.cc",
+ "address_space_bench.cc",
+ "attribute_bench.cc",
+ "builtin_type_bench.cc",
+ "builtin_value_bench.cc",
+ "interpolation_sampling_bench.cc",
+ "interpolation_type_bench.cc",
+ "texel_format_bench.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/utils/traits",
+ ]
+ }
+}
diff --git a/src/tint/lang/core/builtin_fn.cc b/src/tint/lang/core/builtin_fn.cc
index c74963f..3388c19 100644
--- a/src/tint/lang/core/builtin_fn.cc
+++ b/src/tint/lang/core/builtin_fn.cc
@@ -284,9 +284,6 @@
if (name == "workgroupBarrier") {
return BuiltinFn::kWorkgroupBarrier;
}
- if (name == "workgroupUniformLoad") {
- return BuiltinFn::kWorkgroupUniformLoad;
- }
if (name == "textureBarrier") {
return BuiltinFn::kTextureBarrier;
}
@@ -556,8 +553,6 @@
return "unpack4x8unorm";
case BuiltinFn::kWorkgroupBarrier:
return "workgroupBarrier";
- case BuiltinFn::kWorkgroupUniformLoad:
- return "workgroupUniformLoad";
case BuiltinFn::kTextureBarrier:
return "textureBarrier";
case BuiltinFn::kTextureDimensions:
@@ -702,7 +697,6 @@
case BuiltinFn::kAtomicSub:
case BuiltinFn::kAtomicXor:
case BuiltinFn::kTextureStore:
- case BuiltinFn::kWorkgroupUniformLoad:
return true;
default:
break;
diff --git a/src/tint/lang/core/builtin_fn.cc.tmpl b/src/tint/lang/core/builtin_fn.cc.tmpl
index 0a4ba6d..376b33f 100644
--- a/src/tint/lang/core/builtin_fn.cc.tmpl
+++ b/src/tint/lang/core/builtin_fn.cc.tmpl
@@ -121,7 +121,6 @@
case BuiltinFn::kAtomicSub:
case BuiltinFn::kAtomicXor:
case BuiltinFn::kTextureStore:
- case BuiltinFn::kWorkgroupUniformLoad:
return true;
default:
break;
diff --git a/src/tint/lang/core/builtin_fn.h b/src/tint/lang/core/builtin_fn.h
index 5e58b5e..7754750 100644
--- a/src/tint/lang/core/builtin_fn.h
+++ b/src/tint/lang/core/builtin_fn.h
@@ -120,7 +120,6 @@
kUnpack4X8Snorm,
kUnpack4X8Unorm,
kWorkgroupBarrier,
- kWorkgroupUniformLoad,
kTextureBarrier,
kTextureDimensions,
kTextureGather,
@@ -259,7 +258,6 @@
BuiltinFn::kUnpack4X8Snorm,
BuiltinFn::kUnpack4X8Unorm,
BuiltinFn::kWorkgroupBarrier,
- BuiltinFn::kWorkgroupUniformLoad,
BuiltinFn::kTextureBarrier,
BuiltinFn::kTextureDimensions,
BuiltinFn::kTextureGather,
@@ -380,7 +378,6 @@
"unpack4x8snorm",
"unpack4x8unorm",
"workgroupBarrier",
- "workgroupUniformLoad",
"textureBarrier",
"textureDimensions",
"textureGather",
diff --git a/src/tint/lang/core/constant/BUILD.bazel b/src/tint/lang/core/constant/BUILD.bazel
index 6904781..a78387e 100644
--- a/src/tint/lang/core/constant/BUILD.bazel
+++ b/src/tint/lang/core/constant/BUILD.bazel
@@ -96,7 +96,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/intrinsic",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/resolver:test",
"//src/tint/lang/wgsl/sem",
@@ -114,8 +113,18 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/core/constant/BUILD.cmake b/src/tint/lang/core/constant/BUILD.cmake
index d77761f..c6d7ff9 100644
--- a/src/tint/lang/core/constant/BUILD.cmake
+++ b/src/tint/lang/core/constant/BUILD.cmake
@@ -95,7 +95,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_intrinsic
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_resolver
tint_lang_wgsl_resolver_test
tint_lang_wgsl_sem
@@ -117,3 +116,9 @@
tint_target_add_external_dependencies(tint_lang_core_constant_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_core_constant_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
diff --git a/src/tint/lang/core/constant/BUILD.gn b/src/tint/lang/core/constant/BUILD.gn
index 2f15285..a4d035e 100644
--- a/src/tint/lang/core/constant/BUILD.gn
+++ b/src/tint/lang/core/constant/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -66,7 +66,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"composite_test.cc",
"eval_binary_op_test.cc",
@@ -98,7 +97,6 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/intrinsic",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/resolver:unittests",
"${tint_src_dir}/lang/wgsl/sem",
@@ -116,5 +114,9 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
}
}
diff --git a/src/tint/lang/core/constant/eval_binary_op_test.cc b/src/tint/lang/core/constant/eval_binary_op_test.cc
index 8860d48..6f62abb 100644
--- a/src/tint/lang/core/constant/eval_binary_op_test.cc
+++ b/src/tint/lang/core/constant/eval_binary_op_test.cc
@@ -14,9 +14,12 @@
#include "src/tint/lang/core/constant/eval_test.h"
-#include "src/tint/lang/wgsl/reader/reader.h"
#include "src/tint/utils/result/result.h"
+#if TINT_BUILD_WGSL_READER
+#include "src/tint/lang/wgsl/reader/reader.h"
+#endif
+
using namespace tint::core::fluent_types; // NOLINT
using namespace tint::core::number_suffixes; // NOLINT
using ::testing::HasSubstr;
diff --git a/src/tint/lang/core/constant/eval_construction_test.cc b/src/tint/lang/core/constant/eval_construction_test.cc
index 36b5ace..0e5a3aa 100644
--- a/src/tint/lang/core/constant/eval_construction_test.cc
+++ b/src/tint/lang/core/constant/eval_construction_test.cc
@@ -1446,6 +1446,7 @@
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<core::type::Array>();
ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 2u);
EXPECT_TRUE(arr->ElemType()->Is<core::type::Struct>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
@@ -1478,6 +1479,7 @@
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<core::type::Array>();
ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 4u);
EXPECT_TRUE(arr->ElemType()->Is<core::type::I32>());
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
@@ -1500,6 +1502,131 @@
EXPECT_EQ(sem->ConstantValue()->Index(3)->ValueAs<i32>(), 40_i);
}
+TEST_F(ConstEvalTest, Array_Infer_i32_i32) {
+ auto* expr = Call<array<Infer>>(10_i, 20_i);
+ WrapInFunction(expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ auto* arr = sem->Type()->As<core::type::Array>();
+ ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 2u);
+ EXPECT_TRUE(arr->ElemType()->Is<core::type::I32>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+
+ 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_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<i32>(), 20_i);
+}
+
+TEST_F(ConstEvalTest, Array_Infer_ai_ai) {
+ auto* expr = Call<array<Infer>>(10_a, 20_a);
+ GlobalConst("C", expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ auto* arr = sem->Type()->As<core::type::Array>();
+ ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 2u);
+ EXPECT_TRUE(arr->ElemType()->Is<core::type::AbstractInt>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AInt>(), 10_a);
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AInt>(), 20_a);
+}
+
+TEST_F(ConstEvalTest, Array_Infer_af_af) {
+ auto* expr = Call<array<Infer>>(10.0_a, 20.0_a);
+ GlobalConst("C", expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ auto* arr = sem->Type()->As<core::type::Array>();
+ ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 2u);
+ EXPECT_TRUE(arr->ElemType()->Is<core::type::AbstractFloat>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 10_a);
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 20_a);
+}
+
+TEST_F(ConstEvalTest, Array_Infer_af_ai) {
+ auto* expr = Call<array<Infer>>(10.0_a, 20_a);
+ GlobalConst("C", expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ auto* arr = sem->Type()->As<core::type::Array>();
+ ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 2u);
+ EXPECT_TRUE(arr->ElemType()->Is<core::type::AbstractFloat>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 10_a);
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 20_a);
+}
+
+TEST_F(ConstEvalTest, Array_Infer_ai_af) {
+ auto* expr = Call<array<Infer>>(10_a, 20.0_a);
+ GlobalConst("C", expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ auto* arr = sem->Type()->As<core::type::Array>();
+ ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->ConstantCount(), 2u);
+ EXPECT_TRUE(arr->ElemType()->Is<core::type::AbstractFloat>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(0)->ValueAs<AFloat>(), 10_a);
+
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(1)->ValueAs<AFloat>(), 20_a);
+}
+
namespace ArrayInit {
struct Case {
Value input;
diff --git a/src/tint/lang/core/constant/eval_test.h b/src/tint/lang/core/constant/eval_test.h
index b874287..83fbefa 100644
--- a/src/tint/lang/core/constant/eval_test.h
+++ b/src/tint/lang/core/constant/eval_test.h
@@ -113,9 +113,9 @@
[&](const auto& expected) {
using T = std::decay_t<decltype(expected)>;
- ASSERT_TRUE(std::holds_alternative<T>(got_scalar))
- << "Scalar variant index: " << got_scalar.index();
- auto got = std::get<T>(got_scalar);
+ ASSERT_TRUE(std::holds_alternative<T>(got_scalar.value))
+ << "Scalar variant index: " << got_scalar.value.index();
+ auto got = std::get<T>(got_scalar.value);
if constexpr (std::is_same_v<bool, T>) {
EXPECT_EQ(got, expected) << "index: " << i;
@@ -148,7 +148,7 @@
EXPECT_EQ(AInt(got), AInt(expected)) << "index: " << i;
}
},
- expected_scalar);
+ expected_scalar.value);
}
}
diff --git a/src/tint/lang/core/core.def b/src/tint/lang/core/core.def
index 3ca17b9..83a9a84 100644
--- a/src/tint/lang/core/core.def
+++ b/src/tint/lang/core/core.def
@@ -659,7 +659,6 @@
@must_use @const fn unpack4x8snorm(u32) -> vec4<f32>
@must_use @const fn unpack4x8unorm(u32) -> vec4<f32>
@stage("compute") fn workgroupBarrier()
-@must_use @stage("compute") fn workgroupUniformLoad<T>(ptr<workgroup, T, read_write>) -> T
@stage("compute") fn textureBarrier()
@must_use fn textureDimensions<T: fiu32>(texture: texture_1d<T>) -> u32
diff --git a/src/tint/lang/core/intrinsic/BUILD.gn b/src/tint/lang/core/intrinsic/BUILD.gn
index 2ee3356..e5e9984 100644
--- a/src/tint/lang/core/intrinsic/BUILD.gn
+++ b/src/tint/lang/core/intrinsic/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -60,7 +60,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "table_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/lang/core/intrinsic/data.cc b/src/tint/lang/core/intrinsic/data.cc
index 804e52f..9a4568b 100644
--- a/src/tint/lang/core/intrinsic/data.cc
+++ b/src/tint/lang/core/intrinsic/data.cc
@@ -1871,150 +1871,148 @@
/* [27] */ TypeMatcherIndex(9),
/* [28] */ TypeMatcherIndex(13),
/* [29] */ TypeMatcherIndex(9),
- /* [30] */ TypeMatcherIndex(25),
+ /* [30] */ TypeMatcherIndex(30),
/* [31] */ TypeMatcherIndex(0),
- /* [32] */ TypeMatcherIndex(30),
- /* [33] */ TypeMatcherIndex(0),
- /* [34] */ TypeMatcherIndex(11),
- /* [35] */ TypeMatcherIndex(8),
- /* [36] */ TypeMatcherIndex(31),
+ /* [32] */ TypeMatcherIndex(11),
+ /* [33] */ TypeMatcherIndex(8),
+ /* [34] */ TypeMatcherIndex(31),
+ /* [35] */ TypeMatcherIndex(0),
+ /* [36] */ TypeMatcherIndex(32),
/* [37] */ TypeMatcherIndex(0),
- /* [38] */ TypeMatcherIndex(32),
- /* [39] */ TypeMatcherIndex(0),
- /* [40] */ TypeMatcherIndex(12),
- /* [41] */ TypeMatcherIndex(8),
- /* [42] */ TypeMatcherIndex(33),
+ /* [38] */ TypeMatcherIndex(12),
+ /* [39] */ TypeMatcherIndex(8),
+ /* [40] */ TypeMatcherIndex(33),
+ /* [41] */ TypeMatcherIndex(0),
+ /* [42] */ TypeMatcherIndex(34),
/* [43] */ TypeMatcherIndex(0),
- /* [44] */ TypeMatcherIndex(34),
+ /* [44] */ TypeMatcherIndex(35),
/* [45] */ TypeMatcherIndex(0),
- /* [46] */ TypeMatcherIndex(35),
+ /* [46] */ TypeMatcherIndex(36),
/* [47] */ TypeMatcherIndex(0),
- /* [48] */ TypeMatcherIndex(36),
+ /* [48] */ TypeMatcherIndex(13),
/* [49] */ TypeMatcherIndex(0),
- /* [50] */ TypeMatcherIndex(13),
- /* [51] */ TypeMatcherIndex(0),
- /* [52] */ TypeMatcherIndex(11),
- /* [53] */ TypeMatcherIndex(7),
- /* [54] */ TypeMatcherIndex(12),
+ /* [50] */ TypeMatcherIndex(11),
+ /* [51] */ TypeMatcherIndex(7),
+ /* [52] */ TypeMatcherIndex(12),
+ /* [53] */ TypeMatcherIndex(9),
+ /* [54] */ TypeMatcherIndex(30),
/* [55] */ TypeMatcherIndex(9),
- /* [56] */ TypeMatcherIndex(30),
+ /* [56] */ TypeMatcherIndex(31),
/* [57] */ TypeMatcherIndex(9),
- /* [58] */ TypeMatcherIndex(31),
+ /* [58] */ TypeMatcherIndex(32),
/* [59] */ TypeMatcherIndex(9),
- /* [60] */ TypeMatcherIndex(32),
+ /* [60] */ TypeMatcherIndex(33),
/* [61] */ TypeMatcherIndex(9),
- /* [62] */ TypeMatcherIndex(33),
- /* [63] */ TypeMatcherIndex(9),
- /* [64] */ TypeMatcherIndex(12),
- /* [65] */ TypeMatcherIndex(7),
- /* [66] */ TypeMatcherIndex(34),
+ /* [62] */ TypeMatcherIndex(12),
+ /* [63] */ TypeMatcherIndex(7),
+ /* [64] */ TypeMatcherIndex(34),
+ /* [65] */ TypeMatcherIndex(9),
+ /* [66] */ TypeMatcherIndex(35),
/* [67] */ TypeMatcherIndex(9),
- /* [68] */ TypeMatcherIndex(35),
- /* [69] */ TypeMatcherIndex(9),
- /* [70] */ TypeMatcherIndex(11),
- /* [71] */ TypeMatcherIndex(0),
+ /* [68] */ TypeMatcherIndex(11),
+ /* [69] */ TypeMatcherIndex(0),
+ /* [70] */ TypeMatcherIndex(13),
+ /* [71] */ TypeMatcherIndex(7),
/* [72] */ TypeMatcherIndex(13),
- /* [73] */ TypeMatcherIndex(7),
- /* [74] */ TypeMatcherIndex(13),
- /* [75] */ TypeMatcherIndex(8),
- /* [76] */ TypeMatcherIndex(11),
+ /* [73] */ TypeMatcherIndex(8),
+ /* [74] */ TypeMatcherIndex(11),
+ /* [75] */ TypeMatcherIndex(1),
+ /* [76] */ TypeMatcherIndex(12),
/* [77] */ TypeMatcherIndex(1),
- /* [78] */ TypeMatcherIndex(12),
- /* [79] */ TypeMatcherIndex(1),
- /* [80] */ TypeMatcherIndex(52),
- /* [81] */ TypeMatcherIndex(0),
- /* [82] */ TypeMatcherIndex(23),
- /* [83] */ TypeMatcherIndex(8),
+ /* [78] */ TypeMatcherIndex(52),
+ /* [79] */ TypeMatcherIndex(0),
+ /* [80] */ TypeMatcherIndex(23),
+ /* [81] */ TypeMatcherIndex(8),
+ /* [82] */ TypeMatcherIndex(11),
+ /* [83] */ TypeMatcherIndex(5),
/* [84] */ TypeMatcherIndex(11),
- /* [85] */ TypeMatcherIndex(5),
+ /* [85] */ TypeMatcherIndex(10),
/* [86] */ TypeMatcherIndex(11),
- /* [87] */ TypeMatcherIndex(10),
- /* [88] */ TypeMatcherIndex(11),
- /* [89] */ TypeMatcherIndex(4),
+ /* [87] */ TypeMatcherIndex(4),
+ /* [88] */ TypeMatcherIndex(12),
+ /* [89] */ TypeMatcherIndex(5),
/* [90] */ TypeMatcherIndex(12),
- /* [91] */ TypeMatcherIndex(5),
+ /* [91] */ TypeMatcherIndex(10),
/* [92] */ TypeMatcherIndex(12),
- /* [93] */ TypeMatcherIndex(10),
- /* [94] */ TypeMatcherIndex(12),
- /* [95] */ TypeMatcherIndex(4),
+ /* [93] */ TypeMatcherIndex(4),
+ /* [94] */ TypeMatcherIndex(13),
+ /* [95] */ TypeMatcherIndex(5),
/* [96] */ TypeMatcherIndex(13),
- /* [97] */ TypeMatcherIndex(5),
+ /* [97] */ TypeMatcherIndex(1),
/* [98] */ TypeMatcherIndex(13),
- /* [99] */ TypeMatcherIndex(1),
+ /* [99] */ TypeMatcherIndex(10),
/* [100] */ TypeMatcherIndex(13),
- /* [101] */ TypeMatcherIndex(10),
- /* [102] */ TypeMatcherIndex(13),
- /* [103] */ TypeMatcherIndex(4),
+ /* [101] */ TypeMatcherIndex(4),
+ /* [102] */ TypeMatcherIndex(14),
+ /* [103] */ TypeMatcherIndex(0),
/* [104] */ TypeMatcherIndex(14),
- /* [105] */ TypeMatcherIndex(0),
+ /* [105] */ TypeMatcherIndex(10),
/* [106] */ TypeMatcherIndex(14),
- /* [107] */ TypeMatcherIndex(10),
- /* [108] */ TypeMatcherIndex(14),
- /* [109] */ TypeMatcherIndex(9),
+ /* [107] */ TypeMatcherIndex(9),
+ /* [108] */ TypeMatcherIndex(15),
+ /* [109] */ TypeMatcherIndex(0),
/* [110] */ TypeMatcherIndex(15),
- /* [111] */ TypeMatcherIndex(0),
+ /* [111] */ TypeMatcherIndex(10),
/* [112] */ TypeMatcherIndex(15),
- /* [113] */ TypeMatcherIndex(10),
- /* [114] */ TypeMatcherIndex(15),
- /* [115] */ TypeMatcherIndex(9),
+ /* [113] */ TypeMatcherIndex(9),
+ /* [114] */ TypeMatcherIndex(16),
+ /* [115] */ TypeMatcherIndex(0),
/* [116] */ TypeMatcherIndex(16),
- /* [117] */ TypeMatcherIndex(0),
+ /* [117] */ TypeMatcherIndex(10),
/* [118] */ TypeMatcherIndex(16),
- /* [119] */ TypeMatcherIndex(10),
- /* [120] */ TypeMatcherIndex(16),
- /* [121] */ TypeMatcherIndex(9),
+ /* [119] */ TypeMatcherIndex(9),
+ /* [120] */ TypeMatcherIndex(17),
+ /* [121] */ TypeMatcherIndex(0),
/* [122] */ TypeMatcherIndex(17),
- /* [123] */ TypeMatcherIndex(0),
+ /* [123] */ TypeMatcherIndex(10),
/* [124] */ TypeMatcherIndex(17),
- /* [125] */ TypeMatcherIndex(10),
- /* [126] */ TypeMatcherIndex(17),
- /* [127] */ TypeMatcherIndex(9),
+ /* [125] */ TypeMatcherIndex(9),
+ /* [126] */ TypeMatcherIndex(18),
+ /* [127] */ TypeMatcherIndex(0),
/* [128] */ TypeMatcherIndex(18),
- /* [129] */ TypeMatcherIndex(0),
+ /* [129] */ TypeMatcherIndex(10),
/* [130] */ TypeMatcherIndex(18),
- /* [131] */ TypeMatcherIndex(10),
- /* [132] */ TypeMatcherIndex(18),
- /* [133] */ TypeMatcherIndex(9),
+ /* [131] */ TypeMatcherIndex(9),
+ /* [132] */ TypeMatcherIndex(19),
+ /* [133] */ TypeMatcherIndex(0),
/* [134] */ TypeMatcherIndex(19),
- /* [135] */ TypeMatcherIndex(0),
+ /* [135] */ TypeMatcherIndex(10),
/* [136] */ TypeMatcherIndex(19),
- /* [137] */ TypeMatcherIndex(10),
- /* [138] */ TypeMatcherIndex(19),
- /* [139] */ TypeMatcherIndex(9),
+ /* [137] */ TypeMatcherIndex(9),
+ /* [138] */ TypeMatcherIndex(20),
+ /* [139] */ TypeMatcherIndex(0),
/* [140] */ TypeMatcherIndex(20),
- /* [141] */ TypeMatcherIndex(0),
+ /* [141] */ TypeMatcherIndex(10),
/* [142] */ TypeMatcherIndex(20),
- /* [143] */ TypeMatcherIndex(10),
- /* [144] */ TypeMatcherIndex(20),
- /* [145] */ TypeMatcherIndex(9),
+ /* [143] */ TypeMatcherIndex(9),
+ /* [144] */ TypeMatcherIndex(21),
+ /* [145] */ TypeMatcherIndex(0),
/* [146] */ TypeMatcherIndex(21),
- /* [147] */ TypeMatcherIndex(0),
+ /* [147] */ TypeMatcherIndex(10),
/* [148] */ TypeMatcherIndex(21),
- /* [149] */ TypeMatcherIndex(10),
- /* [150] */ TypeMatcherIndex(21),
- /* [151] */ TypeMatcherIndex(9),
+ /* [149] */ TypeMatcherIndex(9),
+ /* [150] */ TypeMatcherIndex(22),
+ /* [151] */ TypeMatcherIndex(0),
/* [152] */ TypeMatcherIndex(22),
- /* [153] */ TypeMatcherIndex(0),
+ /* [153] */ TypeMatcherIndex(10),
/* [154] */ TypeMatcherIndex(22),
- /* [155] */ TypeMatcherIndex(10),
- /* [156] */ TypeMatcherIndex(22),
- /* [157] */ TypeMatcherIndex(9),
- /* [158] */ TypeMatcherIndex(47),
- /* [159] */ TypeMatcherIndex(0),
- /* [160] */ TypeMatcherIndex(37),
- /* [161] */ TypeMatcherIndex(38),
- /* [162] */ TypeMatcherIndex(39),
- /* [163] */ TypeMatcherIndex(40),
- /* [164] */ TypeMatcherIndex(41),
- /* [165] */ TypeMatcherIndex(42),
- /* [166] */ TypeMatcherIndex(43),
- /* [167] */ TypeMatcherIndex(44),
- /* [168] */ TypeMatcherIndex(45),
- /* [169] */ TypeMatcherIndex(46),
- /* [170] */ TypeMatcherIndex(28),
- /* [171] */ TypeMatcherIndex(2),
- /* [172] */ TypeMatcherIndex(29),
- /* [173] */ TypeMatcherIndex(3),
+ /* [155] */ TypeMatcherIndex(9),
+ /* [156] */ TypeMatcherIndex(47),
+ /* [157] */ TypeMatcherIndex(0),
+ /* [158] */ TypeMatcherIndex(37),
+ /* [159] */ TypeMatcherIndex(38),
+ /* [160] */ TypeMatcherIndex(39),
+ /* [161] */ TypeMatcherIndex(40),
+ /* [162] */ TypeMatcherIndex(41),
+ /* [163] */ TypeMatcherIndex(42),
+ /* [164] */ TypeMatcherIndex(43),
+ /* [165] */ TypeMatcherIndex(44),
+ /* [166] */ TypeMatcherIndex(45),
+ /* [167] */ TypeMatcherIndex(46),
+ /* [168] */ TypeMatcherIndex(28),
+ /* [169] */ TypeMatcherIndex(2),
+ /* [170] */ TypeMatcherIndex(29),
+ /* [171] */ TypeMatcherIndex(3),
};
static_assert(TypeMatcherIndex::CanIndex(kTypeMatcherIndices),
@@ -2027,24 +2025,22 @@
/* [3] */ NumberMatcherIndex(1),
/* [4] */ NumberMatcherIndex(0),
/* [5] */ NumberMatcherIndex(7),
- /* [6] */ NumberMatcherIndex(13),
- /* [7] */ NumberMatcherIndex(7),
- /* [8] */ NumberMatcherIndex(3),
+ /* [6] */ NumberMatcherIndex(3),
+ /* [7] */ NumberMatcherIndex(9),
+ /* [8] */ NumberMatcherIndex(4),
/* [9] */ NumberMatcherIndex(9),
- /* [10] */ NumberMatcherIndex(4),
+ /* [10] */ NumberMatcherIndex(5),
/* [11] */ NumberMatcherIndex(9),
- /* [12] */ NumberMatcherIndex(5),
- /* [13] */ NumberMatcherIndex(9),
- /* [14] */ NumberMatcherIndex(3),
+ /* [12] */ NumberMatcherIndex(3),
+ /* [13] */ NumberMatcherIndex(8),
+ /* [14] */ NumberMatcherIndex(4),
/* [15] */ NumberMatcherIndex(8),
- /* [16] */ NumberMatcherIndex(4),
+ /* [16] */ NumberMatcherIndex(5),
/* [17] */ NumberMatcherIndex(8),
- /* [18] */ NumberMatcherIndex(5),
- /* [19] */ NumberMatcherIndex(8),
- /* [20] */ NumberMatcherIndex(1),
+ /* [18] */ NumberMatcherIndex(1),
+ /* [19] */ NumberMatcherIndex(2),
+ /* [20] */ NumberMatcherIndex(0),
/* [21] */ NumberMatcherIndex(2),
- /* [22] */ NumberMatcherIndex(0),
- /* [23] */ NumberMatcherIndex(2),
};
static_assert(NumberMatcherIndex::CanIndex(kNumberMatcherIndices),
@@ -2156,25 +2152,25 @@
{
/* [17] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [18] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [19] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [20] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2204,7 +2200,7 @@
{
/* [25] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2216,13 +2212,13 @@
{
/* [27] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(38),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(36),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [28] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2234,25 +2230,25 @@
{
/* [30] */
/* usage */ core::ParameterUsage::kArrayIndex,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [31] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [32] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(159),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [33] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(172),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2276,19 +2272,19 @@
{
/* [37] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [38] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [39] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2312,19 +2308,19 @@
{
/* [43] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [44] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(56),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [45] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2348,61 +2344,61 @@
{
/* [49] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [50] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [51] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [52] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [53] */
/* usage */ core::ParameterUsage::kDdx,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [54] */
/* usage */ core::ParameterUsage::kDdy,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [55] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [56] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [57] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [58] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2414,25 +2410,25 @@
{
/* [60] */
/* usage */ core::ParameterUsage::kDdx,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [61] */
/* usage */ core::ParameterUsage::kDdy,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [62] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [63] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2456,19 +2452,19 @@
{
/* [67] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [68] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(159),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [69] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2492,7 +2488,7 @@
{
/* [73] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2504,13 +2500,13 @@
{
/* [75] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(36),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(34),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [76] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2522,7 +2518,7 @@
{
/* [78] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2534,37 +2530,37 @@
{
/* [80] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(46),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [81] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [82] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [83] */
/* usage */ core::ParameterUsage::kArrayIndex,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [84] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(159),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [85] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2582,19 +2578,19 @@
{
/* [88] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [89] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(158),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [90] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(172),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2612,25 +2608,25 @@
{
/* [93] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [94] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [95] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(172),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [96] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2648,13 +2644,13 @@
{
/* [99] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [100] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2672,19 +2668,19 @@
{
/* [103] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [104] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(56),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [105] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2702,25 +2698,25 @@
{
/* [108] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [109] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [110] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [111] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2732,25 +2728,25 @@
{
/* [113] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [114] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [115] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [116] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2768,43 +2764,43 @@
{
/* [119] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [120] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [121] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [122] */
/* usage */ core::ParameterUsage::kDdx,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [123] */
/* usage */ core::ParameterUsage::kDdy,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [124] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(56),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [125] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2822,25 +2818,25 @@
{
/* [128] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [129] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [130] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [131] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2852,25 +2848,25 @@
{
/* [133] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [134] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [135] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [136] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2888,13 +2884,13 @@
{
/* [139] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(158),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [140] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2912,25 +2908,25 @@
{
/* [143] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [144] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [145] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [146] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2960,13 +2956,13 @@
{
/* [151] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [152] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -2978,31 +2974,31 @@
{
/* [154] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(42),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [155] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [156] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [157] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(158),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [158] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3014,25 +3010,25 @@
{
/* [160] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [161] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(162),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [162] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(172),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [163] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3044,13 +3040,13 @@
{
/* [165] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(58),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(56),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [166] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3062,49 +3058,49 @@
{
/* [168] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [169] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(60),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [170] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [171] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [172] */
/* usage */ core::ParameterUsage::kOffset,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(62),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [173] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [174] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [175] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3116,19 +3112,19 @@
{
/* [177] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(66),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(64),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [178] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [179] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3140,19 +3136,19 @@
{
/* [181] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(162),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [182] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [183] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3164,13 +3160,13 @@
{
/* [185] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
},
{
/* [186] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3188,13 +3184,13 @@
{
/* [189] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
},
{
/* [190] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3206,19 +3202,19 @@
{
/* [192] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [193] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
},
{
/* [194] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3230,43 +3226,43 @@
{
/* [196] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [197] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(38),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(36),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [198] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(76),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [199] */
/* usage */ core::ParameterUsage::kArrayIndex,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [200] */
/* usage */ core::ParameterUsage::kLevel,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(173),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [201] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(159),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [202] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3278,7 +3274,7 @@
{
/* [204] */
/* usage */ core::ParameterUsage::kLevel,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3308,25 +3304,25 @@
{
/* [209] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [210] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [211] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [212] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3356,25 +3352,25 @@
{
/* [217] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [218] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [219] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [220] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3464,13 +3460,13 @@
{
/* [235] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(56),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(54),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [236] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3482,13 +3478,13 @@
{
/* [238] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [239] */
/* usage */ core::ParameterUsage::kSampler,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(170),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3500,8 +3496,8 @@
{
/* [241] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
},
{
/* [242] */
@@ -3518,13 +3514,13 @@
{
/* [244] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
},
{
/* [245] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3536,8 +3532,8 @@
{
/* [247] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
},
{
/* [248] */
@@ -3554,8 +3550,8 @@
{
/* [250] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
},
{
/* [251] */
@@ -3566,32 +3562,32 @@
{
/* [252] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [253] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
},
{
/* [254] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [255] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [256] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(8),
},
{
/* [257] */
@@ -3602,14 +3598,14 @@
{
/* [258] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [259] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
},
{
/* [260] */
@@ -3620,32 +3616,32 @@
{
/* [261] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [262] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
},
{
/* [263] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [264] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [265] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(10),
},
{
/* [266] */
@@ -3656,13 +3652,13 @@
{
/* [267] */
/* usage */ core::ParameterUsage::kValue,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [268] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(32),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(30),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3674,73 +3670,73 @@
{
/* [270] */
/* usage */ core::ParameterUsage::kLevel,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [271] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(36),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(34),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [272] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(76),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [273] */
/* usage */ core::ParameterUsage::kLevel,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [274] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(42),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(40),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [275] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(78),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(76),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [276] */
/* usage */ core::ParameterUsage::kLevel,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [277] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(48),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(46),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [278] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(76),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [279] */
/* usage */ core::ParameterUsage::kSampleIndex,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(171),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [280] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(158),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [281] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3752,13 +3748,13 @@
{
/* [283] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(162),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [284] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3770,13 +3766,13 @@
{
/* [286] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
},
{
/* [287] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3788,13 +3784,13 @@
{
/* [289] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
},
{
/* [290] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3806,13 +3802,13 @@
{
/* [292] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(18),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
},
{
/* [293] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3824,7 +3820,7 @@
{
/* [295] */
/* usage */ core::ParameterUsage::kXy,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3848,7 +3844,7 @@
{
/* [299] */
/* usage */ core::ParameterUsage::kYz,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3872,7 +3868,7 @@
{
/* [303] */
/* usage */ core::ParameterUsage::kZw,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3902,7 +3898,7 @@
{
/* [308] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(32),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(30),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3914,7 +3910,7 @@
{
/* [310] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(36),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(34),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3926,7 +3922,7 @@
{
/* [312] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(38),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(36),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3938,7 +3934,7 @@
{
/* [314] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(42),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(40),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3950,7 +3946,7 @@
{
/* [316] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(42),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3962,7 +3958,7 @@
{
/* [318] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(46),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(44),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3974,7 +3970,7 @@
{
/* [320] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(158),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3986,7 +3982,7 @@
{
/* [322] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(159),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -3998,7 +3994,7 @@
{
/* [324] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(162),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(160),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -4010,7 +4006,7 @@
{
/* [326] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(161),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -4022,20 +4018,20 @@
{
/* [328] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(169),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [329] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [330] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
},
{
/* [331] */
@@ -4046,8 +4042,8 @@
{
/* [332] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
},
{
/* [333] */
@@ -4058,8 +4054,8 @@
{
/* [334] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(18),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
},
{
/* [335] */
@@ -4070,44 +4066,44 @@
{
/* [336] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
},
{
/* [337] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [338] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
},
{
/* [339] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [340] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(18),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
},
{
/* [341] */
/* usage */ core::ParameterUsage::kCoords,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [342] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(12),
},
{
/* [343] */
@@ -4118,8 +4114,8 @@
{
/* [344] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(14),
},
{
/* [345] */
@@ -4130,8 +4126,8 @@
{
/* [346] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(18),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(16),
},
{
/* [347] */
@@ -4148,7 +4144,7 @@
{
/* [349] */
/* usage */ core::ParameterUsage::kSourceLaneIndex,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -4166,7 +4162,7 @@
{
/* [352] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(82),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(80),
/* number_matcher_indices */ NumberMatcherIndicesIndex(1),
},
{
@@ -4215,7 +4211,7 @@
/* [360] */
/* usage */ core::ParameterUsage::kNone,
/* type_matcher_indices */ TypeMatcherIndicesIndex(12),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(22),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(20),
},
{
/* [361] */
@@ -4226,13 +4222,13 @@
{
/* [362] */
/* usage */ core::ParameterUsage::kXy,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [363] */
/* usage */ core::ParameterUsage::kZw,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -4297,44 +4293,44 @@
},
{
/* [374] */
- /* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(30),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(6),
+ /* usage */ core::ParameterUsage::kTexture,
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(163),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(2),
},
{
/* [375] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(164),
/* number_matcher_indices */ NumberMatcherIndicesIndex(2),
},
{
/* [376] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(165),
/* number_matcher_indices */ NumberMatcherIndicesIndex(2),
},
{
/* [377] */
/* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(167),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(166),
/* number_matcher_indices */ NumberMatcherIndicesIndex(2),
},
{
/* [378] */
- /* usage */ core::ParameterUsage::kTexture,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(168),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(2),
+ /* usage */ core::ParameterUsage::kNone,
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(51),
+ /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [379] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(53),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(85),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [380] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(87),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(74),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
@@ -4346,175 +4342,169 @@
{
/* [382] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(78),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(96),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [383] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(98),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(102),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [384] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(104),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(106),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [385] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(108),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(104),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [386] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(106),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(108),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [387] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(110),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(112),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [388] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(114),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(110),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [389] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(112),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(114),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [390] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(116),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(118),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [391] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(120),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(116),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [392] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(118),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(120),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [393] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(122),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(124),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [394] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(126),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(122),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [395] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(124),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(126),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [396] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(128),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(130),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [397] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(132),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(128),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [398] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(130),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(132),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [399] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(134),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(136),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [400] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(138),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(134),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [401] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(136),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(138),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [402] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(140),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(142),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [403] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(144),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(140),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [404] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(142),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(144),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [405] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(146),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(148),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [406] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(150),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(146),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [407] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(148),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(150),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [408] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(152),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(154),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
{
/* [409] */
/* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(156),
- /* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
- },
- {
- /* [410] */
- /* usage */ core::ParameterUsage::kNone,
- /* type_matcher_indices */ TypeMatcherIndicesIndex(154),
+ /* type_matcher_indices */ TypeMatcherIndicesIndex(152),
/* number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
},
};
@@ -4885,7 +4875,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(268),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4898,7 +4888,7 @@
/* template_types */ TemplateTypeIndex(12),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(308),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4911,7 +4901,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(75),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4924,7 +4914,7 @@
/* template_types */ TemplateTypeIndex(12),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(310),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4937,7 +4927,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(27),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4950,7 +4940,7 @@
/* template_types */ TemplateTypeIndex(12),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(312),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4963,7 +4953,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(274),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(40),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(38),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4976,7 +4966,7 @@
/* template_types */ TemplateTypeIndex(12),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(314),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(40),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(38),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -4989,7 +4979,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(154),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5002,7 +4992,7 @@
/* template_types */ TemplateTypeIndex(12),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(316),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5015,7 +5005,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(80),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5028,7 +5018,7 @@
/* template_types */ TemplateTypeIndex(12),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(318),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5041,7 +5031,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(277),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5054,7 +5044,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(89),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5067,7 +5057,7 @@
/* template_types */ TemplateTypeIndex(3),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(320),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5080,7 +5070,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(32),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5093,7 +5083,7 @@
/* template_types */ TemplateTypeIndex(3),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(322),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5106,7 +5096,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(161),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5119,7 +5109,7 @@
/* template_types */ TemplateTypeIndex(3),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(324),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5132,7 +5122,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(94),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5145,7 +5135,7 @@
/* template_types */ TemplateTypeIndex(3),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(326),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5158,7 +5148,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(283),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5170,8 +5160,8 @@
/* num_template_numbers */ 2,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(6),
- /* parameters */ ParameterIndex(375),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* parameters */ ParameterIndex(374),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5183,8 +5173,8 @@
/* num_template_numbers */ 2,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(6),
- /* parameters */ ParameterIndex(376),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* parameters */ ParameterIndex(375),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5196,8 +5186,8 @@
/* num_template_numbers */ 2,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(6),
- /* parameters */ ParameterIndex(377),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* parameters */ ParameterIndex(376),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5209,8 +5199,8 @@
/* num_template_numbers */ 2,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(6),
- /* parameters */ ParameterIndex(378),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(40),
+ /* parameters */ ParameterIndex(377),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(38),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5223,7 +5213,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(238),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5236,7 +5226,7 @@
/* template_types */ TemplateTypeIndex(4),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(268),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5249,7 +5239,7 @@
/* template_types */ TemplateTypeIndex(4),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(271),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5262,7 +5252,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(197),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5275,7 +5265,7 @@
/* template_types */ TemplateTypeIndex(4),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(274),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5288,7 +5278,7 @@
/* template_types */ TemplateTypeIndex(7),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(277),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5366,7 +5356,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(332),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5379,7 +5369,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(334),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5405,7 +5395,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(338),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5418,7 +5408,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(340),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5444,7 +5434,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(289),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5457,7 +5447,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(292),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5483,7 +5473,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(344),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5496,7 +5486,7 @@
/* template_types */ TemplateTypeIndex(1),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(346),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -5509,7 +5499,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(96),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(94),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -5522,7 +5512,7 @@
/* template_types */ TemplateTypeIndex(35),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -5535,7 +5525,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(217),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -5548,7 +5538,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(100),
},
@@ -5561,7 +5551,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(205),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(101),
},
@@ -5574,7 +5564,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(295),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(102),
},
@@ -5587,7 +5577,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(298),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(102),
},
@@ -5600,7 +5590,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(301),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(102),
},
@@ -5613,7 +5603,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(362),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(102),
},
@@ -5626,7 +5616,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(364),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(102),
},
@@ -5639,7 +5629,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(366),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(102),
},
@@ -5651,7 +5641,7 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(383),
+ /* parameters */ ParameterIndex(382),
/* return_type_matcher_indices */ TypeMatcherIndicesIndex(28),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
@@ -5664,8 +5654,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(383),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(100),
+ /* parameters */ ParameterIndex(382),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(98),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -5677,8 +5667,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(18),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(383),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
+ /* parameters */ ParameterIndex(382),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -5690,8 +5680,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(20),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(383),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* parameters */ ParameterIndex(382),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -5703,8 +5693,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(22),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(383),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(102),
+ /* parameters */ ParameterIndex(382),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(100),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6094,7 +6084,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(74),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6107,7 +6097,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(74),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6120,7 +6110,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(26),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6133,7 +6123,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(26),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6146,7 +6136,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(153),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6159,7 +6149,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(79),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(48),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6406,7 +6396,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(90),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(88),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -6496,8 +6486,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(382),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(54),
+ /* parameters */ ParameterIndex(381),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(52),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6509,8 +6499,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(382),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(92),
+ /* parameters */ ParameterIndex(381),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(90),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6522,8 +6512,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(18),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(382),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(64),
+ /* parameters */ ParameterIndex(381),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(62),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6535,8 +6525,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(20),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(382),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(40),
+ /* parameters */ ParameterIndex(381),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(38),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6548,8 +6538,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(22),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(382),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(94),
+ /* parameters */ ParameterIndex(381),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(92),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6562,7 +6552,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(268),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6575,7 +6565,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(75),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6588,7 +6578,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(27),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6601,7 +6591,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(274),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6614,7 +6604,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(154),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6627,7 +6617,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(80),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6640,7 +6630,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(89),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6653,7 +6643,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(32),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6666,7 +6656,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(161),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6679,7 +6669,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(94),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -6692,7 +6682,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(84),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(82),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -6705,7 +6695,7 @@
/* template_types */ TemplateTypeIndex(35),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -6718,7 +6708,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(209),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -6731,7 +6721,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(100),
},
@@ -6744,7 +6734,7 @@
/* template_types */ TemplateTypeIndex(27),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(205),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(70),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(68),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(101),
},
@@ -6756,7 +6746,7 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(381),
+ /* parameters */ ParameterIndex(380),
/* return_type_matcher_indices */ TypeMatcherIndicesIndex(26),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
@@ -6769,8 +6759,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(381),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(86),
+ /* parameters */ ParameterIndex(380),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(84),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6782,8 +6772,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(18),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(381),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(52),
+ /* parameters */ ParameterIndex(380),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(50),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6795,8 +6785,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(20),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(381),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(34),
+ /* parameters */ ParameterIndex(380),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(32),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6808,8 +6798,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(22),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(381),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(88),
+ /* parameters */ ParameterIndex(380),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(86),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -6927,7 +6917,7 @@
/* template_numbers */ TemplateNumberIndex(0),
/* parameters */ ParameterIndex(360),
/* return_type_matcher_indices */ TypeMatcherIndicesIndex(12),
- /* return_number_matcher_indices */ NumberMatcherIndicesIndex(20),
+ /* return_number_matcher_indices */ NumberMatcherIndicesIndex(18),
/* const_eval_fn */ ConstEvalFunctionIndex(82),
},
{
@@ -7381,7 +7371,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(102),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7393,8 +7383,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(384),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
+ /* parameters */ ParameterIndex(383),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(102),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7407,7 +7397,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(102),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7420,7 +7410,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(209),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(102),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7432,8 +7422,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(385),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(106),
+ /* parameters */ ParameterIndex(384),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(104),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7445,8 +7435,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(386),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(108),
+ /* parameters */ ParameterIndex(385),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(106),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7459,7 +7449,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(108),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7471,8 +7461,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(387),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
+ /* parameters */ ParameterIndex(386),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(108),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7485,7 +7475,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(108),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7498,7 +7488,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(213),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(108),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7510,8 +7500,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(388),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(112),
+ /* parameters */ ParameterIndex(387),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(110),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7523,8 +7513,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(389),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(114),
+ /* parameters */ ParameterIndex(388),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(112),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7537,7 +7527,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(114),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7549,8 +7539,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(390),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
+ /* parameters */ ParameterIndex(389),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(114),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7563,7 +7553,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(114),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7576,7 +7566,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(217),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(114),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7588,8 +7578,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(391),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(118),
+ /* parameters */ ParameterIndex(390),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(116),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7601,8 +7591,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(392),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(120),
+ /* parameters */ ParameterIndex(391),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(118),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7615,7 +7605,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(120),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7627,8 +7617,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(393),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
+ /* parameters */ ParameterIndex(392),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(120),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7641,7 +7631,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(120),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7654,7 +7644,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(209),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(120),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7666,8 +7656,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(394),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(124),
+ /* parameters */ ParameterIndex(393),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(122),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7679,8 +7669,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(395),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(126),
+ /* parameters */ ParameterIndex(394),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(124),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7693,7 +7683,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(126),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7705,8 +7695,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(396),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
+ /* parameters */ ParameterIndex(395),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(126),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7719,7 +7709,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(126),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7732,7 +7722,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(213),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(126),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7744,8 +7734,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(397),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(130),
+ /* parameters */ ParameterIndex(396),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(128),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7757,8 +7747,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(398),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(132),
+ /* parameters */ ParameterIndex(397),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(130),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7771,7 +7761,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(132),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7783,8 +7773,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(399),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
+ /* parameters */ ParameterIndex(398),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(132),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7797,7 +7787,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(132),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7810,7 +7800,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(217),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(132),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7822,8 +7812,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(400),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(136),
+ /* parameters */ ParameterIndex(399),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(134),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7835,8 +7825,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(401),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(138),
+ /* parameters */ ParameterIndex(400),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(136),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7849,7 +7839,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(138),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7861,8 +7851,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(402),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
+ /* parameters */ ParameterIndex(401),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(138),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7875,7 +7865,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(138),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7888,7 +7878,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(209),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(138),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7900,8 +7890,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(403),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(142),
+ /* parameters */ ParameterIndex(402),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(140),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7913,8 +7903,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(404),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(144),
+ /* parameters */ ParameterIndex(403),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(142),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7927,7 +7917,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(144),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -7939,8 +7929,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(405),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
+ /* parameters */ ParameterIndex(404),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(144),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -7953,7 +7943,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(144),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -7966,7 +7956,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(213),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(144),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -7978,8 +7968,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(406),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(148),
+ /* parameters */ ParameterIndex(405),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(146),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -7991,8 +7981,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(407),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(150),
+ /* parameters */ ParameterIndex(406),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(148),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -8005,7 +7995,7 @@
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(150),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -8017,8 +8007,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(36),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(408),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
+ /* parameters */ ParameterIndex(407),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(150),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -8031,7 +8021,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(150),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(103),
},
@@ -8044,7 +8034,7 @@
/* template_types */ TemplateTypeIndex(10),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(217),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(150),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(104),
},
@@ -8056,8 +8046,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(16),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(409),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(154),
+ /* parameters */ ParameterIndex(408),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(152),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -8069,8 +8059,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(14),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(410),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(156),
+ /* parameters */ ParameterIndex(409),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(154),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -8083,7 +8073,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(27),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -8096,7 +8086,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(80),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -8109,7 +8099,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(32),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -8122,7 +8112,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(94),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -8134,8 +8124,8 @@
/* num_template_numbers */ 2,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(6),
- /* parameters */ ParameterIndex(377),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* parameters */ ParameterIndex(376),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -8564,7 +8554,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(51),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -8576,8 +8566,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(379),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+ /* parameters */ ParameterIndex(378),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(51),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -8590,7 +8580,7 @@
/* template_types */ TemplateTypeIndex(30),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(51),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -8603,7 +8593,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -8616,7 +8606,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(17),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -8629,7 +8619,7 @@
/* template_types */ TemplateTypeIndex(31),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -8681,7 +8671,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(87),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(85),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(98),
},
@@ -8693,8 +8683,8 @@
/* num_template_numbers */ 0,
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(380),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(87),
+ /* parameters */ ParameterIndex(379),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(85),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
@@ -8707,7 +8697,7 @@
/* template_types */ TemplateTypeIndex(33),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(1),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(87),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(85),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -10137,7 +10127,7 @@
/* template_types */ TemplateTypeIndex(0),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(277),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -10150,7 +10140,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(283),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -10501,7 +10491,7 @@
/* template_types */ TemplateTypeIndex(25),
/* template_numbers */ TemplateNumberIndex(7),
/* parameters */ ParameterIndex(368),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -10553,7 +10543,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(17),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(53),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(51),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -10566,7 +10556,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(17),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
@@ -10605,7 +10595,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(372),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(43),
},
@@ -10618,7 +10608,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(372),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(44),
},
@@ -10631,7 +10621,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(372),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(45),
},
@@ -10644,7 +10634,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(373),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(46),
},
@@ -10657,7 +10647,7 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(373),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(35),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(33),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(47),
},
@@ -10780,19 +10770,6 @@
},
{
/* [454] */
- /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
- /* num_parameters */ 1,
- /* num_template_types */ 1,
- /* num_template_numbers */ 0,
- /* template_types */ TemplateTypeIndex(25),
- /* template_numbers */ TemplateNumberIndex(/* invalid */),
- /* parameters */ ParameterIndex(374),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(2),
- /* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
- /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
- },
- {
- /* [455] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* num_parameters */ 1,
/* num_template_types */ 1,
@@ -10805,7 +10782,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
{
- /* [456] */
+ /* [455] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* num_parameters */ 2,
/* num_template_types */ 1,
@@ -10818,7 +10795,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
{
- /* [457] */
+ /* [456] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* num_parameters */ 2,
/* num_template_types */ 1,
@@ -10831,7 +10808,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
{
- /* [458] */
+ /* [457] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* num_parameters */ 3,
/* num_template_types */ 1,
@@ -10839,12 +10816,12 @@
/* template_types */ TemplateTypeIndex(26),
/* template_numbers */ TemplateNumberIndex(8),
/* parameters */ ParameterIndex(0),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(80),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(78),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
{
- /* [459] */
+ /* [458] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* num_parameters */ 0,
/* num_template_types */ 0,
@@ -10852,12 +10829,12 @@
/* template_types */ TemplateTypeIndex(/* invalid */),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(/* invalid */),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(74),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(72),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
{
- /* [460] */
+ /* [459] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* num_parameters */ 2,
/* num_template_types */ 1,
@@ -10870,7 +10847,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
},
{
- /* [461] */
+ /* [460] */
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* num_parameters */ 1,
/* num_template_types */ 1,
@@ -10883,7 +10860,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(73),
},
{
- /* [462] */
+ /* [461] */
/* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* num_parameters */ 2,
/* num_template_types */ 0,
@@ -10896,7 +10873,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(88),
},
{
- /* [463] */
+ /* [462] */
/* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* num_parameters */ 2,
/* num_template_types */ 0,
@@ -10909,7 +10886,7 @@
/* const_eval_fn */ ConstEvalFunctionIndex(89),
},
{
- /* [464] */
+ /* [463] */
/* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
/* num_parameters */ 1,
/* num_template_types */ 1,
@@ -10917,7 +10894,7 @@
/* template_types */ TemplateTypeIndex(35),
/* template_numbers */ TemplateNumberIndex(/* invalid */),
/* parameters */ ParameterIndex(213),
- /* return_type_matcher_indices */ TypeMatcherIndicesIndex(158),
+ /* return_type_matcher_indices */ TypeMatcherIndicesIndex(156),
/* return_number_matcher_indices */ NumberMatcherIndicesIndex(/* invalid */),
/* const_eval_fn */ ConstEvalFunctionIndex(99),
},
@@ -11510,18 +11487,12 @@
},
{
/* [86] */
- /* fn workgroupUniformLoad<T>(ptr<workgroup, T, read_write>) -> T */
- /* num overloads */ 1,
- /* overloads */ OverloadIndex(454),
- },
- {
- /* [87] */
/* fn textureBarrier() */
/* num overloads */ 1,
/* overloads */ OverloadIndex(447),
},
{
- /* [88] */
+ /* [87] */
/* fn textureDimensions<T : fiu32>(texture: texture_1d<T>) -> u32 */
/* fn textureDimensions<T : fiu32, L : iu32>(texture: texture_1d<T>, level: L) -> u32 */
/* fn textureDimensions<T : fiu32>(texture: texture_2d<T>) -> vec2<u32> */
@@ -11553,7 +11524,7 @@
/* overloads */ OverloadIndex(0),
},
{
- /* [89] */
+ /* [88] */
/* fn textureGather<T : fiu32, C : iu32>(@const component: C, texture: texture_2d<T>, sampler: sampler, coords: vec2<f32>) -> vec4<T> */
/* fn textureGather<T : fiu32, C : iu32>(@const component: C, texture: texture_2d<T>, sampler: sampler, coords: vec2<f32>, @const offset: vec2<i32>) -> vec4<T> */
/* fn textureGather<T : fiu32, C : iu32, A : iu32>(@const component: C, texture: texture_2d_array<T>, sampler: sampler, coords: vec2<f32>, array_index: A) -> vec4<T> */
@@ -11570,7 +11541,7 @@
/* overloads */ OverloadIndex(93),
},
{
- /* [90] */
+ /* [89] */
/* fn textureGatherCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> vec4<f32> */
/* fn textureGatherCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, @const offset: vec2<i32>) -> vec4<f32> */
/* fn textureGatherCompare<A : iu32>(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32) -> vec4<f32> */
@@ -11581,7 +11552,7 @@
/* overloads */ OverloadIndex(174),
},
{
- /* [91] */
+ /* [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 */
@@ -11591,7 +11562,7 @@
/* overloads */ OverloadIndex(246),
},
{
- /* [92] */
+ /* [91] */
/* fn textureNumLevels<T : fiu32>(texture: texture_1d<T>) -> u32 */
/* fn textureNumLevels<T : fiu32>(texture: texture_2d<T>) -> u32 */
/* fn textureNumLevels<T : fiu32>(texture: texture_2d_array<T>) -> u32 */
@@ -11606,14 +11577,14 @@
/* overloads */ OverloadIndex(129),
},
{
- /* [93] */
+ /* [92] */
/* fn textureNumSamples<T : fiu32>(texture: texture_multisampled_2d<T>) -> u32 */
/* fn textureNumSamples(texture: texture_depth_multisampled_2d) -> u32 */
/* num overloads */ 2,
/* overloads */ OverloadIndex(404),
},
{
- /* [94] */
+ /* [93] */
/* fn textureSample(texture: texture_1d<f32>, sampler: sampler, coords: f32) -> vec4<f32> */
/* fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>) -> vec4<f32> */
/* fn textureSample(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, @const offset: vec2<i32>) -> vec4<f32> */
@@ -11633,7 +11604,7 @@
/* overloads */ OverloadIndex(64),
},
{
- /* [95] */
+ /* [94] */
/* fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32) -> vec4<f32> */
/* fn textureSampleBias(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, bias: f32, @const offset: vec2<i32>) -> vec4<f32> */
/* fn textureSampleBias<A : iu32>(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: A, bias: f32) -> vec4<f32> */
@@ -11646,7 +11617,7 @@
/* overloads */ OverloadIndex(158),
},
{
- /* [96] */
+ /* [95] */
/* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32 */
/* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, @const offset: vec2<i32>) -> f32 */
/* fn textureSampleCompare<A : iu32>(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32) -> f32 */
@@ -11657,7 +11628,7 @@
/* overloads */ OverloadIndex(180),
},
{
- /* [97] */
+ /* [96] */
/* fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32 */
/* fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2<f32>, depth_ref: f32, @const offset: vec2<i32>) -> f32 */
/* fn textureSampleCompareLevel<A : iu32>(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32) -> f32 */
@@ -11668,7 +11639,7 @@
/* overloads */ OverloadIndex(186),
},
{
- /* [98] */
+ /* [97] */
/* fn textureSampleGrad(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32> */
/* fn textureSampleGrad(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>, @const offset: vec2<i32>) -> vec4<f32> */
/* fn textureSampleGrad<A : iu32>(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: A, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32> */
@@ -11681,7 +11652,7 @@
/* overloads */ OverloadIndex(166),
},
{
- /* [99] */
+ /* [98] */
/* fn textureSampleLevel(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, level: f32) -> vec4<f32> */
/* fn textureSampleLevel(texture: texture_2d<f32>, sampler: sampler, coords: vec2<f32>, level: f32, @const offset: vec2<i32>) -> vec4<f32> */
/* fn textureSampleLevel<A : iu32>(texture: texture_2d_array<f32>, sampler: sampler, coords: vec2<f32>, array_index: A, level: f32) -> vec4<f32> */
@@ -11700,14 +11671,14 @@
/* overloads */ OverloadIndex(79),
},
{
- /* [100] */
+ /* [99] */
/* 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 */ OverloadIndex(406),
},
{
- /* [101] */
+ /* [100] */
/* fn textureStore<C : iu32>(texture: texture_storage_1d<f32_texel_format, writable>, coords: C, value: vec4<f32>) */
/* fn textureStore<C : iu32>(texture: texture_storage_2d<f32_texel_format, writable>, coords: vec2<C>, value: vec4<f32>) */
/* fn textureStore<C : iu32, A : iu32>(texture: texture_storage_2d_array<f32_texel_format, writable>, coords: vec2<C>, array_index: A, value: vec4<f32>) */
@@ -11724,7 +11695,7 @@
/* overloads */ OverloadIndex(105),
},
{
- /* [102] */
+ /* [101] */
/* fn textureLoad<T : fiu32, C : iu32, L : iu32>(texture: texture_1d<T>, coords: C, level: L) -> vec4<T> */
/* fn textureLoad<T : fiu32, C : iu32, L : iu32>(texture: texture_2d<T>, coords: vec2<C>, level: L) -> vec4<T> */
/* fn textureLoad<T : fiu32, C : iu32, A : iu32, L : iu32>(texture: texture_2d_array<T>, coords: vec2<C>, array_index: A, level: L) -> vec4<T> */
@@ -11750,88 +11721,88 @@
/* overloads */ OverloadIndex(27),
},
{
- /* [103] */
+ /* [102] */
/* fn atomicLoad<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>) -> T */
/* num overloads */ 1,
+ /* overloads */ OverloadIndex(454),
+ },
+ {
+ /* [103] */
+ /* fn atomicStore<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) */
+ /* num overloads */ 1,
/* overloads */ OverloadIndex(455),
},
{
/* [104] */
- /* fn atomicStore<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) */
+ /* fn atomicAdd<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
/* overloads */ OverloadIndex(456),
},
{
/* [105] */
- /* fn atomicAdd<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicSub<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [106] */
- /* fn atomicSub<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicMax<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [107] */
- /* fn atomicMax<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicMin<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [108] */
- /* fn atomicMin<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicAnd<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [109] */
- /* fn atomicAnd<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicOr<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [110] */
- /* fn atomicOr<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicXor<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [111] */
- /* fn atomicXor<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* fn atomicExchange<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(457),
+ /* overloads */ OverloadIndex(456),
},
{
/* [112] */
- /* fn atomicExchange<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T */
+ /* 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 */ OverloadIndex(457),
},
{
/* [113] */
- /* fn atomicCompareExchangeWeak<T : iu32, S : workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T, T) -> __atomic_compare_exchange_result<T> */
+ /* fn subgroupBallot() -> vec4<u32> */
/* num overloads */ 1,
/* overloads */ OverloadIndex(458),
},
{
/* [114] */
- /* fn subgroupBallot() -> vec4<u32> */
+ /* fn subgroupBroadcast<T : fiu32>(value: T, @const sourceLaneIndex: u32) -> T */
/* num overloads */ 1,
/* overloads */ OverloadIndex(459),
},
{
/* [115] */
- /* fn subgroupBroadcast<T : fiu32>(value: T, @const sourceLaneIndex: u32) -> T */
- /* num overloads */ 1,
- /* overloads */ OverloadIndex(460),
- },
- {
- /* [116] */
/* fn _tint_materialize<T>(T) -> T */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(461),
+ /* overloads */ OverloadIndex(460),
},
};
@@ -11944,13 +11915,13 @@
/* [8] */
/* op &&(bool, bool) -> bool */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(462),
+ /* overloads */ OverloadIndex(461),
},
{
/* [9] */
/* op ||(bool, bool) -> bool */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(463),
+ /* overloads */ OverloadIndex(462),
},
{
/* [10] */
@@ -12225,7 +12196,7 @@
/* [17] */
/* conv packedVec3<T : concrete_scalar>(vec3<T>) -> packedVec3<T> */
/* num overloads */ 1,
- /* overloads */ OverloadIndex(464),
+ /* overloads */ OverloadIndex(463),
},
};
diff --git a/src/tint/lang/core/ir/BUILD.gn b/src/tint/lang/core/ir/BUILD.gn
index ff12f1e..928d9c3 100644
--- a/src/tint/lang/core/ir/BUILD.gn
+++ b/src/tint/lang/core/ir/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -153,7 +153,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"access_test.cc",
"binary_test.cc",
diff --git a/src/tint/lang/core/ir/block.cc b/src/tint/lang/core/ir/block.cc
index 00654b9..3a8f8e3 100644
--- a/src/tint/lang/core/ir/block.cc
+++ b/src/tint/lang/core/ir/block.cc
@@ -186,4 +186,10 @@
inst->next = nullptr;
}
+void Block::Destroy() {
+ while (instructions_.first) {
+ instructions_.first->Destroy();
+ }
+}
+
} // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/block.h b/src/tint/lang/core/ir/block.h
index a01e8a0..3dea344 100644
--- a/src/tint/lang/core/ir/block.h
+++ b/src/tint/lang/core/ir/block.h
@@ -142,6 +142,9 @@
/// @param parent the parent instruction that owns this block
void SetParent(ControlInstruction* parent) { parent_ = parent; }
+ /// Destroys the block and all of its instructions.
+ void Destroy();
+
private:
struct {
Instruction* first = nullptr;
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index 64448cf..75f7266 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -356,6 +356,11 @@
ir.constant_values.Composite(ty, Vector{ConstantValue(std::forward<ARGS>(values))...}));
}
+ /// Creates a new zero-value ir::Constant
+ /// @param ty the constant type
+ /// @returns the new constant
+ ir::Constant* Zero(const core::type::Type* ty) { return Constant(ir.constant_values.Zero(ty)); }
+
/// @param in the input value. One of: nullptr, ir::Value*, ir::Instruction* or a numeric value.
/// @returns an ir::Value* from the given argument.
template <typename T>
diff --git a/src/tint/lang/core/ir/control_instruction.cc b/src/tint/lang/core/ir/control_instruction.cc
index af0670a..31a4078 100644
--- a/src/tint/lang/core/ir/control_instruction.cc
+++ b/src/tint/lang/core/ir/control_instruction.cc
@@ -14,6 +14,8 @@
#include "src/tint/lang/core/ir/control_instruction.h"
+#include "src/tint/lang/core/ir/block.h"
+
TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ControlInstruction);
namespace tint::core::ir {
@@ -32,4 +34,9 @@
exits_.Remove(exit);
}
+void ControlInstruction::Destroy() {
+ Base::Destroy();
+ ForeachBlock([](ir::Block* blk) { blk->Destroy(); });
+}
+
} // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/control_instruction.h b/src/tint/lang/core/ir/control_instruction.h
index fe8f6ce..74a4558 100644
--- a/src/tint/lang/core/ir/control_instruction.h
+++ b/src/tint/lang/core/ir/control_instruction.h
@@ -77,6 +77,9 @@
/// @param exit the exit instruction
void RemoveExit(Exit* exit);
+ /// @copydoc Instruction::Destroy
+ void Destroy() override;
+
protected:
/// The flow control exits
Hashset<Exit*, 2> exits_;
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembler.cc
index 6625466..0cbf490 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembler.cc
@@ -74,6 +74,10 @@
} // namespace
+std::string Disassemble(Module& mod) {
+ return Disassembler{mod}.Disassemble();
+}
+
Disassembler::Disassembler(Module& mod) : mod_(mod) {}
Disassembler::~Disassembler() = default;
@@ -487,6 +491,9 @@
if (v->Attributes().location.has_value()) {
out_ << " @location(" << v->Attributes().location.value() << ")";
}
+ if (v->Attributes().index.has_value()) {
+ out_ << " @index(" << v->Attributes().index.value() << ")";
+ }
if (v->Attributes().interpolation.has_value()) {
auto& interp = v->Attributes().interpolation.value();
out_ << " @interpolate(" << interp.type;
diff --git a/src/tint/lang/core/ir/disassembler.h b/src/tint/lang/core/ir/disassembler.h
index bb0bd44..e0cbc7b 100644
--- a/src/tint/lang/core/ir/disassembler.h
+++ b/src/tint/lang/core/ir/disassembler.h
@@ -36,6 +36,10 @@
namespace tint::core::ir {
+/// @returns the disassembly for the module @p mod
+/// @param mod the module to disassemble
+std::string Disassemble(Module& mod);
+
/// Helper class to disassemble the IR
class Disassembler {
public:
diff --git a/src/tint/lang/core/ir/function.cc b/src/tint/lang/core/ir/function.cc
index 57309c0..7b68cca 100644
--- a/src/tint/lang/core/ir/function.cc
+++ b/src/tint/lang/core/ir/function.cc
@@ -46,7 +46,6 @@
block_->CloneInto(ctx, new_func->block_);
ctx.ir.SetName(new_func, ctx.ir.NameOf(this).Name());
- ctx.ir.functions.Push(new_func);
return new_func;
}
@@ -60,6 +59,11 @@
TINT_ASSERT(!params_.Any(IsNull));
}
+void Function::Destroy() {
+ Base::Destroy();
+ block_->Destroy();
+}
+
std::string_view ToString(Function::PipelineStage value) {
switch (value) {
case Function::PipelineStage::kVertex:
diff --git a/src/tint/lang/core/ir/function.h b/src/tint/lang/core/ir/function.h
index 34a9276..ba3263f 100644
--- a/src/tint/lang/core/ir/function.h
+++ b/src/tint/lang/core/ir/function.h
@@ -140,6 +140,9 @@
/// @returns the function root block
ir::Block* Block() { return block_; }
+ /// Destroys the function and all of its instructions.
+ void Destroy() override;
+
private:
PipelineStage pipeline_stage_;
std::optional<std::array<uint32_t, 3>> workgroup_size_;
diff --git a/src/tint/lang/core/ir/function_test.cc b/src/tint/lang/core/ir/function_test.cc
index 6739793..b2b58d3 100644
--- a/src/tint/lang/core/ir/function_test.cc
+++ b/src/tint/lang/core/ir/function_test.cc
@@ -111,7 +111,8 @@
EXPECT_EQ(new_param1, new_f->Params()[0]);
EXPECT_EQ(new_param2, new_f->Params()[1]);
- EXPECT_EQ(new_f, mod.functions.Back());
+ // Cloned functions are not automatically added to the module.
+ EXPECT_EQ(mod.functions.Length(), 1u);
}
TEST_F(IR_FunctionTest, CloneWithExits) {
diff --git a/src/tint/lang/core/ir/operand_instruction.h b/src/tint/lang/core/ir/operand_instruction.h
index 980c696..afa699a 100644
--- a/src/tint/lang/core/ir/operand_instruction.h
+++ b/src/tint/lang/core/ir/operand_instruction.h
@@ -75,6 +75,9 @@
operands_.Clear();
}
+ /// Removes all results from the instruction.
+ void ClearResults() { results_.Clear(); }
+
/// @returns the operands of the instruction
VectorRef<ir::Value*> Operands() override { return operands_; }
diff --git a/src/tint/lang/core/ir/transform/BUILD.bazel b/src/tint/lang/core/ir/transform/BUILD.bazel
index e4c3240..fd23d7f 100644
--- a/src/tint/lang/core/ir/transform/BUILD.bazel
+++ b/src/tint/lang/core/ir/transform/BUILD.bazel
@@ -32,9 +32,12 @@
"binding_remapper.cc",
"block_decorated_structs.cc",
"builtin_polyfill.cc",
+ "combine_access_instructions.cc",
+ "conversion_polyfill.cc",
"demote_to_helper.cc",
"direct_variable_access.cc",
"multiplanar_external_texture.cc",
+ "preserve_padding.cc",
"robustness.cc",
"shader_io.cc",
"std140.cc",
@@ -47,9 +50,12 @@
"binding_remapper.h",
"block_decorated_structs.h",
"builtin_polyfill.h",
+ "combine_access_instructions.h",
+ "conversion_polyfill.h",
"demote_to_helper.h",
"direct_variable_access.h",
"multiplanar_external_texture.h",
+ "preserve_padding.h",
"robustness.h",
"shader_io.h",
"std140.h",
@@ -90,18 +96,25 @@
"binding_remapper_test.cc",
"block_decorated_structs_test.cc",
"builtin_polyfill_test.cc",
+ "combine_access_instructions_test.cc",
+ "conversion_polyfill_test.cc",
"demote_to_helper_test.cc",
"direct_variable_access_test.cc",
"helper_test.h",
"multiplanar_external_texture_test.cc",
+ "preserve_padding_test.cc",
"robustness_test.cc",
"std140_test.cc",
"zero_init_workgroup_memory_test.cc",
] + select({
+ "//conditions:default": [],
+ }) + select({
":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
"direct_variable_access_wgsl_test.cc",
],
"//conditions:default": [],
+ }) + select({
+ "//conditions:default": [],
}),
deps = [
"//src/tint/api/common",
@@ -115,10 +128,7 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/lang/wgsl/writer/ir_to_program",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -134,7 +144,20 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
diff --git a/src/tint/lang/core/ir/transform/BUILD.cmake b/src/tint/lang/core/ir/transform/BUILD.cmake
index 1164934..2533c85 100644
--- a/src/tint/lang/core/ir/transform/BUILD.cmake
+++ b/src/tint/lang/core/ir/transform/BUILD.cmake
@@ -38,12 +38,18 @@
lang/core/ir/transform/block_decorated_structs.h
lang/core/ir/transform/builtin_polyfill.cc
lang/core/ir/transform/builtin_polyfill.h
+ lang/core/ir/transform/combine_access_instructions.cc
+ lang/core/ir/transform/combine_access_instructions.h
+ lang/core/ir/transform/conversion_polyfill.cc
+ lang/core/ir/transform/conversion_polyfill.h
lang/core/ir/transform/demote_to_helper.cc
lang/core/ir/transform/demote_to_helper.h
lang/core/ir/transform/direct_variable_access.cc
lang/core/ir/transform/direct_variable_access.h
lang/core/ir/transform/multiplanar_external_texture.cc
lang/core/ir/transform/multiplanar_external_texture.h
+ lang/core/ir/transform/preserve_padding.cc
+ lang/core/ir/transform/preserve_padding.h
lang/core/ir/transform/robustness.cc
lang/core/ir/transform/robustness.h
lang/core/ir/transform/shader_io.cc
@@ -88,10 +94,13 @@
lang/core/ir/transform/binding_remapper_test.cc
lang/core/ir/transform/block_decorated_structs_test.cc
lang/core/ir/transform/builtin_polyfill_test.cc
+ lang/core/ir/transform/combine_access_instructions_test.cc
+ lang/core/ir/transform/conversion_polyfill_test.cc
lang/core/ir/transform/demote_to_helper_test.cc
lang/core/ir/transform/direct_variable_access_test.cc
lang/core/ir/transform/helper_test.h
lang/core/ir/transform/multiplanar_external_texture_test.cc
+ lang/core/ir/transform/preserve_padding_test.cc
lang/core/ir/transform/robustness_test.cc
lang/core/ir/transform/std140_test.cc
lang/core/ir/transform/zero_init_workgroup_memory_test.cc
@@ -109,10 +118,7 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_program
- tint_lang_wgsl_reader
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_lang_wgsl_writer_ir_to_program
tint_utils_containers
tint_utils_diagnostic
@@ -133,8 +139,21 @@
"gtest"
)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_core_ir_transform_test test
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
tint_target_add_sources(tint_lang_core_ir_transform_test test
"lang/core/ir/transform/direct_variable_access_wgsl_test.cc"
)
endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_core_ir_transform_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
diff --git a/src/tint/lang/core/ir/transform/BUILD.gn b/src/tint/lang/core/ir/transform/BUILD.gn
index 9ee4ae0..4185b72 100644
--- a/src/tint/lang/core/ir/transform/BUILD.gn
+++ b/src/tint/lang/core/ir/transform/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -43,12 +43,18 @@
"block_decorated_structs.h",
"builtin_polyfill.cc",
"builtin_polyfill.h",
+ "combine_access_instructions.cc",
+ "combine_access_instructions.h",
+ "conversion_polyfill.cc",
+ "conversion_polyfill.h",
"demote_to_helper.cc",
"demote_to_helper.h",
"direct_variable_access.cc",
"direct_variable_access.h",
"multiplanar_external_texture.cc",
"multiplanar_external_texture.h",
+ "preserve_padding.cc",
+ "preserve_padding.h",
"robustness.cc",
"robustness.h",
"shader_io.cc",
@@ -83,7 +89,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"add_empty_entry_point_test.cc",
"bgra8unorm_polyfill_test.cc",
@@ -91,10 +96,13 @@
"binding_remapper_test.cc",
"block_decorated_structs_test.cc",
"builtin_polyfill_test.cc",
+ "combine_access_instructions_test.cc",
+ "conversion_polyfill_test.cc",
"demote_to_helper_test.cc",
"direct_variable_access_test.cc",
"helper_test.h",
"multiplanar_external_texture_test.cc",
+ "preserve_padding_test.cc",
"robustness_test.cc",
"std140_test.cc",
"zero_init_workgroup_memory_test.cc",
@@ -112,10 +120,7 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/lang/wgsl/writer/ir_to_program",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -132,8 +137,19 @@
"${tint_src_dir}/utils/traits",
]
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
+
if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
sources += [ "direct_variable_access_wgsl_test.cc" ]
}
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
diff --git a/src/tint/lang/core/ir/transform/binding_remapper.cc b/src/tint/lang/core/ir/transform/binding_remapper.cc
index 47a591f..b927fd1 100644
--- a/src/tint/lang/core/ir/transform/binding_remapper.cc
+++ b/src/tint/lang/core/ir/transform/binding_remapper.cc
@@ -28,8 +28,9 @@
namespace {
-Result<SuccessType> Run(ir::Module& ir, const BindingRemapperOptions& options) {
- if (options.binding_points.empty()) {
+Result<SuccessType> Run(ir::Module& ir,
+ const std::unordered_map<BindingPoint, BindingPoint>& binding_points) {
+ if (binding_points.empty()) {
return Success;
}
if (ir.root_block->IsEmpty()) {
@@ -49,8 +50,8 @@
}
// Replace group and binding index if requested.
- auto to = options.binding_points.find(bp.value());
- if (to != options.binding_points.end()) {
+ auto to = binding_points.find(bp.value());
+ if (to != binding_points.end()) {
var->SetBindingPoint(to->second.group, to->second.binding);
}
}
@@ -60,13 +61,15 @@
} // namespace
-Result<SuccessType> BindingRemapper(Module& ir, const BindingRemapperOptions& options) {
+Result<SuccessType> BindingRemapper(
+ Module& ir,
+ const std::unordered_map<BindingPoint, BindingPoint>& binding_points) {
auto result = ValidateAndDumpIfNeeded(ir, "BindingRemapper transform");
if (!result) {
return result;
}
- return Run(ir, options);
+ return Run(ir, binding_points);
}
} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/binding_remapper.h b/src/tint/lang/core/ir/transform/binding_remapper.h
index 5d7a2a0..51f4f14 100644
--- a/src/tint/lang/core/ir/transform/binding_remapper.h
+++ b/src/tint/lang/core/ir/transform/binding_remapper.h
@@ -16,8 +16,9 @@
#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BINDING_REMAPPER_H_
#include <string>
+#include <unordered_map>
-#include "src/tint/api/options/binding_remapper.h"
+#include "src/tint/api/common/binding_point.h"
#include "src/tint/utils/result/result.h"
// Forward declarations.
@@ -29,9 +30,11 @@
/// BindingRemapper is a transform that remaps binding point indices and access controls.
/// @param module the module to transform
-/// @param options the remapping options
+/// @param binding_points the remapping data
/// @returns success or failure
-Result<SuccessType> BindingRemapper(Module& module, const BindingRemapperOptions& options);
+Result<SuccessType> BindingRemapper(
+ Module& module,
+ const std::unordered_map<BindingPoint, BindingPoint>& binding_points);
} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/binding_remapper_test.cc b/src/tint/lang/core/ir/transform/binding_remapper_test.cc
index 81383c8..9f016fa 100644
--- a/src/tint/lang/core/ir/transform/binding_remapper_test.cc
+++ b/src/tint/lang/core/ir/transform/binding_remapper_test.cc
@@ -41,8 +41,8 @@
auto* expect = src;
- BindingRemapperOptions options;
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
@@ -62,9 +62,9 @@
auto* expect = src;
- BindingRemapperOptions options;
- options.binding_points[tint::BindingPoint{0u, 1u}] = tint::BindingPoint{1u, 0u};
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ binding_points[tint::BindingPoint{0u, 1u}] = tint::BindingPoint{1u, 0u};
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
@@ -89,9 +89,9 @@
)";
- BindingRemapperOptions options;
- options.binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{3u, 2u};
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{3u, 2u};
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
@@ -116,9 +116,9 @@
)";
- BindingRemapperOptions options;
- options.binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{1u, 3u};
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{1u, 3u};
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
@@ -143,9 +143,9 @@
)";
- BindingRemapperOptions options;
- options.binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{3u, 4u};
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{3u, 4u};
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
@@ -175,10 +175,10 @@
)";
- BindingRemapperOptions options;
- options.binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{3u, 4u};
- options.binding_points[tint::BindingPoint{3u, 4u}] = tint::BindingPoint{1u, 2u};
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{3u, 4u};
+ binding_points[tint::BindingPoint{3u, 4u}] = tint::BindingPoint{1u, 2u};
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
@@ -229,10 +229,10 @@
}
)";
- BindingRemapperOptions options;
- options.binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{0u, 1u};
- options.binding_points[tint::BindingPoint{3u, 4u}] = tint::BindingPoint{0u, 1u};
- Run(BindingRemapper, options);
+ std::unordered_map<tint::BindingPoint, tint::BindingPoint> binding_points;
+ binding_points[tint::BindingPoint{1u, 2u}] = tint::BindingPoint{0u, 1u};
+ binding_points[tint::BindingPoint{3u, 4u}] = tint::BindingPoint{0u, 1u};
+ Run(BindingRemapper, binding_points);
EXPECT_EQ(expect, str());
}
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs.cc b/src/tint/lang/core/ir/transform/block_decorated_structs.cc
index 55eada7..bb534b2 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs.cc
@@ -30,6 +30,7 @@
void Run(Module& ir) {
Builder builder{ir};
+ type::Manager& ty{ir.Types()};
if (ir.root_block->IsEmpty()) {
return;
@@ -54,58 +55,38 @@
auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
auto* store_ty = ptr->StoreType();
- bool wrapped = false;
- Vector<const core::type::StructMember*, 4> members;
-
- // Build the member list for the block-decorated structure.
if (auto* str = store_ty->As<core::type::Struct>(); str && !str->HasFixedFootprint()) {
// We know the original struct will only ever be used as the store type of a buffer, so
- // just redeclare it as a block-decorated struct.
- for (auto* member : str->Members()) {
- members.Push(member);
- }
- } else {
- // The original struct might be used in other places, so create a new block-decorated
- // struct that wraps the original struct.
- members.Push(ir.Types().Get<core::type::StructMember>(
- /* name */ ir.symbols.New(),
- /* type */ store_ty,
- /* index */ 0u,
- /* offset */ 0u,
- /* align */ store_ty->Align(),
- /* size */ store_ty->Size(),
- /* attributes */ core::type::StructMemberAttributes{}));
- wrapped = true;
+ // just mark it as a block-decorated struct.
+ // TODO(crbug.com/tint/745): Remove the const_cast.
+ const_cast<type::Struct*>(str)->SetStructFlag(type::kBlock);
+ continue;
}
- // Create the block-decorated struct.
- auto* block_struct = ir.Types().Get<core::type::Struct>(
- /* name */ ir.symbols.New(),
- /* members */ members,
- /* align */ store_ty->Align(),
- /* size */ tint::RoundUp(store_ty->Align(), store_ty->Size()),
- /* size_no_padding */ store_ty->Size());
+ // The original struct might be used in other places, so create a new block-decorated
+ // struct that wraps the original struct.
+ auto inner_name = ir.symbols.New();
+ auto wrapper_name = ir.symbols.New();
+ auto* block_struct = ty.Struct(wrapper_name, {{inner_name, store_ty}});
block_struct->SetStructFlag(core::type::StructFlag::kBlock);
// Replace the old variable declaration with one that uses the block-decorated struct type.
- auto* new_var =
- builder.Var(ir.Types().ptr(ptr->AddressSpace(), block_struct, ptr->Access()));
+ auto* new_var = builder.Var(ty.ptr(ptr->AddressSpace(), block_struct, ptr->Access()));
if (var->BindingPoint()) {
new_var->SetBindingPoint(var->BindingPoint()->group, var->BindingPoint()->binding);
}
var->ReplaceWith(new_var);
// Replace uses of the old variable.
+ // The structure has been wrapped, so replace all uses of the old variable with a member
+ // accessor on the new variable.
var->Result()->ReplaceAllUsesWith([&](Usage use) -> Value* {
- if (wrapped) {
- // The structure has been wrapped, so replace all uses of the old variable with a
- // member accessor on the new variable.
- auto* access = builder.Access(var->Result()->Type(), new_var, 0_u);
- access->InsertBefore(use.instruction);
- return access->Result();
- }
- return new_var->Result();
+ auto* access = builder.Access(var->Result()->Type(), new_var, 0_u);
+ access->InsertBefore(use.instruction);
+ return access->Result();
});
+
+ var->Destroy();
}
}
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
index 500bfdd..4ad7380 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
@@ -205,18 +205,13 @@
});
auto* expect = R"(
-MyStruct = struct @align(4) {
- i:i32 @offset(0)
- arr:array<i32> @offset(4)
-}
-
-tint_symbol = struct @align(4), @block {
+MyStruct = struct @align(4), @block {
i:i32 @offset(0)
arr:array<i32> @offset(4)
}
%b1 = block { # root
- %1:ptr<storage, tint_symbol, read_write> = var @binding_point(0, 0)
+ %1:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
}
%foo = func():void -> %b2 {
@@ -235,6 +230,51 @@
EXPECT_EQ(expect, str());
}
+TEST_F(IR_BlockDecoratedStructsTest, RuntimeArray_InStruct_ArrayLengthViaLets) {
+ auto* structure =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("i"), ty.i32()},
+ {mod.symbols.New("arr"), ty.array<i32>()},
+ });
+
+ auto* buffer = b.Var(ty.ptr(storage, structure, core::Access::kReadWrite));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* let_root = b.Let("root", buffer->Result());
+ auto* let_arr = b.Let("arr", b.Access(ty.ptr(storage, ty.array<i32>()), let_root, 1_u));
+ auto* length = b.Call(ty.u32(), core::BuiltinFn::kArrayLength, let_arr);
+ b.Return(func, length);
+ });
+
+ auto* expect = R"(
+MyStruct = struct @align(4), @block {
+ i:i32 @offset(0)
+ arr:array<i32> @offset(4)
+}
+
+%b1 = block { # root
+ %1:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 -> %b2 {
+ %b2 = block {
+ %root:ptr<storage, MyStruct, read_write> = let %1
+ %4:ptr<storage, array<i32>, read_write> = access %root, 1u
+ %arr:ptr<storage, array<i32>, read_write> = let %4
+ %6:u32 = arrayLength %arr
+ ret %6
+ }
+}
+)";
+
+ Run(BlockDecoratedStructs);
+
+ EXPECT_EQ(expect, str());
+}
+
TEST_F(IR_BlockDecoratedStructsTest, StructUsedElsewhere) {
auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
{mod.symbols.New("a"), ty.i32()},
@@ -296,11 +336,12 @@
root->Append(buffer_c);
auto* func = b.Function("foo", ty.void_());
- auto* block = func->Block();
- auto* load_b = block->Append(b.Load(buffer_b));
- auto* load_c = block->Append(b.Load(buffer_c));
- block->Append(b.Store(buffer_a, b.Add(ty.i32(), load_b, load_c)));
- block->Append(b.Return(func));
+ b.Append(func->Block(), [&] {
+ auto* load_b = b.Load(buffer_b);
+ auto* load_c = b.Load(buffer_c);
+ b.Store(buffer_a, b.Add(ty.i32(), load_b, load_c));
+ b.Return(func);
+ });
auto* expect = R"(
tint_symbol_1 = struct @align(4), @block {
@@ -327,8 +368,9 @@
%6:i32 = load %5
%7:ptr<storage, i32, read_write> = access %3, 0u
%8:i32 = load %7
- %9:ptr<storage, i32, read_write> = access %1, 0u
- store %9, %10
+ %9:i32 = add %6, %8
+ %10:ptr<storage, i32, read_write> = access %1, 0u
+ store %10, %9
ret
}
}
diff --git a/src/tint/lang/core/ir/transform/combine_access_instructions.cc b/src/tint/lang/core/ir/transform/combine_access_instructions.cc
new file mode 100644
index 0000000..71b42c9
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/combine_access_instructions.cc
@@ -0,0 +1,80 @@
+// 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/lang/core/ir/transform/combine_access_instructions.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+namespace tint::core::ir::transform {
+
+namespace {
+
+/// PIMPL state for the transform.
+struct State {
+ /// The IR module.
+ Module& ir;
+
+ /// Process the module.
+ void Process() {
+ // Loop over every instruction looking for access instructions.
+ for (auto* inst : ir.instructions.Objects()) {
+ if (auto* access = inst->As<ir::Access>(); access && access->Alive()) {
+ // Look for places where the result of this access instruction is used as a base
+ // pointer for another access instruction.
+ access->Result()->ForEachUse([&](Usage use) {
+ auto* child = use.instruction->As<ir::Access>();
+ if (child && use.operand_index == ir::Access::kObjectOperandOffset) {
+ // Push the indices of the parent access instruction into the child.
+ Vector<ir::Value*, 4> operands;
+ operands.Push(access->Object());
+ for (auto* idx : access->Indices()) {
+ operands.Push(idx);
+ }
+ for (auto* idx : child->Indices()) {
+ operands.Push(idx);
+ }
+ child->SetOperands(std::move(operands));
+ }
+ });
+
+ // If there are no other uses of the access instruction, remove it.
+ if (access->Result()->Usages().IsEmpty()) {
+ access->Destroy();
+ }
+ }
+ }
+ }
+};
+
+} // namespace
+
+Result<SuccessType> CombineAccessInstructions(Module& ir) {
+ auto result = ValidateAndDumpIfNeeded(ir, "CombineAccessInstructions transform");
+ if (!result) {
+ return result;
+ }
+
+ State{ir}.Process();
+
+ return Success;
+}
+
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/combine_access_instructions.h b/src/tint/lang/core/ir/transform/combine_access_instructions.h
new file mode 100644
index 0000000..55005e2
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/combine_access_instructions.h
@@ -0,0 +1,34 @@
+// 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_LANG_CORE_IR_TRANSFORM_COMBINE_ACCESS_INSTRUCTIONS_H_
+#define SRC_TINT_LANG_CORE_IR_TRANSFORM_COMBINE_ACCESS_INSTRUCTIONS_H_
+
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Module;
+}
+
+namespace tint::core::ir::transform {
+
+/// CombineAccessInstructions is a transform that combines chains of access instructions.
+/// @param module the module to transform
+/// @returns success or failure
+Result<SuccessType> CombineAccessInstructions(Module& module);
+
+} // namespace tint::core::ir::transform
+
+#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_COMBINE_ACCESS_INSTRUCTIONS_H_
diff --git a/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc b/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc
new file mode 100644
index 0000000..7c79865
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc
@@ -0,0 +1,874 @@
+// 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/lang/core/ir/transform/combine_access_instructions.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/transform/helper_test.h"
+
+namespace tint::core::ir::transform {
+namespace {
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+using IR_CombineAccessInstructionsTest = TransformTest;
+
+TEST_F(IR_CombineAccessInstructionsTest, NoModify_NoChaining) {
+ auto* vec = ty.vec3<f32>();
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_root = b.Access(ty.ptr(uniform, structure), buffer);
+ b.Load(access_root);
+
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ b.Load(access_arr);
+
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), buffer, 0_u, 1_u);
+ b.Load(access_mat);
+
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), buffer, 0_u, 1_u, 2_u);
+ b.Load(access_vec);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, MyStruct, read_write> = access %buffer
+ %4:MyStruct = load %3
+ %5:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %6:array<mat3x3<f32>, 4> = load %5
+ %7:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 1u
+ %8:mat3x3<f32> = load %7
+ %9:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 2u
+ %10:vec3<f32> = load %9
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, SimpleChain) {
+ auto* vec = ty.vec3<f32>();
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 2_u);
+ b.Load(access_vec);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %5:ptr<uniform, vec3<f32>, read_write> = access %4, 2u
+ %6:vec3<f32> = load %5
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 2u
+ %4:vec3<f32> = load %3
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, NoIndices_Root) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_root = b.Access(ty.ptr(uniform, structure), buffer);
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), access_root, 0_u);
+ b.Load(access_arr);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, MyStruct, read_write> = access %buffer
+ %4:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %3, 0u
+ %5:array<mat3x3<f32>, 4> = load %4
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:array<mat3x3<f32>, 4> = load %3
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, NoIndices_Middle) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* access_copy = b.Access(ty.ptr(uniform, arr), access_arr);
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_copy, 1_u);
+ b.Load(access_mat);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %3
+ %5:ptr<uniform, mat3x3<f32>, read_write> = access %4, 1u
+ %6:mat3x3<f32> = load %5
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 1u
+ %4:mat3x3<f32> = load %3
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, NoIndices_End) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+ auto* access_copy = b.Access(ty.ptr(uniform, mat), access_mat);
+ b.Load(access_copy);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %5:ptr<uniform, mat3x3<f32>, read_write> = access %4
+ %6:mat3x3<f32> = load %5
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 1u
+ %4:mat3x3<f32> = load %3
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, MutipleChains_FromRoot) {
+ auto* vec = ty.vec3<f32>();
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+
+ {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 2_u);
+ b.Load(access_vec);
+ }
+ {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 2_u);
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 0_u);
+ b.Load(access_vec);
+ }
+ {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 3_u);
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 1_u);
+ b.Load(access_vec);
+ }
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %5:ptr<uniform, vec3<f32>, read_write> = access %4, 2u
+ %6:vec3<f32> = load %5
+ %7:ptr<uniform, mat3x3<f32>, read_write> = access %3, 2u
+ %8:ptr<uniform, vec3<f32>, read_write> = access %7, 0u
+ %9:vec3<f32> = load %8
+ %10:ptr<uniform, mat3x3<f32>, read_write> = access %3, 3u
+ %11:ptr<uniform, vec3<f32>, read_write> = access %10, 1u
+ %12:vec3<f32> = load %11
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 2u
+ %4:vec3<f32> = load %3
+ %5:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 2u, 0u
+ %6:vec3<f32> = load %5
+ %7:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 3u, 1u
+ %8:vec3<f32> = load %7
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, MutipleChains_FromMiddle) {
+ auto* vec = ty.vec3<f32>();
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+
+ {
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 2_u);
+ b.Load(access_vec);
+ }
+ {
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 0_u);
+ b.Load(access_vec);
+ }
+ {
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 1_u);
+ b.Load(access_vec);
+ }
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %5:ptr<uniform, vec3<f32>, read_write> = access %4, 2u
+ %6:vec3<f32> = load %5
+ %7:ptr<uniform, vec3<f32>, read_write> = access %4, 0u
+ %8:vec3<f32> = load %7
+ %9:ptr<uniform, vec3<f32>, read_write> = access %4, 1u
+ %10:vec3<f32> = load %9
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 2u
+ %4:vec3<f32> = load %3
+ %5:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 0u
+ %6:vec3<f32> = load %5
+ %7:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 1u
+ %8:vec3<f32> = load %7
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, OtherUses_Root) {
+ auto* vec = ty.vec3<f32>();
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ b.Load(access_arr);
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 2_u);
+ b.Load(access_vec);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:array<mat3x3<f32>, 4> = load %3
+ %5:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %6:ptr<uniform, vec3<f32>, read_write> = access %5, 2u
+ %7:vec3<f32> = load %6
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:array<mat3x3<f32>, 4> = load %3
+ %5:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 2u
+ %6:vec3<f32> = load %5
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, OtherUses_Middle) {
+ auto* vec = ty.vec3<f32>();
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+ b.Load(access_mat);
+ auto* access_vec = b.Access(ty.ptr(uniform, vec), access_mat, 2_u);
+ b.Load(access_vec);
+
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %5:mat3x3<f32> = load %4
+ %6:ptr<uniform, vec3<f32>, read_write> = access %4, 2u
+ %7:vec3<f32> = load %6
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 1u
+ %4:mat3x3<f32> = load %3
+ %5:ptr<uniform, vec3<f32>, read_write> = access %buffer, 0u, 1u, 2u
+ %6:vec3<f32> = load %5
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, AccessResultUsesAsAccessIndex) {
+ auto* func = b.Function("foo", ty.f32());
+ auto* indices = b.FunctionParam("indices", ty.array<u32, 4>());
+ auto* values = b.FunctionParam("values", ty.array<f32, 4>());
+ b.Append(func->Block(), [&] {
+ auto* access_index = b.Access(ty.u32(), indices, 1_u);
+ auto* access_value = b.Access(ty.f32(), values, access_index);
+ b.Return(func, access_value);
+ });
+
+ auto* src = R"(
+%foo = func():f32 -> %b1 {
+ %b1 = block {
+ %2:u32 = access %indices, 1u
+ %4:f32 = access %values, %2
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, UseInDifferentBlock_If) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* ifelse = b.If(true);
+ b.Append(ifelse->True(), [&] {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 1_u);
+ b.Load(access_mat);
+ b.ExitIf(ifelse);
+ });
+ b.Append(ifelse->False(), [&] {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 2_u);
+ b.Load(access_mat);
+ b.ExitIf(ifelse);
+ });
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ if true [t: %b3, f: %b4] { # if_1
+ %b3 = block { # true
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 1u
+ %5:mat3x3<f32> = load %4
+ exit_if # if_1
+ }
+ %b4 = block { # false
+ %6:ptr<uniform, mat3x3<f32>, read_write> = access %3, 2u
+ %7:mat3x3<f32> = load %6
+ exit_if # if_1
+ }
+ }
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ if true [t: %b3, f: %b4] { # if_1
+ %b3 = block { # true
+ %3:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 1u
+ %4:mat3x3<f32> = load %3
+ exit_if # if_1
+ }
+ %b4 = block { # false
+ %5:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 2u
+ %6:mat3x3<f32> = load %5
+ exit_if # if_1
+ }
+ }
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_CombineAccessInstructionsTest, UseInDifferentBlock_Loop) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(uniform, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ auto* access_arr = b.Access(ty.ptr(uniform, arr), buffer, 0_u);
+ auto* loop = b.Loop();
+ b.Append(loop->Body(), [&] {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 2_u);
+ b.Load(access_mat);
+ b.Continue(loop);
+ });
+ b.Append(loop->Continuing(), [&] {
+ auto* access_mat = b.Access(ty.ptr(uniform, mat), access_arr, 3_u);
+ b.Load(access_mat);
+ b.BreakIf(loop, true);
+ });
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ %3:ptr<uniform, array<mat3x3<f32>, 4>, read_write> = access %buffer, 0u
+ loop [b: %b3, c: %b4] { # loop_1
+ %b3 = block { # body
+ %4:ptr<uniform, mat3x3<f32>, read_write> = access %3, 2u
+ %5:mat3x3<f32> = load %4
+ continue %b4
+ }
+ %b4 = block { # continuing
+ %6:ptr<uniform, mat3x3<f32>, read_write> = access %3, 3u
+ %7:mat3x3<f32> = load %6
+ break_if true %b3
+ }
+ }
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:array<mat3x3<f32>, 4> @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<uniform, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ loop [b: %b3, c: %b4] { # loop_1
+ %b3 = block { # body
+ %3:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 2u
+ %4:mat3x3<f32> = load %3
+ continue %b4
+ }
+ %b4 = block { # continuing
+ %5:ptr<uniform, mat3x3<f32>, read_write> = access %buffer, 0u, 3u
+ %6:mat3x3<f32> = load %5
+ break_if true %b3
+ }
+ }
+ ret
+ }
+}
+)";
+
+ Run(CombineAccessInstructions);
+
+ EXPECT_EQ(expect, str());
+}
+
+} // namespace
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/conversion_polyfill.cc b/src/tint/lang/core/ir/transform/conversion_polyfill.cc
new file mode 100644
index 0000000..dcae17e
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/conversion_polyfill.cc
@@ -0,0 +1,227 @@
+// 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/lang/core/ir/transform/conversion_polyfill.h"
+
+#include <cmath>
+#include <utility>
+
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+namespace tint::core::ir::transform {
+
+namespace {
+
+/// PIMPL state for the transform.
+struct State {
+ /// The polyfill config.
+ const ConversionPolyfillConfig& config;
+
+ /// The IR module.
+ Module& ir;
+
+ /// The IR builder.
+ Builder b{ir};
+
+ /// The type manager.
+ core::type::Manager& ty{ir.Types()};
+
+ /// The symbol table.
+ SymbolTable& sym{ir.symbols};
+
+ /// Map from integer type to its f32toi helper function.
+ Hashmap<const type::Type*, Function*, 4> f32toi_helpers{};
+
+ /// Map from integer type to its f16toi helper function.
+ Hashmap<const type::Type*, Function*, 4> f16toi_helpers{};
+
+ /// Process the module.
+ void Process() {
+ // Find the conversion instructions that need to be polyfilled.
+ Vector<ir::Convert*, 64> ftoi_worklist;
+ for (auto* inst : ir.instructions.Objects()) {
+ if (!inst->Alive()) {
+ continue;
+ }
+ if (auto* convert = inst->As<ir::Convert>()) {
+ auto* src_ty = convert->Args()[0]->Type();
+ auto* res_ty = convert->Result()->Type();
+ if (config.ftoi && //
+ src_ty->is_float_scalar_or_vector() && //
+ res_ty->is_integer_scalar_or_vector()) {
+ ftoi_worklist.Push(convert);
+ }
+ }
+ }
+
+ // Polyfill the conversion instructions that we found.
+ for (auto* convert : ftoi_worklist) {
+ auto* replacement = ftoi(convert);
+
+ // Replace the old conversion instruction result with the new value.
+ if (auto name = ir.NameOf(convert->Result())) {
+ ir.SetName(replacement, name);
+ }
+ convert->Result()->ReplaceAllUsesWith(replacement);
+ convert->Destroy();
+ }
+ }
+
+ /// Replace a conversion instruction with a call to helper function that manually clamps the
+ /// result to within the limit of the destination type.
+ /// @param convert the conversion instruction
+ /// @returns the replacement value
+ ir::Value* ftoi(ir::Convert* convert) {
+ auto* res_ty = convert->Result()->Type();
+ auto* src_ty = convert->Args()[0]->Type();
+ auto* src_el_ty = src_ty->DeepestElement();
+
+ auto& helpers = src_el_ty->Is<type::F32>() ? f32toi_helpers : f16toi_helpers;
+ auto* helper = helpers.GetOrCreate(res_ty, [&] {
+ // Generate a name for the helper function.
+ StringStream name;
+ name << "tint_";
+ if (auto* src_vec = src_ty->As<type::Vector>()) {
+ name << "v" << src_vec->Width() << src_vec->type()->FriendlyName();
+ } else {
+ name << src_ty->FriendlyName();
+ }
+ name << "_to_";
+ if (auto* res_vec = res_ty->As<type::Vector>()) {
+ name << "v" << res_vec->Width() << res_vec->type()->FriendlyName();
+ } else {
+ name << res_ty->FriendlyName();
+ }
+
+ // Generate constants for the limits.
+ struct {
+ ir::Constant* low_limit_f = nullptr;
+ ir::Constant* high_limit_f = nullptr;
+ ir::Constant* low_limit_i = nullptr;
+ ir::Constant* high_limit_i = nullptr;
+ } limits;
+
+ // Integer limits.
+ if (res_ty->is_signed_integer_scalar_or_vector()) {
+ limits.low_limit_i = MatchWidth(b.Constant(i32(INT32_MIN)), res_ty);
+ limits.high_limit_i = MatchWidth(b.Constant(i32(INT32_MAX)), res_ty);
+ } else {
+ limits.low_limit_i = MatchWidth(b.Constant(u32(0)), res_ty);
+ limits.high_limit_i = MatchWidth(b.Constant(u32(UINT32_MAX)), res_ty);
+ }
+
+ // Largest integers representable in the source floating point format.
+ if (src_el_ty->Is<type::F32>()) {
+ if (res_ty->is_signed_integer_scalar_or_vector()) {
+ // INT32_MIN is -(2^31), which is exactly representable as an f32.
+ // INT32_MAX is (2^31 - 1), which is not exactly representable as an f32, so we
+ // instead use the next highest integer value in the f32 domain.
+ const float kMaxI32AsF32 = std::nexttowardf(0x1p+31f, 0.0L);
+ limits.low_limit_f = MatchWidth(b.Constant(f32(INT32_MIN)), res_ty);
+ limits.high_limit_f = MatchWidth(b.Constant(f32(kMaxI32AsF32)), res_ty);
+ } else {
+ // UINT32_MAX is (2^32 - 1), which is not exactly representable as an f32, so we
+ // instead use the next highest integer value in the f32 domain.
+ const float kMaxU32AsF32 = std::nexttowardf(0x1p+32f, 0.0L);
+ limits.low_limit_f = MatchWidth(b.Constant(f32(0)), res_ty);
+ limits.high_limit_f = MatchWidth(b.Constant(f32(kMaxU32AsF32)), res_ty);
+ }
+ } else if (src_el_ty->Is<type::F16>()) {
+ constexpr float MAX_F16 = 65504;
+ if (res_ty->is_signed_integer_scalar_or_vector()) {
+ limits.low_limit_f = MatchWidth(b.Constant(f16(-MAX_F16)), res_ty);
+ limits.high_limit_f = MatchWidth(b.Constant(f16(MAX_F16)), res_ty);
+ } else {
+ limits.low_limit_f = MatchWidth(b.Constant(f16(0)), res_ty);
+ limits.high_limit_f = MatchWidth(b.Constant(f16(MAX_F16)), res_ty);
+ }
+ } else {
+ TINT_UNIMPLEMENTED() << "unhandled floating-point type";
+ }
+
+ // Create the helper function.
+ auto* func = b.Function(name.str(), res_ty);
+ auto* value = b.FunctionParam("value", src_ty);
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ auto* bool_ty = MatchWidth(ty.bool_(), res_ty);
+
+ auto* converted = b.Convert(res_ty, value);
+
+ // low = select(low_limit_i, i32(value), value >= low_limit_f)
+ auto* low_cond = b.GreaterThanEqual(bool_ty, value, limits.low_limit_f);
+ auto* select_low = b.Call(res_ty, core::BuiltinFn::kSelect, limits.low_limit_i,
+ converted, low_cond);
+
+ // result = select(high_limit_i, low, value <= high_limit_f)
+ auto* high_cond = b.LessThanEqual(bool_ty, value, limits.high_limit_f);
+ auto* select_high = b.Call(res_ty, core::BuiltinFn::kSelect, limits.high_limit_i,
+ select_low, high_cond);
+
+ b.Return(func, select_high->Result());
+ });
+ return func;
+ });
+
+ // Call the helper function, splatting the arguments to match the target vector width.
+ auto* call = b.Call(res_ty, helper, convert->Args()[0]);
+ call->InsertBefore(convert);
+ return call->Result();
+ }
+
+ /// Return a type with element type @p type that has the same number of vector components as
+ /// @p match. If @p match is scalar just return @p type.
+ /// @param el_ty the type to extend
+ /// @param match the type to match the component count of
+ /// @returns a type with the same number of vector components as @p match
+ const core::type::Type* MatchWidth(const core::type::Type* el_ty,
+ const core::type::Type* match) {
+ if (auto* vec = match->As<core::type::Vector>()) {
+ return ty.vec(el_ty, vec->Width());
+ }
+ return el_ty;
+ }
+
+ /// Return a constant that has the same number of vector components as @p match, each with the
+ /// value @p element. If @p match is scalar just return @p element.
+ /// @param element the value to extend
+ /// @param match the type to match the component count of
+ /// @returns a value with the same number of vector components as @p match
+ ir::Constant* MatchWidth(ir::Constant* element, const core::type::Type* match) {
+ if (auto* vec = match->As<core::type::Vector>()) {
+ return b.Splat(MatchWidth(element->Type(), match), element, vec->Width());
+ }
+ return element;
+ }
+};
+
+} // namespace
+
+Result<SuccessType> ConversionPolyfill(Module& ir, const ConversionPolyfillConfig& config) {
+ auto result = ValidateAndDumpIfNeeded(ir, "ConversionPolyfill transform");
+ if (!result) {
+ return result;
+ }
+
+ State{config, ir}.Process();
+
+ return Success;
+}
+
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/conversion_polyfill.h b/src/tint/lang/core/ir/transform/conversion_polyfill.h
new file mode 100644
index 0000000..0c51a67
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/conversion_polyfill.h
@@ -0,0 +1,44 @@
+// 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_LANG_CORE_IR_TRANSFORM_CONVERSION_POLYFILL_H_
+#define SRC_TINT_LANG_CORE_IR_TRANSFORM_CONVERSION_POLYFILL_H_
+
+#include <string>
+
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Module;
+}
+
+namespace tint::core::ir::transform {
+
+/// The set of polyfills that should be applied.
+struct ConversionPolyfillConfig {
+ /// Should converting floating point values to integers be polyfilled?
+ bool ftoi = false;
+};
+
+/// ConversionPolyfill is a transform that modifies convert instructions to prepare them for raising
+/// to backend dialects that may have different semantics.
+/// @param module the module to transform
+/// @param config the polyfill configuration
+/// @returns success or failure
+Result<SuccessType> ConversionPolyfill(Module& module, const ConversionPolyfillConfig& config);
+
+} // namespace tint::core::ir::transform
+
+#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_CONVERSION_POLYFILL_H_
diff --git a/src/tint/lang/core/ir/transform/conversion_polyfill_test.cc b/src/tint/lang/core/ir/transform/conversion_polyfill_test.cc
new file mode 100644
index 0000000..f091dbb
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/conversion_polyfill_test.cc
@@ -0,0 +1,403 @@
+// 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/lang/core/ir/transform/conversion_polyfill.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/transform/helper_test.h"
+
+namespace tint::core::ir::transform {
+namespace {
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+class IR_ConversionPolyfillTest : public TransformTest {
+ protected:
+ /// Helper to build a function that executes a convert instruction.
+ /// @param src_ty the type of the source
+ /// @param res_ty the type of the result
+ void Build(const core::type::Type* src_ty, const core::type::Type* res_ty) {
+ auto* func = b.Function("foo", res_ty);
+ auto* src = b.FunctionParam("src", src_ty);
+ func->SetParams({src});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(res_ty, src);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+ }
+};
+
+// No change expected in this direction.
+TEST_F(IR_ConversionPolyfillTest, I32_to_F32) {
+ Build(ty.i32(), ty.f32());
+ auto* src = R"(
+%foo = func(%src:i32):f32 -> %b1 {
+ %b1 = block {
+ %result:f32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = src;
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+// No change expected in this direction.
+TEST_F(IR_ConversionPolyfillTest, U32_to_F32) {
+ Build(ty.u32(), ty.f32());
+ auto* src = R"(
+%foo = func(%src:u32):f32 -> %b1 {
+ %b1 = block {
+ %result:f32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = src;
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F32_to_I32_NoPolyfill) {
+ Build(ty.f32(), ty.i32());
+ auto* src = R"(
+%foo = func(%src:f32):i32 -> %b1 {
+ %b1 = block {
+ %result:i32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = src;
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = false;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F32_to_I32) {
+ Build(ty.f32(), ty.i32());
+ auto* src = R"(
+%foo = func(%src:f32):i32 -> %b1 {
+ %b1 = block {
+ %result:i32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:f32):i32 -> %b1 {
+ %b1 = block {
+ %result:i32 = call %tint_f32_to_i32, %src
+ ret %result
+ }
+}
+%tint_f32_to_i32 = func(%value:f32):i32 -> %b2 {
+ %b2 = block {
+ %6:i32 = convert %value
+ %7:bool = gte %value, -2147483648.0f
+ %8:i32 = select -2147483648i, %6, %7
+ %9:bool = lte %value, 2147483520.0f
+ %10:i32 = select 2147483647i, %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F32_to_U32) {
+ Build(ty.f32(), ty.u32());
+ auto* src = R"(
+%foo = func(%src:f32):u32 -> %b1 {
+ %b1 = block {
+ %result:u32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:f32):u32 -> %b1 {
+ %b1 = block {
+ %result:u32 = call %tint_f32_to_u32, %src
+ ret %result
+ }
+}
+%tint_f32_to_u32 = func(%value:f32):u32 -> %b2 {
+ %b2 = block {
+ %6:u32 = convert %value
+ %7:bool = gte %value, 0.0f
+ %8:u32 = select 0u, %6, %7
+ %9:bool = lte %value, 4294967040.0f
+ %10:u32 = select 4294967295u, %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F32_to_I32_Vec2) {
+ Build(ty.vec2<f32>(), ty.vec2<i32>());
+ auto* src = R"(
+%foo = func(%src:vec2<f32>):vec2<i32> -> %b1 {
+ %b1 = block {
+ %result:vec2<i32> = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:vec2<f32>):vec2<i32> -> %b1 {
+ %b1 = block {
+ %result:vec2<i32> = call %tint_v2f32_to_v2i32, %src
+ ret %result
+ }
+}
+%tint_v2f32_to_v2i32 = func(%value:vec2<f32>):vec2<i32> -> %b2 {
+ %b2 = block {
+ %6:vec2<i32> = convert %value
+ %7:vec2<bool> = gte %value, vec2<f32>(-2147483648.0f)
+ %8:vec2<i32> = select vec2<i32>(-2147483648i), %6, %7
+ %9:vec2<bool> = lte %value, vec2<f32>(2147483520.0f)
+ %10:vec2<i32> = select vec2<i32>(2147483647i), %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F32_to_U32_Vec3) {
+ Build(ty.vec2<f32>(), ty.vec2<u32>());
+ auto* src = R"(
+%foo = func(%src:vec2<f32>):vec2<u32> -> %b1 {
+ %b1 = block {
+ %result:vec2<u32> = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:vec2<f32>):vec2<u32> -> %b1 {
+ %b1 = block {
+ %result:vec2<u32> = call %tint_v2f32_to_v2u32, %src
+ ret %result
+ }
+}
+%tint_v2f32_to_v2u32 = func(%value:vec2<f32>):vec2<u32> -> %b2 {
+ %b2 = block {
+ %6:vec2<u32> = convert %value
+ %7:vec2<bool> = gte %value, vec2<f32>(0.0f)
+ %8:vec2<u32> = select vec2<u32>(0u), %6, %7
+ %9:vec2<bool> = lte %value, vec2<f32>(4294967040.0f)
+ %10:vec2<u32> = select vec2<u32>(4294967295u), %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F16_to_I32) {
+ Build(ty.f16(), ty.i32());
+ auto* src = R"(
+%foo = func(%src:f16):i32 -> %b1 {
+ %b1 = block {
+ %result:i32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:f16):i32 -> %b1 {
+ %b1 = block {
+ %result:i32 = call %tint_f16_to_i32, %src
+ ret %result
+ }
+}
+%tint_f16_to_i32 = func(%value:f16):i32 -> %b2 {
+ %b2 = block {
+ %6:i32 = convert %value
+ %7:bool = gte %value, -65504.0h
+ %8:i32 = select -2147483648i, %6, %7
+ %9:bool = lte %value, 65504.0h
+ %10:i32 = select 2147483647i, %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F16_to_U32) {
+ Build(ty.f16(), ty.u32());
+ auto* src = R"(
+%foo = func(%src:f16):u32 -> %b1 {
+ %b1 = block {
+ %result:u32 = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:f16):u32 -> %b1 {
+ %b1 = block {
+ %result:u32 = call %tint_f16_to_u32, %src
+ ret %result
+ }
+}
+%tint_f16_to_u32 = func(%value:f16):u32 -> %b2 {
+ %b2 = block {
+ %6:u32 = convert %value
+ %7:bool = gte %value, 0.0h
+ %8:u32 = select 0u, %6, %7
+ %9:bool = lte %value, 65504.0h
+ %10:u32 = select 4294967295u, %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F16_to_I32_Vec2) {
+ Build(ty.vec2<f16>(), ty.vec2<i32>());
+ auto* src = R"(
+%foo = func(%src:vec2<f16>):vec2<i32> -> %b1 {
+ %b1 = block {
+ %result:vec2<i32> = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:vec2<f16>):vec2<i32> -> %b1 {
+ %b1 = block {
+ %result:vec2<i32> = call %tint_v2f16_to_v2i32, %src
+ ret %result
+ }
+}
+%tint_v2f16_to_v2i32 = func(%value:vec2<f16>):vec2<i32> -> %b2 {
+ %b2 = block {
+ %6:vec2<i32> = convert %value
+ %7:vec2<bool> = gte %value, vec2<f16>(-65504.0h)
+ %8:vec2<i32> = select vec2<i32>(-2147483648i), %6, %7
+ %9:vec2<bool> = lte %value, vec2<f16>(65504.0h)
+ %10:vec2<i32> = select vec2<i32>(2147483647i), %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ConversionPolyfillTest, F16_to_U32_Vec3) {
+ Build(ty.vec2<f16>(), ty.vec2<u32>());
+ auto* src = R"(
+%foo = func(%src:vec2<f16>):vec2<u32> -> %b1 {
+ %b1 = block {
+ %result:vec2<u32> = convert %src
+ ret %result
+ }
+}
+)";
+ auto* expect = R"(
+%foo = func(%src:vec2<f16>):vec2<u32> -> %b1 {
+ %b1 = block {
+ %result:vec2<u32> = call %tint_v2f16_to_v2u32, %src
+ ret %result
+ }
+}
+%tint_v2f16_to_v2u32 = func(%value:vec2<f16>):vec2<u32> -> %b2 {
+ %b2 = block {
+ %6:vec2<u32> = convert %value
+ %7:vec2<bool> = gte %value, vec2<f16>(0.0h)
+ %8:vec2<u32> = select vec2<u32>(0u), %6, %7
+ %9:vec2<bool> = lte %value, vec2<f16>(65504.0h)
+ %10:vec2<u32> = select vec2<u32>(4294967295u), %8, %9
+ ret %10
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ ConversionPolyfillConfig config;
+ config.ftoi = true;
+ Run(ConversionPolyfill, config);
+ EXPECT_EQ(expect, str());
+}
+
+} // namespace
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper.cc b/src/tint/lang/core/ir/transform/demote_to_helper.cc
index 8749807..b3c0431 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper.cc
@@ -50,15 +50,13 @@
/// Process the module.
void Process() {
- // Check each fragment shader entry point for discard instruction, potentially inside
- // functions called (transitively) by the entry point.
+ // Check each function for discard instructions, potentially inside other functions called
+ // (transitively) by the function.
Vector<Function*, 4> to_process;
for (auto* func : ir.functions) {
- // If the function is a fragment shader that contains a discard, we need to process it.
- if (func->Stage() == Function::PipelineStage::kFragment) {
- if (HasDiscard(func)) {
- to_process.Push(func);
- }
+ // If the function contains a discard (directly or indirectly), we need to process it.
+ if (HasDiscard(func)) {
+ to_process.Push(func);
}
}
if (to_process.IsEmpty()) {
@@ -70,7 +68,7 @@
continue_execution->SetInitializer(b.Constant(true));
ir.root_block->Append(continue_execution);
- // Process each entry point function that contains a discard.
+ // Process each function that directly or indirectly discards.
for (auto* ep : to_process) {
ProcessFunction(ep);
}
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper_test.cc b/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
index 3efe9f4..9da0b70 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
@@ -860,5 +860,41 @@
EXPECT_EQ(expect, str());
}
+// Test that we transform unreachable functions that discard (see crbug.com/tint/2052).
+TEST_F(IR_DemoteToHelperTest, UnreachableHelperThatDiscards) {
+ auto* helper = b.Function("foo", ty.void_());
+ b.Append(helper->Block(), [&] {
+ b.Discard();
+ b.Return(helper);
+ });
+
+ auto* src = R"(
+%foo = func():void -> %b1 {
+ %b1 = block {
+ discard
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %continue_execution:ptr<private, bool, read_write> = var, true
+}
+
+%foo = func():void -> %b2 {
+ %b2 = block {
+ store %continue_execution, false
+ ret
+ }
+}
+)";
+
+ Run(DemoteToHelper);
+
+ EXPECT_EQ(expect, str());
+}
+
} // namespace
} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/direct_variable_access.cc b/src/tint/lang/core/ir/transform/direct_variable_access.cc
index 5939b82..b1079fa 100644
--- a/src/tint/lang/core/ir/transform/direct_variable_access.cc
+++ b/src/tint/lang/core/ir/transform/direct_variable_access.cc
@@ -571,6 +571,7 @@
ir.functions.Clear();
for (auto* fn : input_fns) {
if (auto info = need_forking.Get(fn)) {
+ fn->Destroy();
for (auto variant : (*info)->ordered_variants) {
ir.functions.Push(variant);
}
diff --git a/src/tint/lang/core/ir/transform/direct_variable_access_test.cc b/src/tint/lang/core/ir/transform/direct_variable_access_test.cc
index 5bccb80..4c1d25c 100644
--- a/src/tint/lang/core/ir/transform/direct_variable_access_test.cc
+++ b/src/tint/lang/core/ir/transform/direct_variable_access_test.cc
@@ -22,11 +22,6 @@
#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/core/type/struct.h"
-#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
-#include "src/tint/lang/wgsl/reader/reader.h"
-#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
-#include "src/tint/lang/wgsl/writer/writer.h"
-
namespace tint::core::ir::transform {
namespace {
@@ -3912,20 +3907,19 @@
EXPECT_EQ(expect, str());
}
-TEST_F(IR_DirectVariableAccessTest_BuiltinFn, WorkgroupUniformLoad) {
+TEST_F(IR_DirectVariableAccessTest_BuiltinFn, AtomicLoad) {
Var* W = nullptr;
b.Append(b.ir.root_block,
[&] { //
- W = b.Var<workgroup, f32>("W");
+ W = b.Var("W", ty.ptr<workgroup>(ty.atomic<i32>()));
});
- auto* fn_load = b.Function("load", ty.f32());
- auto* fn_load_p = b.FunctionParam("p", ty.ptr<workgroup, f32>());
+ auto* fn_load = b.Function("load", ty.i32());
+ auto* fn_load_p = b.FunctionParam("p", ty.ptr<workgroup>(ty.atomic<i32>()));
fn_load->SetParams({fn_load_p});
b.Append(fn_load->Block(),
[&] { //
- b.Return(fn_load,
- b.Call(ty.f32(), core::BuiltinFn::kWorkgroupUniformLoad, fn_load_p));
+ b.Return(fn_load, b.Call(ty.i32(), core::BuiltinFn::kAtomicLoad, fn_load_p));
});
auto* fn_f = b.Function("b", ty.void_());
@@ -3936,18 +3930,18 @@
auto* src = R"(
%b1 = block { # root
- %W:ptr<workgroup, f32, read_write> = var
+ %W:ptr<workgroup, atomic<i32>, read_write> = var
}
-%load = func(%p:ptr<workgroup, f32, read_write>):f32 -> %b2 {
+%load = func(%p:ptr<workgroup, atomic<i32>, read_write>):i32 -> %b2 {
%b2 = block {
- %4:f32 = workgroupUniformLoad %p
+ %4:i32 = atomicLoad %p
ret %4
}
}
%b = func():void -> %b3 {
%b3 = block {
- %6:f32 = call %load, %W
+ %6:i32 = call %load, %W
ret
}
}
@@ -3957,19 +3951,19 @@
auto* expect = R"(
%b1 = block { # root
- %W:ptr<workgroup, f32, read_write> = var
+ %W:ptr<workgroup, atomic<i32>, read_write> = var
}
-%load_W = func():f32 -> %b2 {
+%load_W = func():i32 -> %b2 {
%b2 = block {
- %3:ptr<workgroup, f32, read_write> = access %W
- %4:f32 = workgroupUniformLoad %3
+ %3:ptr<workgroup, atomic<i32>, read_write> = access %W
+ %4:i32 = atomicLoad %3
ret %4
}
}
%b = func():void -> %b3 {
%b3 = block {
- %6:f32 = call %load_W
+ %6:i32 = call %load_W
ret
}
}
diff --git a/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc b/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
index a764250..adfcbd7 100644
--- a/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
+++ b/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
@@ -65,7 +65,7 @@
auto transformed = wgsl::writer::IRToProgram(module.Get());
if (!transformed.IsValid()) {
return "wgsl::writer::IRToProgram() failed: \n" + transformed.Diagnostics().str() +
- "\n\nIR:\n" + ir::Disassembler(module.Get()).Disassemble() + //
+ "\n\nIR:\n" + ir::Disassemble(module.Get()) + //
"\n\nAST:\n" + Program::printer(transformed);
}
diff --git a/src/tint/lang/core/ir/transform/helper_test.h b/src/tint/lang/core/ir/transform/helper_test.h
index b188428..59142ab 100644
--- a/src/tint/lang/core/ir/transform/helper_test.h
+++ b/src/tint/lang/core/ir/transform/helper_test.h
@@ -49,10 +49,7 @@
}
/// @returns the transformed module as a disassembled string
- std::string str() {
- ir::Disassembler dis(mod);
- return "\n" + dis.Disassemble();
- }
+ std::string str() { return "\n" + ir::Disassemble(mod); }
protected:
/// The test IR module.
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
index db78182..96859cb 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
@@ -83,7 +83,8 @@
}
// Find function parameters that need to be replaced.
- for (auto* func : ir.functions) {
+ auto functions = ir.functions;
+ for (auto* func : functions) {
for (uint32_t index = 0; index < func->Params().Length(); index++) {
auto* param = func->Params()[index];
if (param->Type()->Is<core::type::ExternalTexture>()) {
diff --git a/src/tint/lang/core/ir/transform/preserve_padding.cc b/src/tint/lang/core/ir/transform/preserve_padding.cc
new file mode 100644
index 0000000..18f18f6
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/preserve_padding.cc
@@ -0,0 +1,173 @@
+// 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/lang/core/ir/transform/preserve_padding.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+namespace tint::core::ir::transform {
+
+namespace {
+
+/// PIMPL state for the transform.
+struct State {
+ /// The IR module.
+ Module& ir;
+
+ /// The IR builder.
+ Builder b{ir};
+
+ /// The type manager.
+ core::type::Manager& ty{ir.Types()};
+
+ /// The symbol table.
+ SymbolTable& sym{ir.symbols};
+
+ /// Map from a type to a helper function that will store a decomposed value.
+ Hashmap<const core::type::Type*, Function*, 4> helpers{};
+
+ /// Process the module.
+ void Process() {
+ // Find host-visible stores of types that contain padding bytes.
+ Vector<Store*, 8> worklist;
+ for (auto inst : ir.instructions.Objects()) {
+ if (auto* store = inst->As<Store>(); store && store->Alive()) {
+ auto* ptr = store->To()->Type()->As<core::type::Pointer>();
+ if (ptr->AddressSpace() == core::AddressSpace::kStorage &&
+ ContainsPadding(ptr->StoreType())) {
+ worklist.Push(store);
+ }
+ }
+ }
+
+ // Replace the stores we found with calls to helper functions that decompose the accesses.
+ for (auto* store : worklist) {
+ auto* replacement = MakeStore(store->To(), store->From());
+ store->ReplaceWith(replacement);
+ store->Destroy();
+ }
+ }
+
+ /// Check if a type contains padding bytes.
+ /// @param type the type to check
+ /// @returns true if the type contains padding bytes
+ bool ContainsPadding(const type::Type* type) {
+ return tint::Switch(
+ type, //
+ [&](const type::Array* arr) {
+ auto* elem_ty = arr->ElemType();
+ if (arr->Stride() > elem_ty->Size()) {
+ return true;
+ }
+ return ContainsPadding(elem_ty);
+ },
+ [&](const type::Matrix* mat) {
+ return mat->ColumnStride() > mat->ColumnType()->Size();
+ },
+ [&](const type::Struct* str) {
+ uint32_t current_offset = 0;
+ for (auto* member : str->Members()) {
+ if (member->Offset() > current_offset) {
+ return true;
+ }
+ if (ContainsPadding(member->Type())) {
+ return true;
+ }
+ current_offset += member->Type()->Size();
+ }
+ return (current_offset < str->Size());
+ });
+ }
+
+ /// Create an instruction that stores a (possibly padded) type to memory, decomposing the access
+ /// into separate components to preserve padding if necessary.
+ /// @param to the pointer to store to
+ /// @param value the value to store
+ /// @returns the instruction that performs the store
+ Instruction* MakeStore(Value* to, Value* value) {
+ auto* store_type = value->Type();
+
+ // If there are no padding bytes in this type, just use a regular store instruction.
+ if (!ContainsPadding(store_type)) {
+ return b.Store(to, value);
+ }
+
+ // The type contains padding bytes, so call a helper function that decomposes the accesses.
+ auto* helper = helpers.GetOrCreate(store_type, [&] {
+ auto* func = b.Function("tint_store_and_preserve_padding", ty.void_());
+ auto* target = b.FunctionParam("target", ty.ptr(storage, store_type));
+ auto* value_param = b.FunctionParam("value_param", store_type);
+ func->SetParams({target, value_param});
+
+ b.Append(func->Block(), [&] {
+ tint::Switch(
+ store_type, //
+ [&](const type::Array* arr) {
+ b.LoopRange(
+ ty, 0_u, u32(arr->ConstantCount().value()), 1_u, [&](Value* idx) {
+ auto* el_ptr =
+ b.Access(ty.ptr(storage, arr->ElemType()), target, idx);
+ auto* el_value = b.Access(arr->ElemType(), value_param, idx);
+ MakeStore(el_ptr->Result(), el_value->Result());
+ });
+ },
+ [&](const type::Matrix* mat) {
+ for (uint32_t i = 0; i < mat->columns(); i++) {
+ auto* col_ptr =
+ b.Access(ty.ptr(storage, mat->ColumnType()), target, u32(i));
+ auto* col_value = b.Access(mat->ColumnType(), value_param, u32(i));
+ MakeStore(col_ptr->Result(), col_value->Result());
+ }
+ },
+ [&](const type::Struct* str) {
+ for (auto* member : str->Members()) {
+ auto* sub_ptr = b.Access(ty.ptr(storage, member->Type()), target,
+ u32(member->Index()));
+ auto* sub_value =
+ b.Access(member->Type(), value_param, u32(member->Index()));
+ MakeStore(sub_ptr->Result(), sub_value->Result());
+ }
+ });
+
+ b.Return(func);
+ });
+
+ return func;
+ });
+
+ return b.Call(helper, to, value);
+ }
+};
+
+} // namespace
+
+Result<SuccessType> PreservePadding(Module& ir) {
+ auto result = ValidateAndDumpIfNeeded(ir, "PreservePadding transform");
+ if (!result) {
+ return result;
+ }
+
+ State{ir}.Process();
+
+ return Success;
+}
+
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/preserve_padding.h b/src/tint/lang/core/ir/transform/preserve_padding.h
new file mode 100644
index 0000000..fb0082d
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/preserve_padding.h
@@ -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.
+
+#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_PRESERVE_PADDING_H_
+#define SRC_TINT_LANG_CORE_IR_TRANSFORM_PRESERVE_PADDING_H_
+
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Module;
+}
+
+namespace tint::core::ir::transform {
+
+/// PreservePadding is a transform that decomposes stores of whole structure and array types to
+/// preserve padding bytes.
+///
+/// @note assumes that DirectVariableAccess will be run afterwards for backends that need it.
+/// @param module the module to transform
+/// @returns success or failure
+Result<SuccessType> PreservePadding(Module& module);
+
+} // namespace tint::core::ir::transform
+
+#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_PRESERVE_PADDING_H_
diff --git a/src/tint/lang/core/ir/transform/preserve_padding_test.cc b/src/tint/lang/core/ir/transform/preserve_padding_test.cc
new file mode 100644
index 0000000..88fcebc
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/preserve_padding_test.cc
@@ -0,0 +1,1291 @@
+// 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/lang/core/ir/transform/preserve_padding.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/transform/helper_test.h"
+#include "src/tint/lang/core/type/array.h"
+#include "src/tint/lang/core/type/matrix.h"
+#include "src/tint/lang/core/type/pointer.h"
+#include "src/tint/lang/core/type/struct.h"
+
+namespace tint::core::ir::transform {
+namespace {
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+class IR_PreservePaddingTest : public TransformTest {
+ protected:
+ const type::Struct* MakeStructWithoutPadding() {
+ auto* structure =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), ty.vec4<u32>()},
+ {mod.symbols.New("b"), ty.vec4<u32>()},
+ {mod.symbols.New("c"), ty.vec4<u32>()},
+ });
+ return structure;
+ }
+
+ const type::Struct* MakeStructWithTrailingPadding() {
+ auto* structure =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), ty.vec4<u32>()},
+ {mod.symbols.New("b"), ty.u32()},
+ });
+ return structure;
+ }
+
+ const type::Struct* MakeStructWithInternalPadding() {
+ auto* structure =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), ty.vec4<u32>()},
+ {mod.symbols.New("b"), ty.u32()},
+ {mod.symbols.New("c"), ty.vec4<u32>()},
+ });
+ return structure;
+ }
+};
+
+TEST_F(IR_PreservePaddingTest, NoModify_Workgroup) {
+ auto* structure = MakeStructWithTrailingPadding();
+ auto* buffer = b.Var("buffer", ty.ptr(workgroup, structure));
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<workgroup, MyStruct, read_write> = var
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_Private) {
+ auto* structure = MakeStructWithTrailingPadding();
+ auto* buffer = b.Var("buffer", ty.ptr(private_, structure));
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<private, MyStruct, read_write> = var
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_Function) {
+ auto* structure = MakeStructWithTrailingPadding();
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ auto* buffer = b.Var("buffer", ty.ptr(function, structure));
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%foo = func(%value:MyStruct):void -> %b1 {
+ %b1 = block {
+ %buffer:ptr<function, MyStruct, read_write> = var
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_StructWithoutPadding) {
+ auto* structure = MakeStructWithoutPadding();
+ auto* buffer = b.Var("buffer", ty.ptr(storage, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:vec4<u32> @offset(16)
+ c:vec4<u32> @offset(32)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_MatrixWithoutPadding) {
+ auto* mat = ty.mat4x4<f32>();
+ auto* buffer = b.Var("buffer", ty.ptr(storage, mat));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", mat);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, mat4x4<f32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:mat4x4<f32>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_ArrayWithoutPadding) {
+ auto* arr = ty.array<vec4<f32>>();
+ auto* buffer = b.Var("buffer", ty.ptr(storage, arr));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", arr);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<vec4<f32>>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<vec4<f32>>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_Vec3) {
+ auto* buffer = b.Var("buffer", ty.ptr(storage, ty.vec3<f32>()));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", ty.vec3<f32>());
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, vec3<f32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:vec3<f32>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NoModify_LoadStructWithTrailingPadding) {
+ auto* structure = MakeStructWithTrailingPadding();
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", structure);
+ b.Append(func->Block(), [&] {
+ auto* load = b.Load(buffer);
+ b.Return(func, load);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():MyStruct -> %b2 {
+ %b2 = block {
+ %3:MyStruct = load %buffer
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, Struct_TrailingPadding) {
+ auto* structure = MakeStructWithTrailingPadding();
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, MyStruct, read_write>, %value_param:MyStruct):void -> %b3 {
+ %b3 = block {
+ %8:ptr<storage, vec4<u32>, read_write> = access %target, 0u
+ %9:vec4<u32> = access %value_param, 0u
+ store %8, %9
+ %10:ptr<storage, u32, read_write> = access %target, 1u
+ %11:u32 = access %value_param, 1u
+ store %10, %11
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, Struct_InternalPadding) {
+ auto* structure = MakeStructWithInternalPadding();
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+ c:vec4<u32> @offset(32)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+ c:vec4<u32> @offset(32)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, MyStruct, read_write>, %value_param:MyStruct):void -> %b3 {
+ %b3 = block {
+ %8:ptr<storage, vec4<u32>, read_write> = access %target, 0u
+ %9:vec4<u32> = access %value_param, 0u
+ store %8, %9
+ %10:ptr<storage, u32, read_write> = access %target, 1u
+ %11:u32 = access %value_param, 1u
+ store %10, %11
+ %12:ptr<storage, vec4<u32>, read_write> = access %target, 2u
+ %13:vec4<u32> = access %value_param, 2u
+ store %12, %13
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, NestedStructWithPadding) {
+ auto* inner = MakeStructWithInternalPadding();
+ auto* outer = ty.Struct(mod.symbols.New("Outer"), {
+ {mod.symbols.New("inner"), inner},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, outer));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", outer);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+ c:vec4<u32> @offset(32)
+}
+
+Outer = struct @align(16) {
+ inner:MyStruct @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, Outer, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:Outer):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+ c:vec4<u32> @offset(32)
+}
+
+Outer = struct @align(16) {
+ inner:MyStruct @offset(0)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, Outer, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:Outer):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, Outer, read_write>, %value_param:Outer):void -> %b3 {
+ %b3 = block {
+ %8:ptr<storage, MyStruct, read_write> = access %target, 0u
+ %9:MyStruct = access %value_param, 0u
+ %10:void = call %tint_store_and_preserve_padding_1, %8, %9
+ ret
+ }
+}
+%tint_store_and_preserve_padding_1 = func(%target_1:ptr<storage, MyStruct, read_write>, %value_param_1:MyStruct):void -> %b4 { # %tint_store_and_preserve_padding_1: 'tint_store_and_preserve_padding', %target_1: 'target', %value_param_1: 'value_param'
+ %b4 = block {
+ %14:ptr<storage, vec4<u32>, read_write> = access %target_1, 0u
+ %15:vec4<u32> = access %value_param_1, 0u
+ store %14, %15
+ %16:ptr<storage, u32, read_write> = access %target_1, 1u
+ %17:u32 = access %value_param_1, 1u
+ store %16, %17
+ %18:ptr<storage, vec4<u32>, read_write> = access %target_1, 2u
+ %19:vec4<u32> = access %value_param_1, 2u
+ store %18, %19
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, StructWithPadding_InArray) {
+ auto* structure = MakeStructWithTrailingPadding();
+ auto* arr = ty.array(structure, 4);
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, arr));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", arr);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, array<MyStruct, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<MyStruct, 4>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:vec4<u32> @offset(0)
+ b:u32 @offset(16)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, array<MyStruct, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<MyStruct, 4>):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, array<MyStruct, 4>, read_write>, %value_param:array<MyStruct, 4>):void -> %b3 {
+ %b3 = block {
+ loop [i: %b4, b: %b5, c: %b6] { # loop_1
+ %b4 = block { # initializer
+ next_iteration %b5 0u
+ }
+ %b5 = block (%idx:u32) { # body
+ %9:bool = gte %idx:u32, 4u
+ if %9 [t: %b7] { # if_1
+ %b7 = block { # true
+ exit_loop # loop_1
+ }
+ }
+ %10:ptr<storage, MyStruct, read_write> = access %target, %idx:u32
+ %11:MyStruct = access %value_param, %idx:u32
+ %12:void = call %tint_store_and_preserve_padding_1, %10, %11
+ continue %b6
+ }
+ %b6 = block { # continuing
+ %14:u32 = add %idx:u32, 1u
+ next_iteration %b5 %14
+ }
+ }
+ ret
+ }
+}
+%tint_store_and_preserve_padding_1 = func(%target_1:ptr<storage, MyStruct, read_write>, %value_param_1:MyStruct):void -> %b8 { # %tint_store_and_preserve_padding_1: 'tint_store_and_preserve_padding', %target_1: 'target', %value_param_1: 'value_param'
+ %b8 = block {
+ %17:ptr<storage, vec4<u32>, read_write> = access %target_1, 0u
+ %18:vec4<u32> = access %value_param_1, 0u
+ store %17, %18
+ %19:ptr<storage, u32, read_write> = access %target_1, 1u
+ %20:u32 = access %value_param_1, 1u
+ store %19, %20
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, Mat3x3) {
+ auto* mat = ty.mat3x3<f32>();
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, mat));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", mat);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, mat3x3<f32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:mat3x3<f32>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, mat3x3<f32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:mat3x3<f32>):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, mat3x3<f32>, read_write>, %value_param:mat3x3<f32>):void -> %b3 {
+ %b3 = block {
+ %8:ptr<storage, vec3<f32>, read_write> = access %target, 0u
+ %9:vec3<f32> = access %value_param, 0u
+ store %8, %9
+ %10:ptr<storage, vec3<f32>, read_write> = access %target, 1u
+ %11:vec3<f32> = access %value_param, 1u
+ store %10, %11
+ %12:ptr<storage, vec3<f32>, read_write> = access %target, 2u
+ %13:vec3<f32> = access %value_param, 2u
+ store %12, %13
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, Mat3x3_InStruct) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), mat},
+ {mod.symbols.New("b"), mat},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, structure));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", structure);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ a:mat3x3<f32> @offset(0)
+ b:mat3x3<f32> @offset(48)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ a:mat3x3<f32> @offset(0)
+ b:mat3x3<f32> @offset(48)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:MyStruct):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, MyStruct, read_write>, %value_param:MyStruct):void -> %b3 {
+ %b3 = block {
+ %8:ptr<storage, mat3x3<f32>, read_write> = access %target, 0u
+ %9:mat3x3<f32> = access %value_param, 0u
+ %10:void = call %tint_store_and_preserve_padding_1, %8, %9
+ %12:ptr<storage, mat3x3<f32>, read_write> = access %target, 1u
+ %13:mat3x3<f32> = access %value_param, 1u
+ %14:void = call %tint_store_and_preserve_padding_1, %12, %13
+ ret
+ }
+}
+%tint_store_and_preserve_padding_1 = func(%target_1:ptr<storage, mat3x3<f32>, read_write>, %value_param_1:mat3x3<f32>):void -> %b4 { # %tint_store_and_preserve_padding_1: 'tint_store_and_preserve_padding', %target_1: 'target', %value_param_1: 'value_param'
+ %b4 = block {
+ %17:ptr<storage, vec3<f32>, read_write> = access %target_1, 0u
+ %18:vec3<f32> = access %value_param_1, 0u
+ store %17, %18
+ %19:ptr<storage, vec3<f32>, read_write> = access %target_1, 1u
+ %20:vec3<f32> = access %value_param_1, 1u
+ store %19, %20
+ %21:ptr<storage, vec3<f32>, read_write> = access %target_1, 2u
+ %22:vec3<f32> = access %value_param_1, 2u
+ store %21, %22
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, Mat3x3_Array) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, arr));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", arr);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<mat3x3<f32>, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<mat3x3<f32>, 4>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<mat3x3<f32>, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<mat3x3<f32>, 4>):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, array<mat3x3<f32>, 4>, read_write>, %value_param:array<mat3x3<f32>, 4>):void -> %b3 {
+ %b3 = block {
+ loop [i: %b4, b: %b5, c: %b6] { # loop_1
+ %b4 = block { # initializer
+ next_iteration %b5 0u
+ }
+ %b5 = block (%idx:u32) { # body
+ %9:bool = gte %idx:u32, 4u
+ if %9 [t: %b7] { # if_1
+ %b7 = block { # true
+ exit_loop # loop_1
+ }
+ }
+ %10:ptr<storage, mat3x3<f32>, read_write> = access %target, %idx:u32
+ %11:mat3x3<f32> = access %value_param, %idx:u32
+ %12:void = call %tint_store_and_preserve_padding_1, %10, %11
+ continue %b6
+ }
+ %b6 = block { # continuing
+ %14:u32 = add %idx:u32, 1u
+ next_iteration %b5 %14
+ }
+ }
+ ret
+ }
+}
+%tint_store_and_preserve_padding_1 = func(%target_1:ptr<storage, mat3x3<f32>, read_write>, %value_param_1:mat3x3<f32>):void -> %b8 { # %tint_store_and_preserve_padding_1: 'tint_store_and_preserve_padding', %target_1: 'target', %value_param_1: 'value_param'
+ %b8 = block {
+ %17:ptr<storage, vec3<f32>, read_write> = access %target_1, 0u
+ %18:vec3<f32> = access %value_param_1, 0u
+ store %17, %18
+ %19:ptr<storage, vec3<f32>, read_write> = access %target_1, 1u
+ %20:vec3<f32> = access %value_param_1, 1u
+ store %19, %20
+ %21:ptr<storage, vec3<f32>, read_write> = access %target_1, 2u
+ %22:vec3<f32> = access %value_param_1, 2u
+ store %21, %22
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, Vec3_Array) {
+ auto* arr = ty.array(ty.vec3<f32>(), 4);
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, arr));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", arr);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<vec3<f32>, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<vec3<f32>, 4>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<vec3<f32>, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<vec3<f32>, 4>):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, array<vec3<f32>, 4>, read_write>, %value_param:array<vec3<f32>, 4>):void -> %b3 {
+ %b3 = block {
+ loop [i: %b4, b: %b5, c: %b6] { # loop_1
+ %b4 = block { # initializer
+ next_iteration %b5 0u
+ }
+ %b5 = block (%idx:u32) { # body
+ %9:bool = gte %idx:u32, 4u
+ if %9 [t: %b7] { # if_1
+ %b7 = block { # true
+ exit_loop # loop_1
+ }
+ }
+ %10:ptr<storage, vec3<f32>, read_write> = access %target, %idx:u32
+ %11:vec3<f32> = access %value_param, %idx:u32
+ store %10, %11
+ continue %b6
+ }
+ %b6 = block { # continuing
+ %12:u32 = add %idx:u32, 1u
+ next_iteration %b5 %12
+ }
+ }
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, ComplexNesting) {
+ auto* inner =
+ ty.Struct(mod.symbols.New("Inner"), {
+ {mod.symbols.New("a"), ty.u32()},
+ {mod.symbols.New("b"), ty.array<vec3<f32>, 4>()},
+ {mod.symbols.New("c"), ty.mat3x3<f32>()},
+ {mod.symbols.New("d"), ty.u32()},
+ });
+
+ auto* outer =
+ ty.Struct(mod.symbols.New("Outer"), {
+ {mod.symbols.New("a"), ty.u32()},
+ {mod.symbols.New("inner"), inner},
+ {mod.symbols.New("inner_arr"), ty.array(inner, 4)},
+ {mod.symbols.New("b"), ty.u32()},
+ });
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, ty.array(outer, 3)));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", ty.array(outer, 3));
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(buffer, value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+Inner = struct @align(16) {
+ a:u32 @offset(0)
+ b:array<vec3<f32>, 4> @offset(16)
+ c:mat3x3<f32> @offset(80)
+ d:u32 @offset(128)
+}
+
+Outer = struct @align(16) {
+ a_1:u32 @offset(0)
+ inner:Inner @offset(16)
+ inner_arr:array<Inner, 4> @offset(160)
+ b_1:u32 @offset(736)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, array<Outer, 3>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<Outer, 3>):void -> %b2 {
+ %b2 = block {
+ store %buffer, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+Inner = struct @align(16) {
+ a:u32 @offset(0)
+ b:array<vec3<f32>, 4> @offset(16)
+ c:mat3x3<f32> @offset(80)
+ d:u32 @offset(128)
+}
+
+Outer = struct @align(16) {
+ a_1:u32 @offset(0)
+ inner:Inner @offset(16)
+ inner_arr:array<Inner, 4> @offset(160)
+ b_1:u32 @offset(736)
+}
+
+%b1 = block { # root
+ %buffer:ptr<storage, array<Outer, 3>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:array<Outer, 3>):void -> %b2 {
+ %b2 = block {
+ %4:void = call %tint_store_and_preserve_padding, %buffer, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, array<Outer, 3>, read_write>, %value_param:array<Outer, 3>):void -> %b3 {
+ %b3 = block {
+ loop [i: %b4, b: %b5, c: %b6] { # loop_1
+ %b4 = block { # initializer
+ next_iteration %b5 0u
+ }
+ %b5 = block (%idx:u32) { # body
+ %9:bool = gte %idx:u32, 3u
+ if %9 [t: %b7] { # if_1
+ %b7 = block { # true
+ exit_loop # loop_1
+ }
+ }
+ %10:ptr<storage, Outer, read_write> = access %target, %idx:u32
+ %11:Outer = access %value_param, %idx:u32
+ %12:void = call %tint_store_and_preserve_padding_1, %10, %11
+ continue %b6
+ }
+ %b6 = block { # continuing
+ %14:u32 = add %idx:u32, 1u
+ next_iteration %b5 %14
+ }
+ }
+ ret
+ }
+}
+%tint_store_and_preserve_padding_1 = func(%target_1:ptr<storage, Outer, read_write>, %value_param_1:Outer):void -> %b8 { # %tint_store_and_preserve_padding_1: 'tint_store_and_preserve_padding', %target_1: 'target', %value_param_1: 'value_param'
+ %b8 = block {
+ %17:ptr<storage, u32, read_write> = access %target_1, 0u
+ %18:u32 = access %value_param_1, 0u
+ store %17, %18
+ %19:ptr<storage, Inner, read_write> = access %target_1, 1u
+ %20:Inner = access %value_param_1, 1u
+ %21:void = call %tint_store_and_preserve_padding_2, %19, %20
+ %23:ptr<storage, array<Inner, 4>, read_write> = access %target_1, 2u
+ %24:array<Inner, 4> = access %value_param_1, 2u
+ %25:void = call %tint_store_and_preserve_padding_3, %23, %24
+ %27:ptr<storage, u32, read_write> = access %target_1, 3u
+ %28:u32 = access %value_param_1, 3u
+ store %27, %28
+ ret
+ }
+}
+%tint_store_and_preserve_padding_2 = func(%target_2:ptr<storage, Inner, read_write>, %value_param_2:Inner):void -> %b9 { # %tint_store_and_preserve_padding_2: 'tint_store_and_preserve_padding', %target_2: 'target', %value_param_2: 'value_param'
+ %b9 = block {
+ %31:ptr<storage, u32, read_write> = access %target_2, 0u
+ %32:u32 = access %value_param_2, 0u
+ store %31, %32
+ %33:ptr<storage, array<vec3<f32>, 4>, read_write> = access %target_2, 1u
+ %34:array<vec3<f32>, 4> = access %value_param_2, 1u
+ %35:void = call %tint_store_and_preserve_padding_4, %33, %34
+ %37:ptr<storage, mat3x3<f32>, read_write> = access %target_2, 2u
+ %38:mat3x3<f32> = access %value_param_2, 2u
+ %39:void = call %tint_store_and_preserve_padding_5, %37, %38
+ %41:ptr<storage, u32, read_write> = access %target_2, 3u
+ %42:u32 = access %value_param_2, 3u
+ store %41, %42
+ ret
+ }
+}
+%tint_store_and_preserve_padding_4 = func(%target_3:ptr<storage, array<vec3<f32>, 4>, read_write>, %value_param_3:array<vec3<f32>, 4>):void -> %b10 { # %tint_store_and_preserve_padding_4: 'tint_store_and_preserve_padding', %target_3: 'target', %value_param_3: 'value_param'
+ %b10 = block {
+ loop [i: %b11, b: %b12, c: %b13] { # loop_2
+ %b11 = block { # initializer
+ next_iteration %b12 0u
+ }
+ %b12 = block (%idx_1:u32) { # body
+ %46:bool = gte %idx_1:u32, 4u
+ if %46 [t: %b14] { # if_2
+ %b14 = block { # true
+ exit_loop # loop_2
+ }
+ }
+ %47:ptr<storage, vec3<f32>, read_write> = access %target_3, %idx_1:u32
+ %48:vec3<f32> = access %value_param_3, %idx_1:u32
+ store %47, %48
+ continue %b13
+ }
+ %b13 = block { # continuing
+ %49:u32 = add %idx_1:u32, 1u
+ next_iteration %b12 %49
+ }
+ }
+ ret
+ }
+}
+%tint_store_and_preserve_padding_5 = func(%target_4:ptr<storage, mat3x3<f32>, read_write>, %value_param_4:mat3x3<f32>):void -> %b15 { # %tint_store_and_preserve_padding_5: 'tint_store_and_preserve_padding', %target_4: 'target', %value_param_4: 'value_param'
+ %b15 = block {
+ %52:ptr<storage, vec3<f32>, read_write> = access %target_4, 0u
+ %53:vec3<f32> = access %value_param_4, 0u
+ store %52, %53
+ %54:ptr<storage, vec3<f32>, read_write> = access %target_4, 1u
+ %55:vec3<f32> = access %value_param_4, 1u
+ store %54, %55
+ %56:ptr<storage, vec3<f32>, read_write> = access %target_4, 2u
+ %57:vec3<f32> = access %value_param_4, 2u
+ store %56, %57
+ ret
+ }
+}
+%tint_store_and_preserve_padding_3 = func(%target_5:ptr<storage, array<Inner, 4>, read_write>, %value_param_5:array<Inner, 4>):void -> %b16 { # %tint_store_and_preserve_padding_3: 'tint_store_and_preserve_padding', %target_5: 'target', %value_param_5: 'value_param'
+ %b16 = block {
+ loop [i: %b17, b: %b18, c: %b19] { # loop_3
+ %b17 = block { # initializer
+ next_iteration %b18 0u
+ }
+ %b18 = block (%idx_2:u32) { # body
+ %61:bool = gte %idx_2:u32, 4u
+ if %61 [t: %b20] { # if_3
+ %b20 = block { # true
+ exit_loop # loop_3
+ }
+ }
+ %62:ptr<storage, Inner, read_write> = access %target_5, %idx_2:u32
+ %63:Inner = access %value_param_5, %idx_2:u32
+ %64:void = call %tint_store_and_preserve_padding_2, %62, %63
+ continue %b19
+ }
+ %b19 = block { # continuing
+ %65:u32 = add %idx_2:u32, 1u
+ next_iteration %b18 %65
+ }
+ }
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_PreservePaddingTest, MultipleStoresSameType) {
+ auto* mat = ty.mat3x3<f32>();
+ auto* arr = ty.array(mat, 4);
+
+ auto* buffer = b.Var("buffer", ty.ptr(storage, arr));
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* value = b.FunctionParam("value", mat);
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({value});
+ b.Append(func->Block(), [&] {
+ b.Store(b.Access(ty.ptr(storage, mat), buffer, 0_u), value);
+ b.Store(b.Access(ty.ptr(storage, mat), buffer, 1_u), value);
+ b.Store(b.Access(ty.ptr(storage, mat), buffer, 2_u), value);
+ b.Store(b.Access(ty.ptr(storage, mat), buffer, 3_u), value);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<mat3x3<f32>, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:mat3x3<f32>):void -> %b2 {
+ %b2 = block {
+ %4:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 0u
+ store %4, %value
+ %5:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 1u
+ store %5, %value
+ %6:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 2u
+ store %6, %value
+ %7:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 3u
+ store %7, %value
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %buffer:ptr<storage, array<mat3x3<f32>, 4>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%value:mat3x3<f32>):void -> %b2 {
+ %b2 = block {
+ %4:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 0u
+ %5:void = call %tint_store_and_preserve_padding, %4, %value
+ %7:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 1u
+ %8:void = call %tint_store_and_preserve_padding, %7, %value
+ %9:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 2u
+ %10:void = call %tint_store_and_preserve_padding, %9, %value
+ %11:ptr<storage, mat3x3<f32>, read_write> = access %buffer, 3u
+ %12:void = call %tint_store_and_preserve_padding, %11, %value
+ ret
+ }
+}
+%tint_store_and_preserve_padding = func(%target:ptr<storage, mat3x3<f32>, read_write>, %value_param:mat3x3<f32>):void -> %b3 {
+ %b3 = block {
+ %15:ptr<storage, vec3<f32>, read_write> = access %target, 0u
+ %16:vec3<f32> = access %value_param, 0u
+ store %15, %16
+ %17:ptr<storage, vec3<f32>, read_write> = access %target, 1u
+ %18:vec3<f32> = access %value_param, 1u
+ store %17, %18
+ %19:ptr<storage, vec3<f32>, read_write> = access %target, 2u
+ %20:vec3<f32> = access %value_param, 2u
+ store %19, %20
+ ret
+ }
+}
+)";
+
+ Run(PreservePadding);
+
+ EXPECT_EQ(expect, str());
+}
+
+} // namespace
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/shader_io.cc b/src/tint/lang/core/ir/transform/shader_io.cc
index df9987c..74fe767 100644
--- a/src/tint/lang/core/ir/transform/shader_io.cc
+++ b/src/tint/lang/core/ir/transform/shader_io.cc
@@ -263,7 +263,10 @@
void RunShaderIOBase(Module& module, std::function<MakeBackendStateFunc> make_backend_state) {
State state{module};
- for (auto* func : module.functions) {
+
+ // Take a copy of the function list since the transform will add new functions to the module.
+ auto functions = module.functions;
+ for (auto* func : functions) {
// Only process entry points.
if (func->Stage() == Function::PipelineStage::kUndefined) {
continue;
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
index 4e9c88b..7980ca7 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
@@ -156,7 +156,11 @@
});
} else {
// Use a loop for arrayed stores.
- GenerateZeroingLoop(local_index, count, wgsize, *element_stores);
+ b.LoopRange(ty, local_index, u32(count), u32(wgsize), [&](Value* index) {
+ for (auto& store : *element_stores) {
+ GenerateStore(store, count, index);
+ }
+ });
}
}
b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
@@ -328,46 +332,6 @@
}
}
- /// Generate a loop for a list of stores with the same iteration count.
- /// @param local_index the local invocation index
- /// @param total_count the number of iterations needed to store to all elements
- /// @param wgsize the linearized workgroup size
- /// @param stores the list of store descriptors
- void GenerateZeroingLoop(Value* local_index,
- uint32_t total_count,
- uint32_t wgsize,
- const StoreList& stores) {
- // The loop is equivalent to:
- // for (var idx = local_index; idx < linear_iteration_count; idx += wgsize) {
- // <store to elements at `idx`>
- // }
- auto* loop = b.Loop();
- auto* index = b.BlockParam(ty.u32());
- loop->Body()->SetParams({index});
- b.Append(loop->Initializer(), [&] { //
- b.NextIteration(loop, local_index);
- });
- b.Append(loop->Body(), [&] {
- // Exit the loop when the iteration count has been exceeded.
- auto* gt_max = b.GreaterThan(ty.bool_(), index, u32(total_count - 1u));
- auto* ifelse = b.If(gt_max);
- b.Append(ifelse->True(), [&] { //
- b.ExitLoop(loop);
- });
-
- // Insert all of the store instructions.
- for (auto& store : stores) {
- GenerateStore(store, total_count, index);
- }
-
- b.Continue(loop);
- });
- b.Append(loop->Continuing(), [&] { //
- // Increment the loop index by linearized workgroup size.
- b.NextIteration(loop, b.Add(ty.u32(), index, u32(wgsize)));
- });
- }
-
/// Check if a type can be efficiently zeroed with a single store. Returns `false` if there are
/// any nested arrays or atomics.
/// @param type the type to inspect
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
index 026d5e3..955582c 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
@@ -466,19 +466,19 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 3u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 4u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:ptr<workgroup, i32, read_write> = access %wgvar, %4:u32
+ %6:ptr<workgroup, i32, read_write> = access %wgvar, %idx:u32
store %6, 0i
continue %b5
}
%b5 = block { # continuing
- %7:u32 = add %4:u32, 66u
+ %7:u32 = add %idx:u32, 66u
next_iteration %b4 %7
}
}
@@ -528,21 +528,21 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 34u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 35u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %4:u32, 5u
- %7:u32 = div %4:u32, 5u
+ %6:u32 = mod %idx:u32, 5u
+ %7:u32 = div %idx:u32, 5u
%8:ptr<workgroup, u32, read_write> = access %wgvar, %7, %6
store %8, 0u
continue %b5
}
%b5 = block { # continuing
- %9:u32 = add %4:u32, 66u
+ %9:u32 = add %idx:u32, 66u
next_iteration %b4 %9
}
}
@@ -592,23 +592,23 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 104u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 105u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %4:u32, 7u
- %7:u32 = div %4:u32, 7u
+ %6:u32 = mod %idx:u32, 7u
+ %7:u32 = div %idx:u32, 7u
%8:u32 = mod %7, 5u
- %9:u32 = div %4:u32, 35u
+ %9:u32 = div %idx:u32, 35u
%10:ptr<workgroup, i32, read_write> = access %wgvar, %9, %8, %6
store %10, 0i
continue %b5
}
%b5 = block { # continuing
- %11:u32 = add %4:u32, 1u
+ %11:u32 = add %idx:u32, 1u
next_iteration %b4 %11
}
}
@@ -658,21 +658,21 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 14u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 15u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %4:u32, 5u
- %7:u32 = div %4:u32, 5u
+ %6:u32 = mod %idx:u32, 5u
+ %7:u32 = div %idx:u32, 5u
%8:ptr<workgroup, i32, read_write> = access %wgvar, %7, %6, 0u
store %8, 0i
continue %b5
}
%b5 = block { # continuing
- %9:u32 = add %4:u32, 1u
+ %9:u32 = add %idx:u32, 1u
next_iteration %b4 %9
}
}
@@ -722,21 +722,21 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 14u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 15u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %4:u32, 3u
- %7:u32 = div %4:u32, 3u
+ %6:u32 = mod %idx:u32, 3u
+ %7:u32 = div %idx:u32, 3u
%8:ptr<workgroup, i32, read_write> = access %wgvar, %7, 0u, %6
store %8, 0i
continue %b5
}
%b5 = block { # continuing
- %9:u32 = add %4:u32, 1u
+ %9:u32 = add %idx:u32, 1u
next_iteration %b4 %9
}
}
@@ -786,21 +786,21 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 14u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 15u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %4:u32, 3u
- %7:u32 = div %4:u32, 3u
+ %6:u32 = mod %idx:u32, 3u
+ %7:u32 = div %idx:u32, 3u
%8:ptr<workgroup, i32, read_write> = access %wgvar, 0u, %7, %6
store %8, 0i
continue %b5
}
%b5 = block { # continuing
- %9:u32 = add %4:u32, 1u
+ %9:u32 = add %idx:u32, 1u
next_iteration %b4 %9
}
}
@@ -1165,21 +1165,21 @@
%b3 = block { # initializer
next_iteration %b4 %tint_local_index
}
- %b4 = block (%4:u32) { # body
- %5:bool = gt %4:u32, 6u
+ %b4 = block (%idx:u32) { # body
+ %5:bool = gte %idx:u32, 7u
if %5 [t: %b6] { # if_1
%b6 = block { # true
exit_loop # loop_1
}
}
- %6:ptr<workgroup, f32, read_write> = access %wgvar, %4:u32, 0u
+ %6:ptr<workgroup, f32, read_write> = access %wgvar, %idx:u32, 0u
store %6, 0.0f
- %7:ptr<workgroup, bool, read_write> = access %wgvar, %4:u32, 2u
+ %7:ptr<workgroup, bool, read_write> = access %wgvar, %idx:u32, 2u
store %7, false
continue %b5
}
%b5 = block { # continuing
- %8:u32 = add %4:u32, 42u
+ %8:u32 = add %idx:u32, 42u
next_iteration %b4 %8
}
}
@@ -1187,25 +1187,25 @@
%b7 = block { # initializer
next_iteration %b8 %tint_local_index
}
- %b8 = block (%9:u32) { # body
- %10:bool = gt %9:u32, 90u
+ %b8 = block (%idx_1:u32) { # body
+ %10:bool = gte %idx_1:u32, 91u
if %10 [t: %b10] { # if_2
%b10 = block { # true
exit_loop # loop_2
}
}
- %11:u32 = mod %9:u32, 13u
- %12:u32 = div %9:u32, 13u
+ %11:u32 = mod %idx_1:u32, 13u
+ %12:u32 = div %idx_1:u32, 13u
%13:ptr<workgroup, i32, read_write> = access %wgvar, %12, 1u, %11, 0u
store %13, 0i
- %14:u32 = mod %9:u32, 13u
- %15:u32 = div %9:u32, 13u
+ %14:u32 = mod %idx_1:u32, 13u
+ %15:u32 = div %idx_1:u32, 13u
%16:ptr<workgroup, atomic<u32>, read_write> = access %wgvar, %15, 1u, %14, 1u
%17:void = atomicStore %16, 0u
continue %b9
}
%b9 = block { # continuing
- %18:u32 = add %9:u32, 42u
+ %18:u32 = add %idx_1:u32, 42u
next_iteration %b8 %18
}
}
@@ -1272,19 +1272,19 @@
%b4 = block { # initializer
next_iteration %b5 %tint_local_index
}
- %b5 = block (%7:u32) { # body
- %8:bool = gt %7:u32, 3u
+ %b5 = block (%idx:u32) { # body
+ %8:bool = gte %idx:u32, 4u
if %8 [t: %b7] { # if_2
%b7 = block { # true
exit_loop # loop_1
}
}
- %9:ptr<workgroup, i32, read_write> = access %var_b, %7:u32
+ %9:ptr<workgroup, i32, read_write> = access %var_b, %idx:u32
store %9, 0i
continue %b6
}
%b6 = block { # continuing
- %10:u32 = add %7:u32, 66u
+ %10:u32 = add %idx:u32, 66u
next_iteration %b5 %10
}
}
@@ -1292,21 +1292,21 @@
%b8 = block { # initializer
next_iteration %b9 %tint_local_index
}
- %b9 = block (%11:u32) { # body
- %12:bool = gt %11:u32, 34u
+ %b9 = block (%idx_1:u32) { # body
+ %12:bool = gte %idx_1:u32, 35u
if %12 [t: %b11] { # if_3
%b11 = block { # true
exit_loop # loop_2
}
}
- %13:u32 = mod %11:u32, 5u
- %14:u32 = div %11:u32, 5u
+ %13:u32 = mod %idx_1:u32, 5u
+ %14:u32 = div %idx_1:u32, 5u
%15:ptr<workgroup, u32, read_write> = access %var_c, %14, %13
store %15, 0u
continue %b10
}
%b10 = block { # continuing
- %16:u32 = add %11:u32, 66u
+ %16:u32 = add %idx_1:u32, 66u
next_iteration %b9 %16
}
}
@@ -1381,23 +1381,23 @@
%b4 = block { # initializer
next_iteration %b5 %tint_local_index
}
- %b5 = block (%8:u32) { # body
- %9:bool = gt %8:u32, 41u
+ %b5 = block (%idx:u32) { # body
+ %9:bool = gte %idx:u32, 42u
if %9 [t: %b7] { # if_2
%b7 = block { # true
exit_loop # loop_1
}
}
- %10:ptr<workgroup, i32, read_write> = access %var_c, %8:u32
+ %10:ptr<workgroup, i32, read_write> = access %var_c, %idx:u32
store %10, 0i
- %11:u32 = mod %8:u32, 6u
- %12:u32 = div %8:u32, 6u
+ %11:u32 = mod %idx:u32, 6u
+ %12:u32 = div %idx:u32, 6u
%13:ptr<workgroup, u32, read_write> = access %var_d, %12, %11
store %13, 0u
continue %b6
}
%b6 = block { # continuing
- %14:u32 = add %8:u32, 66u
+ %14:u32 = add %idx:u32, 66u
next_iteration %b5 %14
}
}
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 8edf526..fbac2a8 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -271,6 +271,7 @@
Disassembler dis_{mod_};
Block* current_block_ = nullptr;
Hashset<Function*, 4> all_functions_;
+ Hashset<Instruction*, 4> visited_instructions_;
Vector<ControlInstruction*, 8> control_stack_;
void DisassembleIfNeeded();
@@ -300,6 +301,15 @@
CheckFunction(func);
}
+ if (!diagnostics_.contains_errors()) {
+ // Check for orphaned instructions.
+ for (auto* inst : mod_.instructions.Objects()) {
+ if (inst->Alive() && !visited_instructions_.Contains(inst)) {
+ AddError("orphaned instruction: " + inst->FriendlyName());
+ }
+ }
+ }
+
if (diagnostics_.contains_errors()) {
DisassembleIfNeeded();
diagnostics_.add_note(tint::diag::System::IR,
@@ -448,6 +458,7 @@
}
void Validator::CheckInstruction(Instruction* inst) {
+ visited_instructions_.Add(inst);
if (!inst->Alive()) {
AddError(inst, InstError(inst, "destroyed instruction found in instruction list"));
return;
@@ -893,11 +904,10 @@
Result<SuccessType> ValidateAndDumpIfNeeded([[maybe_unused]] Module& ir,
[[maybe_unused]] const char* msg) {
#if TINT_DUMP_IR_WHEN_VALIDATING
- Disassembler disasm(ir);
std::cout << "=========================================================" << std::endl;
std::cout << "== IR dump before " << msg << ":" << std::endl;
std::cout << "=========================================================" << std::endl;
- std::cout << disasm.Disassemble();
+ std::cout << Disassemble(ir);
#endif
#ifndef NDEBUG
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 56ec9da..1521cf9 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -1183,6 +1183,29 @@
)");
}
+TEST_F(IR_ValidatorTest, Instruction_OrphanedInstruction) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ auto sb = b.Append(f->Block());
+ auto* v = sb.Var(ty.ptr<function, f32>());
+ auto* load = sb.Load(v);
+ sb.Return(f);
+
+ load->Remove();
+
+ auto res = ir::Validate(mod);
+ ASSERT_FALSE(res);
+ EXPECT_EQ(res.Failure().reason.str(), R"(error: orphaned instruction: load
+note: # Disassembly
+%my_func = func():void -> %b1 {
+ %b1 = block {
+ %2:ptr<function, f32, read_write> = var
+ ret
+ }
+}
+)");
+}
+
TEST_F(IR_ValidatorTest, Binary_LHS_Nullptr) {
auto* f = b.Function("my_func", ty.void_());
diff --git a/src/tint/lang/core/ir/value.cc b/src/tint/lang/core/ir/value.cc
index ab886da..042bbad 100644
--- a/src/tint/lang/core/ir/value.cc
+++ b/src/tint/lang/core/ir/value.cc
@@ -28,7 +28,6 @@
void Value::Destroy() {
TINT_ASSERT(Alive());
- TINT_ASSERT(Usages().Count() == 0);
flags_.Add(Flag::kDead);
}
diff --git a/src/tint/lang/core/ir/value_test.cc b/src/tint/lang/core/ir/value_test.cc
index 36fb415..3de50df 100644
--- a/src/tint/lang/core/ir/value_test.cc
+++ b/src/tint/lang/core/ir/value_test.cc
@@ -53,18 +53,6 @@
EXPECT_FALSE(val->Alive());
}
-TEST_F(IR_ValueTest, Destroy_HasUsage) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- auto* val = b.InstructionResult(mod.Types().i32());
- b.Add(mod.Types().i32(), val, 1_i);
- val->Destroy();
- },
- "");
-}
-
TEST_F(IR_ValueTest, Destroy_HasSource) {
EXPECT_FATAL_FAILURE(
{
diff --git a/src/tint/lang/core/number.h b/src/tint/lang/core/number.h
index 3326ee8..b8e2b60 100644
--- a/src/tint/lang/core/number.h
+++ b/src/tint/lang/core/number.h
@@ -427,10 +427,6 @@
#endif
#endif
-/// Disables the false-positive maybe-uninitialized compiler warnings
-/// @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
-TINT_BEGIN_DISABLE_WARNING(MAYBE_UNINITIALIZED);
-
/// @param a the LHS number
/// @param b the RHS number
/// @returns a + b, or an empty optional if the resulting value overflowed the AInt
@@ -661,9 +657,6 @@
return result;
}
-/// Re-enables the maybe-uninitialized compiler warnings
-TINT_END_DISABLE_WARNING(MAYBE_UNINITIALIZED);
-
} // namespace tint::core
namespace tint::core::number_suffixes {
diff --git a/src/tint/lang/core/type/BUILD.gn b/src/tint/lang/core/type/BUILD.gn
index c80abf5..79ad01f 100644
--- a/src/tint/lang/core/type/BUILD.gn
+++ b/src/tint/lang/core/type/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -119,7 +119,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"array_test.cc",
"atomic_test.cc",
diff --git a/src/tint/lang/core/type/array.h b/src/tint/lang/core/type/array.h
index 0f97911..ea29674 100644
--- a/src/tint/lang/core/type/array.h
+++ b/src/tint/lang/core/type/array.h
@@ -28,7 +28,7 @@
namespace tint::core::type {
/// Array holds the type information for Array nodes.
-class Array final : public Castable<Array, Type> {
+class Array : public Castable<Array, Type> {
public:
/// An error message string stating that the array count was expected to be a constant
/// expression. Used by multiple writers and transforms.
diff --git a/src/tint/lang/core/type/storage_texture.cc b/src/tint/lang/core/type/storage_texture.cc
index f1d7204..07ca8a0 100644
--- a/src/tint/lang/core/type/storage_texture.cc
+++ b/src/tint/lang/core/type/storage_texture.cc
@@ -28,7 +28,7 @@
StorageTexture::StorageTexture(TextureDimension dim,
core::TexelFormat format,
core::Access access,
- Type* subtype)
+ const Type* subtype)
: Base(Hash(tint::TypeInfo::Of<StorageTexture>().full_hashcode, dim, format, access), dim),
texel_format_(format),
access_(access),
diff --git a/src/tint/lang/core/type/storage_texture.h b/src/tint/lang/core/type/storage_texture.h
index 491e7fa..7abcab1 100644
--- a/src/tint/lang/core/type/storage_texture.h
+++ b/src/tint/lang/core/type/storage_texture.h
@@ -40,7 +40,7 @@
StorageTexture(TextureDimension dim,
core::TexelFormat format,
core::Access access,
- Type* subtype);
+ const Type* subtype);
/// Destructor
~StorageTexture() override;
@@ -50,7 +50,7 @@
bool Equals(const UniqueNode& other) const override;
/// @returns the storage subtype
- Type* type() const { return subtype_; }
+ const Type* type() const { return subtype_; }
/// @returns the texel format
core::TexelFormat texel_format() const { return texel_format_; }
@@ -74,7 +74,7 @@
private:
core::TexelFormat const texel_format_;
core::Access const access_;
- Type* const subtype_;
+ const Type* const subtype_;
};
} // namespace tint::core::type
diff --git a/src/tint/lang/glsl/BUILD.cmake b/src/tint/lang/glsl/BUILD.cmake
index d393f94..b067618d2 100644
--- a/src/tint/lang/glsl/BUILD.cmake
+++ b/src/tint/lang/glsl/BUILD.cmake
@@ -21,4 +21,5 @@
# Do not modify this file directly
################################################################################
+include(lang/glsl/validate/BUILD.cmake)
include(lang/glsl/writer/BUILD.cmake)
diff --git a/src/tint/lang/glsl/validate/BUILD.bazel b/src/tint/lang/glsl/validate/BUILD.bazel
new file mode 100644
index 0000000..30fa6ad
--- /dev/null
+++ b/src/tint/lang/glsl/validate/BUILD.bazel
@@ -0,0 +1,66 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+cc_library(
+ name = "validate",
+ srcs = [
+ "validate.cc",
+ ],
+ hdrs = [
+ "validate.h",
+ ],
+ deps = [
+ "//src/tint/lang/wgsl/ast",
+ "//src/tint/utils/containers",
+ "//src/tint/utils/diagnostic",
+ "//src/tint/utils/ice",
+ "//src/tint/utils/macros",
+ "//src/tint/utils/math",
+ "//src/tint/utils/memory",
+ "//src/tint/utils/result",
+ "//src/tint/utils/rtti",
+ "//src/tint/utils/text",
+ "//src/tint/utils/traits",
+ ] + select({
+ ":tint_build_glsl_writer": [
+
+
+ ],
+ "//conditions:default": [],
+ }),
+ copts = COPTS,
+ visibility = ["//visibility:public"],
+)
+
+alias(
+ name = "tint_build_glsl_validator",
+ actual = "//src/tint:tint_build_glsl_validator_true",
+)
+
+alias(
+ name = "tint_build_glsl_writer",
+ actual = "//src/tint:tint_build_glsl_writer_true",
+)
+
diff --git a/src/tint/lang/glsl/validate/BUILD.cfg b/src/tint/lang/glsl/validate/BUILD.cfg
new file mode 100644
index 0000000..eb4a63d
--- /dev/null
+++ b/src/tint/lang/glsl/validate/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_glsl_validator"
+}
diff --git a/src/tint/lang/glsl/validate/BUILD.cmake b/src/tint/lang/glsl/validate/BUILD.cmake
new file mode 100644
index 0000000..7119d00
--- /dev/null
+++ b/src/tint/lang/glsl/validate/BUILD.cmake
@@ -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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+# tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+if(TINT_BUILD_GLSL_VALIDATOR)
+################################################################################
+# Target: tint_lang_glsl_validate
+# Kind: lib
+# Condition: TINT_BUILD_GLSL_VALIDATOR
+################################################################################
+tint_add_target(tint_lang_glsl_validate lib
+ lang/glsl/validate/validate.cc
+ lang/glsl/validate/validate.h
+)
+
+tint_target_add_dependencies(tint_lang_glsl_validate lib
+ tint_lang_wgsl_ast
+ tint_utils_containers
+ tint_utils_diagnostic
+ tint_utils_ice
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_result
+ tint_utils_rtti
+ tint_utils_text
+ tint_utils_traits
+)
+
+if(TINT_BUILD_GLSL_WRITER)
+ tint_target_add_external_dependencies(tint_lang_glsl_validate lib
+ "glslang"
+ "glslang-res-limits"
+ )
+endif(TINT_BUILD_GLSL_WRITER)
+
+endif(TINT_BUILD_GLSL_VALIDATOR)
\ No newline at end of file
diff --git a/src/tint/lang/glsl/validate/BUILD.gn b/src/tint/lang/glsl/validate/BUILD.gn
new file mode 100644
index 0000000..944e029
--- /dev/null
+++ b/src/tint/lang/glsl/validate/BUILD.gn
@@ -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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+# tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+import("../../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+if (tint_build_glsl_validator) {
+ libtint_source_set("validate") {
+ sources = [
+ "validate.cc",
+ "validate.h",
+ ]
+ deps = [
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_glsl_writer) {
+ deps += [
+ "${tint_glslang_dir}:glslang_default_resource_limits_sources",
+ "${tint_glslang_dir}:glslang_lib_sources",
+ ]
+ }
+ }
+}
diff --git a/src/tint/lang/glsl/validate/validate.cc b/src/tint/lang/glsl/validate/validate.cc
new file mode 100644
index 0000000..8134c34
--- /dev/null
+++ b/src/tint/lang/glsl/validate/validate.cc
@@ -0,0 +1,68 @@
+// 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/lang/glsl/validate/validate.h"
+
+#include <string>
+
+#include "glslang/Public/ResourceLimits.h"
+#include "glslang/Public/ShaderLang.h"
+#include "src/tint/utils/macros/static_init.h"
+#include "src/tint/utils/text/string_stream.h"
+
+namespace tint::glsl::validate {
+
+namespace {
+
+EShLanguage PipelineStageToEshLanguage(tint::ast::PipelineStage stage) {
+ switch (stage) {
+ case tint::ast::PipelineStage::kFragment:
+ return EShLangFragment;
+ case tint::ast::PipelineStage::kVertex:
+ return EShLangVertex;
+ case tint::ast::PipelineStage::kCompute:
+ return EShLangCompute;
+ default:
+ TINT_UNREACHABLE();
+ return EShLangVertex;
+ }
+}
+
+} // namespace
+
+Result<SuccessType> Validate(const std::string& source, const EntryPointList& entry_points) {
+ TINT_STATIC_INIT(glslang::InitializeProcess());
+
+ for (auto entry_pt : entry_points) {
+ EShLanguage lang = PipelineStageToEshLanguage(entry_pt.second);
+ glslang::TShader shader(lang);
+ const char* strings[1] = {source.c_str()};
+ int lengths[1] = {static_cast<int>(source.length())};
+ shader.setStringsWithLengths(strings, lengths, 1);
+ shader.setEntryPoint("main");
+ bool result =
+ shader.parse(GetDefaultResources(), 310, EEsProfile, false, false, EShMsgDefault);
+ if (!result) {
+ StringStream err;
+ err << "Error parsing GLSL shader:\n"
+ << shader.getInfoLog() << "\n"
+ << shader.getInfoDebugLog() << "\n";
+ return Failure{err.str()};
+ }
+ }
+
+ return Success;
+}
+
+} // namespace tint::glsl::validate
diff --git a/src/tint/lang/glsl/validate/validate.h b/src/tint/lang/glsl/validate/validate.h
new file mode 100644
index 0000000..c30b23c
--- /dev/null
+++ b/src/tint/lang/glsl/validate/validate.h
@@ -0,0 +1,42 @@
+// 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_LANG_GLSL_VALIDATE_VALIDATE_H_
+#define SRC_TINT_LANG_GLSL_VALIDATE_VALIDATE_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "src/tint/lang/wgsl/ast/pipeline_stage.h"
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations
+namespace tint {
+class Program;
+} // namespace tint
+
+namespace tint::glsl::validate {
+
+using EntryPointList = std::vector<std::pair<std::string, ast::PipelineStage>>;
+
+/// Validate checks that the GLSL source passes validation.
+/// @param source the GLSL source
+/// @param entry_points the list of entry points to validate
+/// @return the result
+Result<SuccessType> Validate(const std::string& source, const EntryPointList& entry_points);
+
+} // namespace tint::glsl::validate
+
+#endif // SRC_TINT_LANG_GLSL_VALIDATE_VALIDATE_H_
diff --git a/src/tint/lang/glsl/writer/BUILD.bazel b/src/tint/lang/glsl/writer/BUILD.bazel
index a0e6bb2..19020bd 100644
--- a/src/tint/lang/glsl/writer/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/BUILD.bazel
@@ -70,13 +70,14 @@
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"writer_bench.cc",
],
deps = [
"//src/tint/api/common",
"//src/tint/api/options",
- "//src/tint/cmd/bench",
+ "//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
@@ -97,6 +98,7 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
+ "@benchmark",
] + select({
":tint_build_glsl_writer": [
"//src/tint/lang/glsl/writer",
diff --git a/src/tint/lang/glsl/writer/BUILD.cmake b/src/tint/lang/glsl/writer/BUILD.cmake
index 232ff0d..0afac03 100644
--- a/src/tint/lang/glsl/writer/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/BUILD.cmake
@@ -86,7 +86,7 @@
tint_target_add_dependencies(tint_lang_glsl_writer_bench bench
tint_api_common
tint_api_options
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
@@ -109,6 +109,10 @@
tint_utils_traits
)
+tint_target_add_external_dependencies(tint_lang_glsl_writer_bench bench
+ "google-benchmark"
+)
+
if(TINT_BUILD_GLSL_WRITER)
tint_target_add_dependencies(tint_lang_glsl_writer_bench bench
tint_lang_glsl_writer
diff --git a/src/tint/lang/glsl/writer/BUILD.gn b/src/tint/lang/glsl/writer/BUILD.gn
index 96574b1..85dbaeb 100644
--- a/src/tint/lang/glsl/writer/BUILD.gn
+++ b/src/tint/lang/glsl/writer/BUILD.gn
@@ -24,6 +24,10 @@
import("../../../../../scripts/tint_overrides_with_defaults.gni")
import("${tint_src_dir}/tint.gni")
+
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
if (tint_build_glsl_writer) {
libtint_source_set("writer") {
sources = [
@@ -67,3 +71,43 @@
}
}
}
+if (tint_build_benchmarks) {
+ if (tint_build_glsl_writer) {
+ tint_unittests_source_set("bench") {
+ sources = [ "writer_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/api/options",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_glsl_writer) {
+ deps += [
+ "${tint_src_dir}/lang/glsl/writer",
+ "${tint_src_dir}/lang/glsl/writer/common",
+ ]
+ }
+ }
+ }
+}
diff --git a/src/tint/lang/glsl/writer/ast_printer/BUILD.bazel b/src/tint/lang/glsl/writer/ast_printer/BUILD.bazel
index 23ab99f..6afad1d 100644
--- a/src/tint/lang/glsl/writer/ast_printer/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/ast_printer/BUILD.bazel
@@ -64,11 +64,6 @@
"//src/tint/lang/glsl/writer/common",
],
"//conditions:default": [],
- }) + select({
- ":tint_build_hlsl_writer": [
- "//src/tint/lang/hlsl/writer/ast_raise",
- ],
- "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -155,8 +150,3 @@
actual = "//src/tint:tint_build_glsl_writer_true",
)
-alias(
- name = "tint_build_hlsl_writer",
- actual = "//src/tint:tint_build_hlsl_writer_true",
-)
-
diff --git a/src/tint/lang/glsl/writer/ast_printer/BUILD.cmake b/src/tint/lang/glsl/writer/ast_printer/BUILD.cmake
index 80b5a82..08de69c 100644
--- a/src/tint/lang/glsl/writer/ast_printer/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/ast_printer/BUILD.cmake
@@ -68,12 +68,6 @@
)
endif(TINT_BUILD_GLSL_WRITER)
-if(TINT_BUILD_HLSL_WRITER)
- tint_target_add_dependencies(tint_lang_glsl_writer_ast_printer lib
- tint_lang_hlsl_writer_ast_raise
- )
-endif(TINT_BUILD_HLSL_WRITER)
-
endif(TINT_BUILD_GLSL_WRITER)
if(TINT_BUILD_GLSL_WRITER)
################################################################################
diff --git a/src/tint/lang/glsl/writer/ast_printer/BUILD.gn b/src/tint/lang/glsl/writer/ast_printer/BUILD.gn
index fc1c41e..cb02db6 100644
--- a/src/tint/lang/glsl/writer/ast_printer/BUILD.gn
+++ b/src/tint/lang/glsl/writer/ast_printer/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_glsl_writer) {
@@ -69,16 +69,11 @@
"${tint_src_dir}/lang/glsl/writer/common",
]
}
-
- if (tint_build_hlsl_writer) {
- deps += [ "${tint_src_dir}/lang/hlsl/writer/ast_raise" ]
- }
}
}
if (tint_build_unittests) {
if (tint_build_glsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"array_accessor_test.cc",
"assign_test.cc",
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 6bf0f92..8263553 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -38,7 +38,6 @@
#include "src/tint/lang/glsl/writer/ast_raise/texture_1d_to_2d.h"
#include "src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.h"
#include "src/tint/lang/glsl/writer/common/options.h"
-#include "src/tint/lang/hlsl/writer/ast_raise/decompose_memory_access.h"
#include "src/tint/lang/wgsl/ast/call_statement.h"
#include "src/tint/lang/wgsl/ast/id_attribute.h"
#include "src/tint/lang/wgsl/ast/internal_attribute.h"
@@ -279,7 +278,7 @@
ASTPrinter::~ASTPrinter() = default;
bool ASTPrinter::Generate() {
- if (!tint::writer::CheckSupportedExtensions(
+ if (!tint::wgsl::CheckSupportedExtensions(
"GLSL", builder_.AST(), diagnostics_,
Vector{
wgsl::Extension::kChromiumDisableUniformityAnalysis,
@@ -1535,7 +1534,7 @@
if (auto* array_index = arg(Usage::kArrayIndex)) {
// Array index needs to be appended to the coordinates.
param_coords =
- tint::writer::AppendVector(&builder_, param_coords, array_index)->Declaration();
+ tint::wgsl::AppendVector(&builder_, param_coords, array_index)->Declaration();
}
// GLSL requires Dref to be appended to the coordinates, *unless* it's
@@ -1552,8 +1551,7 @@
// append zero here.
depth_ref = CreateF32Zero(builder_.Sem().Get(param_coords)->Stmt());
}
- param_coords =
- tint::writer::AppendVector(&builder_, param_coords, depth_ref)->Declaration();
+ param_coords = tint::wgsl::AppendVector(&builder_, param_coords, depth_ref)->Declaration();
}
emit_expr_as_signed(param_coords);
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
index e0b9f70..8926b55 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
@@ -85,11 +85,8 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/ast/transform:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -109,6 +106,21 @@
"//src/tint/lang/glsl/writer/ast_raise",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/ast/transform:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -119,3 +131,29 @@
actual = "//src/tint:tint_build_glsl_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_glsl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_glsl_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.cfg b/src/tint/lang/glsl/writer/ast_raise/BUILD.cfg
index 7459430..375c295 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.cfg
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.cfg
@@ -1,3 +1,6 @@
{
- "condition": "tint_build_glsl_writer"
+ "condition": "tint_build_glsl_writer",
+ "test": {
+ "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer",
+ }
}
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
index 0666ae3..44ed836 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
@@ -66,11 +66,11 @@
)
endif(TINT_BUILD_GLSL_WRITER)
-if(TINT_BUILD_GLSL_WRITER)
+if(TINT_BUILD_GLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_glsl_writer_ast_raise_test
# Kind: test
-# Condition: TINT_BUILD_GLSL_WRITER
+# Condition: TINT_BUILD_GLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_glsl_writer_ast_raise_test test
lang/glsl/writer/ast_raise/combine_samplers_test.cc
@@ -89,11 +89,8 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
- tint_lang_wgsl_ast_transform_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -119,4 +116,22 @@
)
endif(TINT_BUILD_GLSL_WRITER)
-endif(TINT_BUILD_GLSL_WRITER)
\ No newline at end of file
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_glsl_writer_ast_raise_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_glsl_writer_ast_raise_test test
+ tint_lang_wgsl_ast_transform_test
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_glsl_writer_ast_raise_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_GLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
index 7b7a0e0..6ee810f 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_glsl_writer) {
@@ -69,9 +69,9 @@
}
}
if (tint_build_unittests) {
- if (tint_build_glsl_writer) {
+ if (tint_build_glsl_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"combine_samplers_test.cc",
"pad_structs_test.cc",
@@ -89,11 +89,8 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/ast/transform:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -112,6 +109,18 @@
if (tint_build_glsl_writer) {
deps += [ "${tint_src_dir}/lang/glsl/writer/ast_raise" ]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
}
diff --git a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
index c00f0fe3..3f5ad64 100644
--- a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
@@ -33,8 +33,8 @@
namespace {
bool IsGlobal(const tint::sem::VariablePair& pair) {
- return pair.first->Is<tint::sem::GlobalVariable>() &&
- (!pair.second || pair.second->Is<tint::sem::GlobalVariable>());
+ return (!pair.first || tint::Is<tint::sem::GlobalVariable>(pair.first)) &&
+ (!pair.second || tint::Is<tint::sem::GlobalVariable>(pair.second));
}
} // namespace
@@ -104,7 +104,9 @@
const sem::Variable* sampler_var,
std::string name) {
SamplerTexturePair bp_pair;
- bp_pair.texture_binding_point = *texture_var->As<sem::GlobalVariable>()->BindingPoint();
+ bp_pair.texture_binding_point =
+ texture_var ? *texture_var->As<sem::GlobalVariable>()->BindingPoint()
+ : binding_info->placeholder_binding_point;
bp_pair.sampler_binding_point =
sampler_var ? *sampler_var->As<sem::GlobalVariable>()->BindingPoint()
: binding_info->placeholder_binding_point;
@@ -132,16 +134,24 @@
/// Creates Identifier for a given texture and sampler variable pair.
/// Depth textures with no samplers are turned into the corresponding
/// f32 texture (e.g., texture_depth_2d -> texture_2d<f32>).
+ /// Either texture or sampler could be nullptr, but cannot be nullptr at the same time.
+ /// The texture can only be nullptr, when the sampler is a dangling function parameter.
/// @param texture the texture variable of interest
/// @param sampler the texture variable of interest
/// @returns the newly-created type
ast::Type CreateCombinedASTTypeFor(const sem::Variable* texture, const sem::Variable* sampler) {
- const core::type::Type* texture_type = texture->Type()->UnwrapRef();
- const core::type::DepthTexture* depth = texture_type->As<core::type::DepthTexture>();
- if (depth && !sampler) {
- return ctx.dst->ty.sampled_texture(depth->dim(), ctx.dst->ty.f32());
+ if (texture) {
+ const core::type::Type* texture_type = texture->Type()->UnwrapRef();
+ const core::type::DepthTexture* depth = texture_type->As<core::type::DepthTexture>();
+ if (depth && !sampler) {
+ return ctx.dst->ty.sampled_texture(depth->dim(), ctx.dst->ty.f32());
+ } else {
+ return CreateASTTypeFor(ctx, texture_type);
+ }
} else {
- return CreateASTTypeFor(ctx, texture_type);
+ TINT_ASSERT(sampler != nullptr);
+ const core::type::Type* sampler_type = sampler->Type()->UnwrapRef();
+ return CreateASTTypeFor(ctx, sampler_type);
}
}
@@ -155,9 +165,15 @@
tint::Vector<const ast::Parameter*, 8>* params) {
const sem::Variable* texture_var = pair.first;
const sem::Variable* sampler_var = pair.second;
- std::string name = texture_var->Declaration()->name->symbol.Name();
+ std::string name = "";
+ if (texture_var) {
+ name = texture_var->Declaration()->name->symbol.Name();
+ }
if (sampler_var) {
- name += "_" + sampler_var->Declaration()->name->symbol.Name();
+ if (!name.empty()) {
+ name += "_";
+ }
+ name += sampler_var->Declaration()->name->symbol.Name();
}
if (IsGlobal(pair)) {
// Both texture and sampler are global; add a new global variable
diff --git a/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc b/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc
index d408a8b..a324e24 100644
--- a/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc
@@ -982,5 +982,180 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(CombineSamplersTest, UnusedTextureFunctionParameter) {
+ auto* src = R"(
+@group(0) @binding(0) var t : texture_2d<f32>;
+
+fn f(tex: texture_2d<f32>) -> u32 {
+ return 1u;
+}
+
+fn main() {
+ _ = f(t);
+}
+)";
+ auto* expect = R"(
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
+
+fn f() -> u32 {
+ return 1u;
+}
+
+fn main() {
+ _ = f();
+}
+)";
+
+ ast::transform::DataMap data;
+ data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), BindingPoint());
+ auto got = Run<CombineSamplers>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CombineSamplersTest, UnusedSamplerFunctionParameter) {
+ auto* src = R"(
+@group(0) @binding(0) var s : sampler;
+
+fn f(sampler1: sampler) -> u32 {
+ return 1u;
+}
+
+fn main() {
+ _ = f(s);
+}
+)";
+ auto* expect = R"(
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
+
+fn f() -> u32 {
+ return 1u;
+}
+
+fn main() {
+ _ = f();
+}
+)";
+
+ ast::transform::DataMap data;
+ data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), BindingPoint());
+ auto got = Run<CombineSamplers>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CombineSamplersTest, UnusedTextureAndSamplerFunctionParameter) {
+ auto* src = R"(
+@group(0) @binding(0) var t : texture_2d<f32>;
+
+@group(0) @binding(1) var s : sampler;
+
+fn f(tex: texture_2d<f32>, sampler1: sampler) -> u32 {
+ return 1u;
+}
+
+fn main() {
+ _ = f(t, s);
+}
+)";
+ auto* expect = R"(
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
+
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
+
+fn f() -> u32 {
+ return 1u;
+}
+
+fn main() {
+ _ = f();
+}
+)";
+
+ ast::transform::DataMap data;
+ data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), BindingPoint());
+ auto got = Run<CombineSamplers>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CombineSamplersTest, UnusedTextureFunctionParameter_Multiple) {
+ auto* src = R"(
+@group(0) @binding(0) var t1 : texture_2d<f32>;
+
+@group(0) @binding(1) var t2 : texture_2d_array<f32>;
+
+@group(0) @binding(2) var s : sampler;
+
+fn f(tex1: texture_2d<f32>, tex2: texture_2d<f32>, tex3: texture_2d_array<f32>, sampler1: sampler) -> u32 {
+ return 1u + textureNumLayers(tex3);
+}
+
+fn main() {
+ _ = f(t1, t1, t2, s);
+}
+)";
+ auto* expect = R"(
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
+
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t1_1 : texture_2d<f32>;
+
+fn f(tex3_1 : texture_2d_array<f32>) -> u32 {
+ return (1u + textureNumLayers(tex3_1));
+}
+
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t2_1 : texture_2d_array<f32>;
+
+fn main() {
+ _ = f(t2_1);
+}
+)";
+
+ ast::transform::DataMap data;
+ data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), BindingPoint());
+ auto got = Run<CombineSamplers>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CombineSamplersTest, UnusedTextureFunctionParameter_Nested) {
+ auto* src = R"(
+@group(0) @binding(0) var t : texture_2d<f32>;
+
+fn f_nested(tex: texture_2d<f32>) -> u32 {
+ return 1u;
+}
+
+fn f(tex: texture_2d<f32>) -> u32 {
+ return f_nested(tex);
+}
+
+fn main() {
+ _ = f(t);
+}
+)";
+ auto* expect = R"(
+fn f_nested(tex_1 : texture_2d<f32>) -> u32 {
+ return 1u;
+}
+
+fn f(tex_2 : texture_2d<f32>) -> u32 {
+ return f_nested(tex_2);
+}
+
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
+
+fn main() {
+ _ = f(t_1);
+}
+)";
+
+ ast::transform::DataMap data;
+ data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), BindingPoint());
+ auto got = Run<CombineSamplers>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
} // namespace
} // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/ast_raise/pad_structs.cc b/src/tint/lang/glsl/writer/ast_raise/pad_structs.cc
index 8057eee..73cc410 100644
--- a/src/tint/lang/glsl/writer/ast_raise/pad_structs.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/pad_structs.cc
@@ -145,13 +145,13 @@
tint::Vector<const ast::Expression*, 8> new_args;
- auto* arg = ast_call->args.begin();
+ auto arg = ast_call->args.begin();
for (auto* member : new_struct->members) {
if (padding_members.Contains(member)) {
new_args.Push(b.Expr(0_u));
} else {
new_args.Push(ctx.Clone(*arg));
- arg++;
+ ++arg;
}
}
return b.Call(CreateASTTypeFor(ctx, str), new_args);
diff --git a/src/tint/lang/glsl/writer/writer_bench.cc b/src/tint/lang/glsl/writer/writer_bench.cc
index de9d3e6..904b4dc 100644
--- a/src/tint/lang/glsl/writer/writer_bench.cc
+++ b/src/tint/lang/glsl/writer/writer_bench.cc
@@ -24,11 +24,11 @@
void GenerateGLSL(benchmark::State& state, std::string input_name) {
auto res = bench::LoadProgram(input_name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- state.SkipWithError(err->msg.c_str());
+ if (!res) {
+ state.SkipWithError(res.Failure().reason.str());
return;
}
- auto& program = std::get<bench::ProgramAndFile>(res).program;
+ auto& program = res->program;
std::vector<std::string> entry_points;
for (auto& fn : program.AST().Functions()) {
if (fn->IsEntryPoint()) {
@@ -38,9 +38,9 @@
for (auto _ : state) {
for (auto& ep : entry_points) {
- auto res = Generate(program, {}, ep);
- if (!res) {
- state.SkipWithError(res.Failure().reason.str());
+ auto gen_res = Generate(program, {}, ep);
+ if (!gen_res) {
+ state.SkipWithError(gen_res.Failure().reason.str());
}
}
}
diff --git a/src/tint/lang/hlsl/writer/BUILD.bazel b/src/tint/lang/hlsl/writer/BUILD.bazel
index 323d038..58d4602 100644
--- a/src/tint/lang/hlsl/writer/BUILD.bazel
+++ b/src/tint/lang/hlsl/writer/BUILD.bazel
@@ -71,13 +71,14 @@
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"writer_bench.cc",
],
deps = [
"//src/tint/api/common",
"//src/tint/api/options",
- "//src/tint/cmd/bench",
+ "//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
@@ -99,6 +100,7 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
+ "@benchmark",
] + select({
":tint_build_hlsl_writer": [
"//src/tint/lang/hlsl/writer",
diff --git a/src/tint/lang/hlsl/writer/BUILD.cmake b/src/tint/lang/hlsl/writer/BUILD.cmake
index 887529b..3565fce 100644
--- a/src/tint/lang/hlsl/writer/BUILD.cmake
+++ b/src/tint/lang/hlsl/writer/BUILD.cmake
@@ -87,7 +87,7 @@
tint_target_add_dependencies(tint_lang_hlsl_writer_bench bench
tint_api_common
tint_api_options
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
@@ -111,6 +111,10 @@
tint_utils_traits
)
+tint_target_add_external_dependencies(tint_lang_hlsl_writer_bench bench
+ "google-benchmark"
+)
+
if(TINT_BUILD_HLSL_WRITER)
tint_target_add_dependencies(tint_lang_hlsl_writer_bench bench
tint_lang_hlsl_writer
diff --git a/src/tint/lang/hlsl/writer/BUILD.gn b/src/tint/lang/hlsl/writer/BUILD.gn
index b270131..5cd6f64 100644
--- a/src/tint/lang/hlsl/writer/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/BUILD.gn
@@ -24,6 +24,10 @@
import("../../../../../scripts/tint_overrides_with_defaults.gni")
import("${tint_src_dir}/tint.gni")
+
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
if (tint_build_hlsl_writer) {
libtint_source_set("writer") {
sources = [
@@ -68,3 +72,41 @@
}
}
}
+if (tint_build_benchmarks) {
+ if (tint_build_hlsl_writer) {
+ tint_unittests_source_set("bench") {
+ sources = [ "writer_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/api/options",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/hlsl/writer/common",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_hlsl_writer) {
+ deps += [ "${tint_src_dir}/lang/hlsl/writer" ]
+ }
+ }
+ }
+}
diff --git a/src/tint/lang/hlsl/writer/ast_printer/BUILD.gn b/src/tint/lang/hlsl/writer/ast_printer/BUILD.gn
index 017911b..e44df18 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/ast_printer/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_hlsl_writer) {
@@ -72,7 +72,6 @@
if (tint_build_unittests) {
if (tint_build_hlsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"array_accessor_test.cc",
"assign_test.cc",
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
index f19e36d..94c372a 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
@@ -337,7 +337,7 @@
ASTPrinter::~ASTPrinter() = default;
bool ASTPrinter::Generate() {
- if (!tint::writer::CheckSupportedExtensions(
+ if (!tint::wgsl::CheckSupportedExtensions(
"HLSL", builder_.AST(), diagnostics_,
Vector{
wgsl::Extension::kChromiumDisableUniformityAnalysis,
@@ -2842,13 +2842,13 @@
zero, i32, core::EvaluationStage::kRuntime, stmt,
/* constant_value */ nullptr,
/* has_side_effects */ false));
- auto* packed = tint::writer::AppendVector(&builder_, vector, zero);
+ auto* packed = tint::wgsl::AppendVector(&builder_, vector, zero);
return EmitExpression(out, packed->Declaration());
};
auto emit_vector_appended_with_level = [&](const ast::Expression* vector) {
if (auto* level = arg(Usage::kLevel)) {
- auto* packed = tint::writer::AppendVector(&builder_, vector, level);
+ auto* packed = tint::wgsl::AppendVector(&builder_, vector, level);
return EmitExpression(out, packed->Declaration());
}
return emit_vector_appended_with_i32_zero(vector);
@@ -2856,7 +2856,7 @@
if (auto* array_index = arg(Usage::kArrayIndex)) {
// Array index needs to be appended to the coordinates.
- auto* packed = tint::writer::AppendVector(&builder_, param_coords, array_index);
+ auto* packed = tint::wgsl::AppendVector(&builder_, param_coords, array_index);
if (pack_level_in_coords) {
// Then mip level needs to be appended to the coordinates.
if (!emit_vector_appended_with_level(packed->Declaration())) {
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
index fd49ad8..0741302 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
@@ -89,11 +89,8 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/ast/transform:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -113,6 +110,21 @@
"//src/tint/lang/hlsl/writer/ast_raise",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/ast/transform:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -123,3 +135,29 @@
actual = "//src/tint:tint_build_hlsl_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_hlsl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_hlsl_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cfg b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cfg
index 31b4636..dd6ef8b 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cfg
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cfg
@@ -1,3 +1,6 @@
{
- "condition": "tint_build_hlsl_writer"
+ "condition": "tint_build_hlsl_writer",
+ "test": {
+ "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer",
+ }
}
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
index 97916d3..d7240e6 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
@@ -69,11 +69,11 @@
)
endif(TINT_BUILD_HLSL_WRITER)
-if(TINT_BUILD_HLSL_WRITER)
+if(TINT_BUILD_HLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_hlsl_writer_ast_raise_test
# Kind: test
-# Condition: TINT_BUILD_HLSL_WRITER
+# Condition: TINT_BUILD_HLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_hlsl_writer_ast_raise_test test
lang/hlsl/writer/ast_raise/calculate_array_length_test.cc
@@ -93,11 +93,8 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
- tint_lang_wgsl_ast_transform_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -123,4 +120,22 @@
)
endif(TINT_BUILD_HLSL_WRITER)
-endif(TINT_BUILD_HLSL_WRITER)
\ No newline at end of file
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_hlsl_writer_ast_raise_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_hlsl_writer_ast_raise_test test
+ tint_lang_wgsl_ast_transform_test
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_hlsl_writer_ast_raise_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_HLSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn b/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
index 24b8ca4..8fcad6b 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_hlsl_writer) {
@@ -72,9 +72,9 @@
}
}
if (tint_build_unittests) {
- if (tint_build_hlsl_writer) {
+ if (tint_build_hlsl_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"calculate_array_length_test.cc",
"decompose_memory_access_test.cc",
@@ -93,11 +93,8 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/ast/transform:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -116,6 +113,18 @@
if (tint_build_hlsl_writer) {
deps += [ "${tint_src_dir}/lang/hlsl/writer/ast_raise" ]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
}
diff --git a/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.h b/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.h
index d98deac..ba61303 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.h
+++ b/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.h
@@ -107,8 +107,8 @@
Config& operator=(const Config&);
/// Indicate which interstage io locations are actually used by the later stage.
- /// There can be at most 16 user defined interstage variables with locations.
- std::bitset<16> interstage_locations;
+ /// There can be at most 30 user defined interstage variables with locations.
+ std::bitset<30> interstage_locations;
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
TINT_REFLECT(interstage_variables);
diff --git a/src/tint/lang/hlsl/writer/common/options.h b/src/tint/lang/hlsl/writer/common/options.h
index bca3db6..10bc497 100644
--- a/src/tint/lang/hlsl/writer/common/options.h
+++ b/src/tint/lang/hlsl/writer/common/options.h
@@ -28,6 +28,10 @@
namespace tint::hlsl::writer {
+/// kMaxInterStageLocations == D3D11_PS_INPUT_REGISTER_COUNT - 2
+/// D3D11_PS_INPUT_REGISTER_COUNT == D3D12_PS_INPUT_REGISTER_COUNT
+constexpr uint32_t kMaxInterStageLocations = 30;
+
/// Configuration options used for generating HLSL.
struct Options {
/// Constructor
@@ -58,7 +62,7 @@
/// Interstage locations actually used as inputs in the next stage of the pipeline.
/// This is potentially used for truncating unused interstage outputs at current shader stage.
- std::bitset<16> interstage_locations;
+ std::bitset<kMaxInterStageLocations> interstage_locations;
/// The binding point to use for information passed via root constants.
std::optional<BindingPoint> root_constant_binding_point;
diff --git a/src/tint/lang/hlsl/writer/writer_bench.cc b/src/tint/lang/hlsl/writer/writer_bench.cc
index 00c5d39..727e696 100644
--- a/src/tint/lang/hlsl/writer/writer_bench.cc
+++ b/src/tint/lang/hlsl/writer/writer_bench.cc
@@ -22,15 +22,14 @@
void GenerateHLSL(benchmark::State& state, std::string input_name) {
auto res = bench::LoadProgram(input_name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- state.SkipWithError(err->msg.c_str());
+ if (!res) {
+ state.SkipWithError(res.Failure().reason.str());
return;
}
- auto& program = std::get<bench::ProgramAndFile>(res).program;
for (auto _ : state) {
- auto res = Generate(program, {});
- if (!res) {
- state.SkipWithError(res.Failure().reason.str());
+ auto gen_res = Generate(res->program, {});
+ if (!gen_res) {
+ state.SkipWithError(gen_res.Failure().reason.str());
}
}
}
diff --git a/src/tint/lang/msl/validate/val.h b/src/tint/lang/msl/validate/val.h
index e9f4037..58767f1 100644
--- a/src/tint/lang/msl/validate/val.h
+++ b/src/tint/lang/msl/validate/val.h
@@ -17,7 +17,6 @@
#include <string>
#include <utility>
-#include <vector>
#include "src/tint/lang/wgsl/ast/pipeline_stage.h"
@@ -28,8 +27,6 @@
namespace tint::msl::validate {
-using EntryPointList = std::vector<std::pair<std::string, ast::PipelineStage>>;
-
/// The version of MSL to validate against.
/// Note: these must kept be in ascending order
enum class MslVersion {
diff --git a/src/tint/lang/msl/writer/BUILD.bazel b/src/tint/lang/msl/writer/BUILD.bazel
index 4348b90..098f03e 100644
--- a/src/tint/lang/msl/writer/BUILD.bazel
+++ b/src/tint/lang/msl/writer/BUILD.bazel
@@ -45,7 +45,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/reader/lower",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -68,19 +67,25 @@
"//src/tint/lang/msl/writer/printer",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"writer_bench.cc",
],
deps = [
"//src/tint/api/common",
"//src/tint/api/options",
- "//src/tint/cmd/bench",
+ "//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
@@ -101,6 +106,7 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
+ "@benchmark",
] + select({
":tint_build_msl_writer": [
"//src/tint/lang/msl/writer",
@@ -117,3 +123,8 @@
actual = "//src/tint:tint_build_msl_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/msl/writer/BUILD.cmake b/src/tint/lang/msl/writer/BUILD.cmake
index d3291bc..1e6b9f1 100644
--- a/src/tint/lang/msl/writer/BUILD.cmake
+++ b/src/tint/lang/msl/writer/BUILD.cmake
@@ -52,7 +52,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_program
tint_lang_wgsl_reader_lower
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_sem
tint_utils_containers
tint_utils_diagnostic
@@ -78,6 +77,12 @@
)
endif(TINT_BUILD_MSL_WRITER)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_msl_writer lib
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
endif(TINT_BUILD_MSL_WRITER)
if(TINT_BUILD_MSL_WRITER)
################################################################################
@@ -92,7 +97,7 @@
tint_target_add_dependencies(tint_lang_msl_writer_bench bench
tint_api_common
tint_api_options
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
@@ -115,6 +120,10 @@
tint_utils_traits
)
+tint_target_add_external_dependencies(tint_lang_msl_writer_bench bench
+ "google-benchmark"
+)
+
if(TINT_BUILD_MSL_WRITER)
tint_target_add_dependencies(tint_lang_msl_writer_bench bench
tint_lang_msl_writer
diff --git a/src/tint/lang/msl/writer/BUILD.gn b/src/tint/lang/msl/writer/BUILD.gn
index 9f13b86..b356e63 100644
--- a/src/tint/lang/msl/writer/BUILD.gn
+++ b/src/tint/lang/msl/writer/BUILD.gn
@@ -24,6 +24,10 @@
import("../../../../../scripts/tint_overrides_with_defaults.gni")
import("${tint_src_dir}/tint.gni")
+
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
if (tint_build_msl_writer) {
libtint_source_set("writer") {
sources = [
@@ -44,7 +48,6 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/reader/lower",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -69,5 +72,49 @@
"${tint_src_dir}/lang/msl/writer/printer",
]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader/program_to_ir" ]
+ }
+ }
+}
+if (tint_build_benchmarks) {
+ if (tint_build_msl_writer) {
+ tint_unittests_source_set("bench") {
+ sources = [ "writer_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/api/options",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_msl_writer) {
+ deps += [
+ "${tint_src_dir}/lang/msl/writer",
+ "${tint_src_dir}/lang/msl/writer/common",
+ ]
+ }
+ }
}
}
diff --git a/src/tint/lang/msl/writer/ast_printer/BUILD.gn b/src/tint/lang/msl/writer/ast_printer/BUILD.gn
index 072b550..2402e43 100644
--- a/src/tint/lang/msl/writer/ast_printer/BUILD.gn
+++ b/src/tint/lang/msl/writer/ast_printer/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_msl_writer) {
@@ -73,7 +73,6 @@
if (tint_build_unittests) {
if (tint_build_msl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"array_accessor_test.cc",
"assign_test.cc",
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index 254e2b2..fde3e46 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -253,7 +253,7 @@
ASTPrinter::~ASTPrinter() = default;
bool ASTPrinter::Generate() {
- if (!tint::writer::CheckSupportedExtensions(
+ if (!tint::wgsl::CheckSupportedExtensions(
"MSL", builder_.AST(), diagnostics_,
Vector{
wgsl::Extension::kChromiumDisableUniformityAnalysis,
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
index 5a68d70..cd51db5 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
@@ -83,12 +83,9 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/ast/transform:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -108,6 +105,21 @@
"//src/tint/lang/msl/writer/ast_raise",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/ast/transform:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -118,3 +130,29 @@
actual = "//src/tint:tint_build_msl_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_msl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_msl_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.cfg b/src/tint/lang/msl/writer/ast_raise/BUILD.cfg
index 1c7e256..98cff52 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.cfg
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.cfg
@@ -1,3 +1,6 @@
{
- "condition": "tint_build_msl_writer"
+ "condition": "tint_build_msl_writer",
+ "test": {
+ "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer",
+ }
}
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
index 386768b..6af7310 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
@@ -65,11 +65,11 @@
)
endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_MSL_WRITER)
+if(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_msl_writer_ast_raise_test
# Kind: test
-# Condition: TINT_BUILD_MSL_WRITER
+# Condition: TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_msl_writer_ast_raise_test test
lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param_test.cc
@@ -87,12 +87,9 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
- tint_lang_wgsl_ast_transform_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -118,4 +115,22 @@
)
endif(TINT_BUILD_MSL_WRITER)
-endif(TINT_BUILD_MSL_WRITER)
\ No newline at end of file
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
+ tint_lang_wgsl_ast_transform_test
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.gn b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
index cf231b6..b7ebdb3 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_msl_writer) {
@@ -68,9 +68,9 @@
}
}
if (tint_build_unittests) {
- if (tint_build_msl_writer) {
+ if (tint_build_msl_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"module_scope_var_to_entry_point_param_test.cc",
"packed_vec3_test.cc",
@@ -87,12 +87,9 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/ast/transform:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -111,6 +108,18 @@
if (tint_build_msl_writer) {
deps += [ "${tint_src_dir}/lang/msl/writer/ast_raise" ]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
}
diff --git a/src/tint/lang/msl/writer/common/BUILD.gn b/src/tint/lang/msl/writer/common/BUILD.gn
index 8e834d8..7938be9 100644
--- a/src/tint/lang/msl/writer/common/BUILD.gn
+++ b/src/tint/lang/msl/writer/common/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_msl_writer) {
@@ -59,7 +59,6 @@
if (tint_build_unittests) {
if (tint_build_msl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "printer_support_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/lang/msl/writer/printer/BUILD.gn b/src/tint/lang/msl/writer/printer/BUILD.gn
index cf2af5a..0c07cdf 100644
--- a/src/tint/lang/msl/writer/printer/BUILD.gn
+++ b/src/tint/lang/msl/writer/printer/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_msl_writer) {
@@ -64,7 +64,6 @@
if (tint_build_unittests) {
if (tint_build_msl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"binary_test.cc",
"constant_test.cc",
diff --git a/src/tint/lang/msl/writer/writer.cc b/src/tint/lang/msl/writer/writer.cc
index 54fffe0..92fd019 100644
--- a/src/tint/lang/msl/writer/writer.cc
+++ b/src/tint/lang/msl/writer/writer.cc
@@ -21,7 +21,10 @@
#include "src/tint/lang/msl/writer/printer/printer.h"
#include "src/tint/lang/msl/writer/raise/raise.h"
#include "src/tint/lang/wgsl/reader/lower/lower.h"
+
+#if TINT_BUILD_WGSL_READER
#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
+#endif
namespace tint::msl::writer {
@@ -33,6 +36,7 @@
Output output;
if (options.use_tint_ir) {
+#if TINT_BUILD_WGSL_READER
// Convert the AST program to an IR module.
auto converted = wgsl::reader::ProgramToIR(program);
if (!converted) {
@@ -58,6 +62,9 @@
return result.Failure();
}
output.msl = impl->Result();
+#else
+ return Failure{"use_tint_ir requires building with TINT_BUILD_WGSL_READER"};
+#endif
} else {
// Sanitize the program.
auto sanitized_result = Sanitize(program, options);
diff --git a/src/tint/lang/msl/writer/writer_bench.cc b/src/tint/lang/msl/writer/writer_bench.cc
index aa04473..712d272 100644
--- a/src/tint/lang/msl/writer/writer_bench.cc
+++ b/src/tint/lang/msl/writer/writer_bench.cc
@@ -24,11 +24,11 @@
void GenerateMSL(benchmark::State& state, std::string input_name) {
auto res = bench::LoadProgram(input_name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- state.SkipWithError(err->msg.c_str());
+ if (!res) {
+ state.SkipWithError(res.Failure().reason.str());
return;
}
- auto& program = std::get<bench::ProgramAndFile>(res).program;
+ auto& program = res->program;
tint::msl::writer::Options gen_options = {};
gen_options.array_length_from_uniform.ubo_binding = tint::BindingPoint{0, 30};
@@ -61,9 +61,9 @@
}
}
for (auto _ : state) {
- auto res = Generate(program, gen_options);
- if (!res) {
- state.SkipWithError(res.Failure().reason.str());
+ auto gen_res = Generate(program, gen_options);
+ if (!gen_res) {
+ state.SkipWithError(gen_res.Failure().reason.str());
}
}
}
diff --git a/src/tint/lang/spirv/ir/BUILD.bazel b/src/tint/lang/spirv/ir/BUILD.bazel
index c6570fc..5e02b2f 100644
--- a/src/tint/lang/spirv/ir/BUILD.bazel
+++ b/src/tint/lang/spirv/ir/BUILD.bazel
@@ -27,9 +27,11 @@
name = "ir",
srcs = [
"builtin_call.cc",
+ "literal_operand.cc",
],
hdrs = [
"builtin_call.h",
+ "literal_operand.h",
],
deps = [
"//src/tint/api/common",
diff --git a/src/tint/lang/spirv/ir/BUILD.cmake b/src/tint/lang/spirv/ir/BUILD.cmake
index e17a474..da5b68f 100644
--- a/src/tint/lang/spirv/ir/BUILD.cmake
+++ b/src/tint/lang/spirv/ir/BUILD.cmake
@@ -28,6 +28,8 @@
tint_add_target(tint_lang_spirv_ir lib
lang/spirv/ir/builtin_call.cc
lang/spirv/ir/builtin_call.h
+ lang/spirv/ir/literal_operand.cc
+ lang/spirv/ir/literal_operand.h
)
tint_target_add_dependencies(tint_lang_spirv_ir lib
diff --git a/src/tint/lang/spirv/ir/BUILD.gn b/src/tint/lang/spirv/ir/BUILD.gn
index 2a81280..588ee98 100644
--- a/src/tint/lang/spirv/ir/BUILD.gn
+++ b/src/tint/lang/spirv/ir/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -33,6 +33,8 @@
sources = [
"builtin_call.cc",
"builtin_call.h",
+ "literal_operand.cc",
+ "literal_operand.h",
]
deps = [
"${tint_src_dir}/api/common",
@@ -60,7 +62,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "builtin_call_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/cmd/bench/benchmark.cc b/src/tint/lang/spirv/ir/literal_operand.cc
similarity index 65%
copy from src/tint/cmd/bench/benchmark.cc
copy to src/tint/lang/spirv/ir/literal_operand.cc
index ad8658b..bc24878 100644
--- a/src/tint/cmd/bench/benchmark.cc
+++ b/src/tint/lang/spirv/ir/literal_operand.cc
@@ -12,9 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
-#endif
+#include "src/tint/lang/spirv/ir/literal_operand.h"
-// A placeholder symbol used to emit a symbol for this lib target.
-int tint_cmd_bench_symbol = 1;
+TINT_INSTANTIATE_TYPEINFO(tint::spirv::ir::LiteralOperand);
+
+namespace tint::spirv::ir {
+
+LiteralOperand::LiteralOperand(const core::constant::Value* value) : Base(value) {}
+
+LiteralOperand::~LiteralOperand() = default;
+
+} // namespace tint::spirv::ir
diff --git a/src/tint/lang/spirv/ir/literal_operand.h b/src/tint/lang/spirv/ir/literal_operand.h
new file mode 100644
index 0000000..cbda1e6
--- /dev/null
+++ b/src/tint/lang/spirv/ir/literal_operand.h
@@ -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.
+
+#ifndef SRC_TINT_LANG_SPIRV_IR_LITERAL_OPERAND_H_
+#define SRC_TINT_LANG_SPIRV_IR_LITERAL_OPERAND_H_
+
+#include "src/tint/lang/core/ir/constant.h"
+#include "src/tint/utils/rtti/castable.h"
+
+namespace tint::spirv::ir {
+
+/// LiteralOperand is a type of constant value that is intended to be emitted as a literal in
+/// the SPIR-V instruction stream.
+class LiteralOperand final : public Castable<LiteralOperand, core::ir::Constant> {
+ public:
+ /// Constructor
+ /// @param value the operand value
+ explicit LiteralOperand(const core::constant::Value* value);
+ /// Destructor
+ ~LiteralOperand() override;
+};
+
+} // namespace tint::spirv::ir
+
+#endif // SRC_TINT_LANG_SPIRV_IR_LITERAL_OPERAND_H_
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel b/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
index 37651a6..aabcbe3 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
@@ -83,13 +83,9 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/ast/transform:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
- "//src/tint/lang/wgsl/reader/parser",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -109,6 +105,22 @@
"//src/tint/lang/spirv/reader/ast_lower",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/parser",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/ast/transform:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -119,3 +131,29 @@
actual = "//src/tint:tint_build_spv_reader_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_spv_reader_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_spv_reader",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.cfg b/src/tint/lang/spirv/reader/ast_lower/BUILD.cfg
index a460fd5..18f78f3 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.cfg
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.cfg
@@ -1,3 +1,6 @@
{
- "condition": "tint_build_spv_reader"
+ "condition": "tint_build_spv_reader",
+ "test": {
+ "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer",
+ }
}
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake b/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
index f7a4893..3525002 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
@@ -65,11 +65,11 @@
)
endif(TINT_BUILD_SPV_READER)
-if(TINT_BUILD_SPV_READER)
+if(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_spirv_reader_ast_lower_test
# Kind: test
-# Condition: TINT_BUILD_SPV_READER
+# Condition: TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_spirv_reader_ast_lower_test test
lang/spirv/reader/ast_lower/atomics_test.cc
@@ -87,13 +87,9 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
- tint_lang_wgsl_ast_transform_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
- tint_lang_wgsl_reader_parser
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -119,4 +115,23 @@
)
endif(TINT_BUILD_SPV_READER)
-endif(TINT_BUILD_SPV_READER)
\ No newline at end of file
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_spirv_reader_ast_lower_test test
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_parser
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_reader_ast_lower_test test
+ tint_lang_wgsl_ast_transform_test
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_reader_ast_lower_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.gn b/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
index 12924c2..19ed437 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_reader) {
@@ -68,9 +68,9 @@
}
}
if (tint_build_unittests) {
- if (tint_build_spv_reader) {
+ if (tint_build_spv_reader && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"atomics_test.cc",
"decompose_strided_array_test.cc",
@@ -87,13 +87,9 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/ast/transform:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/reader/parser",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -112,6 +108,21 @@
if (tint_build_spv_reader) {
deps += [ "${tint_src_dir}/lang/spirv/reader/ast_lower" ]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/parser",
+ ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
}
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel b/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel
index 4a97ba1..70e4340 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel
@@ -138,7 +138,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer/ast_printer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/generator",
@@ -166,6 +165,11 @@
"@spirv_tools",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer/ast_printer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -181,6 +185,11 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
selects.config_setting_group(
name = "tint_build_spv_reader_or_tint_build_spv_writer",
match_any = [
@@ -189,3 +198,11 @@
],
)
+selects.config_setting_group(
+ name = "tint_build_spv_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_spv_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.cfg b/src/tint/lang/spirv/reader/ast_parser/BUILD.cfg
index a460fd5..c15bc20 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.cfg
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.cfg
@@ -1,3 +1,6 @@
{
- "condition": "tint_build_spv_reader"
+ "condition": "tint_build_spv_reader",
+ "test": {
+ "condition": "tint_build_wgsl_writer",
+ }
}
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake b/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake
index c8b5c9d..84c427f 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake
@@ -91,11 +91,11 @@
endif(TINT_BUILD_SPV_READER OR TINT_BUILD_SPV_WRITER)
endif(TINT_BUILD_SPV_READER)
-if(TINT_BUILD_SPV_READER)
+if(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_spirv_reader_ast_parser_test
# Kind: test
-# Condition: TINT_BUILD_SPV_READER
+# Condition: TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_spirv_reader_ast_parser_test test
lang/spirv/reader/ast_parser/ast_parser_test.cc
@@ -144,7 +144,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_program
tint_lang_wgsl_sem
- tint_lang_wgsl_writer_ast_printer
tint_utils_containers
tint_utils_diagnostic
tint_utils_generator
@@ -179,4 +178,10 @@
)
endif(TINT_BUILD_SPV_READER OR TINT_BUILD_SPV_WRITER)
-endif(TINT_BUILD_SPV_READER)
\ No newline at end of file
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_reader_ast_parser_test test
+ tint_lang_wgsl_writer_ast_printer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_SPV_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.gn b/src/tint/lang/spirv/reader/ast_parser/BUILD.gn
index 163e8be..d8d6256 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.gn
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_reader) {
@@ -88,15 +88,15 @@
"${tint_spirv_headers_dir}:spv_headers",
"${tint_spirv_tools_dir}:spvtools",
"${tint_spirv_tools_dir}:spvtools_opt",
+ "${tint_spirv_tools_dir}:spvtools_val",
]
}
public_configs = [ "${tint_spirv_tools_dir}/:spvtools_internal_config" ]
}
}
if (tint_build_unittests) {
- if (tint_build_spv_reader) {
+ if (tint_build_spv_reader && tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"ast_parser_test.cc",
"barrier_test.cc",
@@ -144,7 +144,6 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer/ast_printer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/generator",
@@ -172,8 +171,13 @@
"${tint_spirv_tools_dir}:spvtools_headers",
"${tint_spirv_tools_dir}:spvtools_opt",
"${tint_spirv_tools_dir}:spvtools_val",
+ "${tint_spirv_tools_dir}:spvtools_val",
]
}
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer/ast_printer" ]
+ }
public_configs = [ "${tint_spirv_tools_dir}/:spvtools_internal_config" ]
}
}
diff --git a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
index eea7fce..af55917 100644
--- a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
@@ -377,7 +377,7 @@
case spvtools::opt::analysis::Type::kArray:
return ConvertType(type_id, spirv_type->AsArray());
case spvtools::opt::analysis::Type::kStruct:
- return ConvertType(type_id, spirv_type->AsStruct());
+ return ConvertStructType(type_id);
case spvtools::opt::analysis::Type::kPointer:
return ConvertType(type_id, ptr_as, spirv_type->AsPointer());
case spvtools::opt::analysis::Type::kFunction:
@@ -1061,8 +1061,7 @@
return true;
}
-const Type* ASTParser::ConvertType(uint32_t type_id,
- const spvtools::opt::analysis::Struct* struct_ty) {
+const Type* ASTParser::ConvertStructType(uint32_t type_id) {
// Compute the struct decoration.
auto struct_decorations = this->GetDecorationsFor(type_id);
if (struct_decorations.size() == 1) {
@@ -1079,18 +1078,22 @@
return nullptr;
}
- // Compute members
- tint::Vector<const ast::StructMember*, 8> ast_members;
- const auto members = struct_ty->element_types();
- if (members.empty()) {
+ // The SPIR-V optimizer's types representation deduplicates types. We don't want that
+ // deduplication, so get the member types from the SPIR-V instruction directly.
+ const auto* inst = def_use_mgr_->GetDef(type_id);
+ auto num_members = inst->NumOperands() - 1;
+ if (num_members == 0) {
Fail() << "WGSL does not support empty structures. can't convert type: "
<< def_use_mgr_->GetDef(type_id)->PrettyPrint();
return nullptr;
}
+
+ // Compute members
+ tint::Vector<const ast::StructMember*, 8> ast_members;
TypeList ast_member_types;
unsigned num_non_writable_members = 0;
- for (uint32_t member_index = 0; member_index < members.size(); ++member_index) {
- const auto member_type_id = type_mgr_->GetId(members[member_index]);
+ for (uint32_t member_index = 0; member_index < num_members; ++member_index) {
+ const auto member_type_id = inst->GetOperand(member_index + 1).AsId();
auto* ast_member_ty = ConvertType(member_type_id);
if (ast_member_ty == nullptr) {
// Already emitted diagnostics.
@@ -1181,7 +1184,7 @@
auto sym = builder_.Symbols().Register(name);
auto* ast_struct =
create<ast::Struct>(Source{}, builder_.Ident(sym), std::move(ast_members), tint::Empty);
- if (num_non_writable_members == members.size()) {
+ if (num_non_writable_members == num_members) {
read_only_struct_types_.insert(ast_struct->name->symbol);
}
AddTypeDecl(sym, ast_struct);
diff --git a/src/tint/lang/spirv/reader/ast_parser/ast_parser.h b/src/tint/lang/spirv/reader/ast_parser/ast_parser.h
index 69aa099..4ba25f5 100644
--- a/src/tint/lang/spirv/reader/ast_parser/ast_parser.h
+++ b/src/tint/lang/spirv/reader/ast_parser/ast_parser.h
@@ -774,8 +774,7 @@
/// preserve member names, which are given by OpMemberName which is normally
/// not significant to the optimizer's module representation.
/// @param type_id the SPIR-V ID for the type.
- /// @param struct_ty the Tint type
- const Type* ConvertType(uint32_t type_id, const spvtools::opt::analysis::Struct* struct_ty);
+ const Type* ConvertStructType(uint32_t type_id);
/// Converts a specific SPIR-V type to a Tint type. Pointer / Reference case
/// The pointer to gl_PerVertex maps to nullptr, and instead is recorded
/// in member #builtin_position_.
diff --git a/src/tint/lang/spirv/reader/ast_parser/named_types_test.cc b/src/tint/lang/spirv/reader/ast_parser/named_types_test.cc
index 86c44e1..f84d2d1 100644
--- a/src/tint/lang/spirv/reader/ast_parser/named_types_test.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/named_types_test.cc
@@ -143,6 +143,91 @@
p->DeliberatelyInvalidSpirv();
}
+// Make sure that we do not deduplicate nested structures, as this will break the names used for
+// chained accessors.
+TEST_F(SpirvASTParserTest, NamedTypes_NestedStructsDifferOnlyInMemberNames) {
+ auto p = parser(test::Assemble(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpName %main "main"
+
+ OpName %FooInner "FooInner"
+ OpName %FooOuter "FooOuter"
+ OpMemberName %FooInner 0 "foo_member"
+ OpMemberName %FooOuter 0 "foo_inner"
+
+ OpName %BarInner "BarInner"
+ OpName %BarOuter "BarOuter"
+ OpMemberName %BarInner 0 "bar_member"
+ OpMemberName %BarOuter 0 "bar_inner"
+
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+
+ %FooInner = OpTypeStruct %int
+ %FooOuter = OpTypeStruct %FooInner
+
+ %BarInner = OpTypeStruct %int
+ %BarOuter = OpTypeStruct %BarInner
+
+ %FooPtr = OpTypePointer Private %FooOuter
+ %FooVar = OpVariable %FooPtr Private
+
+ %BarPtr = OpTypePointer Private %BarOuter
+ %BarVar = OpVariable %BarPtr Private
+
+ %ptr_int = OpTypePointer Private %int
+
+ %main = OpFunction %void None %3
+ %start = OpLabel
+ %access_foo = OpAccessChain %ptr_int %FooVar %int_0 %int_0
+ %access_bar = OpAccessChain %ptr_int %BarVar %int_0 %int_0
+ %fooval = OpLoad %int %access_foo
+ %barval = OpLoad %int %access_bar
+ OpReturn
+ OpFunctionEnd
+ )"));
+
+ EXPECT_TRUE(p->BuildAndParseInternalModule());
+
+ auto program = p->program();
+ EXPECT_EQ(test::ToString(program), R"(struct FooInner {
+ foo_member : i32,
+}
+
+struct FooOuter {
+ foo_inner : FooInner,
+}
+
+struct BarInner {
+ bar_member : i32,
+}
+
+struct BarOuter {
+ bar_inner : BarInner,
+}
+
+var<private> x_11 : FooOuter;
+
+var<private> x_13 : BarOuter;
+
+fn main_1() {
+ let x_18 = x_11.foo_inner.foo_member;
+ let x_19 = x_13.bar_inner.bar_member;
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn main() {
+ main_1();
+}
+)");
+}
+
// TODO(dneto): Handle arrays sized by a spec constant.
// Blocked by crbug.com/tint/32
diff --git a/src/tint/lang/spirv/writer/BUILD.bazel b/src/tint/lang/spirv/writer/BUILD.bazel
index f8d6a11..f48468d 100644
--- a/src/tint/lang/spirv/writer/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/BUILD.bazel
@@ -47,7 +47,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/reader/lower",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -75,6 +74,11 @@
"//src/tint/lang/spirv/writer/raise",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -106,7 +110,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
@@ -149,13 +152,13 @@
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"writer_bench.cc",
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
- "//src/tint/cmd/bench",
+ "//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
@@ -176,6 +179,7 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
+ "@benchmark",
] + select({
":tint_build_spv_writer": [
"//src/tint/lang/spirv/writer",
@@ -197,6 +201,11 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
selects.config_setting_group(
name = "tint_build_spv_reader_or_tint_build_spv_writer",
match_any = [
diff --git a/src/tint/lang/spirv/writer/BUILD.cmake b/src/tint/lang/spirv/writer/BUILD.cmake
index 0910cfb..5536c7c 100644
--- a/src/tint/lang/spirv/writer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/BUILD.cmake
@@ -24,6 +24,7 @@
include(lang/spirv/writer/ast_printer/BUILD.cmake)
include(lang/spirv/writer/ast_raise/BUILD.cmake)
include(lang/spirv/writer/common/BUILD.cmake)
+include(lang/spirv/writer/helpers/BUILD.cmake)
include(lang/spirv/writer/printer/BUILD.cmake)
include(lang/spirv/writer/raise/BUILD.cmake)
@@ -54,7 +55,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_program
tint_lang_wgsl_reader_lower
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_sem
tint_utils_containers
tint_utils_diagnostic
@@ -86,6 +86,12 @@
)
endif(TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_spirv_writer lib
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
endif(TINT_BUILD_SPV_WRITER)
if(TINT_BUILD_SPV_WRITER)
################################################################################
@@ -118,7 +124,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_intrinsic
@@ -175,8 +180,7 @@
tint_target_add_dependencies(tint_lang_spirv_writer_bench bench
tint_api_common
- tint_api_options
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
@@ -199,6 +203,10 @@
tint_utils_traits
)
+tint_target_add_external_dependencies(tint_lang_spirv_writer_bench bench
+ "google-benchmark"
+)
+
if(TINT_BUILD_SPV_WRITER)
tint_target_add_dependencies(tint_lang_spirv_writer_bench bench
tint_lang_spirv_writer
diff --git a/src/tint/lang/spirv/writer/BUILD.gn b/src/tint/lang/spirv/writer/BUILD.gn
index 38d4260..4587f07 100644
--- a/src/tint/lang/spirv/writer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_writer) {
@@ -50,7 +50,6 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/reader/lower",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -79,12 +78,15 @@
"${tint_src_dir}/lang/spirv/writer/raise",
]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader/program_to_ir" ]
+ }
}
}
if (tint_build_unittests) {
if (tint_build_spv_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"access_test.cc",
"atomic_builtin_test.cc",
@@ -110,7 +112,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
@@ -153,3 +154,42 @@
}
}
}
+if (tint_build_benchmarks) {
+ if (tint_build_spv_writer) {
+ tint_unittests_source_set("bench") {
+ sources = [ "writer_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_spv_writer) {
+ deps += [
+ "${tint_src_dir}/lang/spirv/writer",
+ "${tint_src_dir}/lang/spirv/writer/common",
+ ]
+ }
+ }
+ }
+}
diff --git a/src/tint/lang/spirv/writer/access_test.cc b/src/tint/lang/spirv/writer/access_test.cc
index ffdd185..967cdf5 100644
--- a/src/tint/lang/spirv/writer/access_test.cc
+++ b/src/tint/lang/spirv/writer/access_test.cc
@@ -22,11 +22,11 @@
TEST_F(SpirvWriterTest, Access_Array_Value_ConstantIndex) {
auto* arr_val = b.FunctionParam("arr", ty.array(ty.i32(), 4));
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
func->SetParams({arr_val});
b.Append(func->Block(), [&] {
auto* result = b.Access(ty.i32(), arr_val, 1_u);
- b.Return(func);
+ b.Return(func, result);
mod.SetName(result, "result");
});
@@ -35,11 +35,11 @@
}
TEST_F(SpirvWriterTest, Access_Array_Pointer_ConstantIndex) {
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
b.Append(func->Block(), [&] {
auto* arr_var = b.Var("arr", ty.ptr<function, array<i32, 4>>());
auto* result = b.Access(ty.ptr<function, i32>(), arr_var, 1_u);
- b.Return(func);
+ b.Return(func, b.Load(result));
mod.SetName(result, "result");
});
@@ -49,31 +49,31 @@
TEST_F(SpirvWriterTest, Access_Array_Pointer_DynamicIndex) {
auto* idx = b.FunctionParam("idx", ty.i32());
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
func->SetParams({idx});
b.Append(func->Block(), [&] {
auto* arr_var = b.Var("arr", ty.ptr<function, array<i32, 4>>());
auto* result = b.Access(ty.ptr<function, i32>(), arr_var, idx);
- b.Return(func);
+ b.Return(func, b.Load(result));
mod.SetName(result, "result");
});
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST(R"(
- %13 = OpBitcast %uint %idx
- %14 = OpExtInst %uint %15 UMin %13 %uint_3
- %result = OpAccessChain %_ptr_Function_int %arr %14
+ %12 = OpBitcast %uint %idx
+ %13 = OpExtInst %uint %14 UMin %12 %uint_3
+ %result = OpAccessChain %_ptr_Function_int %arr %13
)");
}
TEST_F(SpirvWriterTest, Access_Matrix_Value_ConstantIndex) {
auto* mat_val = b.FunctionParam("mat", ty.mat2x2(ty.f32()));
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.vec2<f32>());
func->SetParams({mat_val});
b.Append(func->Block(), [&] {
auto* result_vector = b.Access(ty.vec2(ty.f32()), mat_val, 1_u);
auto* result_scalar = b.Access(ty.f32(), mat_val, 1_u, 0_u);
- b.Return(func);
+ b.Return(func, b.Multiply(ty.vec2<f32>(), result_vector, result_scalar));
mod.SetName(result_vector, "result_vector");
mod.SetName(result_scalar, "result_scalar");
});
@@ -127,11 +127,11 @@
TEST_F(SpirvWriterTest, Access_Vector_Value_ConstantIndex) {
auto* vec_val = b.FunctionParam("vec", ty.vec4(ty.i32()));
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
func->SetParams({vec_val});
b.Append(func->Block(), [&] {
auto* result = b.Access(ty.i32(), vec_val, 1_u);
- b.Return(func);
+ b.Return(func, result);
mod.SetName(result, "result");
});
@@ -142,82 +142,84 @@
TEST_F(SpirvWriterTest, Access_Vector_Value_DynamicIndex) {
auto* vec_val = b.FunctionParam("vec", ty.vec4(ty.i32()));
auto* idx = b.FunctionParam("idx", ty.i32());
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
func->SetParams({vec_val, idx});
b.Append(func->Block(), [&] {
auto* result = b.Access(ty.i32(), vec_val, idx);
- b.Return(func);
+ b.Return(func, result);
mod.SetName(result, "result");
});
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST(R"(
- %10 = OpBitcast %uint %idx
- %11 = OpExtInst %uint %12 UMin %10 %uint_3
- %result = OpVectorExtractDynamic %int %vec %11
+ %9 = OpBitcast %uint %idx
+ %10 = OpExtInst %uint %11 UMin %9 %uint_3
+ %result = OpVectorExtractDynamic %int %vec %10
)");
}
TEST_F(SpirvWriterTest, Access_NestedVector_Value_DynamicIndex) {
auto* val = b.FunctionParam("arr", ty.array(ty.array(ty.vec4(ty.i32()), 4), 4));
auto* idx = b.FunctionParam("idx", ty.i32());
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
func->SetParams({val, idx});
b.Append(func->Block(), [&] {
auto* result = b.Access(ty.i32(), val, 1_u, 2_u, idx);
- b.Return(func);
+ b.Return(func, result);
mod.SetName(result, "result");
});
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST(R"(
- %13 = OpBitcast %uint %idx
- %14 = OpExtInst %uint %15 UMin %13 %uint_3
- %18 = OpCompositeExtract %v4int %arr 1 2
- %result = OpVectorExtractDynamic %int %18 %14
+ %12 = OpBitcast %uint %idx
+ %13 = OpExtInst %uint %14 UMin %12 %uint_3
+ %17 = OpCompositeExtract %v4int %arr 1 2
+ %result = OpVectorExtractDynamic %int %17 %13
)");
}
TEST_F(SpirvWriterTest, Access_Struct_Value_ConstantIndex) {
auto* str =
ty.Struct(mod.symbols.New("MyStruct"), {
- {mod.symbols.Register("a"), ty.f32()},
+ {mod.symbols.Register("a"), ty.i32()},
{mod.symbols.Register("b"), ty.vec4<i32>()},
});
auto* str_val = b.FunctionParam("str", str);
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
func->SetParams({str_val});
b.Append(func->Block(), [&] {
- auto* result_a = b.Access(ty.f32(), str_val, 0_u);
+ auto* result_a = b.Access(ty.i32(), str_val, 0_u);
auto* result_b = b.Access(ty.i32(), str_val, 1_u, 2_u);
- b.Return(func);
+ b.Return(func, b.Add(ty.i32(), result_a, result_b));
mod.SetName(result_a, "result_a");
mod.SetName(result_b, "result_b");
});
ASSERT_TRUE(Generate()) << Error() << output_;
- EXPECT_INST("%result_a = OpCompositeExtract %float %str 0");
+ EXPECT_INST("%result_a = OpCompositeExtract %int %str 0");
EXPECT_INST("%result_b = OpCompositeExtract %int %str 1 2");
}
TEST_F(SpirvWriterTest, Access_Struct_Pointer_ConstantIndex) {
auto* str =
ty.Struct(mod.symbols.New("MyStruct"), {
- {mod.symbols.Register("a"), ty.f32()},
+ {mod.symbols.Register("a"), ty.i32()},
{mod.symbols.Register("b"), ty.vec4<i32>()},
});
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.vec4<i32>());
b.Append(func->Block(), [&] {
auto* str_var = b.Var("str", ty.ptr(function, str, read_write));
- auto* result_a = b.Access(ty.ptr<function, f32>(), str_var, 0_u);
+ auto* result_a = b.Access(ty.ptr<function, i32>(), str_var, 0_u);
auto* result_b = b.Access(ty.ptr<function, vec4<i32>>(), str_var, 1_u);
- b.Return(func);
+ auto* val_a = b.Load(result_a);
+ auto* val_b = b.Load(result_b);
+ b.Return(func, b.Add(ty.vec4<i32>(), val_a, val_b));
mod.SetName(result_a, "result_a");
mod.SetName(result_b, "result_b");
});
ASSERT_TRUE(Generate()) << Error() << output_;
- EXPECT_INST("%result_a = OpAccessChain %_ptr_Function_float %str %uint_0");
+ EXPECT_INST("%result_a = OpAccessChain %_ptr_Function_int %str %uint_0");
EXPECT_INST("%result_b = OpAccessChain %_ptr_Function_v4int %str %uint_1");
}
diff --git a/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel b/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel
index 99c7cd5..22c6d85 100644
--- a/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel
@@ -109,7 +109,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
diff --git a/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake b/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake
index 46151c0..81b45cd 100644
--- a/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake
@@ -115,7 +115,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_ast_printer_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
diff --git a/src/tint/lang/spirv/writer/ast_printer/BUILD.gn b/src/tint/lang/spirv/writer/ast_printer/BUILD.gn
index 4344f94..b855543 100644
--- a/src/tint/lang/spirv/writer/ast_printer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/ast_printer/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_writer) {
@@ -79,7 +79,6 @@
if (tint_build_unittests) {
if (tint_build_spv_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"accessor_expression_test.cc",
"assign_test.cc",
@@ -113,7 +112,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/type",
diff --git a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
index fa7d322..e8d1c45 100644
--- a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
@@ -24,6 +24,7 @@
#include "src/tint/lang/spirv/writer/ast_raise/var_for_dynamic_index.h"
#include "src/tint/lang/spirv/writer/ast_raise/vectorize_matrix_conversions.h"
#include "src/tint/lang/spirv/writer/ast_raise/while_to_loop.h"
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
#include "src/tint/lang/wgsl/ast/transform/add_block_attribute.h"
#include "src/tint/lang/wgsl/ast/transform/add_empty_entry_point.h"
#include "src/tint/lang/wgsl/ast/transform/binding_remapper.h"
@@ -93,16 +94,21 @@
data.Add<ast::transform::Robustness::Config>(config);
}
+ ExternalTextureOptions external_texture_options{};
+ RemapperData remapper_data{};
+ PopulateRemapperAndMultiplanarOptions(options, remapper_data, external_texture_options);
+
// BindingRemapper must come before MultiplanarExternalTexture. Note, this is flipped to the
// other generators which run Multiplanar first and then binding remapper.
manager.Add<ast::transform::BindingRemapper>();
+
data.Add<ast::transform::BindingRemapper::Remappings>(
- options.binding_remapper_options.binding_points,
- std::unordered_map<BindingPoint, core::Access>{}, /* allow_collisions */ false);
+ remapper_data, std::unordered_map<BindingPoint, core::Access>{},
+ /* allow_collisions */ false);
// Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
data.Add<ast::transform::MultiplanarExternalTexture::NewBindingPoints>(
- options.external_texture_options.bindings_map);
+ external_texture_options.bindings_map);
manager.Add<ast::transform::MultiplanarExternalTexture>();
{ // Builtin polyfills
diff --git a/src/tint/lang/spirv/writer/ast_printer/builder.cc b/src/tint/lang/spirv/writer/ast_printer/builder.cc
index 24fca39..0ebb922 100644
--- a/src/tint/lang/spirv/writer/ast_printer/builder.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/builder.cc
@@ -260,7 +260,7 @@
Builder::~Builder() = default;
bool Builder::Build() {
- if (!tint::writer::CheckSupportedExtensions(
+ if (!tint::wgsl::CheckSupportedExtensions(
"SPIR-V", builder_.AST(), builder_.Diagnostics(),
Vector{
wgsl::Extension::kChromiumDisableUniformityAnalysis,
@@ -1223,20 +1223,24 @@
return 0;
}
-bool Builder::IsConstructorConst(const ast::Expression* expr) {
+bool Builder::IsConstructorConst(const ast::CallExpression* expr) {
bool is_const = true;
ast::TraverseExpressions(expr, [&](const ast::Expression* e) {
+ auto* val = builder_.Sem().GetVal(e);
+ if (!val) {
+ return ast::TraverseAction::Descend;
+ }
+
if (e->Is<ast::LiteralExpression>()) {
return ast::TraverseAction::Descend;
}
- if (auto* ce = e->As<ast::CallExpression>()) {
- auto* sem = builder_.Sem().Get(ce);
- if (sem->Is<sem::Materialize>()) {
+ if (e->Is<ast::CallExpression>()) {
+ if (val->Is<sem::Materialize>()) {
// Materialize can only occur on compile time expressions, so this sub-tree must be
// constant.
return ast::TraverseAction::Skip;
}
- auto* call = sem->As<sem::Call>();
+ auto* call = val->As<sem::Call>();
if (call->Target()->Is<sem::ValueConstructor>()) {
return ast::TraverseAction::Descend;
}
@@ -1949,8 +1953,6 @@
}
// Create the result matrix from the added/subtracted column vectors
- TINT_BEGIN_DISABLE_WARNING(MAYBE_UNINITIALIZED); // GCC false-positive
-
auto result_mat_id = result_op();
ops.insert(ops.begin(), result_mat_id);
ops.insert(ops.begin(), Operand(GenerateTypeIfNeeded(type)));
@@ -1958,8 +1960,6 @@
return 0;
}
- TINT_END_DISABLE_WARNING(MAYBE_UNINITIALIZED); // GCC false-positive
-
return std::get<uint32_t>(result_mat_id);
}
@@ -2754,8 +2754,8 @@
auto append_coords_to_spirv_params = [&]() -> bool {
if (auto* array_index = arg(Usage::kArrayIndex)) {
// Array index needs to be appended to the coordinates.
- auto* packed = tint::writer::AppendVector(&builder_, arg(Usage::kCoords)->Declaration(),
- array_index->Declaration());
+ auto* packed = tint::wgsl::AppendVector(&builder_, arg(Usage::kCoords)->Declaration(),
+ array_index->Declaration());
auto param = GenerateExpression(packed);
if (param == 0) {
return false;
diff --git a/src/tint/lang/spirv/writer/ast_printer/builder.h b/src/tint/lang/spirv/writer/ast_printer/builder.h
index ae4b639..78214d1 100644
--- a/src/tint/lang/spirv/writer/ast_printer/builder.h
+++ b/src/tint/lang/spirv/writer/ast_printer/builder.h
@@ -465,7 +465,7 @@
/// Determines if the given value constructor is created from constant values
/// @param expr the expression to check
/// @returns true if the constructor is constant
- bool IsConstructorConst(const ast::Expression* expr);
+ bool IsConstructorConst(const ast::CallExpression* expr);
private:
/// @returns an Operand with a new result ID in it. Increments the next_id_
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
index b68aec9..836fdc5 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
@@ -89,11 +89,8 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/ast/transform:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -113,6 +110,21 @@
"//src/tint/lang/spirv/writer/ast_raise",
],
"//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/ast/transform:test",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
}),
copts = COPTS,
visibility = ["//visibility:public"],
@@ -123,3 +135,29 @@
actual = "//src/tint:tint_build_spv_writer_true",
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_spv_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_spv_writer",
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.cfg b/src/tint/lang/spirv/writer/ast_raise/BUILD.cfg
index 0a24987..54005ef 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.cfg
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.cfg
@@ -1,3 +1,6 @@
{
- "condition": "tint_build_spv_writer"
+ "condition": "tint_build_spv_writer",
+ "test": {
+ "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer",
+ }
}
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
index b36edc2..20a5f43 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
@@ -69,11 +69,11 @@
)
endif(TINT_BUILD_SPV_WRITER)
-if(TINT_BUILD_SPV_WRITER)
+if(TINT_BUILD_SPV_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_spirv_writer_ast_raise_test
# Kind: test
-# Condition: TINT_BUILD_SPV_WRITER
+# Condition: TINT_BUILD_SPV_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_spirv_writer_ast_raise_test test
lang/spirv/writer/ast_raise/clamp_frag_depth_test.cc
@@ -93,11 +93,8 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
- tint_lang_wgsl_ast_transform_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -123,4 +120,22 @@
)
endif(TINT_BUILD_SPV_WRITER)
-endif(TINT_BUILD_SPV_WRITER)
\ No newline at end of file
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_spirv_writer_ast_raise_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_writer_ast_raise_test test
+ tint_lang_wgsl_ast_transform_test
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_writer_ast_raise_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_SPV_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
index 5ab53d5..735bb0b 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_writer) {
@@ -72,9 +72,9 @@
}
}
if (tint_build_unittests) {
- if (tint_build_spv_writer) {
+ if (tint_build_spv_writer && tint_build_wgsl_reader &&
+ tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"clamp_frag_depth_test.cc",
"for_loop_to_loop_test.cc",
@@ -93,11 +93,8 @@
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/ast/transform:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -116,6 +113,18 @@
if (tint_build_spv_writer) {
deps += [ "${tint_src_dir}/lang/spirv/writer/ast_raise" ]
}
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
}
diff --git a/src/tint/lang/spirv/writer/binary_test.cc b/src/tint/lang/spirv/writer/binary_test.cc
index 8e3fe2e..45eb416 100644
--- a/src/tint/lang/spirv/writer/binary_test.cc
+++ b/src/tint/lang/spirv/writer/binary_test.cc
@@ -408,6 +408,7 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%16 = OpConstantNull %v4int");
EXPECT_INST(R"(
; Function foo
%foo = OpFunction %v4int None %6
@@ -425,13 +426,13 @@
%rhs_0 = OpFunctionParameter %v4int
%14 = OpLabel
%15 = OpIEqual %v4bool %rhs_0 %16
- %20 = OpIEqual %v4bool %lhs_0 %21
- %23 = OpIEqual %v4bool %rhs_0 %24
- %26 = OpLogicalAnd %v4bool %20 %23
- %27 = OpLogicalOr %v4bool %15 %26
- %28 = OpSelect %v4int %27 %29 %rhs_0
- %31 = OpSDiv %v4int %lhs_0 %28
- OpReturnValue %31
+ %19 = OpIEqual %v4bool %lhs_0 %20
+ %22 = OpIEqual %v4bool %rhs_0 %23
+ %25 = OpLogicalAnd %v4bool %19 %22
+ %26 = OpLogicalOr %v4bool %15 %25
+ %27 = OpSelect %v4int %26 %28 %rhs_0
+ %30 = OpSDiv %v4int %lhs_0 %27
+ OpReturnValue %30
OpFunctionEnd
)");
}
@@ -449,6 +450,7 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%16 = OpConstantNull %v4int");
EXPECT_INST(R"(
; Function foo
%foo = OpFunction %v4int None %6
@@ -466,13 +468,13 @@
%rhs_0 = OpFunctionParameter %v4int
%14 = OpLabel
%15 = OpIEqual %v4bool %rhs_0 %16
- %20 = OpIEqual %v4bool %lhs_0 %21
- %23 = OpIEqual %v4bool %rhs_0 %24
- %26 = OpLogicalAnd %v4bool %20 %23
- %27 = OpLogicalOr %v4bool %15 %26
- %28 = OpSelect %v4int %27 %29 %rhs_0
- %31 = OpSDiv %v4int %lhs_0 %28
- OpReturnValue %31
+ %19 = OpIEqual %v4bool %lhs_0 %20
+ %22 = OpIEqual %v4bool %rhs_0 %23
+ %25 = OpLogicalAnd %v4bool %19 %22
+ %26 = OpLogicalOr %v4bool %15 %25
+ %27 = OpSelect %v4int %26 %28 %rhs_0
+ %30 = OpSDiv %v4int %lhs_0 %27
+ OpReturnValue %30
OpFunctionEnd
)");
}
@@ -570,6 +572,7 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%16 = OpConstantNull %v4int");
EXPECT_INST(R"(
; Function foo
%foo = OpFunction %v4int None %6
@@ -587,15 +590,15 @@
%rhs_0 = OpFunctionParameter %v4int
%14 = OpLabel
%15 = OpIEqual %v4bool %rhs_0 %16
- %20 = OpIEqual %v4bool %lhs_0 %21
- %23 = OpIEqual %v4bool %rhs_0 %24
- %26 = OpLogicalAnd %v4bool %20 %23
- %27 = OpLogicalOr %v4bool %15 %26
- %28 = OpSelect %v4int %27 %29 %rhs_0
- %31 = OpSDiv %v4int %lhs_0 %28
- %32 = OpIMul %v4int %31 %28
- %33 = OpISub %v4int %lhs_0 %32
- OpReturnValue %33
+ %19 = OpIEqual %v4bool %lhs_0 %20
+ %22 = OpIEqual %v4bool %rhs_0 %23
+ %25 = OpLogicalAnd %v4bool %19 %22
+ %26 = OpLogicalOr %v4bool %15 %25
+ %27 = OpSelect %v4int %26 %28 %rhs_0
+ %30 = OpSDiv %v4int %lhs_0 %27
+ %31 = OpIMul %v4int %30 %27
+ %32 = OpISub %v4int %lhs_0 %31
+ OpReturnValue %32
OpFunctionEnd
)");
}
@@ -613,6 +616,7 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%16 = OpConstantNull %v4int");
EXPECT_INST(R"(
; Function foo
%foo = OpFunction %v4int None %6
@@ -630,15 +634,15 @@
%rhs_0 = OpFunctionParameter %v4int
%14 = OpLabel
%15 = OpIEqual %v4bool %rhs_0 %16
- %20 = OpIEqual %v4bool %lhs_0 %21
- %23 = OpIEqual %v4bool %rhs_0 %24
- %26 = OpLogicalAnd %v4bool %20 %23
- %27 = OpLogicalOr %v4bool %15 %26
- %28 = OpSelect %v4int %27 %29 %rhs_0
- %31 = OpSDiv %v4int %lhs_0 %28
- %32 = OpIMul %v4int %31 %28
- %33 = OpISub %v4int %lhs_0 %32
- OpReturnValue %33
+ %19 = OpIEqual %v4bool %lhs_0 %20
+ %22 = OpIEqual %v4bool %rhs_0 %23
+ %25 = OpLogicalAnd %v4bool %19 %22
+ %26 = OpLogicalOr %v4bool %15 %25
+ %27 = OpSelect %v4int %26 %28 %rhs_0
+ %30 = OpSDiv %v4int %lhs_0 %27
+ %31 = OpIMul %v4int %30 %27
+ %32 = OpISub %v4int %lhs_0 %31
+ OpReturnValue %32
OpFunctionEnd
)");
}
diff --git a/src/tint/lang/spirv/writer/builtin_test.cc b/src/tint/lang/spirv/writer/builtin_test.cc
index ababde5..adce399 100644
--- a/src/tint/lang/spirv/writer/builtin_test.cc
+++ b/src/tint/lang/spirv/writer/builtin_test.cc
@@ -687,38 +687,38 @@
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%8 = OpConstantComposite %v2uint %uint_65535 %uint_65535");
EXPECT_INST("%13 = OpConstantComposite %v2uint %uint_16 %uint_16");
- EXPECT_INST("%15 = OpConstantComposite %v2uint %uint_0 %uint_0");
- EXPECT_INST("%19 = OpConstantComposite %v2uint %uint_16777215 %uint_16777215");
- EXPECT_INST("%22 = OpConstantComposite %v2uint %uint_8 %uint_8");
- EXPECT_INST("%26 = OpConstantComposite %v2uint %uint_268435455 %uint_268435455");
- EXPECT_INST("%29 = OpConstantComposite %v2uint %uint_4 %uint_4");
- EXPECT_INST("%33 = OpConstantComposite %v2uint %uint_1073741823 %uint_1073741823");
- EXPECT_INST("%36 = OpConstantComposite %v2uint %uint_2 %uint_2");
- EXPECT_INST("%40 = OpConstantComposite %v2uint %uint_2147483647 %uint_2147483647");
- EXPECT_INST("%43 = OpConstantComposite %v2uint %uint_1 %uint_1");
+ EXPECT_INST("%15 = OpConstantNull %v2uint");
+ EXPECT_INST("%18 = OpConstantComposite %v2uint %uint_16777215 %uint_16777215");
+ EXPECT_INST("%21 = OpConstantComposite %v2uint %uint_8 %uint_8");
+ EXPECT_INST("%25 = OpConstantComposite %v2uint %uint_268435455 %uint_268435455");
+ EXPECT_INST("%28 = OpConstantComposite %v2uint %uint_4 %uint_4");
+ EXPECT_INST("%32 = OpConstantComposite %v2uint %uint_1073741823 %uint_1073741823");
+ EXPECT_INST("%35 = OpConstantComposite %v2uint %uint_2 %uint_2");
+ EXPECT_INST("%39 = OpConstantComposite %v2uint %uint_2147483647 %uint_2147483647");
+ EXPECT_INST("%42 = OpConstantComposite %v2uint %uint_1 %uint_1");
EXPECT_INST(R"(
%7 = OpULessThanEqual %v2bool %arg %8
%12 = OpSelect %v2uint %7 %13 %15
- %17 = OpShiftLeftLogical %v2uint %arg %12
- %18 = OpULessThanEqual %v2bool %17 %19
- %21 = OpSelect %v2uint %18 %22 %15
- %24 = OpShiftLeftLogical %v2uint %17 %21
- %25 = OpULessThanEqual %v2bool %24 %26
- %28 = OpSelect %v2uint %25 %29 %15
- %31 = OpShiftLeftLogical %v2uint %24 %28
- %32 = OpULessThanEqual %v2bool %31 %33
- %35 = OpSelect %v2uint %32 %36 %15
- %38 = OpShiftLeftLogical %v2uint %31 %35
- %39 = OpULessThanEqual %v2bool %38 %40
- %42 = OpSelect %v2uint %39 %43 %15
- %45 = OpIEqual %v2bool %38 %15
- %46 = OpSelect %v2uint %45 %43 %15
- %47 = OpBitwiseOr %v2uint %42 %46
- %48 = OpBitwiseOr %v2uint %35 %47
- %49 = OpBitwiseOr %v2uint %28 %48
- %50 = OpBitwiseOr %v2uint %21 %49
- %51 = OpBitwiseOr %v2uint %12 %50
- %result = OpIAdd %v2uint %51 %46
+ %16 = OpShiftLeftLogical %v2uint %arg %12
+ %17 = OpULessThanEqual %v2bool %16 %18
+ %20 = OpSelect %v2uint %17 %21 %15
+ %23 = OpShiftLeftLogical %v2uint %16 %20
+ %24 = OpULessThanEqual %v2bool %23 %25
+ %27 = OpSelect %v2uint %24 %28 %15
+ %30 = OpShiftLeftLogical %v2uint %23 %27
+ %31 = OpULessThanEqual %v2bool %30 %32
+ %34 = OpSelect %v2uint %31 %35 %15
+ %37 = OpShiftLeftLogical %v2uint %30 %34
+ %38 = OpULessThanEqual %v2bool %37 %39
+ %41 = OpSelect %v2uint %38 %42 %15
+ %44 = OpIEqual %v2bool %37 %15
+ %45 = OpSelect %v2uint %44 %42 %15
+ %46 = OpBitwiseOr %v2uint %41 %45
+ %47 = OpBitwiseOr %v2uint %34 %46
+ %48 = OpBitwiseOr %v2uint %27 %47
+ %49 = OpBitwiseOr %v2uint %20 %48
+ %50 = OpBitwiseOr %v2uint %12 %49
+ %result = OpIAdd %v2uint %50 %45
)");
}
@@ -818,42 +818,42 @@
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%8 = OpConstantComposite %v2uint %uint_65535 %uint_65535");
- EXPECT_INST("%11 = OpConstantComposite %v2uint %uint_0 %uint_0");
- EXPECT_INST("%16 = OpConstantComposite %v2uint %uint_16 %uint_16");
- EXPECT_INST("%20 = OpConstantComposite %v2uint %uint_255 %uint_255");
- EXPECT_INST("%24 = OpConstantComposite %v2uint %uint_8 %uint_8");
- EXPECT_INST("%28 = OpConstantComposite %v2uint %uint_15 %uint_15");
- EXPECT_INST("%32 = OpConstantComposite %v2uint %uint_4 %uint_4");
- EXPECT_INST("%36 = OpConstantComposite %v2uint %uint_3 %uint_3");
- EXPECT_INST("%40 = OpConstantComposite %v2uint %uint_2 %uint_2");
- EXPECT_INST("%44 = OpConstantComposite %v2uint %uint_1 %uint_1");
+ EXPECT_INST("%11 = OpConstantNull %v2uint");
+ EXPECT_INST("%15 = OpConstantComposite %v2uint %uint_16 %uint_16");
+ EXPECT_INST("%19 = OpConstantComposite %v2uint %uint_255 %uint_255");
+ EXPECT_INST("%23 = OpConstantComposite %v2uint %uint_8 %uint_8");
+ EXPECT_INST("%27 = OpConstantComposite %v2uint %uint_15 %uint_15");
+ EXPECT_INST("%31 = OpConstantComposite %v2uint %uint_4 %uint_4");
+ EXPECT_INST("%35 = OpConstantComposite %v2uint %uint_3 %uint_3");
+ EXPECT_INST("%39 = OpConstantComposite %v2uint %uint_2 %uint_2");
+ EXPECT_INST("%43 = OpConstantComposite %v2uint %uint_1 %uint_1");
EXPECT_INST(R"(
%7 = OpBitwiseAnd %v2uint %arg %8
%10 = OpIEqual %v2bool %7 %11
- %15 = OpSelect %v2uint %10 %16 %11
- %18 = OpShiftRightLogical %v2uint %arg %15
- %19 = OpBitwiseAnd %v2uint %18 %20
- %22 = OpIEqual %v2bool %19 %11
- %23 = OpSelect %v2uint %22 %24 %11
- %26 = OpShiftRightLogical %v2uint %18 %23
- %27 = OpBitwiseAnd %v2uint %26 %28
- %30 = OpIEqual %v2bool %27 %11
- %31 = OpSelect %v2uint %30 %32 %11
- %34 = OpShiftRightLogical %v2uint %26 %31
- %35 = OpBitwiseAnd %v2uint %34 %36
- %38 = OpIEqual %v2bool %35 %11
- %39 = OpSelect %v2uint %38 %40 %11
- %42 = OpShiftRightLogical %v2uint %34 %39
- %43 = OpBitwiseAnd %v2uint %42 %44
- %46 = OpIEqual %v2bool %43 %11
- %47 = OpSelect %v2uint %46 %44 %11
- %48 = OpIEqual %v2bool %42 %11
- %49 = OpSelect %v2uint %48 %44 %11
- %50 = OpBitwiseOr %v2uint %39 %47
- %51 = OpBitwiseOr %v2uint %31 %50
- %52 = OpBitwiseOr %v2uint %23 %51
- %53 = OpBitwiseOr %v2uint %15 %52
- %result = OpIAdd %v2uint %53 %49
+ %14 = OpSelect %v2uint %10 %15 %11
+ %17 = OpShiftRightLogical %v2uint %arg %14
+ %18 = OpBitwiseAnd %v2uint %17 %19
+ %21 = OpIEqual %v2bool %18 %11
+ %22 = OpSelect %v2uint %21 %23 %11
+ %25 = OpShiftRightLogical %v2uint %17 %22
+ %26 = OpBitwiseAnd %v2uint %25 %27
+ %29 = OpIEqual %v2bool %26 %11
+ %30 = OpSelect %v2uint %29 %31 %11
+ %33 = OpShiftRightLogical %v2uint %25 %30
+ %34 = OpBitwiseAnd %v2uint %33 %35
+ %37 = OpIEqual %v2bool %34 %11
+ %38 = OpSelect %v2uint %37 %39 %11
+ %41 = OpShiftRightLogical %v2uint %33 %38
+ %42 = OpBitwiseAnd %v2uint %41 %43
+ %45 = OpIEqual %v2bool %42 %11
+ %46 = OpSelect %v2uint %45 %43 %11
+ %47 = OpIEqual %v2bool %41 %11
+ %48 = OpSelect %v2uint %47 %43 %11
+ %49 = OpBitwiseOr %v2uint %38 %46
+ %50 = OpBitwiseOr %v2uint %30 %49
+ %51 = OpBitwiseOr %v2uint %22 %50
+ %52 = OpBitwiseOr %v2uint %14 %51
+ %result = OpIAdd %v2uint %52 %48
)");
}
@@ -954,42 +954,42 @@
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%8 = OpConstantComposite %v2uint %uint_4294901760 %uint_4294901760");
- EXPECT_INST("%11 = OpConstantComposite %v2uint %uint_0 %uint_0");
- EXPECT_INST("%16 = OpConstantComposite %v2uint %uint_16 %uint_16");
- EXPECT_INST("%20 = OpConstantComposite %v2uint %uint_65280 %uint_65280");
- EXPECT_INST("%24 = OpConstantComposite %v2uint %uint_8 %uint_8");
- EXPECT_INST("%28 = OpConstantComposite %v2uint %uint_240 %uint_240");
- EXPECT_INST("%32 = OpConstantComposite %v2uint %uint_4 %uint_4");
- EXPECT_INST("%36 = OpConstantComposite %v2uint %uint_12 %uint_12");
- EXPECT_INST("%40 = OpConstantComposite %v2uint %uint_2 %uint_2");
- EXPECT_INST("%46 = OpConstantComposite %v2uint %uint_1 %uint_1");
- EXPECT_INST("%54 = OpConstantComposite %v2uint %uint_4294967295 %uint_4294967295");
+ EXPECT_INST("%11 = OpConstantNull %v2uint");
+ EXPECT_INST("%15 = OpConstantComposite %v2uint %uint_16 %uint_16");
+ EXPECT_INST("%19 = OpConstantComposite %v2uint %uint_65280 %uint_65280");
+ EXPECT_INST("%23 = OpConstantComposite %v2uint %uint_8 %uint_8");
+ EXPECT_INST("%27 = OpConstantComposite %v2uint %uint_240 %uint_240");
+ EXPECT_INST("%31 = OpConstantComposite %v2uint %uint_4 %uint_4");
+ EXPECT_INST("%35 = OpConstantComposite %v2uint %uint_12 %uint_12");
+ EXPECT_INST("%39 = OpConstantComposite %v2uint %uint_2 %uint_2");
+ EXPECT_INST("%45 = OpConstantComposite %v2uint %uint_1 %uint_1");
+ EXPECT_INST("%53 = OpConstantComposite %v2uint %uint_4294967295 %uint_4294967295");
EXPECT_INST(R"(
%7 = OpBitwiseAnd %v2uint %arg %8
%10 = OpIEqual %v2bool %7 %11
- %15 = OpSelect %v2uint %10 %11 %16
- %18 = OpShiftRightLogical %v2uint %arg %15
- %19 = OpBitwiseAnd %v2uint %18 %20
- %22 = OpIEqual %v2bool %19 %11
- %23 = OpSelect %v2uint %22 %11 %24
- %26 = OpShiftRightLogical %v2uint %18 %23
- %27 = OpBitwiseAnd %v2uint %26 %28
- %30 = OpIEqual %v2bool %27 %11
- %31 = OpSelect %v2uint %30 %11 %32
- %34 = OpShiftRightLogical %v2uint %26 %31
- %35 = OpBitwiseAnd %v2uint %34 %36
- %38 = OpIEqual %v2bool %35 %11
- %39 = OpSelect %v2uint %38 %11 %40
- %42 = OpShiftRightLogical %v2uint %34 %39
- %43 = OpBitwiseAnd %v2uint %42 %40
- %44 = OpIEqual %v2bool %43 %11
- %45 = OpSelect %v2uint %44 %11 %46
- %48 = OpBitwiseOr %v2uint %39 %45
- %49 = OpBitwiseOr %v2uint %31 %48
- %50 = OpBitwiseOr %v2uint %23 %49
- %51 = OpBitwiseOr %v2uint %15 %50
- %52 = OpIEqual %v2bool %42 %11
- %result = OpSelect %v2uint %52 %54 %51
+ %14 = OpSelect %v2uint %10 %11 %15
+ %17 = OpShiftRightLogical %v2uint %arg %14
+ %18 = OpBitwiseAnd %v2uint %17 %19
+ %21 = OpIEqual %v2bool %18 %11
+ %22 = OpSelect %v2uint %21 %11 %23
+ %25 = OpShiftRightLogical %v2uint %17 %22
+ %26 = OpBitwiseAnd %v2uint %25 %27
+ %29 = OpIEqual %v2bool %26 %11
+ %30 = OpSelect %v2uint %29 %11 %31
+ %33 = OpShiftRightLogical %v2uint %25 %30
+ %34 = OpBitwiseAnd %v2uint %33 %35
+ %37 = OpIEqual %v2bool %34 %11
+ %38 = OpSelect %v2uint %37 %11 %39
+ %41 = OpShiftRightLogical %v2uint %33 %38
+ %42 = OpBitwiseAnd %v2uint %41 %39
+ %43 = OpIEqual %v2bool %42 %11
+ %44 = OpSelect %v2uint %43 %11 %45
+ %47 = OpBitwiseOr %v2uint %38 %44
+ %48 = OpBitwiseOr %v2uint %30 %47
+ %49 = OpBitwiseOr %v2uint %22 %48
+ %50 = OpBitwiseOr %v2uint %14 %49
+ %51 = OpIEqual %v2bool %41 %11
+ %result = OpSelect %v2uint %51 %53 %50
)");
}
@@ -1087,42 +1087,42 @@
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%8 = OpConstantComposite %v2uint %uint_65535 %uint_65535");
- EXPECT_INST("%11 = OpConstantComposite %v2uint %uint_0 %uint_0");
- EXPECT_INST("%16 = OpConstantComposite %v2uint %uint_16 %uint_16");
- EXPECT_INST("%20 = OpConstantComposite %v2uint %uint_255 %uint_255");
- EXPECT_INST("%24 = OpConstantComposite %v2uint %uint_8 %uint_8");
- EXPECT_INST("%28 = OpConstantComposite %v2uint %uint_15 %uint_15");
- EXPECT_INST("%32 = OpConstantComposite %v2uint %uint_4 %uint_4");
- EXPECT_INST("%36 = OpConstantComposite %v2uint %uint_3 %uint_3");
- EXPECT_INST("%40 = OpConstantComposite %v2uint %uint_2 %uint_2");
- EXPECT_INST("%44 = OpConstantComposite %v2uint %uint_1 %uint_1");
- EXPECT_INST("%54 = OpConstantComposite %v2uint %uint_4294967295 %uint_4294967295");
+ EXPECT_INST("%11 = OpConstantNull %v2uint");
+ EXPECT_INST("%15 = OpConstantComposite %v2uint %uint_16 %uint_16");
+ EXPECT_INST("%19 = OpConstantComposite %v2uint %uint_255 %uint_255");
+ EXPECT_INST("%23 = OpConstantComposite %v2uint %uint_8 %uint_8");
+ EXPECT_INST("%27 = OpConstantComposite %v2uint %uint_15 %uint_15");
+ EXPECT_INST("%31 = OpConstantComposite %v2uint %uint_4 %uint_4");
+ EXPECT_INST("%35 = OpConstantComposite %v2uint %uint_3 %uint_3");
+ EXPECT_INST("%39 = OpConstantComposite %v2uint %uint_2 %uint_2");
+ EXPECT_INST("%43 = OpConstantComposite %v2uint %uint_1 %uint_1");
+ EXPECT_INST("%53 = OpConstantComposite %v2uint %uint_4294967295 %uint_4294967295");
EXPECT_INST(R"(
%7 = OpBitwiseAnd %v2uint %arg %8
%10 = OpIEqual %v2bool %7 %11
- %15 = OpSelect %v2uint %10 %16 %11
- %18 = OpShiftRightLogical %v2uint %arg %15
- %19 = OpBitwiseAnd %v2uint %18 %20
- %22 = OpIEqual %v2bool %19 %11
- %23 = OpSelect %v2uint %22 %24 %11
- %26 = OpShiftRightLogical %v2uint %18 %23
- %27 = OpBitwiseAnd %v2uint %26 %28
- %30 = OpIEqual %v2bool %27 %11
- %31 = OpSelect %v2uint %30 %32 %11
- %34 = OpShiftRightLogical %v2uint %26 %31
- %35 = OpBitwiseAnd %v2uint %34 %36
- %38 = OpIEqual %v2bool %35 %11
- %39 = OpSelect %v2uint %38 %40 %11
- %42 = OpShiftRightLogical %v2uint %34 %39
- %43 = OpBitwiseAnd %v2uint %42 %44
- %46 = OpIEqual %v2bool %43 %11
- %47 = OpSelect %v2uint %46 %44 %11
- %48 = OpBitwiseOr %v2uint %39 %47
- %49 = OpBitwiseOr %v2uint %31 %48
- %50 = OpBitwiseOr %v2uint %23 %49
- %51 = OpBitwiseOr %v2uint %15 %50
- %52 = OpIEqual %v2bool %42 %11
- %result = OpSelect %v2uint %52 %54 %51
+ %14 = OpSelect %v2uint %10 %15 %11
+ %17 = OpShiftRightLogical %v2uint %arg %14
+ %18 = OpBitwiseAnd %v2uint %17 %19
+ %21 = OpIEqual %v2bool %18 %11
+ %22 = OpSelect %v2uint %21 %23 %11
+ %25 = OpShiftRightLogical %v2uint %17 %22
+ %26 = OpBitwiseAnd %v2uint %25 %27
+ %29 = OpIEqual %v2bool %26 %11
+ %30 = OpSelect %v2uint %29 %31 %11
+ %33 = OpShiftRightLogical %v2uint %25 %30
+ %34 = OpBitwiseAnd %v2uint %33 %35
+ %37 = OpIEqual %v2bool %34 %11
+ %38 = OpSelect %v2uint %37 %39 %11
+ %41 = OpShiftRightLogical %v2uint %33 %38
+ %42 = OpBitwiseAnd %v2uint %41 %43
+ %45 = OpIEqual %v2bool %42 %11
+ %46 = OpSelect %v2uint %45 %43 %11
+ %47 = OpBitwiseOr %v2uint %38 %46
+ %48 = OpBitwiseOr %v2uint %30 %47
+ %49 = OpBitwiseOr %v2uint %22 %48
+ %50 = OpBitwiseOr %v2uint %14 %49
+ %51 = OpIEqual %v2bool %41 %11
+ %result = OpSelect %v2uint %51 %53 %50
)");
}
@@ -1151,11 +1151,10 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%9 = OpConstantNull %v4half");
EXPECT_INST(
- "%9 = OpConstantComposite %v4half %half_0x0p_0 %half_0x0p_0 %half_0x0p_0 %half_0x0p_0");
- EXPECT_INST(
- "%11 = OpConstantComposite %v4half %half_0x1p_0 %half_0x1p_0 %half_0x1p_0 %half_0x1p_0");
- EXPECT_INST("%result = OpExtInst %v4half %8 NClamp %arg %9 %11");
+ "%10 = OpConstantComposite %v4half %half_0x1p_0 %half_0x1p_0 %half_0x1p_0 %half_0x1p_0");
+ EXPECT_INST("%result = OpExtInst %v4half %8 NClamp %arg %9 %10");
}
// Tests for builtins with the signature: T = func(T, T)
@@ -1981,8 +1980,8 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
- EXPECT_INST("%1 = OpVariable %_ptr_StorageBuffer_tint_symbol StorageBuffer");
- EXPECT_INST("%result = OpArrayLength %uint %1 2");
+ EXPECT_INST("%var = OpVariable %_ptr_StorageBuffer_Buffer StorageBuffer");
+ EXPECT_INST("%result = OpArrayLength %uint %var 2");
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/lang/spirv/writer/common/BUILD.bazel b/src/tint/lang/spirv/writer/common/BUILD.bazel
index bf196f2..ecd94ab 100644
--- a/src/tint/lang/spirv/writer/common/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/common/BUILD.bazel
@@ -31,6 +31,7 @@
"instruction.cc",
"module.cc",
"operand.cc",
+ "option_builder.cc",
],
hdrs = [
"binary_writer.h",
@@ -38,13 +39,14 @@
"instruction.h",
"module.h",
"operand.h",
+ "option_builder.h",
"options.h",
],
deps = [
"//src/tint/api/common",
"//src/tint/api/options",
- "//src/tint/lang/core",
"//src/tint/utils/containers",
+ "//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
"//src/tint/utils/macros",
"//src/tint/utils/math",
@@ -76,7 +78,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/common/BUILD.cmake b/src/tint/lang/spirv/writer/common/BUILD.cmake
index 086cac1..dcb2f58 100644
--- a/src/tint/lang/spirv/writer/common/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/common/BUILD.cmake
@@ -38,14 +38,16 @@
lang/spirv/writer/common/module.h
lang/spirv/writer/common/operand.cc
lang/spirv/writer/common/operand.h
+ lang/spirv/writer/common/option_builder.cc
+ lang/spirv/writer/common/option_builder.h
lang/spirv/writer/common/options.h
)
tint_target_add_dependencies(tint_lang_spirv_writer_common lib
tint_api_common
tint_api_options
- tint_lang_core
tint_utils_containers
+ tint_utils_diagnostic
tint_utils_ice
tint_utils_macros
tint_utils_math
@@ -81,7 +83,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_common_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_intrinsic
diff --git a/src/tint/lang/spirv/writer/common/BUILD.gn b/src/tint/lang/spirv/writer/common/BUILD.gn
index 5c12785..becae92 100644
--- a/src/tint/lang/spirv/writer/common/BUILD.gn
+++ b/src/tint/lang/spirv/writer/common/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_writer) {
@@ -41,13 +41,15 @@
"module.h",
"operand.cc",
"operand.h",
+ "option_builder.cc",
+ "option_builder.h",
"options.h",
]
deps = [
"${tint_src_dir}/api/common",
"${tint_src_dir}/api/options",
- "${tint_src_dir}/lang/core",
"${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
"${tint_src_dir}/utils/macros",
"${tint_src_dir}/utils/math",
@@ -66,7 +68,6 @@
if (tint_build_unittests) {
if (tint_build_spv_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"binary_writer_test.cc",
"helper_test.h",
@@ -79,7 +80,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/common/module.h b/src/tint/lang/spirv/writer/common/module.h
index df95adc..bd209cc 100644
--- a/src/tint/lang/spirv/writer/common/module.h
+++ b/src/tint/lang/spirv/writer/common/module.h
@@ -17,6 +17,7 @@
#include <cstdint>
#include <functional>
+#include <string>
#include <vector>
#include "src/tint/lang/spirv/writer/common/function.h"
@@ -154,7 +155,7 @@
InstructionList annotations_;
std::vector<Function> functions_;
Hashset<uint32_t, 8> capability_set_;
- Hashset<const char*, 8> extension_set_;
+ Hashset<std::string, 8> extension_set_;
};
} // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/common/option_builder.cc b/src/tint/lang/spirv/writer/common/option_builder.cc
new file mode 100644
index 0000000..1bec1e9
--- /dev/null
+++ b/src/tint/lang/spirv/writer/common/option_builder.cc
@@ -0,0 +1,224 @@
+// 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/lang/spirv/writer/common/option_builder.h"
+
+#include "src/tint/utils/containers/hashset.h"
+
+namespace tint::spirv::writer {
+
+bool ValidateBindingOptions(const Options& options, diag::List& diagnostics) {
+ tint::Hashset<tint::BindingPoint, 8> seen_wgsl_bindings{};
+ tint::Hashset<binding::BindingInfo, 8> seen_spirv_bindings{};
+
+ auto wgsl_seen = [&diagnostics, &seen_wgsl_bindings](const tint::BindingPoint& info) -> bool {
+ if (seen_wgsl_bindings.Contains(info)) {
+ std::stringstream str;
+ str << "Found duplicate WGSL binding point: " << info;
+
+ diagnostics.add_error(diag::System::Writer, str.str());
+ return true;
+ }
+ seen_wgsl_bindings.Add(info);
+ return false;
+ };
+
+ auto spirv_seen = [&diagnostics,
+ &seen_spirv_bindings](const binding::BindingInfo& info) -> bool {
+ if (seen_spirv_bindings.Contains(info)) {
+ std::stringstream str;
+ str << "Found duplicate SPIR-V binding point: [group: " << info.group
+ << ", binding: " << info.binding << "]";
+ diagnostics.add_error(diag::System::Writer, str.str());
+ return true;
+ }
+ seen_spirv_bindings.Add(info);
+ return false;
+ };
+
+ auto valid = [&wgsl_seen, &spirv_seen](const auto& hsh) -> bool {
+ for (const auto it : hsh) {
+ const auto& src_binding = it.first;
+ const auto& dst_binding = it.second;
+
+ if (wgsl_seen(src_binding)) {
+ return false;
+ }
+
+ if (spirv_seen(dst_binding)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ if (!valid(options.bindings.uniform)) {
+ diagnostics.add_note(diag::System::Writer, "When processing uniform", {});
+ return false;
+ }
+ if (!valid(options.bindings.storage)) {
+ diagnostics.add_note(diag::System::Writer, "When processing storage", {});
+ return false;
+ }
+ if (!valid(options.bindings.texture)) {
+ diagnostics.add_note(diag::System::Writer, "When processing texture", {});
+ return false;
+ }
+ if (!valid(options.bindings.storage_texture)) {
+ diagnostics.add_note(diag::System::Writer, "When processing storage_texture", {});
+ return false;
+ }
+ if (!valid(options.bindings.sampler)) {
+ diagnostics.add_note(diag::System::Writer, "When processing sampler", {});
+ return false;
+ }
+
+ for (const auto it : options.bindings.external_texture) {
+ const auto& src_binding = it.first;
+ const auto& plane0 = it.second.plane0;
+ const auto& plane1 = it.second.plane1;
+ const auto& metadata = it.second.metadata;
+
+ // Validate with the actual source regardless of what the remapper will do
+ if (wgsl_seen(src_binding)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+
+ if (spirv_seen(plane0)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+ if (spirv_seen(plane1)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+ if (spirv_seen(metadata)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// The remapped binding data and external texture data need to coordinate in order to put things in
+// the correct place when we're done.
+//
+// When the data comes in we have a list of all WGSL origin (group,binding) pairs to SPIR-V
+// (group,binding) pairs in the `uniform`, `storage`, `texture`, and `sampler` arrays.
+//
+// The `external_texture` array stores a WGSL origin (group,binding) pair for the external textures
+// which provide `plane0`, `plane1`, and `metadata` SPIR-V (group,binding) pairs.
+//
+// If the remapper is run first, then the `external_texture` will end up being moved from the WGSL
+// point, or the SPIR-V point (or the `plane0` value). There will also, possibly, have been bindings
+// moved aside in order to place the `external_texture` bindings.
+//
+// If multiplanar runs first, care needs to be taken that when the texture is split and we create
+// `plane1` and `metadata` that they do not collide with existing bindings. If they would collide
+// then we need to place them elsewhere and have the remapper place them in the correct locations.
+//
+// # Example
+// WGSL:
+// @group(0) @binding(0) var<uniform> u: Uniforms;
+// @group(0) @binding(1) var s: sampler;
+// @group(0) @binding(2) var t: texture_external;
+//
+// Given that program, Dawn may decide to do the remappings such that:
+// * WGSL u (0, 0) -> SPIR-V (0, 1)
+// * WGSL s (0, 1) -> SPIR-V (0, 2)
+// * WGSL t (0, 2):
+// * plane0 -> SPIR-V (0, 3)
+// * plane1 -> SPIR-V (0, 4)
+// * metadata -> SPIR-V (0, 0)
+//
+// In this case, if we run binding remapper first, then tell multiplanar to look for the texture at
+// (0, 3) instead of the original (0, 2).
+//
+// If multiplanar runs first, then metadata (0, 0) needs to be placed elsewhere and then remapped
+// back to (0, 0) by the remapper. (Otherwise, we'll have two `@group(0) @binding(0)` items in the
+// program.)
+//
+// # Status
+// The below method assumes we run binding remapper first. So it will setup the binding data and
+// switch the value used by the multiplanar.
+void PopulateRemapperAndMultiplanarOptions(const Options& options,
+ RemapperData& remapper_data,
+ ExternalTextureOptions& external_texture) {
+ auto create_remappings = [&remapper_data](const auto& hsh) {
+ for (const auto it : hsh) {
+ const BindingPoint& src_binding_point = it.first;
+ const binding::Uniform& dst_binding_point = it.second;
+
+ // Bindings which go to the same slot in SPIR-V do not need to be re-bound.
+ if (src_binding_point.group == dst_binding_point.group &&
+ src_binding_point.binding == dst_binding_point.binding) {
+ continue;
+ }
+
+ remapper_data.emplace(src_binding_point,
+ BindingPoint{dst_binding_point.group, dst_binding_point.binding});
+ }
+ };
+
+ create_remappings(options.bindings.uniform);
+ create_remappings(options.bindings.storage);
+ create_remappings(options.bindings.texture);
+ create_remappings(options.bindings.storage_texture);
+ create_remappings(options.bindings.sampler);
+
+ // External textures are re-bound to their plane0 location
+ for (const auto it : options.bindings.external_texture) {
+ const BindingPoint& src_binding_point = it.first;
+ const binding::BindingInfo& plane0 = it.second.plane0;
+ const binding::BindingInfo& plane1 = it.second.plane1;
+ const binding::BindingInfo& metadata = it.second.metadata;
+
+ BindingPoint plane0_binding_point{plane0.group, plane0.binding};
+ BindingPoint plane1_binding_point{plane1.group, plane1.binding};
+ BindingPoint metadata_binding_point{metadata.group, metadata.binding};
+
+ // Use the re-bound spir-v plane0 value for the lookup key.
+ external_texture.bindings_map.emplace(
+ plane0_binding_point,
+ ExternalTextureOptions::BindingPoints{plane1_binding_point, metadata_binding_point});
+
+ // Bindings which go to the same slot in SPIR-V do not need to be re-bound.
+ if (src_binding_point.group == plane0.group &&
+ src_binding_point.binding == plane0.binding) {
+ continue;
+ }
+
+ remapper_data.emplace(src_binding_point, BindingPoint{plane0.group, plane0.binding});
+ }
+}
+
+} // namespace tint::spirv::writer
+
+namespace std {
+
+/// Custom std::hash specialization for tint::spirv::writer::binding::BindingInfo so
+/// they can be used as keys for std::unordered_map and std::unordered_set.
+template <>
+class hash<tint::spirv::writer::binding::BindingInfo> {
+ public:
+ /// @param info the binding to create a hash for
+ /// @return the hash value
+ inline std::size_t operator()(const tint::spirv::writer::binding::BindingInfo& info) const {
+ return tint::Hash(info.group, info.binding);
+ }
+};
+
+} // namespace std
diff --git a/src/tint/lang/spirv/writer/common/option_builder.h b/src/tint/lang/spirv/writer/common/option_builder.h
new file mode 100644
index 0000000..0187b48
--- /dev/null
+++ b/src/tint/lang/spirv/writer/common/option_builder.h
@@ -0,0 +1,44 @@
+// 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_LANG_SPIRV_WRITER_COMMON_OPTION_BUILDER_H_
+#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_BUILDER_H_
+
+#include <unordered_map>
+
+#include "src/tint/api/common/binding_point.h"
+#include "src/tint/api/options/external_texture.h"
+#include "src/tint/lang/spirv/writer/common/options.h"
+#include "src/tint/utils/diagnostic/diagnostic.h"
+
+namespace tint::spirv::writer {
+
+using RemapperData = std::unordered_map<BindingPoint, BindingPoint>;
+
+/// @param options the options
+/// @returns true if the binding points are valid
+bool ValidateBindingOptions(const Options& options, diag::List& diagnostics);
+
+/// Populates data from the writer options for the remapper and external texture.
+/// @param options the writer options
+/// @param remapper_data where to put the remapper data
+/// @param external_texture where to store the external texture options
+/// Note, these are populated together because there are dependencies between the two types of data.
+void PopulateRemapperAndMultiplanarOptions(const Options& options,
+ RemapperData& remapper_data,
+ ExternalTextureOptions& external_texture);
+
+} // namespace tint::spirv::writer
+
+#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_BUILDER_H_
diff --git a/src/tint/lang/spirv/writer/common/options.h b/src/tint/lang/spirv/writer/common/options.h
index 57e81e8..b18ae0b 100644
--- a/src/tint/lang/spirv/writer/common/options.h
+++ b/src/tint/lang/spirv/writer/common/options.h
@@ -15,11 +15,83 @@
#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_
#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_
-#include "src/tint/api/options/binding_remapper.h"
-#include "src/tint/api/options/external_texture.h"
+#include <unordered_map>
+
+#include "src/tint/api/common/binding_point.h"
#include "src/tint/utils/reflection/reflection.h"
namespace tint::spirv::writer {
+namespace binding {
+
+/// Generic binding point
+struct BindingInfo {
+ /// The group
+ uint32_t group = 0;
+ /// The binding
+ uint32_t binding = 0;
+
+ /// Equality operator
+ /// @param rhs the BindingInfo to compare against
+ /// @returns true if this BindingInfo is equal to `rhs`
+ inline bool operator==(const BindingInfo& rhs) const {
+ return group == rhs.group && binding == rhs.binding;
+ }
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(group, binding);
+};
+using Uniform = BindingInfo;
+using Storage = BindingInfo;
+using Texture = BindingInfo;
+using StorageTexture = BindingInfo;
+using Sampler = BindingInfo;
+
+/// An external texture
+struct ExternalTexture {
+ /// Metadata
+ BindingInfo metadata{};
+ /// Plane0 binding data
+ BindingInfo plane0{};
+ /// Plane1 binding data
+ BindingInfo plane1{};
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(metadata, plane0, plane1);
+};
+
+} // namespace binding
+
+// Maps the WGSL binding point to the SPIR-V group,binding for uniforms
+using UniformBindings = std::unordered_map<BindingPoint, binding::Uniform>;
+// Maps the WGSL binding point to the SPIR-V group,binding for storage
+using StorageBindings = std::unordered_map<BindingPoint, binding::Storage>;
+// Maps the WGSL binding point to the SPIR-V group,binding for textures
+using TextureBindings = std::unordered_map<BindingPoint, binding::Texture>;
+// Maps the WGSL binding point to the SPIR-V group,binding for storage textures
+using StorageTextureBindings = std::unordered_map<BindingPoint, binding::StorageTexture>;
+// Maps the WGSL binding point to the SPIR-V group,binding for samplers
+using SamplerBindings = std::unordered_map<BindingPoint, binding::Sampler>;
+// Maps the WGSL binding point to the plane0, plane1, and metadata information for external textures
+using ExternalTextureBindings = std::unordered_map<BindingPoint, binding::ExternalTexture>;
+
+/// Binding information
+struct Bindings {
+ /// Uniform bindings
+ UniformBindings uniform{};
+ /// Storage bindings
+ StorageBindings storage{};
+ /// Texture bindings
+ TextureBindings texture{};
+ /// Storage texture bindings
+ StorageTextureBindings storage_texture{};
+ /// Sampler bindings
+ SamplerBindings sampler{};
+ /// External bindings
+ ExternalTextureBindings external_texture{};
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(uniform, storage, texture, sampler, external_texture);
+};
/// Configuration options used for generating SPIR-V.
struct Options {
@@ -46,20 +118,20 @@
/// Set to `true` to clamp frag depth
bool clamp_frag_depth = false;
+ /// Set to `true` to always pass matrices to user functions by pointer instead of by value.
+ bool pass_matrix_by_pointer = false;
+
/// Set to `true` to generate SPIR-V via the Tint IR instead of from the AST.
bool use_tint_ir = false;
- /// Options used in the binding mappings for external textures
- ExternalTextureOptions external_texture_options = {};
-
- /// Options used in the bindings remapper
- BindingRemapperOptions binding_remapper_options = {};
-
/// Set to `true` to require `SPV_KHR_subgroup_uniform_control_flow` extension and
/// `SubgroupUniformControlFlowKHR` execution mode for compute stage entry points in generated
/// SPIRV module. Issue: dawn:464
bool experimental_require_subgroup_uniform_control_flow = false;
+ /// The bindings
+ Bindings bindings;
+
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
TINT_REFLECT(disable_robustness,
disable_image_robustness,
@@ -69,9 +141,8 @@
emit_vertex_point_size,
clamp_frag_depth,
use_tint_ir,
- external_texture_options,
- binding_remapper_options,
- experimental_require_subgroup_uniform_control_flow);
+ experimental_require_subgroup_uniform_control_flow,
+ bindings);
};
} // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/constant_test.cc b/src/tint/lang/spirv/writer/constant_test.cc
index e54f8ef..1241487 100644
--- a/src/tint/lang/spirv/writer/constant_test.cc
+++ b/src/tint/lang/spirv/writer/constant_test.cc
@@ -148,6 +148,12 @@
)");
}
+TEST_F(SpirvWriterTest, Constant_Array_LargeAllZero) {
+ writer_.Constant(b.Zero(ty.array<i32, 65535>()));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantNull %_arr_int_uint_65535");
+}
+
TEST_F(SpirvWriterTest, Constant_Struct) {
auto* str_ty = ty.Struct(mod.symbols.New("MyStruct"), {
{mod.symbols.New("a"), ty.i32()},
diff --git a/src/tint/lang/spirv/writer/convert_test.cc b/src/tint/lang/spirv/writer/convert_test.cc
index 10fb71a..6775c9d 100644
--- a/src/tint/lang/spirv/writer/convert_test.cc
+++ b/src/tint/lang/spirv/writer/convert_test.cc
@@ -80,14 +80,12 @@
ConvertCase{kBool, kF16, "OpSelect", "half"},
// To i32.
- ConvertCase{kF32, kI32, "OpConvertFToS", "int"},
- ConvertCase{kF16, kI32, "OpConvertFToS", "int"},
+ // Note: ftoi cases are polyfilled and tested separately.
ConvertCase{kU32, kI32, "OpBitcast", "int"},
ConvertCase{kBool, kI32, "OpSelect", "int"},
// To u32.
- ConvertCase{kF32, kU32, "OpConvertFToU", "uint"},
- ConvertCase{kF16, kU32, "OpConvertFToU", "uint"},
+ // Note: ftoi cases are polyfilled and tested separately.
ConvertCase{kI32, kU32, "OpBitcast", "uint"},
ConvertCase{kBool, kU32, "OpSelect", "uint"},
@@ -140,5 +138,309 @@
)");
}
+TEST_F(SpirvWriterTest, Convert_F32_to_I32) {
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({b.FunctionParam("arg", ty.f32())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.i32(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ ; Function foo
+ %foo = OpFunction %int None %5
+ %arg = OpFunctionParameter %float
+ %6 = OpLabel
+ %result = OpFunctionCall %int %tint_f32_to_i32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_f32_to_i32
+%tint_f32_to_i32 = OpFunction %int None %5
+ %value = OpFunctionParameter %float
+ %10 = OpLabel
+ %11 = OpConvertFToS %int %value
+ %12 = OpFOrdGreaterThanEqual %bool %value %float_n2_14748365e_09
+ %15 = OpSelect %int %12 %11 %int_n2147483648
+ %17 = OpFOrdLessThanEqual %bool %value %float_2_14748352e_09
+ %19 = OpSelect %int %17 %15 %int_2147483647
+ OpReturnValue %19
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F32_to_U32) {
+ auto* func = b.Function("foo", ty.u32());
+ func->SetParams({b.FunctionParam("arg", ty.f32())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.u32(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ ; Function foo
+ %foo = OpFunction %uint None %5
+ %arg = OpFunctionParameter %float
+ %6 = OpLabel
+ %result = OpFunctionCall %uint %tint_f32_to_u32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_f32_to_u32
+%tint_f32_to_u32 = OpFunction %uint None %5
+ %value = OpFunctionParameter %float
+ %10 = OpLabel
+ %11 = OpConvertFToU %uint %value
+ %12 = OpFOrdGreaterThanEqual %bool %value %float_0
+ %15 = OpSelect %uint %12 %11 %uint_0
+ %17 = OpFOrdLessThanEqual %bool %value %float_4_29496704e_09
+ %19 = OpSelect %uint %17 %15 %uint_4294967295
+ OpReturnValue %19
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F16_to_I32) {
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({b.FunctionParam("arg", ty.f16())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.i32(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ ; Function foo
+ %foo = OpFunction %int None %5
+ %arg = OpFunctionParameter %half
+ %6 = OpLabel
+ %result = OpFunctionCall %int %tint_f16_to_i32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_f16_to_i32
+%tint_f16_to_i32 = OpFunction %int None %5
+ %value = OpFunctionParameter %half
+ %10 = OpLabel
+ %11 = OpConvertFToS %int %value
+ %12 = OpFOrdGreaterThanEqual %bool %value %half_n0x1_ffcp_15
+ %15 = OpSelect %int %12 %11 %int_n2147483648
+ %17 = OpFOrdLessThanEqual %bool %value %half_0x1_ffcp_15
+ %19 = OpSelect %int %17 %15 %int_2147483647
+ OpReturnValue %19
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F16_to_U32) {
+ auto* func = b.Function("foo", ty.u32());
+ func->SetParams({b.FunctionParam("arg", ty.f16())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.u32(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ ; Function foo
+ %foo = OpFunction %uint None %5
+ %arg = OpFunctionParameter %half
+ %6 = OpLabel
+ %result = OpFunctionCall %uint %tint_f16_to_u32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_f16_to_u32
+%tint_f16_to_u32 = OpFunction %uint None %5
+ %value = OpFunctionParameter %half
+ %10 = OpLabel
+ %11 = OpConvertFToU %uint %value
+ %12 = OpFOrdGreaterThanEqual %bool %value %half_0x0p_0
+ %15 = OpSelect %uint %12 %11 %uint_0
+ %17 = OpFOrdLessThanEqual %bool %value %half_0x1_ffcp_15
+ %19 = OpSelect %uint %17 %15 %uint_4294967295
+ OpReturnValue %19
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F32_to_I32_Vec2) {
+ auto* func = b.Function("foo", ty.vec2<i32>());
+ func->SetParams({b.FunctionParam("arg", ty.vec2<f32>())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.vec2<i32>(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+%float_n2_14748365e_09 = OpConstant %float -2.14748365e+09
+ %15 = OpConstantComposite %v2float %float_n2_14748365e_09 %float_n2_14748365e_09
+ %bool = OpTypeBool
+ %v2bool = OpTypeVector %bool 2
+%int_n2147483648 = OpConstant %int -2147483648
+ %20 = OpConstantComposite %v2int %int_n2147483648 %int_n2147483648
+%float_2_14748352e_09 = OpConstant %float 2.14748352e+09
+ %23 = OpConstantComposite %v2float %float_2_14748352e_09 %float_2_14748352e_09
+%int_2147483647 = OpConstant %int 2147483647
+ %26 = OpConstantComposite %v2int %int_2147483647 %int_2147483647
+ %void = OpTypeVoid
+ %30 = OpTypeFunction %void
+
+ ; Function foo
+ %foo = OpFunction %v2int None %7
+ %arg = OpFunctionParameter %v2float
+ %8 = OpLabel
+ %result = OpFunctionCall %v2int %tint_v2f32_to_v2i32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_v2f32_to_v2i32
+%tint_v2f32_to_v2i32 = OpFunction %v2int None %7
+ %value = OpFunctionParameter %v2float
+ %12 = OpLabel
+ %13 = OpConvertFToS %v2int %value
+ %14 = OpFOrdGreaterThanEqual %v2bool %value %15
+ %19 = OpSelect %v2int %14 %13 %20
+ %22 = OpFOrdLessThanEqual %v2bool %value %23
+ %25 = OpSelect %v2int %22 %19 %26
+ OpReturnValue %25
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F32_to_U32_Vec3) {
+ auto* func = b.Function("foo", ty.vec3<u32>());
+ func->SetParams({b.FunctionParam("arg", ty.vec3<f32>())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.vec3<u32>(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+%float_4_29496704e_09 = OpConstant %float 4.29496704e+09
+ %21 = OpConstantComposite %v3float %float_4_29496704e_09 %float_4_29496704e_09 %float_4_29496704e_09
+%uint_4294967295 = OpConstant %uint 4294967295
+ %24 = OpConstantComposite %v3uint %uint_4294967295 %uint_4294967295 %uint_4294967295
+ %void = OpTypeVoid
+ %28 = OpTypeFunction %void
+
+ ; Function foo
+ %foo = OpFunction %v3uint None %7
+ %arg = OpFunctionParameter %v3float
+ %8 = OpLabel
+ %result = OpFunctionCall %v3uint %tint_v3f32_to_v3u32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_v3f32_to_v3u32
+%tint_v3f32_to_v3u32 = OpFunction %v3uint None %7
+ %value = OpFunctionParameter %v3float
+ %12 = OpLabel
+ %13 = OpConvertFToU %v3uint %value
+ %14 = OpFOrdGreaterThanEqual %v3bool %value %15
+ %18 = OpSelect %v3uint %14 %13 %19
+ %20 = OpFOrdLessThanEqual %v3bool %value %21
+ %23 = OpSelect %v3uint %20 %18 %24
+ OpReturnValue %23
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F16_to_I32_Vec2) {
+ auto* func = b.Function("foo", ty.vec2<i32>());
+ func->SetParams({b.FunctionParam("arg", ty.vec2<f16>())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.vec2<i32>(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+%half_n0x1_ffcp_15 = OpConstant %half -0x1.ffcp+15
+ %15 = OpConstantComposite %v2half %half_n0x1_ffcp_15 %half_n0x1_ffcp_15
+ %bool = OpTypeBool
+ %v2bool = OpTypeVector %bool 2
+%int_n2147483648 = OpConstant %int -2147483648
+ %20 = OpConstantComposite %v2int %int_n2147483648 %int_n2147483648
+%half_0x1_ffcp_15 = OpConstant %half 0x1.ffcp+15
+ %23 = OpConstantComposite %v2half %half_0x1_ffcp_15 %half_0x1_ffcp_15
+%int_2147483647 = OpConstant %int 2147483647
+ %26 = OpConstantComposite %v2int %int_2147483647 %int_2147483647
+ %void = OpTypeVoid
+ %30 = OpTypeFunction %void
+
+ ; Function foo
+ %foo = OpFunction %v2int None %7
+ %arg = OpFunctionParameter %v2half
+ %8 = OpLabel
+ %result = OpFunctionCall %v2int %tint_v2f16_to_v2i32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_v2f16_to_v2i32
+%tint_v2f16_to_v2i32 = OpFunction %v2int None %7
+ %value = OpFunctionParameter %v2half
+ %12 = OpLabel
+ %13 = OpConvertFToS %v2int %value
+ %14 = OpFOrdGreaterThanEqual %v2bool %value %15
+ %19 = OpSelect %v2int %14 %13 %20
+ %22 = OpFOrdLessThanEqual %v2bool %value %23
+ %25 = OpSelect %v2int %22 %19 %26
+ OpReturnValue %25
+ OpFunctionEnd
+)");
+}
+
+TEST_F(SpirvWriterTest, Convert_F16_to_U32_Vec4) {
+ auto* func = b.Function("foo", ty.vec4<u32>());
+ func->SetParams({b.FunctionParam("arg", ty.vec4<f16>())});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Convert(ty.vec4<u32>(), func->Params()[0]);
+ b.Return(func, result);
+ mod.SetName(result, "result");
+ });
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+%half_0x1_ffcp_15 = OpConstant %half 0x1.ffcp+15
+ %21 = OpConstantComposite %v4half %half_0x1_ffcp_15 %half_0x1_ffcp_15 %half_0x1_ffcp_15 %half_0x1_ffcp_15
+%uint_4294967295 = OpConstant %uint 4294967295
+ %24 = OpConstantComposite %v4uint %uint_4294967295 %uint_4294967295 %uint_4294967295 %uint_4294967295
+ %void = OpTypeVoid
+ %28 = OpTypeFunction %void
+
+ ; Function foo
+ %foo = OpFunction %v4uint None %7
+ %arg = OpFunctionParameter %v4half
+ %8 = OpLabel
+ %result = OpFunctionCall %v4uint %tint_v4f16_to_v4u32 %arg
+ OpReturnValue %result
+ OpFunctionEnd
+
+ ; Function tint_v4f16_to_v4u32
+%tint_v4f16_to_v4u32 = OpFunction %v4uint None %7
+ %value = OpFunctionParameter %v4half
+ %12 = OpLabel
+ %13 = OpConvertFToU %v4uint %value
+ %14 = OpFOrdGreaterThanEqual %v4bool %value %15
+ %18 = OpSelect %v4uint %14 %13 %19
+ %20 = OpFOrdLessThanEqual %v4bool %value %21
+ %23 = OpSelect %v4uint %20 %18 %24
+ OpReturnValue %23
+ OpFunctionEnd
+)");
+}
+
} // namespace
} // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/function_test.cc b/src/tint/lang/spirv/writer/function_test.cc
index dcbb23c..ab34b60 100644
--- a/src/tint/lang/spirv/writer/function_test.cc
+++ b/src/tint/lang/spirv/writer/function_test.cc
@@ -346,29 +346,98 @@
});
ASSERT_TRUE(Generate()) << Error() << output_;
- EXPECT_INST(R"(OpEntryPoint Fragment %main "main" %main_loc0_Output %main_loc0_Output_0)");
+ EXPECT_INST(
+ R"(OpEntryPoint Fragment %main "main" %main_loc0_idx0_Output %main_loc0_idx1_Output)");
EXPECT_INST(R"(
- OpDecorate %main_loc0_Output Location 0
- OpDecorate %main_loc0_Output Index 0
- OpDecorate %main_loc0_Output_0 Location 0
- OpDecorate %main_loc0_Output_0 Index 1
+ OpDecorate %main_loc0_idx0_Output Location 0
+ OpDecorate %main_loc0_idx0_Output Index 0
+ OpDecorate %main_loc0_idx1_Output Location 0
+ OpDecorate %main_loc0_idx1_Output Index 1
)");
EXPECT_INST(R"(
-%main_loc0_Output = OpVariable %_ptr_Output_float Output
-%main_loc0_Output_0 = OpVariable %_ptr_Output_float Output
+%main_loc0_idx0_Output = OpVariable %_ptr_Output_float Output
+%main_loc0_idx1_Output = OpVariable %_ptr_Output_float Output
)");
EXPECT_INST(R"(
%main = OpFunction %void None %14
%15 = OpLabel
%16 = OpFunctionCall %Outputs %main_inner
%17 = OpCompositeExtract %float %16 0
- OpStore %main_loc0_Output %17
+ OpStore %main_loc0_idx0_Output %17
%18 = OpCompositeExtract %float %16 1
- OpStore %main_loc0_Output_0 %18
+ OpStore %main_loc0_idx1_Output %18
OpReturn
OpFunctionEnd
)");
}
+TEST_F(SpirvWriterTest, Function_PassMatrixByPointer) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* arr = mod.root_block->Append(b.Var("var", ty.ptr(private_, ty.array(mat_ty, 4))));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value_a = b.FunctionParam("value_a", mat_ty);
+ auto* scalar = b.FunctionParam("scalar", ty.f32());
+ auto* value_b = b.FunctionParam("value_b", mat_ty);
+ target->SetParams({value_a, scalar, value_b});
+ b.Append(target->Block(), [&] {
+ auto* scale = b.Multiply(mat_ty, value_a, scalar);
+ auto* sum = b.Add(mat_ty, scale, value_b);
+ b.Return(target, sum);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* mat_ptr = ty.ptr(private_, mat_ty);
+ auto* ma = b.Load(b.Access(mat_ptr, arr, 0_u));
+ auto* mb = b.Load(b.Access(mat_ptr, arr, 1_u));
+ auto* result = b.Call(mat_ty, target, ma, b.Constant(2_f), mb);
+ b.Return(caller, result);
+ });
+
+ Options options;
+ options.pass_matrix_by_pointer = true;
+ ASSERT_TRUE(Generate(options)) << Error() << output_;
+
+ EXPECT_INST(R"(
+ ; Function target
+ %target = OpFunction %mat3v3float None %15
+ %12 = OpFunctionParameter %_ptr_Function_mat3v3float
+ %scalar = OpFunctionParameter %float
+ %14 = OpFunctionParameter %_ptr_Function_mat3v3float
+ %16 = OpLabel
+ %17 = OpLoad %mat3v3float %14
+ %18 = OpLoad %mat3v3float %12
+ %19 = OpMatrixTimesScalar %mat3v3float %18 %scalar
+ %20 = OpCompositeExtract %v3float %19 0
+ %21 = OpCompositeExtract %v3float %17 0
+ %22 = OpFAdd %v3float %20 %21
+ %23 = OpCompositeExtract %v3float %19 1
+ %24 = OpCompositeExtract %v3float %17 1
+ %25 = OpFAdd %v3float %23 %24
+ %26 = OpCompositeExtract %v3float %19 2
+ %27 = OpCompositeExtract %v3float %17 2
+ %28 = OpFAdd %v3float %26 %27
+ %29 = OpCompositeConstruct %mat3v3float %22 %25 %28
+ OpReturnValue %29
+ OpFunctionEnd
+
+ ; Function caller
+ %caller = OpFunction %mat3v3float None %31
+ %32 = OpLabel
+ %40 = OpVariable %_ptr_Function_mat3v3float Function
+ %41 = OpVariable %_ptr_Function_mat3v3float Function
+ %33 = OpAccessChain %_ptr_Private_mat3v3float %var %uint_0
+ %36 = OpLoad %mat3v3float %33
+ %37 = OpAccessChain %_ptr_Private_mat3v3float %var %uint_1
+ %39 = OpLoad %mat3v3float %37
+ OpStore %40 %36
+ OpStore %41 %39
+ %42 = OpFunctionCall %mat3v3float %target %40 %float_2 %41
+ OpReturnValue %42
+ OpFunctionEnd
+)");
+}
+
} // namespace
} // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.bazel b/src/tint/lang/spirv/writer/helpers/BUILD.bazel
new file mode 100644
index 0000000..190110b
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.bazel
@@ -0,0 +1,70 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+cc_library(
+ name = "helpers",
+ srcs = [
+ "generate_bindings.cc",
+ ],
+ hdrs = [
+ "generate_bindings.h",
+ ],
+ deps = [
+ "//src/tint/api/common",
+ "//src/tint/lang/core",
+ "//src/tint/lang/core/constant",
+ "//src/tint/lang/core/type",
+ "//src/tint/lang/wgsl",
+ "//src/tint/lang/wgsl/ast",
+ "//src/tint/lang/wgsl/program",
+ "//src/tint/lang/wgsl/sem",
+ "//src/tint/utils/containers",
+ "//src/tint/utils/diagnostic",
+ "//src/tint/utils/ice",
+ "//src/tint/utils/id",
+ "//src/tint/utils/macros",
+ "//src/tint/utils/math",
+ "//src/tint/utils/memory",
+ "//src/tint/utils/reflection",
+ "//src/tint/utils/result",
+ "//src/tint/utils/rtti",
+ "//src/tint/utils/symbol",
+ "//src/tint/utils/text",
+ "//src/tint/utils/traits",
+ ] + select({
+ ":tint_build_spv_writer": [
+ "//src/tint/lang/spirv/writer/common",
+ ],
+ "//conditions:default": [],
+ }),
+ copts = COPTS,
+ visibility = ["//visibility:public"],
+)
+
+alias(
+ name = "tint_build_spv_writer",
+ actual = "//src/tint:tint_build_spv_writer_true",
+)
+
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.cfg b/src/tint/lang/spirv/writer/helpers/BUILD.cfg
new file mode 100644
index 0000000..0a24987
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_spv_writer"
+}
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.cmake b/src/tint/lang/spirv/writer/helpers/BUILD.cmake
new file mode 100644
index 0000000..e5ff89c
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.cmake
@@ -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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+# tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+if(TINT_BUILD_SPV_WRITER)
+################################################################################
+# Target: tint_lang_spirv_writer_helpers
+# Kind: lib
+# Condition: TINT_BUILD_SPV_WRITER
+################################################################################
+tint_add_target(tint_lang_spirv_writer_helpers lib
+ lang/spirv/writer/helpers/generate_bindings.cc
+ lang/spirv/writer/helpers/generate_bindings.h
+)
+
+tint_target_add_dependencies(tint_lang_spirv_writer_helpers lib
+ tint_api_common
+ tint_lang_core
+ tint_lang_core_constant
+ tint_lang_core_type
+ tint_lang_wgsl
+ tint_lang_wgsl_ast
+ tint_lang_wgsl_program
+ tint_lang_wgsl_sem
+ tint_utils_containers
+ tint_utils_diagnostic
+ tint_utils_ice
+ tint_utils_id
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_reflection
+ tint_utils_result
+ tint_utils_rtti
+ tint_utils_symbol
+ tint_utils_text
+ tint_utils_traits
+)
+
+if(TINT_BUILD_SPV_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_writer_helpers lib
+ tint_lang_spirv_writer_common
+ )
+endif(TINT_BUILD_SPV_WRITER)
+
+endif(TINT_BUILD_SPV_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.gn b/src/tint/lang/spirv/writer/helpers/BUILD.gn
new file mode 100644
index 0000000..f7e62b3
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.gn
@@ -0,0 +1,61 @@
+# 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:
+# tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+import("../../../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+if (tint_build_spv_writer) {
+ libtint_source_set("helpers") {
+ sources = [
+ "generate_bindings.cc",
+ "generate_bindings.h",
+ ]
+ deps = [
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_spv_writer) {
+ deps += [ "${tint_src_dir}/lang/spirv/writer/common" ]
+ }
+ }
+}
diff --git a/src/tint/lang/spirv/writer/helpers/generate_bindings.cc b/src/tint/lang/spirv/writer/helpers/generate_bindings.cc
new file mode 100644
index 0000000..0285b0b
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/generate_bindings.cc
@@ -0,0 +1,119 @@
+// 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/lang/spirv/writer/helpers/generate_bindings.h"
+
+#include <algorithm>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "src/tint/api/common/binding_point.h"
+#include "src/tint/lang/core/type/external_texture.h"
+#include "src/tint/lang/core/type/storage_texture.h"
+#include "src/tint/lang/wgsl/ast/module.h"
+#include "src/tint/lang/wgsl/program/program.h"
+#include "src/tint/lang/wgsl/sem/variable.h"
+#include "src/tint/utils/rtti/switch.h"
+
+namespace tint::spirv::writer {
+
+Bindings GenerateBindings(const Program& program) {
+ // TODO(tint:1491): Use Inspector once we can get binding info for all
+ // variables, not just those referenced by entry points.
+
+ Bindings bindings{};
+
+ std::unordered_set<tint::BindingPoint> seen_binding_points;
+
+ // Collect next valid binding number per group
+ std::unordered_map<uint32_t, uint32_t> group_to_next_binding_number;
+ std::vector<tint::BindingPoint> ext_tex_bps;
+ for (auto* var : program.AST().GlobalVariables()) {
+ if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) {
+ if (auto bp = sem_var->BindingPoint()) {
+ // This is a bit of a hack. The binding points must be unique over all the `binding`
+ // entries. But, this is looking at _all_ entry points where bindings can overlap.
+ // In the case where both entry points used the same type (uniform, sampler, etc)
+ // then it woudl be fine as it just overwrites with itself. But, if one entry point
+ // has a uniform and the other a sampler at the same (group,binding) pair then we'll
+ // get a validation error due to duplicate WGSL bindings.
+ //
+ // For generate bindings we don't really care as we always map to itself, so if it
+ // exists anywhere, we just pretend that's the only one.
+ if (seen_binding_points.find(*bp) != seen_binding_points.end()) {
+ continue;
+ }
+ seen_binding_points.emplace(*bp);
+
+ auto& n = group_to_next_binding_number[bp->group];
+ n = std::max(n, bp->binding + 1);
+
+ // Store up the external textures, we'll add them in the next step
+ if (sem_var->Type()->UnwrapRef()->Is<core::type::ExternalTexture>()) {
+ ext_tex_bps.emplace_back(*bp);
+ continue;
+ }
+
+ binding::BindingInfo info{bp->group, bp->binding};
+ switch (sem_var->AddressSpace()) {
+ case core::AddressSpace::kHandle:
+ Switch(
+ sem_var->Type()->UnwrapRef(), //
+ [&](const core::type::Sampler*) {
+ bindings.sampler.emplace(*bp, info);
+ },
+ [&](const core::type::StorageTexture*) {
+ bindings.storage_texture.emplace(*bp, info);
+ },
+ [&](const core::type::Texture*) {
+ bindings.texture.emplace(*bp, info);
+ });
+ break;
+ case core::AddressSpace::kStorage:
+ bindings.storage.emplace(*bp, info);
+ break;
+ case core::AddressSpace::kUniform:
+ bindings.uniform.emplace(*bp, info);
+ break;
+
+ case core::AddressSpace::kUndefined:
+ case core::AddressSpace::kPixelLocal:
+ case core::AddressSpace::kPrivate:
+ case core::AddressSpace::kPushConstant:
+ case core::AddressSpace::kIn:
+ case core::AddressSpace::kOut:
+ case core::AddressSpace::kFunction:
+ case core::AddressSpace::kWorkgroup:
+ break;
+ }
+ }
+ }
+ }
+
+ for (auto bp : ext_tex_bps) {
+ uint32_t g = bp.group;
+ uint32_t& next_num = group_to_next_binding_number[g];
+
+ binding::BindingInfo plane0{bp.group, bp.binding};
+ binding::BindingInfo plane1{g, next_num++};
+ binding::BindingInfo metadata{g, next_num++};
+
+ bindings.external_texture.emplace(bp, binding::ExternalTexture{metadata, plane0, plane1});
+ }
+
+ return bindings;
+}
+
+} // namespace tint::spirv::writer
diff --git a/src/tint/fuzzers/apply_substitute_overrides.h b/src/tint/lang/spirv/writer/helpers/generate_bindings.h
similarity index 62%
rename from src/tint/fuzzers/apply_substitute_overrides.h
rename to src/tint/lang/spirv/writer/helpers/generate_bindings.h
index 31f0263..d97120f 100644
--- a/src/tint/fuzzers/apply_substitute_overrides.h
+++ b/src/tint/lang/spirv/writer/helpers/generate_bindings.h
@@ -12,20 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef SRC_TINT_FUZZERS_APPLY_SUBSTITUTE_OVERRIDES_H_
-#define SRC_TINT_FUZZERS_APPLY_SUBSTITUTE_OVERRIDES_H_
+#ifndef SRC_TINT_LANG_SPIRV_WRITER_HELPERS_GENERATE_BINDINGS_H_
+#define SRC_TINT_LANG_SPIRV_WRITER_HELPERS_GENERATE_BINDINGS_H_
+
+#include "src/tint/lang/spirv/writer/common/options.h"
// Forward declarations
namespace tint {
class Program;
}
-namespace tint::fuzzers {
+namespace tint::spirv::writer {
-/// @returns a new program with all overrides subsituted with const variables
-/// @param program the input program
-Program ApplySubstituteOverrides(Program&& program);
+Bindings GenerateBindings(const Program& program);
-} // namespace tint::fuzzers
+} // namespace tint::spirv::writer
-#endif // SRC_TINT_FUZZERS_APPLY_SUBSTITUTE_OVERRIDES_H_
+#endif // SRC_TINT_LANG_SPIRV_WRITER_HELPERS_GENERATE_BINDINGS_H_
diff --git a/src/tint/lang/spirv/writer/printer/BUILD.bazel b/src/tint/lang/spirv/writer/printer/BUILD.bazel
index f595547..21bb414 100644
--- a/src/tint/lang/spirv/writer/printer/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/printer/BUILD.bazel
@@ -33,7 +33,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/printer/BUILD.cmake b/src/tint/lang/spirv/writer/printer/BUILD.cmake
index 81c1626..cdadaec 100644
--- a/src/tint/lang/spirv/writer/printer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/printer/BUILD.cmake
@@ -34,7 +34,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_printer lib
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_intrinsic
diff --git a/src/tint/lang/spirv/writer/printer/BUILD.gn b/src/tint/lang/spirv/writer/printer/BUILD.gn
index 476271a..e57f56c 100644
--- a/src/tint/lang/spirv/writer/printer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/printer/BUILD.gn
@@ -32,7 +32,6 @@
]
deps = [
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index 43ed467..7c6b4da 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -73,6 +73,7 @@
#include "src/tint/lang/core/type/u32.h"
#include "src/tint/lang/core/type/vector.h"
#include "src/tint/lang/core/type/void.h"
+#include "src/tint/lang/spirv/ir/literal_operand.h"
#include "src/tint/lang/spirv/type/sampled_image.h"
#include "src/tint/lang/spirv/writer/ast_printer/ast_printer.h"
#include "src/tint/lang/spirv/writer/common/module.h"
@@ -159,14 +160,10 @@
return valid.Failure();
}
- // TODO(crbug.com/tint/1906): Check supported extensions.
-
module_.PushCapability(SpvCapabilityShader);
module_.PushMemoryModel(spv::Op::OpMemoryModel, {U32Operand(SpvAddressingModelLogical),
U32Operand(SpvMemoryModelGLSL450)});
- // TODO(crbug.com/tint/1906): Emit extensions.
-
// Emit module-scope declarations.
EmitRootBlock(ir_.root_block);
@@ -231,7 +228,7 @@
uint32_t Printer::Constant(core::ir::Constant* constant) {
// If it is a literal operand, just return the value.
- if (auto* literal = constant->As<raise::LiteralOperand>()) {
+ if (auto* literal = constant->As<spirv::ir::LiteralOperand>()) {
return literal->Value()->ValueAs<uint32_t>();
}
@@ -247,8 +244,14 @@
uint32_t Printer::Constant(const core::constant::Value* constant) {
return constants_.GetOrCreate(constant, [&] {
- auto id = module_.NextId();
auto* ty = constant->Type();
+
+ // Use OpConstantNull for zero-valued composite constants.
+ if (!ty->Is<core::type::Scalar>() && constant->AllZero()) {
+ return ConstantNull(ty);
+ }
+
+ auto id = module_.NextId();
Switch(
ty, //
[&](const core::type::Bool*) {
diff --git a/src/tint/lang/spirv/writer/raise/BUILD.bazel b/src/tint/lang/spirv/writer/raise/BUILD.bazel
index f233c85..c89a53a 100644
--- a/src/tint/lang/spirv/writer/raise/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/raise/BUILD.bazel
@@ -30,6 +30,7 @@
"expand_implicit_splats.cc",
"handle_matrix_arithmetic.cc",
"merge_return.cc",
+ "pass_matrix_by_pointer.cc",
"raise.cc",
"shader_io.cc",
"var_for_dynamic_index.cc",
@@ -39,6 +40,7 @@
"expand_implicit_splats.h",
"handle_matrix_arithmetic.h",
"merge_return.h",
+ "pass_matrix_by_pointer.h",
"raise.h",
"shader_io.h",
"var_for_dynamic_index.h",
@@ -91,6 +93,7 @@
"expand_implicit_splats_test.cc",
"handle_matrix_arithmetic_test.cc",
"merge_return_test.cc",
+ "pass_matrix_by_pointer_test.cc",
"shader_io_test.cc",
"var_for_dynamic_index_test.cc",
],
diff --git a/src/tint/lang/spirv/writer/raise/BUILD.cmake b/src/tint/lang/spirv/writer/raise/BUILD.cmake
index 8385c91..6b69a52 100644
--- a/src/tint/lang/spirv/writer/raise/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/raise/BUILD.cmake
@@ -36,6 +36,8 @@
lang/spirv/writer/raise/handle_matrix_arithmetic.h
lang/spirv/writer/raise/merge_return.cc
lang/spirv/writer/raise/merge_return.h
+ lang/spirv/writer/raise/pass_matrix_by_pointer.cc
+ lang/spirv/writer/raise/pass_matrix_by_pointer.h
lang/spirv/writer/raise/raise.cc
lang/spirv/writer/raise/raise.h
lang/spirv/writer/raise/shader_io.cc
@@ -96,6 +98,7 @@
lang/spirv/writer/raise/expand_implicit_splats_test.cc
lang/spirv/writer/raise/handle_matrix_arithmetic_test.cc
lang/spirv/writer/raise/merge_return_test.cc
+ lang/spirv/writer/raise/pass_matrix_by_pointer_test.cc
lang/spirv/writer/raise/shader_io_test.cc
lang/spirv/writer/raise/var_for_dynamic_index_test.cc
)
diff --git a/src/tint/lang/spirv/writer/raise/BUILD.gn b/src/tint/lang/spirv/writer/raise/BUILD.gn
index 6d187d6..d908228 100644
--- a/src/tint/lang/spirv/writer/raise/BUILD.gn
+++ b/src/tint/lang/spirv/writer/raise/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
if (tint_build_spv_writer) {
@@ -39,6 +39,8 @@
"handle_matrix_arithmetic.h",
"merge_return.cc",
"merge_return.h",
+ "pass_matrix_by_pointer.cc",
+ "pass_matrix_by_pointer.h",
"raise.cc",
"raise.h",
"shader_io.cc",
@@ -86,12 +88,12 @@
if (tint_build_unittests) {
if (tint_build_spv_writer) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"builtin_polyfill_test.cc",
"expand_implicit_splats_test.cc",
"handle_matrix_arithmetic_test.cc",
"merge_return_test.cc",
+ "pass_matrix_by_pointer_test.cc",
"shader_io_test.cc",
"var_for_dynamic_index_test.cc",
]
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
index dc5ff8b..feef5fb 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
@@ -29,11 +29,10 @@
#include "src/tint/lang/core/type/storage_texture.h"
#include "src/tint/lang/core/type/texture.h"
#include "src/tint/lang/spirv/ir/builtin_call.h"
+#include "src/tint/lang/spirv/ir/literal_operand.h"
#include "src/tint/lang/spirv/type/sampled_image.h"
#include "src/tint/utils/ice/ice.h"
-TINT_INSTANTIATE_TYPEINFO(tint::spirv::writer::raise::LiteralOperand);
-
using namespace tint::core::number_suffixes; // NOLINT
using namespace tint::core::fluent_types; // NOLINT
@@ -177,8 +176,8 @@
/// Create a literal operand.
/// @param value the literal value
/// @returns the literal operand
- LiteralOperand* Literal(u32 value) {
- return ir.values.Create<LiteralOperand>(b.ConstantValue(value));
+ spirv::ir::LiteralOperand* Literal(u32 value) {
+ return ir.values.Create<spirv::ir::LiteralOperand>(b.ConstantValue(value));
}
/// Handle an `arrayLength()` builtin.
@@ -885,8 +884,4 @@
return Success;
}
-LiteralOperand::LiteralOperand(const core::constant::Value* value) : Base(value) {}
-
-LiteralOperand::~LiteralOperand() = default;
-
} // namespace tint::spirv::writer::raise
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill.h b/src/tint/lang/spirv/writer/raise/builtin_polyfill.h
index 469d6a4..1a1fe62 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill.h
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill.h
@@ -36,18 +36,6 @@
/// @returns success or failure
Result<SuccessType> BuiltinPolyfill(core::ir::Module& module);
-/// LiteralOperand is a type of constant value that is intended to be emitted as a literal in
-/// the SPIR-V instruction stream.
-/// TODO(jrprice): Move this to lang/spirv.
-class LiteralOperand final : public Castable<LiteralOperand, core::ir::Constant> {
- public:
- /// Constructor
- /// @param value the operand value
- explicit LiteralOperand(const core::constant::Value* value);
- /// Destructor
- ~LiteralOperand() override;
-};
-
} // namespace tint::spirv::writer::raise
#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_BUILTIN_POLYFILL_H_
diff --git a/src/tint/lang/spirv/writer/raise/merge_return.cc b/src/tint/lang/spirv/writer/raise/merge_return.cc
index 75e40e6..e172165 100644
--- a/src/tint/lang/spirv/writer/raise/merge_return.cc
+++ b/src/tint/lang/spirv/writer/raise/merge_return.cc
@@ -132,7 +132,7 @@
// Unreachable can become reachable once returns are turned into exits.
// As this is the terminator for the block, simply stop processing the
// instructions. A appropriate terminator will be created for this block below.
- inst->Remove();
+ inst->Destroy();
break;
}
diff --git a/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc b/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc
new file mode 100644
index 0000000..ff54237
--- /dev/null
+++ b/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc
@@ -0,0 +1,128 @@
+// 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/lang/spirv/writer/raise/pass_matrix_by_pointer.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+using namespace tint::core::number_suffixes; // NOLINT
+using namespace tint::core::fluent_types; // NOLINT
+
+namespace tint::spirv::writer::raise {
+
+namespace {
+
+/// PIMPL state for the transform.
+struct State {
+ /// The IR module.
+ core::ir::Module& ir;
+
+ /// The IR builder.
+ core::ir::Builder b{ir};
+
+ /// The type manager.
+ core::type::Manager& ty{ir.Types()};
+
+ /// Process the module.
+ void Process() {
+ // Find user-declared functions that have value arguments containing matrices.
+ for (auto* func : ir.functions) {
+ for (auto* param : func->Params()) {
+ if (ContainsMatrix(param->Type())) {
+ TransformFunction(func);
+ break;
+ }
+ }
+ }
+ }
+
+ /// Checks if a type contains a matrix.
+ /// @param type the type to check
+ /// @returns true if the type contains a matrix, otherwise false
+ bool ContainsMatrix(const core::type::Type* type) {
+ return tint::Switch(
+ type, //
+ [&](const core::type::Matrix*) { return true; },
+ [&](const core::type::Array* arr) { return ContainsMatrix(arr->ElemType()); },
+ [&](const core::type::Struct* str) {
+ for (auto* member : str->Members()) {
+ if (ContainsMatrix(member->Type())) {
+ return true;
+ }
+ }
+ return false;
+ },
+ [&](Default) { return false; });
+ }
+
+ /// Transform a function that has value parameters containing matrices.
+ /// @param func the function to transform
+ void TransformFunction(core::ir::Function* func) {
+ Vector<core::ir::FunctionParam*, 4> replacement_params;
+ for (auto* param : func->Params()) {
+ if (ContainsMatrix(param->Type())) {
+ // Replace the value parameter with a pointer.
+ auto* new_param = b.FunctionParam(ty.ptr(function, param->Type()));
+
+ // Load from the pointer to get the value.
+ auto* load = b.Load(new_param);
+ func->Block()->Prepend(load);
+ param->ReplaceAllUsesWith(load->Result());
+
+ // Modify all of the callsites.
+ func->ForEachUse([&](core::ir::Usage use) {
+ if (auto* call = use.instruction->As<core::ir::UserCall>()) {
+ ReplaceCallArgument(call, replacement_params.Length());
+ }
+ });
+
+ replacement_params.Push(new_param);
+ } else {
+ // No matrices, so just copy the parameter as is.
+ replacement_params.Push(param);
+ }
+ }
+ func->SetParams(std::move(replacement_params));
+ }
+
+ /// Replace a function call argument with an equivalent passed by pointer.
+ void ReplaceCallArgument(core::ir::UserCall* call, size_t arg_index) {
+ // Copy the argument to a locally declared variable.
+ auto* arg = call->Args()[arg_index];
+ auto* local_var = b.Var(ty.ptr(function, arg->Type()));
+ local_var->SetInitializer(arg);
+ local_var->InsertBefore(call);
+
+ call->SetOperand(core::ir::UserCall::kArgsOperandOffset + arg_index, local_var->Result());
+ }
+};
+
+} // namespace
+
+Result<SuccessType> PassMatrixByPointer(core::ir::Module& ir) {
+ auto result = ValidateAndDumpIfNeeded(ir, "PassMatrixByPointer transform");
+ if (!result) {
+ return result;
+ }
+
+ State{ir}.Process();
+
+ return Success;
+}
+
+} // namespace tint::spirv::writer::raise
diff --git a/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h b/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h
new file mode 100644
index 0000000..c22be02
--- /dev/null
+++ b/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h
@@ -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.
+
+#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_PASS_MATRIX_BY_POINTER_H_
+#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_PASS_MATRIX_BY_POINTER_H_
+
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Module;
+}
+
+namespace tint::spirv::writer::raise {
+
+/// PassMatrixByPointer is a transform that modifies function calls that pass values that contain
+/// matrices to pass them by pointer instead.
+/// This is used to workaround bugs in some Qualcomm drivers (see crbug.com/tint/2045).
+/// @param module the module to transform
+/// @returns success or failure
+Result<SuccessType> PassMatrixByPointer(core::ir::Module& module);
+
+} // namespace tint::spirv::writer::raise
+
+#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_PASS_MATRIX_BY_POINTER_H_
diff --git a/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer_test.cc b/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer_test.cc
new file mode 100644
index 0000000..560dda5
--- /dev/null
+++ b/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer_test.cc
@@ -0,0 +1,733 @@
+// 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/lang/spirv/writer/raise/pass_matrix_by_pointer.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/transform/helper_test.h"
+
+namespace tint::spirv::writer::raise {
+namespace {
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+using SpirvWriter_PassMatrixByPointerTest = core::ir::transform::TransformTest;
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, NoModify_ArrayValue) {
+ auto* arr_ty = ty.array<f32, 4u>();
+ auto* arr = mod.root_block->Append(b.Var("var", ty.ptr(private_, arr_ty)));
+
+ auto* target = b.Function("target", ty.f32());
+ auto* value = b.FunctionParam("value", arr_ty);
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* access = b.Access(ty.f32(), value, 1_i);
+ b.Return(target, access);
+ });
+
+ auto* caller = b.Function("caller", ty.f32());
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(ty.f32(), target, b.Load(arr));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, array<f32, 4>, read_write> = var
+}
+
+%target = func(%value:array<f32, 4>):f32 -> %b2 {
+ %b2 = block {
+ %4:f32 = access %value, 1i
+ ret %4
+ }
+}
+%caller = func():f32 -> %b3 {
+ %b3 = block {
+ %6:array<f32, 4> = load %var
+ %7:f32 = call %target, %6
+ ret %7
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, NoModify_MatrixPointer) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* mat = mod.root_block->Append(b.Var("var", ty.ptr(private_, mat_ty)));
+
+ auto* target = b.Function("target", ty.vec3<f32>());
+ auto* value = b.FunctionParam("value", ty.ptr(private_, mat_ty));
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* access = b.Access(ty.ptr<private_, vec3<f32>>(), value, 1_i);
+ b.Return(target, b.Load(access));
+ });
+
+ auto* caller = b.Function("caller", ty.vec3<f32>());
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(ty.vec3<f32>(), target, mat);
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%value:ptr<private, mat3x3<f32>, read_write>):vec3<f32> -> %b2 {
+ %b2 = block {
+ %4:ptr<private, vec3<f32>, read_write> = access %value, 1i
+ %5:vec3<f32> = load %4
+ ret %5
+ }
+}
+%caller = func():vec3<f32> -> %b3 {
+ %b3 = block {
+ %7:vec3<f32> = call %target, %var
+ ret %7
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MatrixValuePassedToBuiltin) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* mat = mod.root_block->Append(b.Var("var", ty.ptr(private_, mat_ty)));
+
+ auto* caller = b.Function("caller", ty.f32());
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(ty.f32(), core::BuiltinFn::kDeterminant, b.Load(mat));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%caller = func():f32 -> %b2 {
+ %b2 = block {
+ %3:mat3x3<f32> = load %var
+ %4:f32 = determinant %3
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, SingleMatrixValue) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* mat = mod.root_block->Append(b.Var("var", ty.ptr(private_, mat_ty)));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value = b.FunctionParam("value", mat_ty);
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* scale = b.Multiply(mat_ty, value, b.Constant(2_f));
+ b.Return(target, scale);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(mat));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%value:mat3x3<f32>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = mul %value, 2.0f
+ ret %4
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %6:mat3x3<f32> = load %var
+ %7:mat3x3<f32> = call %target, %6
+ ret %7
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%3:ptr<function, mat3x3<f32>, read_write>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = load %3
+ %5:mat3x3<f32> = mul %4, 2.0f
+ ret %5
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %7:mat3x3<f32> = load %var
+ %8:ptr<function, mat3x3<f32>, read_write> = var, %7
+ %9:mat3x3<f32> = call %target, %8
+ ret %9
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MultipleMatrixValues) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* arr = mod.root_block->Append(b.Var("var", ty.ptr(private_, ty.array(mat_ty, 4))));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value_a = b.FunctionParam("value_a", mat_ty);
+ auto* scalar = b.FunctionParam("scalar", ty.f32());
+ auto* value_b = b.FunctionParam("value_b", mat_ty);
+ target->SetParams({value_a, scalar, value_b});
+ b.Append(target->Block(), [&] {
+ auto* scale = b.Multiply(mat_ty, value_a, scalar);
+ auto* sum = b.Add(mat_ty, scale, value_b);
+ b.Return(target, sum);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* mat_ptr = ty.ptr(private_, mat_ty);
+ auto* ma = b.Load(b.Access(mat_ptr, arr, 0_u));
+ auto* mb = b.Load(b.Access(mat_ptr, arr, 1_u));
+ auto* result = b.Call(mat_ty, target, ma, b.Constant(2_f), mb);
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, array<mat3x3<f32>, 4>, read_write> = var
+}
+
+%target = func(%value_a:mat3x3<f32>, %scalar:f32, %value_b:mat3x3<f32>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %6:mat3x3<f32> = mul %value_a, %scalar
+ %7:mat3x3<f32> = add %6, %value_b
+ ret %7
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %9:ptr<private, mat3x3<f32>, read_write> = access %var, 0u
+ %10:mat3x3<f32> = load %9
+ %11:ptr<private, mat3x3<f32>, read_write> = access %var, 1u
+ %12:mat3x3<f32> = load %11
+ %13:mat3x3<f32> = call %target, %10, 2.0f, %12
+ ret %13
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %var:ptr<private, array<mat3x3<f32>, 4>, read_write> = var
+}
+
+%target = func(%3:ptr<function, mat3x3<f32>, read_write>, %scalar:f32, %5:ptr<function, mat3x3<f32>, read_write>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %6:mat3x3<f32> = load %5
+ %7:mat3x3<f32> = load %3
+ %8:mat3x3<f32> = mul %7, %scalar
+ %9:mat3x3<f32> = add %8, %6
+ ret %9
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %11:ptr<private, mat3x3<f32>, read_write> = access %var, 0u
+ %12:mat3x3<f32> = load %11
+ %13:ptr<private, mat3x3<f32>, read_write> = access %var, 1u
+ %14:mat3x3<f32> = load %13
+ %15:ptr<function, mat3x3<f32>, read_write> = var, %12
+ %16:ptr<function, mat3x3<f32>, read_write> = var, %14
+ %17:mat3x3<f32> = call %target, %15, 2.0f, %16
+ ret %17
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MultipleParamUses) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* mat = mod.root_block->Append(b.Var("var", ty.ptr(private_, mat_ty)));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value = b.FunctionParam("value", mat_ty);
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* add = b.Add(mat_ty, value, value);
+ auto* mul = b.Multiply(mat_ty, add, value);
+ b.Return(target, mul);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(mat));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%value:mat3x3<f32>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = add %value, %value
+ %5:mat3x3<f32> = mul %4, %value
+ ret %5
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %7:mat3x3<f32> = load %var
+ %8:mat3x3<f32> = call %target, %7
+ ret %8
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%3:ptr<function, mat3x3<f32>, read_write>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = load %3
+ %5:mat3x3<f32> = add %4, %4
+ %6:mat3x3<f32> = mul %5, %4
+ ret %6
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %8:mat3x3<f32> = load %var
+ %9:ptr<function, mat3x3<f32>, read_write> = var, %8
+ %10:mat3x3<f32> = call %target, %9
+ ret %10
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MultipleCallsites) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* mat = mod.root_block->Append(b.Var("var", ty.ptr(private_, mat_ty)));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value = b.FunctionParam("value", mat_ty);
+ auto* scalar = b.FunctionParam("scalar", ty.f32());
+ target->SetParams({value, scalar});
+ b.Append(target->Block(), [&] {
+ auto* scale = b.Multiply(mat_ty, value, scalar);
+ b.Return(target, scale);
+ });
+
+ auto* caller_a = b.Function("caller_a", mat_ty);
+ b.Append(caller_a->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(mat), b.Constant(2_f));
+ b.Return(caller_a, result);
+ });
+
+ auto* caller_b = b.Function("caller_b", mat_ty);
+ b.Append(caller_b->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(mat), b.Constant(3_f));
+ b.Return(caller_b, result);
+ });
+
+ auto* caller_c = b.Function("caller_c", mat_ty);
+ b.Append(caller_c->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(mat), b.Constant(4_f));
+ b.Return(caller_c, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%value:mat3x3<f32>, %scalar:f32):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %5:mat3x3<f32> = mul %value, %scalar
+ ret %5
+ }
+}
+%caller_a = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %7:mat3x3<f32> = load %var
+ %8:mat3x3<f32> = call %target, %7, 2.0f
+ ret %8
+ }
+}
+%caller_b = func():mat3x3<f32> -> %b4 {
+ %b4 = block {
+ %10:mat3x3<f32> = load %var
+ %11:mat3x3<f32> = call %target, %10, 3.0f
+ ret %11
+ }
+}
+%caller_c = func():mat3x3<f32> -> %b5 {
+ %b5 = block {
+ %13:mat3x3<f32> = load %var
+ %14:mat3x3<f32> = call %target, %13, 4.0f
+ ret %14
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %var:ptr<private, mat3x3<f32>, read_write> = var
+}
+
+%target = func(%3:ptr<function, mat3x3<f32>, read_write>, %scalar:f32):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %5:mat3x3<f32> = load %3
+ %6:mat3x3<f32> = mul %5, %scalar
+ ret %6
+ }
+}
+%caller_a = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %8:mat3x3<f32> = load %var
+ %9:ptr<function, mat3x3<f32>, read_write> = var, %8
+ %10:mat3x3<f32> = call %target, %9, 2.0f
+ ret %10
+ }
+}
+%caller_b = func():mat3x3<f32> -> %b4 {
+ %b4 = block {
+ %12:mat3x3<f32> = load %var
+ %13:ptr<function, mat3x3<f32>, read_write> = var, %12
+ %14:mat3x3<f32> = call %target, %13, 3.0f
+ ret %14
+ }
+}
+%caller_c = func():mat3x3<f32> -> %b5 {
+ %b5 = block {
+ %16:mat3x3<f32> = load %var
+ %17:ptr<function, mat3x3<f32>, read_write> = var, %16
+ %18:mat3x3<f32> = call %target, %17, 4.0f
+ ret %18
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MatrixInArray) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* arr_ty = ty.array(mat_ty, 2);
+ auto* arr = mod.root_block->Append(b.Var("var", ty.ptr(private_, arr_ty)));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value = b.FunctionParam("value", arr_ty);
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* ma = b.Access(mat_ty, value, 0_u);
+ auto* mb = b.Access(mat_ty, value, 1_u);
+ auto* add = b.Add(mat_ty, ma, mb);
+ b.Return(target, add);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(arr));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %var:ptr<private, array<mat3x3<f32>, 2>, read_write> = var
+}
+
+%target = func(%value:array<mat3x3<f32>, 2>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = access %value, 0u
+ %5:mat3x3<f32> = access %value, 1u
+ %6:mat3x3<f32> = add %4, %5
+ ret %6
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %8:array<mat3x3<f32>, 2> = load %var
+ %9:mat3x3<f32> = call %target, %8
+ ret %9
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %var:ptr<private, array<mat3x3<f32>, 2>, read_write> = var
+}
+
+%target = func(%3:ptr<function, array<mat3x3<f32>, 2>, read_write>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:array<mat3x3<f32>, 2> = load %3
+ %5:mat3x3<f32> = access %4, 0u
+ %6:mat3x3<f32> = access %4, 1u
+ %7:mat3x3<f32> = add %5, %6
+ ret %7
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %9:array<mat3x3<f32>, 2> = load %var
+ %10:ptr<function, array<mat3x3<f32>, 2>, read_write> = var, %9
+ %11:mat3x3<f32> = call %target, %10
+ ret %11
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MatrixInStruct) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* str_ty = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("m"), mat_ty},
+ {mod.symbols.New("s"), ty.f32()},
+ });
+ auto* structure = mod.root_block->Append(b.Var("var", ty.ptr(private_, str_ty)));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value = b.FunctionParam("value", str_ty);
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* m = b.Access(mat_ty, value, 0_u);
+ auto* s = b.Access(ty.f32(), value, 1_u);
+ auto* mul = b.Multiply(mat_ty, m, s);
+ b.Return(target, mul);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(structure));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ m:mat3x3<f32> @offset(0)
+ s:f32 @offset(48)
+}
+
+%b1 = block { # root
+ %var:ptr<private, MyStruct, read_write> = var
+}
+
+%target = func(%value:MyStruct):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = access %value, 0u
+ %5:f32 = access %value, 1u
+ %6:mat3x3<f32> = mul %4, %5
+ ret %6
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %8:MyStruct = load %var
+ %9:mat3x3<f32> = call %target, %8
+ ret %9
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ m:mat3x3<f32> @offset(0)
+ s:f32 @offset(48)
+}
+
+%b1 = block { # root
+ %var:ptr<private, MyStruct, read_write> = var
+}
+
+%target = func(%3:ptr<function, MyStruct, read_write>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:MyStruct = load %3
+ %5:mat3x3<f32> = access %4, 0u
+ %6:f32 = access %4, 1u
+ %7:mat3x3<f32> = mul %5, %6
+ ret %7
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %9:MyStruct = load %var
+ %10:ptr<function, MyStruct, read_write> = var, %9
+ %11:mat3x3<f32> = call %target, %10
+ ret %11
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvWriter_PassMatrixByPointerTest, MatrixArrayOfStructOfArray) {
+ auto* mat_ty = ty.mat3x3<f32>();
+ auto* str_ty =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("m"), ty.array(mat_ty, 2)},
+ {mod.symbols.New("s"), ty.f32()},
+ });
+ auto* arr_ty = ty.array(str_ty, 4);
+ auto* var = mod.root_block->Append(b.Var("var", ty.ptr(private_, arr_ty)));
+
+ auto* target = b.Function("target", mat_ty);
+ auto* value = b.FunctionParam("value", arr_ty);
+ target->SetParams({value});
+ b.Append(target->Block(), [&] {
+ auto* ma = b.Access(mat_ty, value, 2_u, 0_u, 0_u);
+ auto* mb = b.Access(mat_ty, value, 2_u, 0_u, 1_u);
+ auto* s = b.Access(ty.f32(), value, 2_u, 1_u);
+ auto* add = b.Add(mat_ty, ma, mb);
+ auto* mul = b.Multiply(mat_ty, add, s);
+ b.Return(target, mul);
+ });
+
+ auto* caller = b.Function("caller", mat_ty);
+ b.Append(caller->Block(), [&] {
+ auto* result = b.Call(mat_ty, target, b.Load(var));
+ b.Return(caller, result);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(16) {
+ m:array<mat3x3<f32>, 2> @offset(0)
+ s:f32 @offset(96)
+}
+
+%b1 = block { # root
+ %var:ptr<private, array<MyStruct, 4>, read_write> = var
+}
+
+%target = func(%value:array<MyStruct, 4>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:mat3x3<f32> = access %value, 2u, 0u, 0u
+ %5:mat3x3<f32> = access %value, 2u, 0u, 1u
+ %6:f32 = access %value, 2u, 1u
+ %7:mat3x3<f32> = add %4, %5
+ %8:mat3x3<f32> = mul %7, %6
+ ret %8
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %10:array<MyStruct, 4> = load %var
+ %11:mat3x3<f32> = call %target, %10
+ ret %11
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(16) {
+ m:array<mat3x3<f32>, 2> @offset(0)
+ s:f32 @offset(96)
+}
+
+%b1 = block { # root
+ %var:ptr<private, array<MyStruct, 4>, read_write> = var
+}
+
+%target = func(%3:ptr<function, array<MyStruct, 4>, read_write>):mat3x3<f32> -> %b2 {
+ %b2 = block {
+ %4:array<MyStruct, 4> = load %3
+ %5:mat3x3<f32> = access %4, 2u, 0u, 0u
+ %6:mat3x3<f32> = access %4, 2u, 0u, 1u
+ %7:f32 = access %4, 2u, 1u
+ %8:mat3x3<f32> = add %5, %6
+ %9:mat3x3<f32> = mul %8, %7
+ ret %9
+ }
+}
+%caller = func():mat3x3<f32> -> %b3 {
+ %b3 = block {
+ %11:array<MyStruct, 4> = load %var
+ %12:ptr<function, array<MyStruct, 4>, read_write> = var, %11
+ %13:mat3x3<f32> = call %target, %12
+ ret %13
+ }
+}
+)";
+
+ Run(PassMatrixByPointer);
+
+ EXPECT_EQ(expect, str());
+}
+
+} // namespace
+} // namespace tint::spirv::writer::raise
diff --git a/src/tint/lang/spirv/writer/raise/raise.cc b/src/tint/lang/spirv/writer/raise/raise.cc
index 6045987..de1eb99 100644
--- a/src/tint/lang/spirv/writer/raise/raise.cc
+++ b/src/tint/lang/spirv/writer/raise/raise.cc
@@ -22,15 +22,21 @@
#include "src/tint/lang/core/ir/transform/binding_remapper.h"
#include "src/tint/lang/core/ir/transform/block_decorated_structs.h"
#include "src/tint/lang/core/ir/transform/builtin_polyfill.h"
+#include "src/tint/lang/core/ir/transform/combine_access_instructions.h"
+#include "src/tint/lang/core/ir/transform/conversion_polyfill.h"
#include "src/tint/lang/core/ir/transform/demote_to_helper.h"
+#include "src/tint/lang/core/ir/transform/direct_variable_access.h"
#include "src/tint/lang/core/ir/transform/multiplanar_external_texture.h"
+#include "src/tint/lang/core/ir/transform/preserve_padding.h"
#include "src/tint/lang/core/ir/transform/robustness.h"
#include "src/tint/lang/core/ir/transform/std140.h"
#include "src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h"
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
#include "src/tint/lang/spirv/writer/raise/builtin_polyfill.h"
#include "src/tint/lang/spirv/writer/raise/expand_implicit_splats.h"
#include "src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h"
#include "src/tint/lang/spirv/writer/raise/merge_return.h"
+#include "src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h"
#include "src/tint/lang/spirv/writer/raise/shader_io.h"
#include "src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h"
@@ -45,7 +51,11 @@
} \
} while (false)
- RUN_TRANSFORM(core::ir::transform::BindingRemapper, module, options.binding_remapper_options);
+ ExternalTextureOptions external_texture_options{};
+ RemapperData remapper_data{};
+ PopulateRemapperAndMultiplanarOptions(options, remapper_data, external_texture_options);
+
+ RUN_TRANSFORM(core::ir::transform::BindingRemapper, module, remapper_data);
core::ir::transform::BinaryPolyfillConfig binary_polyfills;
binary_polyfills.bitshift_modulo = true;
@@ -64,6 +74,10 @@
core_polyfills.texture_sample_base_clamp_to_edge_2d_f32 = true;
RUN_TRANSFORM(core::ir::transform::BuiltinPolyfill, module, core_polyfills);
+ core::ir::transform::ConversionPolyfillConfig conversion_polyfills;
+ conversion_polyfills.ftoi = true;
+ RUN_TRANSFORM(core::ir::transform::ConversionPolyfill, module, conversion_polyfills);
+
if (!options.disable_robustness) {
core::ir::transform::RobustnessConfig config;
if (options.disable_image_robustness) {
@@ -75,16 +89,35 @@
}
RUN_TRANSFORM(core::ir::transform::MultiplanarExternalTexture, module,
- options.external_texture_options);
+ external_texture_options);
if (!options.disable_workgroup_init &&
!options.use_zero_initialize_workgroup_memory_extension) {
RUN_TRANSFORM(core::ir::transform::ZeroInitWorkgroupMemory, module);
}
+ // PreservePadding must come before DirectVariableAccess.
+ RUN_TRANSFORM(core::ir::transform::PreservePadding, module);
+
+ core::ir::transform::DirectVariableAccessOptions dva_options;
+ dva_options.transform_function = true;
+ dva_options.transform_private = true;
+ RUN_TRANSFORM(core::ir::transform::DirectVariableAccess, module, dva_options);
+
+ if (options.pass_matrix_by_pointer) {
+ // PassMatrixByPointer must come after PreservePadding+DirectVariableAccess.
+ RUN_TRANSFORM(PassMatrixByPointer, module);
+ }
+
RUN_TRANSFORM(core::ir::transform::AddEmptyEntryPoint, module);
RUN_TRANSFORM(core::ir::transform::Bgra8UnormPolyfill, module);
RUN_TRANSFORM(core::ir::transform::BlockDecoratedStructs, module);
+
+ // CombineAccessInstructions must come after DirectVariableAccess and BlockDecoratedStructs.
+ // We run this transform as some Qualcomm drivers struggle with partial access chains that
+ // produce pointers to matrices.
+ RUN_TRANSFORM(core::ir::transform::CombineAccessInstructions, module);
+
RUN_TRANSFORM(BuiltinPolyfill, module);
RUN_TRANSFORM(core::ir::transform::DemoteToHelper, module);
RUN_TRANSFORM(ExpandImplicitSplats, module);
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.cc b/src/tint/lang/spirv/writer/raise/shader_io.cc
index f807c31..2aa195e 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io.cc
@@ -83,6 +83,9 @@
}
} else {
name << "_loc" << io.attributes.location.value();
+ if (io.attributes.index.has_value()) {
+ name << "_idx" << io.attributes.index.value();
+ }
}
name << name_suffix;
diff --git a/src/tint/lang/spirv/writer/raise/shader_io_test.cc b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
index 343f778..c37f9fb 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
@@ -547,6 +547,78 @@
EXPECT_EQ(expect, str());
}
+TEST_F(SpirvWriter_ShaderIOTest, ReturnValue_DualSourceBlending) {
+ auto* str_ty = ty.Struct(mod.symbols.New("Output"), {
+ {
+ mod.symbols.New("color1"),
+ ty.f32(),
+ {0u, 0u, {}, {}, false},
+ },
+ {
+ mod.symbols.New("color2"),
+ ty.f32(),
+ {0u, 1u, {}, {}, false},
+ },
+ });
+
+ auto* ep = b.Function("foo", str_ty);
+ ep->SetStage(core::ir::Function::PipelineStage::kFragment);
+
+ b.Append(ep->Block(), [&] { //
+ b.Return(ep, b.Construct(str_ty, 0.25_f, 0.75_f));
+ });
+
+ auto* src = R"(
+Output = struct @align(4) {
+ color1:f32 @offset(0), @location(0)
+ color2:f32 @offset(4), @location(0)
+}
+
+%foo = @fragment func():Output -> %b1 {
+ %b1 = block {
+ %2:Output = construct 0.25f, 0.75f
+ ret %2
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+Output = struct @align(4) {
+ color1:f32 @offset(0)
+ color2:f32 @offset(4)
+}
+
+%b1 = block { # root
+ %foo_loc0_idx0_Output:ptr<__out, f32, write> = var @location(0) @index(0)
+ %foo_loc0_idx1_Output:ptr<__out, f32, write> = var @location(0) @index(1)
+}
+
+%foo_inner = func():Output -> %b2 {
+ %b2 = block {
+ %4:Output = construct 0.25f, 0.75f
+ ret %4
+ }
+}
+%foo = @fragment func():void -> %b3 {
+ %b3 = block {
+ %6:Output = call %foo_inner
+ %7:f32 = access %6, 0u
+ store %foo_loc0_idx0_Output, %7
+ %8:f32 = access %6, 1u
+ store %foo_loc0_idx1_Output, %8
+ ret
+ }
+}
+)";
+
+ ShaderIOConfig config;
+ config.clamp_frag_depth = false;
+ Run(ShaderIO, config);
+
+ EXPECT_EQ(expect, str());
+}
+
TEST_F(SpirvWriter_ShaderIOTest, Struct_SharedByVertexAndFragment) {
auto* vec4f = ty.vec4<f32>();
auto* str_ty = ty.Struct(mod.symbols.New("Interface"),
diff --git a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc
index 88d564f..6880fba 100644
--- a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc
+++ b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc
@@ -117,7 +117,7 @@
// Find the access instructions that need replacing.
Vector<AccessToReplace, 4> worklist;
for (auto* inst : ir.instructions.Objects()) {
- if (auto* access = inst->As<core::ir::Access>()) {
+ if (auto* access = inst->As<core::ir::Access>(); access && access->Alive()) {
if (auto to_replace = ShouldReplace(access)) {
worklist.Push(to_replace.value());
}
@@ -184,6 +184,7 @@
// Replace all uses of the old access instruction with the loaded result.
access->Result()->ReplaceAllUsesWith(load->Result());
access->ReplaceWith(load);
+ access->Destroy();
}
}
diff --git a/src/tint/lang/spirv/writer/type_test.cc b/src/tint/lang/spirv/writer/type_test.cc
index cb21390..ff1c4e1 100644
--- a/src/tint/lang/spirv/writer/type_test.cc
+++ b/src/tint/lang/spirv/writer/type_test.cc
@@ -368,9 +368,6 @@
Dim::k3d, Format::kR32Float},
// Test all the formats with 2D.
- // TODO(jrprice): Enable this format when we polyfill it.
- // StorageTextureCase{"%1 = OpTypeImage %float 2D 0 0 0 2 Bgra8Unorm",
- // Dim::k2d, Format::kBgra8Unorm},
StorageTextureCase{"%1 = OpTypeImage %int 2D 0 0 0 2 R32i", //
Dim::k2d, Format::kR32Sint},
StorageTextureCase{"%1 = OpTypeImage %uint 2D 0 0 0 2 R32u", //
diff --git a/src/tint/lang/spirv/writer/writer.cc b/src/tint/lang/spirv/writer/writer.cc
index 1a47183..f1a6763 100644
--- a/src/tint/lang/spirv/writer/writer.cc
+++ b/src/tint/lang/spirv/writer/writer.cc
@@ -18,10 +18,14 @@
#include <utility>
#include "src/tint/lang/spirv/writer/ast_printer/ast_printer.h"
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
#include "src/tint/lang/spirv/writer/printer/printer.h"
#include "src/tint/lang/spirv/writer/raise/raise.h"
#include "src/tint/lang/wgsl/reader/lower/lower.h"
+
+#if TINT_BUILD_WGSL_READER
#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
+#endif
// Included by 'ast_printer.h', included again here for './tools/run gen' track the dependency.
#include "spirv/unified1/spirv.h"
@@ -40,9 +44,17 @@
bool zero_initialize_workgroup_memory =
!options.disable_workgroup_init && options.use_zero_initialize_workgroup_memory_extension;
+ {
+ diag::List validation_diagnostics;
+ if (!ValidateBindingOptions(options, validation_diagnostics)) {
+ return Failure{validation_diagnostics};
+ }
+ }
+
Output output;
if (options.use_tint_ir) {
+#if TINT_BUILD_WGSL_READER
// Convert the AST program to an IR module.
auto converted = wgsl::reader::ProgramToIR(program);
if (!converted) {
@@ -68,6 +80,9 @@
return std::move(spirv.Failure());
}
output.spirv = std::move(spirv.Get());
+#else
+ return Failure{"use_tint_ir requires building with TINT_BUILD_WGSL_READER"};
+#endif
} else {
// Sanitize the program.
auto sanitized_result = Sanitize(program, options);
diff --git a/src/tint/lang/spirv/writer/writer_bench.cc b/src/tint/lang/spirv/writer/writer_bench.cc
index adef3df..c5bccce 100644
--- a/src/tint/lang/spirv/writer/writer_bench.cc
+++ b/src/tint/lang/spirv/writer/writer_bench.cc
@@ -22,15 +22,14 @@
void RunBenchmark(benchmark::State& state, std::string input_name, Options options) {
auto res = bench::LoadProgram(input_name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- state.SkipWithError(err->msg.c_str());
+ if (!res) {
+ state.SkipWithError(res.Failure().reason.str());
return;
}
- auto& program = std::get<bench::ProgramAndFile>(res).program;
for (auto _ : state) {
- auto res = Generate(program, options);
- if (!res) {
- state.SkipWithError(res.Failure().reason.str());
+ auto gen_res = Generate(res->program, options);
+ if (!gen_res) {
+ state.SkipWithError(gen_res.Failure().reason.str());
}
}
}
diff --git a/src/tint/lang/wgsl/BUILD.bazel b/src/tint/lang/wgsl/BUILD.bazel
index 83e4df2..e415e16 100644
--- a/src/tint/lang/wgsl/BUILD.bazel
+++ b/src/tint/lang/wgsl/BUILD.bazel
@@ -60,10 +60,14 @@
"extension_test.cc",
"wgsl_test.cc",
] + select({
+ "//conditions:default": [],
+ }) + select({
":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
"ir_roundtrip_test.cc",
],
"//conditions:default": [],
+ }) + select({
+ "//conditions:default": [],
}),
deps = [
"//src/tint/api/common",
@@ -75,12 +79,9 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/helpers:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/reader/lower",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/lang/wgsl/writer/ir_to_program",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -96,12 +97,26 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"diagnostic_rule_bench.cc",
"diagnostic_severity_bench.cc",
@@ -118,6 +133,7 @@
"//src/tint/utils/rtti",
"//src/tint/utils/text",
"//src/tint/utils/traits",
+ "@benchmark",
],
copts = COPTS,
visibility = ["//visibility:public"],
diff --git a/src/tint/lang/wgsl/BUILD.cmake b/src/tint/lang/wgsl/BUILD.cmake
index c72aa5e..36b6d78 100644
--- a/src/tint/lang/wgsl/BUILD.cmake
+++ b/src/tint/lang/wgsl/BUILD.cmake
@@ -80,12 +80,9 @@
tint_lang_wgsl_ast
tint_lang_wgsl_helpers_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_reader_lower
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_lang_wgsl_writer_ir_to_program
tint_utils_containers
tint_utils_diagnostic
@@ -106,12 +103,25 @@
"gtest"
)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_test test
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
tint_target_add_sources(tint_lang_wgsl_test test
"lang/wgsl/ir_roundtrip_test.cc"
)
endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_wgsl_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
################################################################################
# Target: tint_lang_wgsl_bench
# Kind: bench
@@ -134,3 +144,7 @@
tint_utils_text
tint_utils_traits
)
+
+tint_target_add_external_dependencies(tint_lang_wgsl_bench bench
+ "google-benchmark"
+)
diff --git a/src/tint/lang/wgsl/BUILD.gn b/src/tint/lang/wgsl/BUILD.gn
index 4ddc480..4a8a3bc 100644
--- a/src/tint/lang/wgsl/BUILD.gn
+++ b/src/tint/lang/wgsl/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -54,7 +54,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"diagnostic_rule_test.cc",
"diagnostic_severity_test.cc",
@@ -72,12 +71,9 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/helpers:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/reader/lower",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/lang/wgsl/writer/ir_to_program",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -94,8 +90,41 @@
"${tint_src_dir}/utils/traits",
]
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
+
if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
sources += [ "ir_roundtrip_test.cc" ]
}
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
+ }
+}
+if (tint_build_benchmarks) {
+ tint_unittests_source_set("bench") {
+ sources = [
+ "diagnostic_rule_bench.cc",
+ "diagnostic_severity_bench.cc",
+ "extension_bench.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
}
}
diff --git a/src/tint/lang/wgsl/ast/BUILD.bazel b/src/tint/lang/wgsl/ast/BUILD.bazel
index 3bed5ae..4ca45b5 100644
--- a/src/tint/lang/wgsl/ast/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/BUILD.bazel
@@ -256,7 +256,6 @@
"location_attribute_test.cc",
"loop_statement_test.cc",
"member_accessor_expression_test.cc",
- "module_clone_test.cc",
"module_test.cc",
"phony_expression_test.cc",
"return_statement_test.cc",
@@ -275,7 +274,16 @@
"variable_test.cc",
"while_statement_test.cc",
"workgroup_attribute_test.cc",
- ],
+ ] + select({
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
+ "module_clone_test.cc",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ "//conditions:default": [],
+ }),
deps = [
"//src/tint/api/common",
"//src/tint/lang/core",
@@ -286,10 +294,8 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -304,8 +310,38 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/wgsl/ast/BUILD.cmake b/src/tint/lang/wgsl/ast/BUILD.cmake
index f9293f9..c060fc8 100644
--- a/src/tint/lang/wgsl/ast/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/BUILD.cmake
@@ -256,7 +256,6 @@
lang/wgsl/ast/location_attribute_test.cc
lang/wgsl/ast/loop_statement_test.cc
lang/wgsl/ast/member_accessor_expression_test.cc
- lang/wgsl/ast/module_clone_test.cc
lang/wgsl/ast/module_test.cc
lang/wgsl/ast/phony_expression_test.cc
lang/wgsl/ast/return_statement_test.cc
@@ -287,10 +286,8 @@
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -309,3 +306,21 @@
tint_target_add_external_dependencies(tint_lang_wgsl_ast_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_ast_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+ tint_target_add_sources(tint_lang_wgsl_ast_test test
+ "lang/wgsl/ast/module_clone_test.cc"
+ )
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_wgsl_ast_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
diff --git a/src/tint/lang/wgsl/ast/BUILD.gn b/src/tint/lang/wgsl/ast/BUILD.gn
index 2cc22fe..b8f68a9 100644
--- a/src/tint/lang/wgsl/ast/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -211,7 +211,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"alias_test.cc",
"assignment_statement_test.cc",
@@ -257,7 +256,6 @@
"location_attribute_test.cc",
"loop_statement_test.cc",
"member_accessor_expression_test.cc",
- "module_clone_test.cc",
"module_test.cc",
"phony_expression_test.cc",
"return_statement_test.cc",
@@ -288,10 +286,8 @@
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -306,5 +302,17 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ sources += [ "module_clone_test.cc" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
diff --git a/src/tint/lang/wgsl/ast/module_clone_test.cc b/src/tint/lang/wgsl/ast/module_clone_test.cc
index a683b0a..035a565 100644
--- a/src/tint/lang/wgsl/ast/module_clone_test.cc
+++ b/src/tint/lang/wgsl/ast/module_clone_test.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// GEN_BUILD:CONDITION(tint_build_wgsl_reader && tint_build_wgsl_writer)
+
#include <unordered_set>
#include "gtest/gtest.h"
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.bazel b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
index 03b8500..cf13cce 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
@@ -173,10 +173,8 @@
"//src/tint/lang/wgsl/ast/transform",
"//src/tint/lang/wgsl/ast:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -191,8 +189,36 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }) + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
+selects.config_setting_group(
+ name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
+ match_all = [
+ ":tint_build_wgsl_reader",
+ ":tint_build_wgsl_writer",
+ ],
+)
+
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.cfg b/src/tint/lang/wgsl/ast/transform/BUILD.cfg
new file mode 100644
index 0000000..f31a82c
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.cfg
@@ -0,0 +1,5 @@
+{
+ "test": {
+ "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer"
+ }
+}
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.cmake b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
index 1f7ecf6..bc523fc 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
@@ -118,9 +118,11 @@
tint_utils_traits
)
+if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_wgsl_ast_transform_test
# Kind: test
+# Condition: TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_wgsl_ast_transform_test test
lang/wgsl/ast/transform/add_block_attribute_test.cc
@@ -172,10 +174,8 @@
tint_lang_wgsl_ast_transform
tint_lang_wgsl_ast_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -194,3 +194,17 @@
tint_target_add_external_dependencies(tint_lang_wgsl_ast_transform_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_ast_transform_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_wgsl_ast_transform_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.gn b/src/tint/lang/wgsl/ast/transform/BUILD.gn
index 958683e..5012415 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -123,75 +123,82 @@
]
}
if (tint_build_unittests) {
- tint_unittests_source_set("unittests") {
- testonly = true
- sources = [
- "add_block_attribute_test.cc",
- "add_empty_entry_point_test.cc",
- "array_length_from_uniform_test.cc",
- "binding_remapper_test.cc",
- "builtin_polyfill_test.cc",
- "canonicalize_entry_point_io_test.cc",
- "demote_to_helper_test.cc",
- "direct_variable_access_test.cc",
- "disable_uniformity_analysis_test.cc",
- "expand_compound_assignment_test.cc",
- "first_index_offset_test.cc",
- "get_insertion_point_test.cc",
- "helper_test.h",
- "hoist_to_decl_before_test.cc",
- "manager_test.cc",
- "multiplanar_external_texture_test.cc",
- "preserve_padding_test.cc",
- "promote_initializers_to_let_test.cc",
- "promote_side_effects_to_decl_test.cc",
- "remove_phonies_test.cc",
- "remove_unreachable_statements_test.cc",
- "renamer_test.cc",
- "robustness_test.cc",
- "simplify_pointers_test.cc",
- "single_entry_point_test.cc",
- "std140_exhaustive_test.cc",
- "std140_f16_test.cc",
- "std140_f32_test.cc",
- "std140_test.cc",
- "substitute_override_test.cc",
- "transform_test.cc",
- "unshadow_test.cc",
- "vectorize_scalar_matrix_initializers_test.cc",
- "vertex_pulling_test.cc",
- "zero_init_workgroup_memory_test.cc",
- ]
- deps = [
- "${tint_src_dir}:gmock_and_gtest",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/ast:unittests",
- "${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
+ if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+ tint_unittests_source_set("unittests") {
+ sources = [
+ "add_block_attribute_test.cc",
+ "add_empty_entry_point_test.cc",
+ "array_length_from_uniform_test.cc",
+ "binding_remapper_test.cc",
+ "builtin_polyfill_test.cc",
+ "canonicalize_entry_point_io_test.cc",
+ "demote_to_helper_test.cc",
+ "direct_variable_access_test.cc",
+ "disable_uniformity_analysis_test.cc",
+ "expand_compound_assignment_test.cc",
+ "first_index_offset_test.cc",
+ "get_insertion_point_test.cc",
+ "helper_test.h",
+ "hoist_to_decl_before_test.cc",
+ "manager_test.cc",
+ "multiplanar_external_texture_test.cc",
+ "preserve_padding_test.cc",
+ "promote_initializers_to_let_test.cc",
+ "promote_side_effects_to_decl_test.cc",
+ "remove_phonies_test.cc",
+ "remove_unreachable_statements_test.cc",
+ "renamer_test.cc",
+ "robustness_test.cc",
+ "simplify_pointers_test.cc",
+ "single_entry_point_test.cc",
+ "std140_exhaustive_test.cc",
+ "std140_f16_test.cc",
+ "std140_f32_test.cc",
+ "std140_test.cc",
+ "substitute_override_test.cc",
+ "transform_test.cc",
+ "unshadow_test.cc",
+ "vectorize_scalar_matrix_initializers_test.cc",
+ "vertex_pulling_test.cc",
+ "zero_init_workgroup_memory_test.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/api/options",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/ast:unittests",
+ "${tint_src_dir}/lang/wgsl/ast/transform",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/resolver",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
+ }
}
}
diff --git a/src/tint/lang/wgsl/ast/transform/single_entry_point.cc b/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
index c61798d..8daf8d1 100644
--- a/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
+++ b/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
@@ -20,6 +20,7 @@
#include "src/tint/lang/wgsl/program/clone_context.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolve.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/function.h"
#include "src/tint/lang/wgsl/sem/variable.h"
#include "src/tint/utils/rtti/switch.h"
@@ -73,13 +74,10 @@
decl, //
[&](const TypeDecl* ty) {
// Strip aliases that reference unused override declarations.
- if (auto* arr = sem.Get(ty)->As<core::type::Array>()) {
- auto* refs = sem.TransitivelyReferencedOverrides(arr);
- if (refs) {
- for (auto* o : *refs) {
- if (!referenced_vars.Contains(o)) {
- return;
- }
+ if (auto* arr = sem.Get(ty)->As<sem::Array>()) {
+ for (auto* o : arr->TransitivelyReferencedOverrides()) {
+ if (!referenced_vars.Contains(o)) {
+ return;
}
}
}
diff --git a/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc b/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
index cc747fb..944ecf4 100644
--- a/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
+++ b/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
@@ -126,6 +126,8 @@
return out << "sint32x3";
case VertexFormat::kSint32x4:
return out << "sint32x4";
+ case VertexFormat::kUnorm10_10_10_2:
+ return out << "unorm10-10-10-2";
}
return out << "<unknown>";
}
@@ -223,6 +225,7 @@
case VertexFormat::kSnorm16x4:
case VertexFormat::kFloat16x4:
case VertexFormat::kFloat32x4:
+ case VertexFormat::kUnorm10_10_10_2:
return {VertexDataType::kFloat, 4};
}
return {VertexDataType::kInvalid, 0};
@@ -667,6 +670,15 @@
case VertexFormat::kFloat16x4:
return b.Call<vec4<f32>>(b.Call("unpack2x16float", load_u32()),
b.Call("unpack2x16float", load_next_u32()));
+ case VertexFormat::kUnorm10_10_10_2:
+ auto* u32s = b.Call<vec4<u32>>(load_u32());
+ // shr = u32s >> vec4u(0, 10, 20, 30);
+ auto* shr = b.Shr(u32s, b.Call<vec4<u32>>(0_u, 10_u, 20_u, 30_u));
+ // mask = shr & vec4u(0x3FF, 0x3FF, 0x3FF, 0x3);
+ auto* mask = b.And(shr, b.Call<vec4<u32>>(0x3FF_u, 0x3FF_u, 0x3FF_u, 0x3_u));
+ // return vec4f(mask) / vec4f(1023, 1023, 1023, 3);
+ return b.Div(b.Call<vec4<f32>>(mask),
+ b.Call<vec4<f32>>(1023_f, 1023_f, 1023_f, 3_f));
}
TINT_UNREACHABLE() << "format " << static_cast<int>(format);
diff --git a/src/tint/lang/wgsl/ast/transform/vertex_pulling.h b/src/tint/lang/wgsl/ast/transform/vertex_pulling.h
index deaed5a..e5084ab 100644
--- a/src/tint/lang/wgsl/ast/transform/vertex_pulling.h
+++ b/src/tint/lang/wgsl/ast/transform/vertex_pulling.h
@@ -27,36 +27,37 @@
/// Describes the format of data in a vertex buffer
enum class VertexFormat {
- kUint8x2, // uint8x2
- kUint8x4, // uint8x4
- kSint8x2, // sint8x2
- kSint8x4, // sint8x4
- kUnorm8x2, // unorm8x2
- kUnorm8x4, // unorm8x4
- kSnorm8x2, // snorm8x2
- kSnorm8x4, // snorm8x4
- kUint16x2, // uint16x2
- kUint16x4, // uint16x4
- kSint16x2, // sint16x2
- kSint16x4, // sint16x4
- kUnorm16x2, // unorm16x2
- kUnorm16x4, // unorm16x4
- kSnorm16x2, // snorm16x2
- kSnorm16x4, // snorm16x4
- kFloat16x2, // float16x2
- kFloat16x4, // float16x4
- kFloat32, // float32
- kFloat32x2, // float32x2
- kFloat32x3, // float32x3
- kFloat32x4, // float32x4
- kUint32, // uint32
- kUint32x2, // uint32x2
- kUint32x3, // uint32x3
- kUint32x4, // uint32x4
- kSint32, // sint32
- kSint32x2, // sint32x2
- kSint32x3, // sint32x3
- kSint32x4, // sint32x4
+ kUint8x2, // uint8x2
+ kUint8x4, // uint8x4
+ kSint8x2, // sint8x2
+ kSint8x4, // sint8x4
+ kUnorm8x2, // unorm8x2
+ kUnorm8x4, // unorm8x4
+ kSnorm8x2, // snorm8x2
+ kSnorm8x4, // snorm8x4
+ kUint16x2, // uint16x2
+ kUint16x4, // uint16x4
+ kSint16x2, // sint16x2
+ kSint16x4, // sint16x4
+ kUnorm16x2, // unorm16x2
+ kUnorm16x4, // unorm16x4
+ kSnorm16x2, // snorm16x2
+ kSnorm16x4, // snorm16x4
+ kFloat16x2, // float16x2
+ kFloat16x4, // float16x4
+ kFloat32, // float32
+ kFloat32x2, // float32x2
+ kFloat32x3, // float32x3
+ kFloat32x4, // float32x4
+ kUint32, // uint32
+ kUint32x2, // uint32x2
+ kUint32x3, // uint32x3
+ kUint32x4, // uint32x4
+ kSint32, // sint32
+ kSint32x2, // sint32x2
+ kSint32x3, // sint32x3
+ kSint32x4, // sint32x4
+ kUnorm10_10_10_2, // unorm10-10-10-2
kLastEntry = kSint32x4,
};
diff --git a/src/tint/lang/wgsl/ast/transform/vertex_pulling_test.cc b/src/tint/lang/wgsl/ast/transform/vertex_pulling_test.cc
index 5bb7c59..df3f1c8 100644
--- a/src/tint/lang/wgsl/ast/transform/vertex_pulling_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/vertex_pulling_test.cc
@@ -1000,6 +1000,7 @@
@location(11) float32x2 : vec2<f32>,
@location(12) float32x3 : vec3<f32>,
@location(13) float32x4 : vec4<f32>,
+ @location(14) unorm10_10_10_2 : vec4<f32>,
) -> @builtin(position) vec4<f32> {
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
@@ -1028,6 +1029,7 @@
var float32x2 : vec2<f32>;
var float32x3 : vec3<f32>;
var float32x4 : vec4<f32>;
+ var unorm10_10_10_2 : vec4<f32>;
{
let buffer_array_base_0 = (tint_pulling_vertex_index * 64u);
unorm8x2 = unpack4x8unorm((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] & 65535u)).xy;
@@ -1044,6 +1046,7 @@
float32x2 = vec2<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]));
float32x3 = vec3<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]));
float32x4 = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)]));
+ unorm10_10_10_2 = (vec4<f32>(((vec4<u32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) >> vec4<u32>(0u, 10u, 20u, 30u)) & vec4<u32>(1023u, 1023u, 1023u, 3u))) / vec4<f32>(1023.0f, 1023.0f, 1023.0f, 3.0f));
}
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
@@ -1067,6 +1070,7 @@
{VertexFormat::kFloat32x2, 64, 11},
{VertexFormat::kFloat32x3, 64, 12},
{VertexFormat::kFloat32x4, 64, 13},
+ {VertexFormat::kUnorm10_10_10_2, 64, 14},
}}}};
DataMap data;
@@ -1332,6 +1336,7 @@
@location(11) float32x2 : vec2<f32>,
@location(12) float32x3 : vec3<f32>,
@location(13) float32x4 : vec4<f32>,
+ @location(14) unorm10_10_10_2 : vec4<f32>,
) -> @builtin(position) vec4<f32> {
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
@@ -1360,6 +1365,7 @@
var float32x2 : vec2<f32>;
var float32x3 : vec3<f32>;
var float32x4 : vec4<f32>;
+ var unorm10_10_10_2 : vec4<f32>;
{
let buffer_array_base_0 = (tint_pulling_vertex_index * 64u);
unorm8x2 = unpack4x8unorm((((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u)) & 65535u)).xy;
@@ -1376,6 +1382,7 @@
float32x2 = vec2<f32>(bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))));
float32x3 = vec3<f32>(bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))), bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u))));
float32x4 = vec4<f32>(bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))), bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u))), bitcast<f32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)] << 8u))));
+ unorm10_10_10_2 = (vec4<f32>(((vec4<u32>(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))) >> vec4<u32>(0u, 10u, 20u, 30u)) & vec4<u32>(1023u, 1023u, 1023u, 3u))) / vec4<f32>(1023.0f, 1023.0f, 1023.0f, 3.0f));
}
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
@@ -1399,6 +1406,7 @@
{VertexFormat::kFloat32x2, 63, 11},
{VertexFormat::kFloat32x3, 63, 12},
{VertexFormat::kFloat32x4, 63, 13},
+ {VertexFormat::kUnorm10_10_10_2, 63, 14},
}}}};
DataMap data;
@@ -2088,6 +2096,9 @@
@location(23) sclr_float32x4 : f32 ,
@location(24) vec2_float32x4 : vec2<f32>,
@location(25) vec3_float32x4 : vec3<f32>,
+ @location(26) sclr_unorm10_10_10_2 : f32 ,
+ @location(27) vec2_unorm10_10_10_2 : vec2<f32>,
+ @location(28) vec3_unorm10_10_10_2 : vec3<f32>,
) -> @builtin(position) vec4<f32> {
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
@@ -2128,6 +2139,9 @@
var sclr_float32x4 : f32;
var vec2_float32x4 : vec2<f32>;
var vec3_float32x4 : vec3<f32>;
+ var sclr_unorm10_10_10_2 : f32;
+ var vec2_unorm10_10_10_2 : vec2<f32>;
+ var vec3_unorm10_10_10_2 : vec3<f32>;
{
let buffer_array_base_0 = (tint_pulling_vertex_index * 64u);
sclr_unorm8x2 = unpack4x8unorm((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] & 65535u)).xy.x;
@@ -2156,6 +2170,9 @@
sclr_float32x4 = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])).x;
vec2_float32x4 = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])).xy;
vec3_float32x4 = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])).xyz;
+ sclr_unorm10_10_10_2 = ((vec4<f32>(((vec4<u32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) >> vec4<u32>(0u, 10u, 20u, 30u)) & vec4<u32>(1023u, 1023u, 1023u, 3u))) / vec4<f32>(1023.0f, 1023.0f, 1023.0f, 3.0f))).x;
+ vec2_unorm10_10_10_2 = ((vec4<f32>(((vec4<u32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) >> vec4<u32>(0u, 10u, 20u, 30u)) & vec4<u32>(1023u, 1023u, 1023u, 3u))) / vec4<f32>(1023.0f, 1023.0f, 1023.0f, 3.0f))).xy;
+ vec3_unorm10_10_10_2 = ((vec4<f32>(((vec4<u32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) >> vec4<u32>(0u, 10u, 20u, 30u)) & vec4<u32>(1023u, 1023u, 1023u, 3u))) / vec4<f32>(1023.0f, 1023.0f, 1023.0f, 3.0f))).xyz;
}
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
@@ -2166,19 +2183,21 @@
{{256,
VertexStepMode::kVertex,
{
- {VertexFormat::kUnorm8x2, 64, 0}, {VertexFormat::kUnorm8x4, 64, 1},
- {VertexFormat::kUnorm8x4, 64, 2}, {VertexFormat::kUnorm8x4, 64, 3},
- {VertexFormat::kSnorm8x2, 64, 4}, {VertexFormat::kSnorm8x4, 64, 5},
- {VertexFormat::kSnorm8x4, 64, 6}, {VertexFormat::kSnorm8x4, 64, 7},
- {VertexFormat::kUnorm16x2, 64, 8}, {VertexFormat::kUnorm16x4, 64, 9},
- {VertexFormat::kUnorm16x4, 64, 10}, {VertexFormat::kUnorm16x4, 64, 11},
- {VertexFormat::kSnorm16x2, 64, 12}, {VertexFormat::kSnorm16x4, 64, 13},
- {VertexFormat::kSnorm16x4, 64, 14}, {VertexFormat::kSnorm16x4, 64, 15},
- {VertexFormat::kFloat16x2, 64, 16}, {VertexFormat::kFloat16x4, 64, 17},
- {VertexFormat::kFloat16x4, 64, 18}, {VertexFormat::kFloat16x4, 64, 19},
- {VertexFormat::kFloat32x2, 64, 20}, {VertexFormat::kFloat32x3, 64, 21},
- {VertexFormat::kFloat32x3, 64, 22}, {VertexFormat::kFloat32x4, 64, 23},
- {VertexFormat::kFloat32x4, 64, 24}, {VertexFormat::kFloat32x4, 64, 25},
+ {VertexFormat::kUnorm8x2, 64, 0}, {VertexFormat::kUnorm8x4, 64, 1},
+ {VertexFormat::kUnorm8x4, 64, 2}, {VertexFormat::kUnorm8x4, 64, 3},
+ {VertexFormat::kSnorm8x2, 64, 4}, {VertexFormat::kSnorm8x4, 64, 5},
+ {VertexFormat::kSnorm8x4, 64, 6}, {VertexFormat::kSnorm8x4, 64, 7},
+ {VertexFormat::kUnorm16x2, 64, 8}, {VertexFormat::kUnorm16x4, 64, 9},
+ {VertexFormat::kUnorm16x4, 64, 10}, {VertexFormat::kUnorm16x4, 64, 11},
+ {VertexFormat::kSnorm16x2, 64, 12}, {VertexFormat::kSnorm16x4, 64, 13},
+ {VertexFormat::kSnorm16x4, 64, 14}, {VertexFormat::kSnorm16x4, 64, 15},
+ {VertexFormat::kFloat16x2, 64, 16}, {VertexFormat::kFloat16x4, 64, 17},
+ {VertexFormat::kFloat16x4, 64, 18}, {VertexFormat::kFloat16x4, 64, 19},
+ {VertexFormat::kFloat32x2, 64, 20}, {VertexFormat::kFloat32x3, 64, 21},
+ {VertexFormat::kFloat32x3, 64, 22}, {VertexFormat::kFloat32x4, 64, 23},
+ {VertexFormat::kFloat32x4, 64, 24}, {VertexFormat::kFloat32x4, 64, 25},
+ {VertexFormat::kUnorm10_10_10_2, 64, 26}, {VertexFormat::kUnorm10_10_10_2, 64, 27},
+ {VertexFormat::kUnorm10_10_10_2, 64, 28},
}}}};
DataMap data;
diff --git a/src/tint/lang/wgsl/ast/traverse_expressions.h b/src/tint/lang/wgsl/ast/traverse_expressions.h
index 17688c2..7319a78 100644
--- a/src/tint/lang/wgsl/ast/traverse_expressions.h
+++ b/src/tint/lang/wgsl/ast/traverse_expressions.h
@@ -24,6 +24,7 @@
#include "src/tint/lang/wgsl/ast/literal_expression.h"
#include "src/tint/lang/wgsl/ast/member_accessor_expression.h"
#include "src/tint/lang/wgsl/ast/phony_expression.h"
+#include "src/tint/lang/wgsl/ast/templated_identifier.h"
#include "src/tint/lang/wgsl/ast/unary_op_expression.h"
#include "src/tint/utils/containers/reverse.h"
#include "src/tint/utils/containers/vector.h"
@@ -73,7 +74,7 @@
auto push_single = [&](const Expression* expr, size_t depth) { to_visit.Push({expr, depth}); };
auto push_pair = [&](const Expression* left, const Expression* right, size_t depth) {
- if (ORDER == TraverseOrder::LeftToRight) {
+ if constexpr (ORDER == TraverseOrder::LeftToRight) {
to_visit.Push({right, depth});
to_visit.Push({left, depth});
} else {
@@ -82,7 +83,7 @@
}
};
auto push_list = [&](VectorRef<const Expression*> exprs, size_t depth) {
- if (ORDER == TraverseOrder::LeftToRight) {
+ if constexpr (ORDER == TraverseOrder::LeftToRight) {
for (auto* expr : tint::Reverse(exprs)) {
to_visit.Push({expr, depth});
}
@@ -117,6 +118,12 @@
bool ok = Switch(
expr,
+ [&](const IdentifierExpression* ident) {
+ if (auto* tmpl = ident->identifier->As<TemplatedIdentifier>()) {
+ push_list(tmpl->arguments, p.depth + 1);
+ }
+ return true;
+ },
[&](const IndexAccessorExpression* idx) {
push_pair(idx->object, idx->index, p.depth + 1);
return true;
@@ -130,7 +137,13 @@
return true;
},
[&](const CallExpression* call) {
- push_list(call->args, p.depth + 1);
+ if constexpr (ORDER == TraverseOrder::LeftToRight) {
+ push_list(call->args, p.depth + 1);
+ push_single(call->target, p.depth + 1);
+ } else {
+ push_single(call->target, p.depth + 1);
+ push_list(call->args, p.depth + 1);
+ }
return true;
},
[&](const MemberAccessorExpression* member) {
@@ -142,8 +155,7 @@
return true;
},
[&](Default) {
- if (TINT_LIKELY((expr->IsAnyOf<LiteralExpression, IdentifierExpression,
- PhonyExpression>()))) {
+ if (TINT_LIKELY((expr->IsAnyOf<LiteralExpression, PhonyExpression>()))) {
return true; // Leaf expression
}
TINT_ICE() << "unhandled expression type: "
diff --git a/src/tint/lang/wgsl/ast/traverse_expressions_test.cc b/src/tint/lang/wgsl/ast/traverse_expressions_test.cc
index c477ac0..85da66c 100644
--- a/src/tint/lang/wgsl/ast/traverse_expressions_test.cc
+++ b/src/tint/lang/wgsl/ast/traverse_expressions_test.cc
@@ -27,22 +27,44 @@
using TraverseExpressionsTest = TestHelper;
+TEST_F(TraverseExpressionsTest, DescendTemplatedIdentifier) {
+ tint::Vector e{Expr(1_i), Expr(2_i), Expr(1_i), Expr(1_i)};
+ tint::Vector c{Expr(Ident("a", e[0], e[1])), Expr(Ident("b", e[2], e[3]))};
+ auto* root = Expr(Ident("c", c[0], c[1]));
+ {
+ Vector<const Expression*, 8> l2r;
+ TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
+ l2r.Push(expr);
+ return TraverseAction::Descend;
+ });
+ EXPECT_THAT(l2r, ElementsAre(root, c[0], e[0], e[1], c[1], e[2], e[3]));
+ }
+ {
+ Vector<const Expression*, 8> r2l;
+ TraverseExpressions<TraverseOrder::RightToLeft>(root, [&](const Expression* expr) {
+ r2l.Push(expr);
+ return TraverseAction::Descend;
+ });
+ EXPECT_THAT(r2l, ElementsAre(root, c[1], e[3], e[2], c[0], e[1], e[0]));
+ }
+}
+
TEST_F(TraverseExpressionsTest, DescendIndexAccessor) {
- std::vector<const Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
- std::vector<const Expression*> i = {IndexAccessor(e[0], e[1]), IndexAccessor(e[2], e[3])};
+ Vector e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
+ Vector i = {IndexAccessor(e[0], e[1]), IndexAccessor(e[2], e[3])};
auto* root = IndexAccessor(i[0], i[1]);
{
- std::vector<const Expression*> l2r;
+ Vector<const ast::Expression*, 8> l2r;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- l2r.push_back(expr);
+ l2r.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(l2r, ElementsAre(root, i[0], e[0], e[1], i[1], e[2], e[3]));
}
{
- std::vector<const Expression*> r2l;
+ Vector<const ast::Expression*, 8> r2l;
TraverseExpressions<TraverseOrder::RightToLeft>(root, [&](const Expression* expr) {
- r2l.push_back(expr);
+ r2l.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(r2l, ElementsAre(root, i[1], e[3], e[2], i[0], e[1], e[0]));
@@ -50,21 +72,21 @@
}
TEST_F(TraverseExpressionsTest, DescendBinaryExpression) {
- std::vector<const Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
- std::vector<const Expression*> i = {Add(e[0], e[1]), Sub(e[2], e[3])};
+ Vector e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
+ Vector i = {Add(e[0], e[1]), Sub(e[2], e[3])};
auto* root = Mul(i[0], i[1]);
{
- std::vector<const Expression*> l2r;
+ Vector<const ast::Expression*, 8> l2r;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- l2r.push_back(expr);
+ l2r.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(l2r, ElementsAre(root, i[0], e[0], e[1], i[1], e[2], e[3]));
}
{
- std::vector<const Expression*> r2l;
+ Vector<const ast::Expression*, 8> r2l;
TraverseExpressions<TraverseOrder::RightToLeft>(root, [&](const Expression* expr) {
- r2l.push_back(expr);
+ r2l.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(r2l, ElementsAre(root, i[1], e[3], e[2], i[0], e[1], e[0]));
@@ -72,8 +94,8 @@
}
TEST_F(TraverseExpressionsTest, Depth) {
- std::vector<const Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
- std::vector<const Expression*> i = {Add(e[0], e[1]), Sub(e[2], e[3])};
+ Vector e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
+ Vector i = {Add(e[0], e[1]), Sub(e[2], e[3])};
auto* root = Mul(i[0], i[1]);
size_t j = 0;
@@ -113,16 +135,17 @@
}
TEST_F(TraverseExpressionsTest, DescendCallExpression) {
- tint::Vector e{Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
- tint::Vector c{Call("a", e[0], e[1]), Call("b", e[2], e[3])};
- auto* root = Call("c", c[0], c[1]);
+ tint::Vector i{Expr("a"), Expr("b"), Expr("c")};
+ tint::Vector e{Expr(1_i), Expr(2_i), Expr(1_i), Expr(1_i)};
+ tint::Vector c{Call(i[0], e[0], e[1]), Call(i[1], e[2], e[3])};
+ auto* root = Call(i[2], c[0], c[1]);
{
Vector<const Expression*, 8> l2r;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
l2r.Push(expr);
return TraverseAction::Descend;
});
- EXPECT_THAT(l2r, ElementsAre(root, c[0], e[0], e[1], c[1], e[2], e[3]));
+ EXPECT_THAT(l2r, ElementsAre(root, i[2], c[0], i[0], e[0], e[1], c[1], i[1], e[2], e[3]));
}
{
Vector<const Expression*, 8> r2l;
@@ -130,7 +153,7 @@
r2l.Push(expr);
return TraverseAction::Descend;
});
- EXPECT_THAT(r2l, ElementsAre(root, c[1], e[3], e[2], c[0], e[1], e[0]));
+ EXPECT_THAT(r2l, ElementsAre(root, c[1], e[3], e[2], i[1], c[0], e[1], e[0], i[0], i[2]));
}
}
@@ -139,17 +162,17 @@
auto* m = MemberAccessor(e, "a");
auto* root = MemberAccessor(m, "b");
{
- std::vector<const Expression*> l2r;
+ Vector<const ast::Expression*, 8> l2r;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- l2r.push_back(expr);
+ l2r.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(l2r, ElementsAre(root, m, e));
}
{
- std::vector<const Expression*> r2l;
+ Vector<const ast::Expression*, 8> r2l;
TraverseExpressions<TraverseOrder::RightToLeft>(root, [&](const Expression* expr) {
- r2l.push_back(expr);
+ r2l.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(r2l, ElementsAre(root, m, e));
@@ -165,17 +188,17 @@
auto* f = IndexAccessor(d, e);
auto* root = IndexAccessor(c, f);
{
- std::vector<const Expression*> l2r;
+ Vector<const ast::Expression*, 8> l2r;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- l2r.push_back(expr);
+ l2r.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(l2r, ElementsAre(root, c, a, b, f, d, e));
}
{
- std::vector<const Expression*> r2l;
+ Vector<const ast::Expression*, 8> r2l;
TraverseExpressions<TraverseOrder::RightToLeft>(root, [&](const Expression* expr) {
- r2l.push_back(expr);
+ r2l.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(r2l, ElementsAre(root, f, e, d, c, b, a));
@@ -189,17 +212,17 @@
auto* u2 = AddressOf(u1);
auto* root = Deref(u2);
{
- std::vector<const Expression*> l2r;
+ Vector<const ast::Expression*, 8> l2r;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- l2r.push_back(expr);
+ l2r.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(l2r, ElementsAre(root, u2, u1, u0, e));
}
{
- std::vector<const Expression*> r2l;
+ Vector<const ast::Expression*, 8> r2l;
TraverseExpressions<TraverseOrder::RightToLeft>(root, [&](const Expression* expr) {
- r2l.push_back(expr);
+ r2l.Push(expr);
return TraverseAction::Descend;
});
EXPECT_THAT(r2l, ElementsAre(root, u2, u1, u0, e));
@@ -207,24 +230,24 @@
}
TEST_F(TraverseExpressionsTest, Skip) {
- std::vector<const Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
- std::vector<const Expression*> i = {IndexAccessor(e[0], e[1]), IndexAccessor(e[2], e[3])};
+ Vector e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
+ Vector i = {IndexAccessor(e[0], e[1]), IndexAccessor(e[2], e[3])};
auto* root = IndexAccessor(i[0], i[1]);
- std::vector<const Expression*> order;
+ Vector<const ast::Expression*, 8> order;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- order.push_back(expr);
+ order.Push(expr);
return expr == i[0] ? TraverseAction::Skip : TraverseAction::Descend;
});
EXPECT_THAT(order, ElementsAre(root, i[0], i[1], e[2], e[3]));
}
TEST_F(TraverseExpressionsTest, Stop) {
- std::vector<const Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
- std::vector<const Expression*> i = {IndexAccessor(e[0], e[1]), IndexAccessor(e[2], e[3])};
+ Vector e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
+ Vector i = {IndexAccessor(e[0], e[1]), IndexAccessor(e[2], e[3])};
auto* root = IndexAccessor(i[0], i[1]);
- std::vector<const Expression*> order;
+ Vector<const ast::Expression*, 8> order;
TraverseExpressions<TraverseOrder::LeftToRight>(root, [&](const Expression* expr) {
- order.push_back(expr);
+ order.Push(expr);
return expr == i[0] ? TraverseAction::Stop : TraverseAction::Descend;
});
EXPECT_THAT(order, ElementsAre(root, i[0]));
diff --git a/src/tint/lang/wgsl/helpers/BUILD.bazel b/src/tint/lang/wgsl/helpers/BUILD.bazel
index 16067dd..4afa836 100644
--- a/src/tint/lang/wgsl/helpers/BUILD.bazel
+++ b/src/tint/lang/wgsl/helpers/BUILD.bazel
@@ -27,11 +27,13 @@
name = "helpers",
srcs = [
"append_vector.cc",
+ "apply_substitute_overrides.cc",
"check_supported_extensions.cc",
"flatten_bindings.cc",
],
hdrs = [
"append_vector.h",
+ "apply_substitute_overrides.h",
"check_supported_extensions.h",
"flatten_bindings.h",
],
@@ -70,8 +72,12 @@
"append_vector_test.cc",
"check_supported_extensions_test.cc",
"flatten_bindings_test.cc",
- "ir_program_test.h",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "ir_program_test.h",
+ ],
+ "//conditions:default": [],
+ }),
deps = [
"//src/tint/api/common",
"//src/tint/lang/core",
@@ -85,9 +91,7 @@
"//src/tint/lang/wgsl/helpers",
"//src/tint/lang/wgsl/intrinsic",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/reader/lower",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
@@ -104,8 +108,19 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/wgsl/helpers/BUILD.cmake b/src/tint/lang/wgsl/helpers/BUILD.cmake
index 6eb49fb..9a77250 100644
--- a/src/tint/lang/wgsl/helpers/BUILD.cmake
+++ b/src/tint/lang/wgsl/helpers/BUILD.cmake
@@ -28,6 +28,8 @@
tint_add_target(tint_lang_wgsl_helpers lib
lang/wgsl/helpers/append_vector.cc
lang/wgsl/helpers/append_vector.h
+ lang/wgsl/helpers/apply_substitute_overrides.cc
+ lang/wgsl/helpers/apply_substitute_overrides.h
lang/wgsl/helpers/check_supported_extensions.cc
lang/wgsl/helpers/check_supported_extensions.h
lang/wgsl/helpers/flatten_bindings.cc
@@ -68,7 +70,6 @@
lang/wgsl/helpers/append_vector_test.cc
lang/wgsl/helpers/check_supported_extensions_test.cc
lang/wgsl/helpers/flatten_bindings_test.cc
- lang/wgsl/helpers/ir_program_test.h
)
tint_target_add_dependencies(tint_lang_wgsl_helpers_test test
@@ -84,9 +85,7 @@
tint_lang_wgsl_helpers
tint_lang_wgsl_intrinsic
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_reader_lower
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
tint_utils_containers
@@ -107,3 +106,13 @@
tint_target_add_external_dependencies(tint_lang_wgsl_helpers_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_sources(tint_lang_wgsl_helpers_test test
+ "lang/wgsl/helpers/ir_program_test.h"
+ )
+ tint_target_add_dependencies(tint_lang_wgsl_helpers_test test
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
diff --git a/src/tint/lang/wgsl/helpers/BUILD.gn b/src/tint/lang/wgsl/helpers/BUILD.gn
index 25ea790..42370f6 100644
--- a/src/tint/lang/wgsl/helpers/BUILD.gn
+++ b/src/tint/lang/wgsl/helpers/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -33,6 +33,8 @@
sources = [
"append_vector.cc",
"append_vector.h",
+ "apply_substitute_overrides.cc",
+ "apply_substitute_overrides.h",
"check_supported_extensions.cc",
"check_supported_extensions.h",
"flatten_bindings.cc",
@@ -66,12 +68,10 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"append_vector_test.cc",
"check_supported_extensions_test.cc",
"flatten_bindings_test.cc",
- "ir_program_test.h",
]
deps = [
"${tint_src_dir}:gmock_and_gtest",
@@ -87,9 +87,7 @@
"${tint_src_dir}/lang/wgsl/helpers",
"${tint_src_dir}/lang/wgsl/intrinsic",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/reader/lower",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/containers",
@@ -106,5 +104,13 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_wgsl_reader) {
+ sources += [ "ir_program_test.h" ]
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
}
}
diff --git a/src/tint/lang/wgsl/helpers/append_vector.cc b/src/tint/lang/wgsl/helpers/append_vector.cc
index 0f0da17..6affec6 100644
--- a/src/tint/lang/wgsl/helpers/append_vector.cc
+++ b/src/tint/lang/wgsl/helpers/append_vector.cc
@@ -26,7 +26,7 @@
using namespace tint::core::number_suffixes; // NOLINT
-namespace tint::writer {
+namespace tint::wgsl {
namespace {
struct VectorConstructorInfo {
@@ -134,11 +134,9 @@
if (packed_el_sem_ty != scalar_sem->Type()->UnwrapRef()) {
// Cast scalar to the vector element type
auto* scalar_cast_ast = b->Call(packed_el_ast_ty, scalar_ast);
- auto* scalar_cast_target = b->create<sem::ValueConversion>(
- packed_el_sem_ty,
- b->create<sem::Parameter>(nullptr, 0u, scalar_sem->Type()->UnwrapRef(),
- core::AddressSpace::kUndefined, core::Access::kUndefined),
- core::EvaluationStage::kRuntime);
+ auto* param = b->create<sem::Parameter>(nullptr, 0u, scalar_sem->Type()->UnwrapRef());
+ auto* scalar_cast_target = b->create<sem::ValueConversion>(packed_el_sem_ty, param,
+ core::EvaluationStage::kRuntime);
auto* scalar_cast_sem = b->create<sem::Call>(
scalar_cast_ast, scalar_cast_target, core::EvaluationStage::kRuntime,
Vector<const sem::ValueExpression*, 1>{scalar_sem}, statement,
@@ -157,9 +155,8 @@
packed_sem_ty,
tint::Transform(packed,
[&](const tint::sem::ValueExpression* arg, size_t i) {
- return b->create<sem::Parameter>(
- nullptr, static_cast<uint32_t>(i), arg->Type()->UnwrapRef(),
- core::AddressSpace::kUndefined, core::Access::kUndefined);
+ return b->create<sem::Parameter>(nullptr, static_cast<uint32_t>(i),
+ arg->Type()->UnwrapRef());
}),
core::EvaluationStage::kRuntime);
auto* ctor_sem = b->create<sem::Call>(ctor_ast, ctor_target, core::EvaluationStage::kRuntime,
@@ -170,4 +167,4 @@
return ctor_sem;
}
-} // namespace tint::writer
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/helpers/append_vector.h b/src/tint/lang/wgsl/helpers/append_vector.h
index 3a73fc2..cb51a6a 100644
--- a/src/tint/lang/wgsl/helpers/append_vector.h
+++ b/src/tint/lang/wgsl/helpers/append_vector.h
@@ -26,7 +26,7 @@
class Call;
} // namespace tint::sem
-namespace tint::writer {
+namespace tint::wgsl {
/// A helper function used to append a vector with an additional scalar.
/// If the scalar's type does not match the target vector element type,
@@ -42,6 +42,6 @@
const ast::Expression* vector,
const ast::Expression* scalar);
-} // namespace tint::writer
+} // namespace tint::wgsl
#endif // SRC_TINT_LANG_WGSL_HELPERS_APPEND_VECTOR_H_
diff --git a/src/tint/lang/wgsl/helpers/append_vector_test.cc b/src/tint/lang/wgsl/helpers/append_vector_test.cc
index 8829706..03201c5 100644
--- a/src/tint/lang/wgsl/helpers/append_vector_test.cc
+++ b/src/tint/lang/wgsl/helpers/append_vector_test.cc
@@ -20,7 +20,7 @@
#include "gmock/gmock.h"
-namespace tint::writer {
+namespace tint::wgsl {
namespace {
using namespace tint::core::fluent_types; // NOLINT
@@ -498,4 +498,4 @@
}
} // namespace
-} // namespace tint::writer
+} // namespace tint::wgsl
diff --git a/src/tint/fuzzers/apply_substitute_overrides.cc b/src/tint/lang/wgsl/helpers/apply_substitute_overrides.cc
similarity index 88%
rename from src/tint/fuzzers/apply_substitute_overrides.cc
rename to src/tint/lang/wgsl/helpers/apply_substitute_overrides.cc
index e5ef24d..0065689 100644
--- a/src/tint/fuzzers/apply_substitute_overrides.cc
+++ b/src/tint/lang/wgsl/helpers/apply_substitute_overrides.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/tint/fuzzers/apply_substitute_overrides.h"
+#include "src/tint/lang/wgsl/helpers/apply_substitute_overrides.h"
#include <memory>
#include <utility>
@@ -22,9 +22,9 @@
#include "src/tint/lang/wgsl/inspector/inspector.h"
#include "src/tint/lang/wgsl/program/program.h"
-namespace tint::fuzzers {
+namespace tint::wgsl {
-Program ApplySubstituteOverrides(Program&& program) {
+std::optional<Program> ApplySubstituteOverrides(const Program& program) {
ast::transform::SubstituteOverride::Config cfg;
inspector::Inspector inspector(program);
auto default_values = inspector.GetOverrideDefaultValues();
@@ -37,7 +37,7 @@
}
if (default_values.empty()) {
- return std::move(program);
+ return std::nullopt;
}
ast::transform::DataMap override_data;
@@ -50,4 +50,4 @@
return mgr.Run(program, override_data, outputs);
}
-} // namespace tint::fuzzers
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/helpers/apply_substitute_overrides.h b/src/tint/lang/wgsl/helpers/apply_substitute_overrides.h
new file mode 100644
index 0000000..dd6da44
--- /dev/null
+++ b/src/tint/lang/wgsl/helpers/apply_substitute_overrides.h
@@ -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.
+
+#ifndef SRC_TINT_LANG_WGSL_HELPERS_APPLY_SUBSTITUTE_OVERRIDES_H_
+#define SRC_TINT_LANG_WGSL_HELPERS_APPLY_SUBSTITUTE_OVERRIDES_H_
+
+#include <optional>
+
+// Forward declarations
+namespace tint {
+class Program;
+}
+
+namespace tint::wgsl {
+
+/// If needed, returns a new program with all `override` declarations substituted with `const`
+/// variables.
+/// @param program A valid program
+/// @return A new program with `override`s substituted, or std::nullopt if the program has no
+/// `override`s.
+std::optional<Program> ApplySubstituteOverrides(const Program& program);
+
+} // namespace tint::wgsl
+
+#endif // SRC_TINT_LANG_WGSL_HELPERS_APPLY_SUBSTITUTE_OVERRIDES_H_
diff --git a/src/tint/lang/wgsl/helpers/check_supported_extensions.cc b/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
index ece9b37..79520a7 100644
--- a/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
+++ b/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
@@ -21,7 +21,7 @@
#include "src/tint/utils/diagnostic/diagnostic.h"
#include "src/tint/utils/text/string.h"
-namespace tint::writer {
+namespace tint::wgsl {
bool CheckSupportedExtensions(std::string_view writer_name,
const ast::Module& module,
@@ -46,4 +46,4 @@
return true;
}
-} // namespace tint::writer
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/helpers/check_supported_extensions.h b/src/tint/lang/wgsl/helpers/check_supported_extensions.h
index b2f09f3..c732a0f 100644
--- a/src/tint/lang/wgsl/helpers/check_supported_extensions.h
+++ b/src/tint/lang/wgsl/helpers/check_supported_extensions.h
@@ -25,7 +25,7 @@
class List;
} // namespace tint::diag
-namespace tint::writer {
+namespace tint::wgsl {
/// Checks that all the extensions enabled in @p module are found in @p supported, raising an error
/// diagnostic if an enabled extension is not supported.
@@ -38,6 +38,6 @@
diag::List& diags,
VectorRef<wgsl::Extension> supported);
-} // namespace tint::writer
+} // namespace tint::wgsl
#endif // SRC_TINT_LANG_WGSL_HELPERS_CHECK_SUPPORTED_EXTENSIONS_H_
diff --git a/src/tint/lang/wgsl/helpers/check_supported_extensions_test.cc b/src/tint/lang/wgsl/helpers/check_supported_extensions_test.cc
index 0d90851..27b6b06 100644
--- a/src/tint/lang/wgsl/helpers/check_supported_extensions_test.cc
+++ b/src/tint/lang/wgsl/helpers/check_supported_extensions_test.cc
@@ -18,7 +18,7 @@
#include "src/tint/lang/wgsl/program/program_builder.h"
-namespace tint::writer {
+namespace tint::wgsl {
namespace {
class CheckSupportedExtensionsTest : public ::testing::Test, public ProgramBuilder {};
@@ -44,4 +44,4 @@
}
} // namespace
-} // namespace tint::writer
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/helpers/flatten_bindings.cc b/src/tint/lang/wgsl/helpers/flatten_bindings.cc
index 3400dd9..ebee730 100644
--- a/src/tint/lang/wgsl/helpers/flatten_bindings.cc
+++ b/src/tint/lang/wgsl/helpers/flatten_bindings.cc
@@ -21,7 +21,7 @@
#include "src/tint/lang/wgsl/ast/transform/manager.h"
#include "src/tint/lang/wgsl/inspector/inspector.h"
-namespace tint::writer {
+namespace tint::wgsl {
std::optional<Program> FlattenBindings(const Program& program) {
// TODO(crbug.com/tint/1101): Make this more robust for multiple entry points.
@@ -79,4 +79,4 @@
return {};
}
-} // namespace tint::writer
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/helpers/flatten_bindings.h b/src/tint/lang/wgsl/helpers/flatten_bindings.h
index be2ca44..2124622 100644
--- a/src/tint/lang/wgsl/helpers/flatten_bindings.h
+++ b/src/tint/lang/wgsl/helpers/flatten_bindings.h
@@ -18,7 +18,7 @@
#include <optional>
#include "src/tint/lang/wgsl/program/program.h"
-namespace tint::writer {
+namespace tint::wgsl {
/// If needed, remaps resource numbers of `program` to a flat namespace: all in
/// group 0 within unique binding numbers.
@@ -26,6 +26,6 @@
/// @return A new program with bindings remapped if needed
std::optional<Program> FlattenBindings(const Program& program);
-} // namespace tint::writer
+} // namespace tint::wgsl
#endif // SRC_TINT_LANG_WGSL_HELPERS_FLATTEN_BINDINGS_H_
diff --git a/src/tint/lang/wgsl/helpers/flatten_bindings_test.cc b/src/tint/lang/wgsl/helpers/flatten_bindings_test.cc
index ed04a59..e193bdc 100644
--- a/src/tint/lang/wgsl/helpers/flatten_bindings_test.cc
+++ b/src/tint/lang/wgsl/helpers/flatten_bindings_test.cc
@@ -22,7 +22,7 @@
#include "src/tint/lang/wgsl/resolver/resolve.h"
#include "src/tint/lang/wgsl/sem/variable.h"
-namespace tint::writer {
+namespace tint::wgsl {
namespace {
using namespace tint::core::number_suffixes; // NOLINT
@@ -34,7 +34,7 @@
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics();
- auto flattened = tint::writer::FlattenBindings(program);
+ auto flattened = FlattenBindings(program);
EXPECT_FALSE(flattened);
}
@@ -47,7 +47,7 @@
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics();
- auto flattened = tint::writer::FlattenBindings(program);
+ auto flattened = FlattenBindings(program);
EXPECT_FALSE(flattened);
}
@@ -61,7 +61,7 @@
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics();
- auto flattened = tint::writer::FlattenBindings(program);
+ auto flattened = FlattenBindings(program);
EXPECT_TRUE(flattened);
auto& vars = flattened->AST().GlobalVariables();
@@ -123,7 +123,7 @@
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics();
- auto flattened = tint::writer::FlattenBindings(program);
+ auto flattened = FlattenBindings(program);
EXPECT_TRUE(flattened);
auto& vars = flattened->AST().GlobalVariables();
@@ -149,4 +149,4 @@
}
} // namespace
-} // namespace tint::writer
+} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/helpers/ir_program_test.h b/src/tint/lang/wgsl/helpers/ir_program_test.h
index fb5fd01..87fa102 100644
--- a/src/tint/lang/wgsl/helpers/ir_program_test.h
+++ b/src/tint/lang/wgsl/helpers/ir_program_test.h
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// GEN_BUILD:CONDITION(tint_build_wgsl_reader)
+
#ifndef SRC_TINT_LANG_WGSL_HELPERS_IR_PROGRAM_TEST_H_
#define SRC_TINT_LANG_WGSL_HELPERS_IR_PROGRAM_TEST_H_
@@ -67,7 +69,6 @@
/// @param wgsl the WGSL to convert to IR
/// @returns the generated module
Result<core::ir::Module> Build(std::string wgsl) {
-#if TINT_BUILD_WGSL_READER
Source::File file("test.wgsl", std::move(wgsl));
auto result = wgsl::reader::WgslToIR(&file);
if (result) {
@@ -77,17 +78,6 @@
}
}
return result;
-#else
- (void)wgsl;
- return Failure{"error: Tint not built with the WGSL reader"};
-#endif
- }
-
- /// @param mod the module
- /// @returns the disassembly string of the module
- std::string Disassemble(core::ir::Module& mod) {
- core::ir::Disassembler d(mod);
- return d.Disassemble();
}
};
diff --git a/src/tint/lang/wgsl/inspector/BUILD.bazel b/src/tint/lang/wgsl/inspector/BUILD.bazel
index edbb595..323a326 100644
--- a/src/tint/lang/wgsl/inspector/BUILD.bazel
+++ b/src/tint/lang/wgsl/inspector/BUILD.bazel
@@ -83,7 +83,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/inspector",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
@@ -100,8 +99,18 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/wgsl/inspector/BUILD.cfg b/src/tint/lang/wgsl/inspector/BUILD.cfg
new file mode 100644
index 0000000..22818cc
--- /dev/null
+++ b/src/tint/lang/wgsl/inspector/BUILD.cfg
@@ -0,0 +1,5 @@
+{
+ "test": {
+ "condition": "tint_build_wgsl_reader",
+ }
+}
diff --git a/src/tint/lang/wgsl/inspector/BUILD.cmake b/src/tint/lang/wgsl/inspector/BUILD.cmake
index 8cfe979..623914b 100644
--- a/src/tint/lang/wgsl/inspector/BUILD.cmake
+++ b/src/tint/lang/wgsl/inspector/BUILD.cmake
@@ -60,9 +60,11 @@
tint_utils_traits
)
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_inspector_test
# Kind: test
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_inspector_test test
lang/wgsl/inspector/inspector_builder_test.cc
@@ -82,7 +84,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_inspector
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
tint_utils_containers
@@ -103,3 +104,11 @@
tint_target_add_external_dependencies(tint_lang_wgsl_inspector_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_inspector_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+endif(TINT_BUILD_WGSL_READER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/inspector/BUILD.gn b/src/tint/lang/wgsl/inspector/BUILD.gn
index 566230b..fe581cd 100644
--- a/src/tint/lang/wgsl/inspector/BUILD.gn
+++ b/src/tint/lang/wgsl/inspector/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -65,42 +65,46 @@
]
}
if (tint_build_unittests) {
- tint_unittests_source_set("unittests") {
- testonly = true
- sources = [
- "inspector_builder_test.cc",
- "inspector_builder_test.h",
- "inspector_runner_test.cc",
- "inspector_runner_test.h",
- "inspector_test.cc",
- ]
- deps = [
- "${tint_src_dir}:gmock_and_gtest",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/inspector",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
+ if (tint_build_wgsl_reader) {
+ tint_unittests_source_set("unittests") {
+ sources = [
+ "inspector_builder_test.cc",
+ "inspector_builder_test.h",
+ "inspector_runner_test.cc",
+ "inspector_runner_test.h",
+ "inspector_test.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/inspector",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/resolver",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+ }
}
}
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index 3585594..a3f4584 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -34,8 +34,7 @@
auto ir_module = wgsl::reader::WgslToIR(&file);
ASSERT_TRUE(ir_module) << ir_module;
- tint::core::ir::Disassembler d{ir_module.Get()};
- auto disassembly = d.Disassemble();
+ auto disassembly = tint::core::ir::Disassemble(ir_module.Get());
auto output = wgsl::writer::WgslFromIR(ir_module.Get());
if (!output) {
@@ -313,10 +312,10 @@
TEST_F(IRToProgramRoundtripTest, CoreBuiltinCall_PtrArg) {
Test(R"(
-var<workgroup> v : bool;
+@group(0) @binding(0) var<storage, read> v : array<u32>;
-fn foo() -> bool {
- return workgroupUniformLoad(&(v));
+fn foo() -> u32 {
+ return arrayLength(&(v));
}
)");
}
diff --git a/src/tint/lang/wgsl/program/BUILD.gn b/src/tint/lang/wgsl/program/BUILD.gn
index ea3bd1b..7186f92 100644
--- a/src/tint/lang/wgsl/program/BUILD.gn
+++ b/src/tint/lang/wgsl/program/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -63,7 +63,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"clone_context_test.cc",
"program_builder_test.cc",
diff --git a/src/tint/lang/wgsl/reader/BUILD.bazel b/src/tint/lang/wgsl/reader/BUILD.bazel
index 116874d..a6a57a1 100644
--- a/src/tint/lang/wgsl/reader/BUILD.bazel
+++ b/src/tint/lang/wgsl/reader/BUILD.bazel
@@ -41,8 +41,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/reader/lower",
- "//src/tint/lang/wgsl/reader/parser",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
@@ -58,18 +56,25 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader/parser",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"reader_bench.cc",
],
deps = [
"//src/tint/api/common",
- "//src/tint/cmd/bench",
+ "//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/ir",
@@ -77,7 +82,6 @@
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -92,8 +96,19 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
- ],
+ "@benchmark",
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/wgsl/reader/BUILD.cfg b/src/tint/lang/wgsl/reader/BUILD.cfg
new file mode 100644
index 0000000..e85bddd
--- /dev/null
+++ b/src/tint/lang/wgsl/reader/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_wgsl_reader",
+}
diff --git a/src/tint/lang/wgsl/reader/BUILD.cmake b/src/tint/lang/wgsl/reader/BUILD.cmake
index 2d94eb5..a424d38 100644
--- a/src/tint/lang/wgsl/reader/BUILD.cmake
+++ b/src/tint/lang/wgsl/reader/BUILD.cmake
@@ -25,9 +25,11 @@
include(lang/wgsl/reader/parser/BUILD.cmake)
include(lang/wgsl/reader/program_to_ir/BUILD.cmake)
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_reader
# Kind: lib
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_reader lib
lang/wgsl/reader/reader.cc
@@ -44,8 +46,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_program
tint_lang_wgsl_reader_lower
- tint_lang_wgsl_reader_parser
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
tint_utils_containers
@@ -63,9 +63,19 @@
tint_utils_traits
)
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_reader lib
+ tint_lang_wgsl_reader_parser
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+endif(TINT_BUILD_WGSL_READER)
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_reader_bench
# Kind: bench
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_reader_bench bench
lang/wgsl/reader/reader_bench.cc
@@ -73,7 +83,7 @@
tint_target_add_dependencies(tint_lang_wgsl_reader_bench bench
tint_api_common
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
tint_lang_core_ir
@@ -81,7 +91,6 @@
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_sem
tint_utils_containers
tint_utils_diagnostic
@@ -97,3 +106,15 @@
tint_utils_text
tint_utils_traits
)
+
+tint_target_add_external_dependencies(tint_lang_wgsl_reader_bench bench
+ "google-benchmark"
+)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_reader_bench bench
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+endif(TINT_BUILD_WGSL_READER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/reader/BUILD.gn b/src/tint/lang/wgsl/reader/BUILD.gn
index 7962250..a1502c1 100644
--- a/src/tint/lang/wgsl/reader/BUILD.gn
+++ b/src/tint/lang/wgsl/reader/BUILD.gn
@@ -25,37 +25,84 @@
import("${tint_src_dir}/tint.gni")
-libtint_source_set("reader") {
- sources = [
- "reader.cc",
- "reader.h",
- ]
- deps = [
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader/lower",
- "${tint_src_dir}/lang/wgsl/reader/parser",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
+if (tint_build_wgsl_reader) {
+ libtint_source_set("reader") {
+ sources = [
+ "reader.cc",
+ "reader.h",
+ ]
+ deps = [
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/reader/lower",
+ "${tint_src_dir}/lang/wgsl/resolver",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader/parser",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
+ }
+}
+if (tint_build_benchmarks) {
+ if (tint_build_wgsl_reader) {
+ tint_unittests_source_set("bench") {
+ sources = [ "reader_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
+ }
+ }
}
diff --git a/src/tint/lang/wgsl/reader/lower/BUILD.gn b/src/tint/lang/wgsl/reader/lower/BUILD.gn
index 674130d..35f7ff0 100644
--- a/src/tint/lang/wgsl/reader/lower/BUILD.gn
+++ b/src/tint/lang/wgsl/reader/lower/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -61,7 +61,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "lower_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/lang/wgsl/reader/lower/lower.cc b/src/tint/lang/wgsl/reader/lower/lower.cc
index 64bef4b..9331b21 100644
--- a/src/tint/lang/wgsl/reader/lower/lower.cc
+++ b/src/tint/lang/wgsl/reader/lower/lower.cc
@@ -17,7 +17,9 @@
#include <utility>
#include "src/tint/lang/core/builtin_fn.h"
+#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/core_builtin_call.h"
+#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/wgsl/builtin_fn.h"
#include "src/tint/lang/wgsl/ir/builtin_call.h"
@@ -116,7 +118,6 @@
CASE(kUnpack4X8Snorm)
CASE(kUnpack4X8Unorm)
CASE(kWorkgroupBarrier)
- CASE(kWorkgroupUniformLoad)
CASE(kTextureBarrier)
CASE(kTextureDimensions)
CASE(kTextureGather)
@@ -155,12 +156,40 @@
} // namespace
Result<SuccessType> Lower(core::ir::Module& mod) {
+ if (auto res = core::ir::ValidateAndDumpIfNeeded(mod, "lowering from WGSL"); !res) {
+ return res.Failure();
+ }
+
+ core::ir::Builder b{mod};
+ core::type::Manager& ty{mod.Types()};
for (auto* inst : mod.instructions.Objects()) {
if (auto* call = inst->As<wgsl::ir::BuiltinCall>()) {
- Vector<core::ir::Value*, 8> args(call->Args());
- auto* replacement = mod.instructions.Create<core::ir::CoreBuiltinCall>(
- call->Result(), Convert(call->Func()), std::move(args));
- call->ReplaceWith(replacement);
+ switch (call->Func()) {
+ case BuiltinFn::kWorkgroupUniformLoad: {
+ // Replace:
+ // %value = call workgroupUniformLoad %ptr
+ // With:
+ // call workgroupBarrier
+ // %value = load &ptr
+ // call workgroupBarrier
+ b.InsertBefore(call, [&] {
+ b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
+ auto* load = b.Load(call->Args()[0]);
+ call->Result()->ReplaceAllUsesWith(load->Result());
+ b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
+ });
+ break;
+ }
+ default: {
+ Vector<core::ir::Value*, 8> args(call->Args());
+ auto* replacement = mod.instructions.Create<core::ir::CoreBuiltinCall>(
+ call->Result(), Convert(call->Func()), std::move(args));
+ call->ReplaceWith(replacement);
+ call->ClearResults();
+ break;
+ }
+ }
+ call->Destroy();
}
}
return Success;
diff --git a/src/tint/lang/wgsl/reader/lower/lower_test.cc b/src/tint/lang/wgsl/reader/lower/lower_test.cc
index 589a8c4..0e4f43f 100644
--- a/src/tint/lang/wgsl/reader/lower/lower_test.cc
+++ b/src/tint/lang/wgsl/reader/lower/lower_test.cc
@@ -64,5 +64,51 @@
EXPECT_EQ(expect, str());
}
+TEST_F(Wgslreader_LowerTest, WorkgroupUniformLoad) {
+ auto* wgvar = b.Var("wgvar", ty.ptr<workgroup, i32>());
+ mod.root_block->Append(wgvar);
+
+ auto* f = b.Function("f", ty.i32());
+ b.Append(f->Block(), [&] { //
+ auto* result = b.InstructionResult(ty.i32());
+ b.Append(b.ir.instructions.Create<wgsl::ir::BuiltinCall>(
+ result, wgsl::BuiltinFn::kWorkgroupUniformLoad, Vector{wgvar->Result()}));
+ b.Return(f, result);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %wgvar:ptr<workgroup, i32, read_write> = var
+}
+
+%f = func():i32 -> %b2 {
+ %b2 = block {
+ %3:i32 = wgsl.workgroupUniformLoad %wgvar
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %wgvar:ptr<workgroup, i32, read_write> = var
+}
+
+%f = func():i32 -> %b2 {
+ %b2 = block {
+ %3:void = workgroupBarrier
+ %4:i32 = load %wgvar
+ %5:void = workgroupBarrier
+ ret %4
+ }
+}
+)";
+
+ Run(Lower);
+
+ EXPECT_EQ(expect, str());
+}
+
} // namespace
} // namespace tint::wgsl::reader::lower
diff --git a/src/tint/lang/wgsl/reader/parser/BUILD.bazel b/src/tint/lang/wgsl/reader/parser/BUILD.bazel
index d1d9b22..c6d9f5d 100644
--- a/src/tint/lang/wgsl/reader/parser/BUILD.bazel
+++ b/src/tint/lang/wgsl/reader/parser/BUILD.bazel
@@ -147,7 +147,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader/parser",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
@@ -164,8 +163,18 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader/parser",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/wgsl/reader/parser/BUILD.cfg b/src/tint/lang/wgsl/reader/parser/BUILD.cfg
new file mode 100644
index 0000000..e85bddd
--- /dev/null
+++ b/src/tint/lang/wgsl/reader/parser/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_wgsl_reader",
+}
diff --git a/src/tint/lang/wgsl/reader/parser/BUILD.cmake b/src/tint/lang/wgsl/reader/parser/BUILD.cmake
index 453af11..37231fc 100644
--- a/src/tint/lang/wgsl/reader/parser/BUILD.cmake
+++ b/src/tint/lang/wgsl/reader/parser/BUILD.cmake
@@ -21,9 +21,11 @@
# Do not modify this file directly
################################################################################
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_reader_parser
# Kind: lib
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_reader_parser lib
lang/wgsl/reader/parser/classify_template_args.cc
@@ -63,9 +65,12 @@
tint_utils_traits
)
+endif(TINT_BUILD_WGSL_READER)
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_reader_parser_test
# Kind: test
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_reader_parser_test test
lang/wgsl/reader/parser/additive_expression_test.cc
@@ -146,7 +151,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_ast_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader_parser
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
tint_utils_containers
@@ -167,3 +171,11 @@
tint_target_add_external_dependencies(tint_lang_wgsl_reader_parser_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_reader_parser_test test
+ tint_lang_wgsl_reader_parser
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+endif(TINT_BUILD_WGSL_READER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/reader/parser/BUILD.gn b/src/tint/lang/wgsl/reader/parser/BUILD.gn
index f765960..ee54683 100644
--- a/src/tint/lang/wgsl/reader/parser/BUILD.gn
+++ b/src/tint/lang/wgsl/reader/parser/BUILD.gn
@@ -25,131 +25,30 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
-
-libtint_source_set("parser") {
- sources = [
- "classify_template_args.cc",
- "classify_template_args.h",
- "detail.h",
- "lexer.cc",
- "lexer.h",
- "parser.cc",
- "parser.h",
- "token.cc",
- "token.h",
- ]
- deps = [
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/strconv",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
-}
-if (tint_build_unittests) {
- tint_unittests_source_set("unittests") {
- testonly = true
+if (tint_build_wgsl_reader) {
+ libtint_source_set("parser") {
sources = [
- "additive_expression_test.cc",
- "argument_expression_list_test.cc",
- "assignment_stmt_test.cc",
- "bitwise_expression_test.cc",
- "break_stmt_test.cc",
- "bug_cases_test.cc",
- "call_stmt_test.cc",
- "classify_template_args_test.cc",
- "compound_stmt_test.cc",
- "const_literal_test.cc",
- "continue_stmt_test.cc",
- "continuing_stmt_test.cc",
- "core_lhs_expression_test.cc",
- "diagnostic_attribute_test.cc",
- "diagnostic_control_test.cc",
- "diagnostic_directive_test.cc",
- "enable_directive_test.cc",
- "error_msg_test.cc",
- "error_resync_test.cc",
- "expression_test.cc",
- "for_stmt_test.cc",
- "function_attribute_list_test.cc",
- "function_attribute_test.cc",
- "function_decl_test.cc",
- "function_header_test.cc",
- "global_constant_decl_test.cc",
- "global_decl_test.cc",
- "global_variable_decl_test.cc",
- "helper_test.cc",
- "helper_test.h",
- "if_stmt_test.cc",
- "increment_decrement_stmt_test.cc",
- "lexer_test.cc",
- "lhs_expression_test.cc",
- "loop_stmt_test.cc",
- "math_expression_test.cc",
- "multiplicative_expression_test.cc",
- "param_list_test.cc",
- "paren_expression_test.cc",
- "parser_test.cc",
- "primary_expression_test.cc",
- "relational_expression_test.cc",
- "require_directive_test.cc",
- "reserved_keyword_test.cc",
- "shift_expression_test.cc",
- "singular_expression_test.cc",
- "statement_test.cc",
- "statements_test.cc",
- "struct_attribute_decl_test.cc",
- "struct_body_decl_test.cc",
- "struct_decl_test.cc",
- "struct_member_attribute_decl_test.cc",
- "struct_member_attribute_test.cc",
- "struct_member_test.cc",
- "switch_body_test.cc",
- "switch_stmt_test.cc",
- "token_test.cc",
- "type_alias_test.cc",
- "type_decl_test.cc",
- "unary_expression_test.cc",
- "variable_attribute_list_test.cc",
- "variable_attribute_test.cc",
- "variable_decl_test.cc",
- "variable_ident_decl_test.cc",
- "variable_qualifier_test.cc",
- "variable_stmt_test.cc",
- "while_stmt_test.cc",
+ "classify_template_args.cc",
+ "classify_template_args.h",
+ "detail.h",
+ "lexer.cc",
+ "lexer.h",
+ "parser.cc",
+ "parser.h",
+ "token.cc",
+ "token.h",
]
deps = [
- "${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/ast:unittests",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader/parser",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/containers",
@@ -162,9 +61,115 @@
"${tint_src_dir}/utils/reflection",
"${tint_src_dir}/utils/result",
"${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/strconv",
"${tint_src_dir}/utils/symbol",
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
}
}
+if (tint_build_unittests) {
+ if (tint_build_wgsl_reader) {
+ tint_unittests_source_set("unittests") {
+ sources = [
+ "additive_expression_test.cc",
+ "argument_expression_list_test.cc",
+ "assignment_stmt_test.cc",
+ "bitwise_expression_test.cc",
+ "break_stmt_test.cc",
+ "bug_cases_test.cc",
+ "call_stmt_test.cc",
+ "classify_template_args_test.cc",
+ "compound_stmt_test.cc",
+ "const_literal_test.cc",
+ "continue_stmt_test.cc",
+ "continuing_stmt_test.cc",
+ "core_lhs_expression_test.cc",
+ "diagnostic_attribute_test.cc",
+ "diagnostic_control_test.cc",
+ "diagnostic_directive_test.cc",
+ "enable_directive_test.cc",
+ "error_msg_test.cc",
+ "error_resync_test.cc",
+ "expression_test.cc",
+ "for_stmt_test.cc",
+ "function_attribute_list_test.cc",
+ "function_attribute_test.cc",
+ "function_decl_test.cc",
+ "function_header_test.cc",
+ "global_constant_decl_test.cc",
+ "global_decl_test.cc",
+ "global_variable_decl_test.cc",
+ "helper_test.cc",
+ "helper_test.h",
+ "if_stmt_test.cc",
+ "increment_decrement_stmt_test.cc",
+ "lexer_test.cc",
+ "lhs_expression_test.cc",
+ "loop_stmt_test.cc",
+ "math_expression_test.cc",
+ "multiplicative_expression_test.cc",
+ "param_list_test.cc",
+ "paren_expression_test.cc",
+ "parser_test.cc",
+ "primary_expression_test.cc",
+ "relational_expression_test.cc",
+ "require_directive_test.cc",
+ "reserved_keyword_test.cc",
+ "shift_expression_test.cc",
+ "singular_expression_test.cc",
+ "statement_test.cc",
+ "statements_test.cc",
+ "struct_attribute_decl_test.cc",
+ "struct_body_decl_test.cc",
+ "struct_decl_test.cc",
+ "struct_member_attribute_decl_test.cc",
+ "struct_member_attribute_test.cc",
+ "struct_member_test.cc",
+ "switch_body_test.cc",
+ "switch_stmt_test.cc",
+ "token_test.cc",
+ "type_alias_test.cc",
+ "type_decl_test.cc",
+ "unary_expression_test.cc",
+ "variable_attribute_list_test.cc",
+ "variable_attribute_test.cc",
+ "variable_decl_test.cc",
+ "variable_ident_decl_test.cc",
+ "variable_qualifier_test.cc",
+ "variable_stmt_test.cc",
+ "while_stmt_test.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/ast:unittests",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/resolver",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [ "${tint_src_dir}/lang/wgsl/reader/parser" ]
+ }
+ }
+ }
+}
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.bazel b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.bazel
index e964d93..6a6cb75 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.bazel
+++ b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.bazel
@@ -89,9 +89,7 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/helpers:test",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/reader/lower",
- "//src/tint/lang/wgsl/reader/program_to_ir",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/containers",
@@ -108,8 +106,19 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ "//src/tint/lang/wgsl/reader/program_to_ir",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cfg b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cfg
new file mode 100644
index 0000000..e85bddd
--- /dev/null
+++ b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_wgsl_reader",
+}
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cmake b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cmake
index 7cff404..454341d 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cmake
+++ b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.cmake
@@ -21,9 +21,11 @@
# Do not modify this file directly
################################################################################
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_reader_program_to_ir
# Kind: lib
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_reader_program_to_ir lib
lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -58,9 +60,12 @@
tint_utils_traits
)
+endif(TINT_BUILD_WGSL_READER)
+if(TINT_BUILD_WGSL_READER)
################################################################################
# Target: tint_lang_wgsl_reader_program_to_ir_test
# Kind: test
+# Condition: TINT_BUILD_WGSL_READER
################################################################################
tint_add_target(tint_lang_wgsl_reader_program_to_ir_test test
lang/wgsl/reader/program_to_ir/accessor_test.cc
@@ -88,9 +93,7 @@
tint_lang_wgsl_ast
tint_lang_wgsl_helpers_test
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_reader_lower
- tint_lang_wgsl_reader_program_to_ir
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
tint_utils_containers
@@ -111,3 +114,12 @@
tint_target_add_external_dependencies(tint_lang_wgsl_reader_program_to_ir_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_dependencies(tint_lang_wgsl_reader_program_to_ir_test test
+ tint_lang_wgsl_reader
+ tint_lang_wgsl_reader_program_to_ir
+ )
+endif(TINT_BUILD_WGSL_READER)
+
+endif(TINT_BUILD_WGSL_READER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.gn b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.gn
index 87f764b..57cfd95 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/BUILD.gn
+++ b/src/tint/lang/wgsl/reader/program_to_ir/BUILD.gn
@@ -25,76 +25,27 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
-
-libtint_source_set("program_to_ir") {
- sources = [
- "program_to_ir.cc",
- "program_to_ir.h",
- ]
- deps = [
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/intrinsic",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/intrinsic",
- "${tint_src_dir}/lang/wgsl/ir",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
-}
-if (tint_build_unittests) {
- tint_unittests_source_set("unittests") {
- testonly = true
+if (tint_build_wgsl_reader) {
+ libtint_source_set("program_to_ir") {
sources = [
- "accessor_test.cc",
- "binary_test.cc",
- "builtin_test.cc",
- "call_test.cc",
- "function_test.cc",
- "let_test.cc",
- "literal_test.cc",
- "materialize_test.cc",
- "program_to_ir_test.cc",
- "shadowing_test.cc",
- "store_test.cc",
- "unary_test.cc",
- "var_test.cc",
+ "program_to_ir.cc",
+ "program_to_ir.h",
]
deps = [
- "${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/intrinsic",
"${tint_src_dir}/lang/core/ir",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/helpers:unittests",
+ "${tint_src_dir}/lang/wgsl/intrinsic",
+ "${tint_src_dir}/lang/wgsl/ir",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
- "${tint_src_dir}/lang/wgsl/reader/lower",
- "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
- "${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -112,3 +63,59 @@
]
}
}
+if (tint_build_unittests) {
+ if (tint_build_wgsl_reader) {
+ tint_unittests_source_set("unittests") {
+ sources = [
+ "accessor_test.cc",
+ "binary_test.cc",
+ "builtin_test.cc",
+ "call_test.cc",
+ "function_test.cc",
+ "let_test.cc",
+ "literal_test.cc",
+ "materialize_test.cc",
+ "program_to_ir_test.cc",
+ "shadowing_test.cc",
+ "store_test.cc",
+ "unary_test.cc",
+ "var_test.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/helpers:unittests",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/reader/lower",
+ "${tint_src_dir}/lang/wgsl/resolver",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_reader) {
+ deps += [
+ "${tint_src_dir}/lang/wgsl/reader",
+ "${tint_src_dir}/lang/wgsl/reader/program_to_ir",
+ ]
+ }
+ }
+ }
+}
diff --git a/src/tint/lang/wgsl/reader/reader_bench.cc b/src/tint/lang/wgsl/reader/reader_bench.cc
index b5f736a..be3898c 100644
--- a/src/tint/lang/wgsl/reader/reader_bench.cc
+++ b/src/tint/lang/wgsl/reader/reader_bench.cc
@@ -22,15 +22,14 @@
void ParseWGSL(benchmark::State& state, std::string input_name) {
auto res = bench::LoadInputFile(input_name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- state.SkipWithError(err->msg.c_str());
+ if (!res) {
+ state.SkipWithError(res.Failure().reason.str());
return;
}
- auto& file = std::get<Source::File>(res);
for (auto _ : state) {
- auto res = Parse(&file);
- if (res.Diagnostics().contains_errors()) {
- state.SkipWithError(res.Diagnostics().str().c_str());
+ auto program = Parse(&res.Get());
+ if (program.Diagnostics().contains_errors()) {
+ state.SkipWithError(program.Diagnostics().str());
}
}
}
diff --git a/src/tint/lang/wgsl/resolver/BUILD.bazel b/src/tint/lang/wgsl/resolver/BUILD.bazel
index 5e4635f..8369cba 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.bazel
+++ b/src/tint/lang/wgsl/resolver/BUILD.bazel
@@ -27,18 +27,22 @@
name = "resolver",
srcs = [
"dependency_graph.cc",
+ "incomplete_type.cc",
"resolve.cc",
"resolver.cc",
"sem_helper.cc",
"uniformity.cc",
+ "unresolved_identifier.cc",
"validator.cc",
],
hdrs = [
"dependency_graph.h",
+ "incomplete_type.h",
"resolve.h",
"resolver.h",
"sem_helper.h",
"uniformity.h",
+ "unresolved_identifier.h",
"validator.h",
],
deps = [
@@ -123,14 +127,18 @@
"struct_pipeline_stage_use_test.cc",
"subgroups_extension_test.cc",
"type_validation_test.cc",
- "uniformity_test.cc",
"unresolved_identifier_test.cc",
"validation_test.cc",
"validator_is_storeable_test.cc",
"value_constructor_validation_test.cc",
"variable_test.cc",
"variable_validation_test.cc",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "uniformity_test.cc",
+ ],
+ "//conditions:default": [],
+ }),
deps = [
"//src/tint/api/common",
"//src/tint/lang/core",
@@ -145,7 +153,6 @@
"//src/tint/lang/wgsl/ast:test",
"//src/tint/lang/wgsl/intrinsic",
"//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/reader",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
"//src/tint/lang/wgsl/sem:test",
@@ -163,8 +170,18 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_reader": [
+ "//src/tint/lang/wgsl/reader",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_reader",
+ actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/wgsl/resolver/BUILD.cmake b/src/tint/lang/wgsl/resolver/BUILD.cmake
index fd17863..ff882f1 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.cmake
+++ b/src/tint/lang/wgsl/resolver/BUILD.cmake
@@ -28,6 +28,8 @@
tint_add_target(tint_lang_wgsl_resolver lib
lang/wgsl/resolver/dependency_graph.cc
lang/wgsl/resolver/dependency_graph.h
+ lang/wgsl/resolver/incomplete_type.cc
+ lang/wgsl/resolver/incomplete_type.h
lang/wgsl/resolver/resolve.cc
lang/wgsl/resolver/resolve.h
lang/wgsl/resolver/resolver.cc
@@ -36,6 +38,8 @@
lang/wgsl/resolver/sem_helper.h
lang/wgsl/resolver/uniformity.cc
lang/wgsl/resolver/uniformity.h
+ lang/wgsl/resolver/unresolved_identifier.cc
+ lang/wgsl/resolver/unresolved_identifier.h
lang/wgsl/resolver/validator.cc
lang/wgsl/resolver/validator.h
)
@@ -121,7 +125,6 @@
lang/wgsl/resolver/struct_pipeline_stage_use_test.cc
lang/wgsl/resolver/subgroups_extension_test.cc
lang/wgsl/resolver/type_validation_test.cc
- lang/wgsl/resolver/uniformity_test.cc
lang/wgsl/resolver/unresolved_identifier_test.cc
lang/wgsl/resolver/validation_test.cc
lang/wgsl/resolver/validator_is_storeable_test.cc
@@ -144,7 +147,6 @@
tint_lang_wgsl_ast_test
tint_lang_wgsl_intrinsic
tint_lang_wgsl_program
- tint_lang_wgsl_reader
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
tint_lang_wgsl_sem_test
@@ -166,3 +168,12 @@
tint_target_add_external_dependencies(tint_lang_wgsl_resolver_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_READER)
+ tint_target_add_sources(tint_lang_wgsl_resolver_test test
+ "lang/wgsl/resolver/uniformity_test.cc"
+ )
+ tint_target_add_dependencies(tint_lang_wgsl_resolver_test test
+ tint_lang_wgsl_reader
+ )
+endif(TINT_BUILD_WGSL_READER)
diff --git a/src/tint/lang/wgsl/resolver/BUILD.gn b/src/tint/lang/wgsl/resolver/BUILD.gn
index c10075f..49c8be2 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.gn
+++ b/src/tint/lang/wgsl/resolver/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -33,6 +33,8 @@
sources = [
"dependency_graph.cc",
"dependency_graph.h",
+ "incomplete_type.cc",
+ "incomplete_type.h",
"resolve.cc",
"resolve.h",
"resolver.cc",
@@ -41,6 +43,8 @@
"sem_helper.h",
"uniformity.cc",
"uniformity.h",
+ "unresolved_identifier.cc",
+ "unresolved_identifier.h",
"validator.cc",
"validator.h",
]
@@ -72,7 +76,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"address_space_layout_validation_test.cc",
"address_space_validation_test.cc",
@@ -124,7 +127,6 @@
"struct_pipeline_stage_use_test.cc",
"subgroups_extension_test.cc",
"type_validation_test.cc",
- "uniformity_test.cc",
"unresolved_identifier_test.cc",
"validation_test.cc",
"validator_is_storeable_test.cc",
@@ -147,7 +149,6 @@
"${tint_src_dir}/lang/wgsl/ast/transform",
"${tint_src_dir}/lang/wgsl/intrinsic",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/reader",
"${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/lang/wgsl/sem:unittests",
@@ -165,5 +166,10 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_wgsl_reader) {
+ sources += [ "uniformity_test.cc" ]
+ deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
+ }
}
}
diff --git a/src/tint/lang/wgsl/resolver/address_space_validation_test.cc b/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
index 1d4f390..ecb5107 100644
--- a/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
@@ -216,18 +216,6 @@
56:78 note: while instantiating 'var' g)");
}
-TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_Pointer) {
- // type t = ptr<storage, ptr<private, f32>>;
- Alias("t", ty.ptr<storage>(Source{{56, 78}}, ty.ptr<private_, f32>(Source{{12, 34}})));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(
- r()->error(),
- R"(12:34 error: Type 'ptr<private, f32, read_write>' cannot be used in address space 'storage' as it is non-host-shareable
-56:78 note: while instantiating ptr<storage, ptr<private, f32, read_write>, read>)");
-}
-
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariable_Storage_IntScalar) {
// var<storage> g : i32;
GlobalVar("g", ty.i32(), core::AddressSpace::kStorage, Binding(0_a), Group(0_a));
@@ -631,18 +619,6 @@
56:78 note: while instantiating 'var' g)");
}
-TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_UniformPointer) {
- // type t = ptr<uniform, ptr<private, f32>>;
- Alias("t", ty.ptr<uniform>(Source{{56, 78}}, ty.ptr<private_, f32>(Source{{12, 34}})));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(
- r()->error(),
- R"(12:34 error: Type 'ptr<private, f32, read_write>' cannot be used in address space 'uniform' as it is non-host-shareable
-56:78 note: while instantiating ptr<uniform, ptr<private, f32, read_write>, read>)");
-}
-
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariable_UniformBufferIntScalar) {
// var<uniform> g : i32;
GlobalVar(Source{{56, 78}}, "g", ty.i32(), core::AddressSpace::kUniform, Binding(0_a),
@@ -920,19 +896,6 @@
56:78 note: while instantiating 'var' g)");
}
-TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_PushConstantPointer) {
- // enable chromium_experimental_push_constant;
- // type t = ptr<push_constant, ptr<private, f32>>;
- Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
- Alias(Source{{56, 78}}, "t", ty.ptr<push_constant>(ty.ptr<private_, f32>(Source{{12, 34}})));
-
- ASSERT_FALSE(r()->Resolve());
- EXPECT_EQ(
- r()->error(),
- R"(12:34 error: Type 'ptr<private, f32, read_write>' cannot be used in address space 'push_constant' as it is non-host-shareable
-note: while instantiating ptr<push_constant, ptr<private, f32, read_write>, read_write>)");
-}
-
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariable_PushConstantIntScalar) {
// enable chromium_experimental_push_constant;
// var<push_constant> g : i32;
diff --git a/src/tint/lang/wgsl/resolver/builtin_enum_test.cc b/src/tint/lang/wgsl/resolver/builtin_enum_test.cc
index 3f73a5d..1ad9ea7 100644
--- a/src/tint/lang/wgsl/resolver/builtin_enum_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtin_enum_test.cc
@@ -36,8 +36,8 @@
using ResolverAccessUsedWithTemplateArgs = ResolverTestWithParam<const char*>;
TEST_P(ResolverAccessUsedWithTemplateArgs, Test) {
- // @group(0) @binding(0) var t : texture_storage_2d<rgba8unorm, ACCESS<T>>;
- auto* tmpl = Ident(Source{{12, 34}}, GetParam(), "T");
+ // @group(0) @binding(0) var t : texture_storage_2d<rgba8unorm, ACCESS<i32>>;
+ auto* tmpl = Ident(Source{{12, 34}}, GetParam(), "i32");
GlobalVar("v", ty("texture_storage_2d", "rgba8unorm", tmpl), Group(0_u), Binding(0_u));
EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
index 86e4f4c..d9d475f 100644
--- a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
@@ -35,7 +35,8 @@
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: builtin 'workgroupBarrier' does not return a value");
+ EXPECT_EQ(r()->error(),
+ "12:34 error: builtin function 'workgroupBarrier' does not return a value");
}
TEST_F(ResolverBuiltinValidationTest, InvalidPipelineStageDirect) {
@@ -118,7 +119,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(56:78 error: cannot use function 'mix' as value
-12:34 note: function 'mix' declared here)");
+12:34 note: function 'mix' declared here
+56:78 note: are you missing '()'?)");
}
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalConstUsedAsVariable) {
diff --git a/src/tint/lang/wgsl/resolver/call_validation_test.cc b/src/tint/lang/wgsl/resolver/call_validation_test.cc
index b665d0d..0018bba 100644
--- a/src/tint/lang/wgsl/resolver/call_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/call_validation_test.cc
@@ -501,7 +501,8 @@
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: builtin 'min' does not take template arguments)");
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: builtin function 'min' does not take template arguments)");
}
} // namespace
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index e2f25d8..8d9fcd4 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -349,13 +349,7 @@
expr,
[&](const ast::IdentifierExpression* e) {
AddDependency(e->identifier, e->identifier->symbol);
- if (auto* tmpl_ident = e->identifier->As<ast::TemplatedIdentifier>()) {
- for (auto* arg : tmpl_ident->arguments) {
- pending.Push(arg);
- }
- }
},
- [&](const ast::CallExpression* call) { TraverseExpression(call->target); },
[&](const ast::BitcastExpression* cast) { TraverseExpression(cast->type); });
return ast::TraverseAction::Descend;
});
@@ -533,7 +527,8 @@
auto builtin_info = GetBuiltinInfo(to);
switch (builtin_info.type) {
case BuiltinType::kNone:
- graph_.resolved_identifiers.Add(from, UnresolvedIdentifier{to.Name()});
+ graph_.resolved_identifiers.Add(
+ from, ResolvedIdentifier::UnresolvedIdentifier{to.Name()});
break;
case BuiltinType::kFunction:
graph_.resolved_identifiers.Add(
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.h b/src/tint/lang/wgsl/resolver/dependency_graph.h
index 85a91e2..b9a1440 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.h
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.h
@@ -31,12 +31,6 @@
namespace tint::resolver {
-/// UnresolvedIdentifier is the variant value used by ResolvedIdentifier
-struct UnresolvedIdentifier {
- /// Name of the unresolved identifier
- std::string name;
-};
-
/// ResolvedIdentifier holds the resolution of an ast::Identifier.
/// Can hold one of:
/// - UnresolvedIdentifier
@@ -53,6 +47,12 @@
/// - core::TexelFormat
class ResolvedIdentifier {
public:
+ /// UnresolvedIdentifier is the variant value used to represent an unresolved identifier
+ struct UnresolvedIdentifier {
+ /// Name of the unresolved identifier
+ std::string name;
+ };
+
/// Constructor
/// @param value the resolved identifier value
template <typename T>
diff --git a/src/tint/lang/wgsl/resolver/expression_kind_test.cc b/src/tint/lang/wgsl/resolver/expression_kind_test.cc
index aad7671..2bd1c61 100644
--- a/src/tint/lang/wgsl/resolver/expression_kind_test.cc
+++ b/src/tint/lang/wgsl/resolver/expression_kind_test.cc
@@ -171,7 +171,12 @@
}
case Def::kBuiltinFunction: {
sym = Sym("workgroupBarrier");
- check_expr = [](const sem::Expression* expr) { EXPECT_EQ(expr, nullptr); };
+ check_expr = [](const sem::Expression* expr) {
+ ASSERT_NE(expr, nullptr);
+ auto* fn_expr = expr->As<sem::BuiltinEnumExpression<wgsl::BuiltinFn>>();
+ ASSERT_NE(fn_expr, nullptr);
+ EXPECT_EQ(fn_expr->Value(), wgsl::BuiltinFn::kWorkgroupBarrier);
+ };
break;
}
case Def::kBuiltinType: {
@@ -415,37 +420,40 @@
R"(5:6 error: cannot use address space 'workgroup' as value)"},
{Def::kBuiltinFunction, Use::kAccess,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as access)"},
{Def::kBuiltinFunction, Use::kAddressSpace,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as address space)"},
{Def::kBuiltinFunction, Use::kBinaryOp,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as value
+7:8 note: are you missing '()'?)"},
{Def::kBuiltinFunction, Use::kBuiltinValue,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as builtin value)"},
{Def::kBuiltinFunction, Use::kCallStmt, kPass},
{Def::kBuiltinFunction, Use::kFunctionReturnType,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
{Def::kBuiltinFunction, Use::kInterpolationSampling,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as interpolation sampling)"},
{Def::kBuiltinFunction, Use::kInterpolationType,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as interpolation type)"},
{Def::kBuiltinFunction, Use::kMemberType,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
{Def::kBuiltinFunction, Use::kTexelFormat,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as texel format)"},
{Def::kBuiltinFunction, Use::kValueExpression,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as value
+7:8 note: are you missing '()'?)"},
{Def::kBuiltinFunction, Use::kVariableType,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
{Def::kBuiltinFunction, Use::kUnaryOp,
- R"(7:8 error: missing '(' for builtin function call)"},
+ R"(5:6 error: cannot use builtin function 'workgroupBarrier' as value
+7:8 note: are you missing '()'?)"},
{Def::kBuiltinType, Use::kAccess, R"(5:6 error: cannot use type 'vec4<f32>' as access)"},
{Def::kBuiltinType, Use::kAddressSpace,
R"(5:6 error: cannot use type 'vec4<f32>' as address space)"},
{Def::kBuiltinType, Use::kBinaryOp,
R"(5:6 error: cannot use type 'vec4<f32>' as value
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kBuiltinType, Use::kBuiltinValue,
R"(5:6 error: cannot use type 'vec4<f32>' as builtin value)"},
{Def::kBuiltinType, Use::kCallExpr, kPass},
@@ -459,11 +467,11 @@
R"(5:6 error: cannot use type 'vec4<f32>' as texel format)"},
{Def::kBuiltinType, Use::kValueExpression,
R"(5:6 error: cannot use type 'vec4<f32>' as value
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kBuiltinType, Use::kVariableType, kPass},
{Def::kBuiltinType, Use::kUnaryOp,
R"(5:6 error: cannot use type 'vec4<f32>' as value
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kBuiltinValue, Use::kAccess,
R"(5:6 error: cannot use builtin value 'position' as access)"},
@@ -499,7 +507,8 @@
R"(5:6 error: cannot use function 'FUNCTION' as address space
1:2 note: function 'FUNCTION' declared here)"},
{Def::kFunction, Use::kBinaryOp, R"(5:6 error: cannot use function 'FUNCTION' as value
-1:2 note: function 'FUNCTION' declared here)"},
+1:2 note: function 'FUNCTION' declared here
+7:8 note: are you missing '()'?)"},
{Def::kFunction, Use::kBuiltinValue,
R"(5:6 error: cannot use function 'FUNCTION' as builtin value
1:2 note: function 'FUNCTION' declared here)"},
@@ -522,12 +531,14 @@
1:2 note: function 'FUNCTION' declared here)"},
{Def::kFunction, Use::kValueExpression,
R"(5:6 error: cannot use function 'FUNCTION' as value
-1:2 note: function 'FUNCTION' declared here)"},
+1:2 note: function 'FUNCTION' declared here
+7:8 note: are you missing '()'?)"},
{Def::kFunction, Use::kVariableType,
R"(5:6 error: cannot use function 'FUNCTION' as type
1:2 note: function 'FUNCTION' declared here)"},
{Def::kFunction, Use::kUnaryOp, R"(5:6 error: cannot use function 'FUNCTION' as value
-1:2 note: function 'FUNCTION' declared here)"},
+1:2 note: function 'FUNCTION' declared here
+7:8 note: are you missing '()'?)"},
{Def::kInterpolationSampling, Use::kAccess,
R"(5:6 error: cannot use interpolation sampling 'center' as access)"},
@@ -605,7 +616,7 @@
1:2 note: struct 'STRUCT' declared here)"},
{Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
1:2 note: struct 'STRUCT' declared here
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kStruct, Use::kBuiltinValue,
R"(5:6 error: cannot use type 'STRUCT' as builtin value
1:2 note: struct 'STRUCT' declared here)"},
@@ -622,12 +633,12 @@
{Def::kStruct, Use::kValueExpression,
R"(5:6 error: cannot use type 'STRUCT' as value
1:2 note: struct 'STRUCT' declared here
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kStruct, Use::kVariableType, kPass},
{Def::kStruct, Use::kUnaryOp,
R"(5:6 error: cannot use type 'STRUCT' as value
1:2 note: struct 'STRUCT' declared here
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kTexelFormat, Use::kAccess,
R"(5:6 error: cannot use texel format 'rgba8unorm' as access)"},
@@ -662,7 +673,7 @@
R"(5:6 error: cannot use type 'i32' as address space)"},
{Def::kTypeAlias, Use::kBinaryOp,
R"(5:6 error: cannot use type 'i32' as value
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kTypeAlias, Use::kBuiltinValue,
R"(5:6 error: cannot use type 'i32' as builtin value)"},
{Def::kTypeAlias, Use::kCallExpr, kPass},
@@ -675,11 +686,11 @@
{Def::kTypeAlias, Use::kTexelFormat, R"(5:6 error: cannot use type 'i32' as texel format)"},
{Def::kTypeAlias, Use::kValueExpression,
R"(5:6 error: cannot use type 'i32' as value
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kTypeAlias, Use::kVariableType, kPass},
{Def::kTypeAlias, Use::kUnaryOp,
R"(5:6 error: cannot use type 'i32' as value
-7:8 note: are you missing '()' for value constructor?)"},
+7:8 note: are you missing '()'?)"},
{Def::kVariable, Use::kAccess, R"(5:6 error: cannot use const 'VARIABLE' as access
1:2 note: const 'VARIABLE' declared here)"},
diff --git a/src/tint/lang/wgsl/resolver/incomplete_type.cc b/src/tint/lang/wgsl/resolver/incomplete_type.cc
new file mode 100644
index 0000000..ca4c555
--- /dev/null
+++ b/src/tint/lang/wgsl/resolver/incomplete_type.cc
@@ -0,0 +1,60 @@
+// 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/lang/wgsl/resolver/incomplete_type.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::resolver::IncompleteType);
+
+namespace tint::resolver {
+
+IncompleteType::IncompleteType(core::BuiltinType b)
+ : Base(static_cast<size_t>(tint::TypeInfo::Of<IncompleteType>().full_hashcode),
+ core::type::Flags{}),
+ builtin(b) {}
+
+IncompleteType::~IncompleteType() = default;
+
+std::string IncompleteType::FriendlyName() const {
+ return "<incomplete-type>";
+}
+
+uint32_t IncompleteType::Size() const {
+ return 0;
+}
+
+uint32_t IncompleteType::Align() const {
+ return 0;
+}
+
+core::type::Type* IncompleteType::Clone(core::type::CloneContext&) const {
+ TINT_ICE() << "IncompleteType does not support cloning";
+ return nullptr;
+}
+
+core::type::TypeAndCount IncompleteType::Elements(const Type*, uint32_t) const {
+ return {};
+}
+
+const core::type::Type* IncompleteType::Element(uint32_t) const {
+ return nullptr;
+}
+
+bool IncompleteType::Equals(const core::type::UniqueNode& other) const {
+ if (auto* o = other.As<IncompleteType>()) {
+ return o->builtin == builtin;
+ }
+ return false;
+}
+
+} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/incomplete_type.h b/src/tint/lang/wgsl/resolver/incomplete_type.h
new file mode 100644
index 0000000..da02c59
--- /dev/null
+++ b/src/tint/lang/wgsl/resolver/incomplete_type.h
@@ -0,0 +1,70 @@
+// 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_LANG_WGSL_RESOLVER_INCOMPLETE_TYPE_H_
+#define SRC_TINT_LANG_WGSL_RESOLVER_INCOMPLETE_TYPE_H_
+
+#include <string>
+
+#include "src/tint/lang/core/builtin_type.h"
+#include "src/tint/lang/core/type/type.h"
+
+namespace tint::resolver {
+
+/// Represents a expression that resolved to the name of a type without explicit template arguments.
+/// This is a placeholder type that on successful resolving, is replaced with the type built using
+/// the inferred template arguments.
+/// For example, given the expression `vec3(1i, 2i, 3i)`:
+/// * The IdentifierExpression for `vec3` is resolved first, to an IncompleteType as it does not
+/// know the vector element type.
+/// * Next, the CallExpression replaces the IncompleteType with a core::type::Vector once it can
+/// infer the element type from the call's arguments.
+class IncompleteType : public Castable<IncompleteType, core::type::Type> {
+ public:
+ /// Constructor
+ /// @param b the incomplete builtin type
+ explicit IncompleteType(core::BuiltinType b);
+
+ /// Destructor
+ ~IncompleteType() override;
+
+ /// The incomplete builtin type
+ const core::BuiltinType builtin = core::BuiltinType::kUndefined;
+
+ /// @copydoc core::type::Type::FriendlyName
+ std::string FriendlyName() const override;
+
+ /// @copydoc core::type::Type::Size
+ uint32_t Size() const override;
+
+ /// @copydoc core::type::Type::Align
+ uint32_t Align() const override;
+
+ /// @copydoc core::type::Type::Clone
+ core::type::Type* Clone(core::type::CloneContext& ctx) const override;
+
+ /// @copydoc core::type::Type::Elements
+ core::type::TypeAndCount Elements(const Type* type_if_invalid = nullptr,
+ uint32_t count_if_invalid = 0) const override;
+
+ /// @copydoc core::type::Type::Element
+ const Type* Element(uint32_t index) const override;
+
+ /// @copydoc core::type::UniqueNode::Equals
+ bool Equals(const UniqueNode& other) const override;
+};
+
+} // namespace tint::resolver
+
+#endif // SRC_TINT_LANG_WGSL_RESOLVER_INCOMPLETE_TYPE_H_
diff --git a/src/tint/lang/wgsl/resolver/inferred_type_test.cc b/src/tint/lang/wgsl/resolver/inferred_type_test.cc
index 89212fe..ec9e59a 100644
--- a/src/tint/lang/wgsl/resolver/inferred_type_test.cc
+++ b/src/tint/lang/wgsl/resolver/inferred_type_test.cc
@@ -14,6 +14,7 @@
#include "src/tint/lang/wgsl/resolver/resolver.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "gmock/gmock.h"
@@ -124,9 +125,9 @@
TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
auto type = ty.array<u32, 10>();
- auto* expected_type = create<core::type::Array>(create<core::type::U32>(),
- create<core::type::ConstantArrayCount>(10u), 4u,
- 4u * 10u, 4u, 4u);
+ auto* expected_type =
+ create<sem::Array>(create<core::type::U32>(), create<core::type::ConstantArrayCount>(10u),
+ 4u, 4u * 10u, 4u, 4u);
auto* ctor_expr = Call(type);
auto* var = Var("a", core::AddressSpace::kFunction, ctor_expr);
diff --git a/src/tint/lang/wgsl/resolver/is_host_shareable_test.cc b/src/tint/lang/wgsl/resolver/is_host_shareable_test.cc
index e23a9b5..b7b0aa6 100644
--- a/src/tint/lang/wgsl/resolver/is_host_shareable_test.cc
+++ b/src/tint/lang/wgsl/resolver/is_host_shareable_test.cc
@@ -17,6 +17,7 @@
#include "gmock/gmock.h"
#include "src/tint/lang/core/type/atomic.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
namespace tint::resolver {
namespace {
@@ -106,14 +107,14 @@
}
TEST_F(ResolverIsHostShareable, ArraySizedOfHostShareable) {
- auto* arr = create<core::type::Array>(
- create<core::type::I32>(), create<core::type::ConstantArrayCount>(5u), 4u, 20u, 4u, 4u);
+ auto* arr = create<sem::Array>(create<core::type::I32>(),
+ create<core::type::ConstantArrayCount>(5u), 4u, 20u, 4u, 4u);
EXPECT_TRUE(r()->IsHostShareable(arr));
}
TEST_F(ResolverIsHostShareable, ArrayUnsizedOfHostShareable) {
- auto* arr = create<core::type::Array>(create<core::type::I32>(),
- create<core::type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
+ auto* arr = create<sem::Array>(create<core::type::I32>(),
+ create<core::type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
EXPECT_TRUE(r()->IsHostShareable(arr));
}
diff --git a/src/tint/lang/wgsl/resolver/is_storeable_test.cc b/src/tint/lang/wgsl/resolver/is_storeable_test.cc
index b040dce..e549151 100644
--- a/src/tint/lang/wgsl/resolver/is_storeable_test.cc
+++ b/src/tint/lang/wgsl/resolver/is_storeable_test.cc
@@ -17,6 +17,7 @@
#include "gmock/gmock.h"
#include "src/tint/lang/core/type/atomic.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
using namespace tint::core::fluent_types; // NOLINT
@@ -91,14 +92,14 @@
}
TEST_F(ResolverIsStorableTest, ArraySizedOfStorable) {
- auto* arr = create<core::type::Array>(
- create<core::type::I32>(), create<core::type::ConstantArrayCount>(5u), 4u, 20u, 4u, 4u);
+ auto* arr = create<sem::Array>(create<core::type::I32>(),
+ create<core::type::ConstantArrayCount>(5u), 4u, 20u, 4u, 4u);
EXPECT_TRUE(r()->IsStorable(arr));
}
TEST_F(ResolverIsStorableTest, ArrayUnsizedOfStorable) {
- auto* arr = create<core::type::Array>(create<core::type::I32>(),
- create<core::type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
+ auto* arr = create<sem::Array>(create<core::type::I32>(),
+ create<core::type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
EXPECT_TRUE(r()->IsStorable(arr));
}
diff --git a/src/tint/lang/wgsl/resolver/materialize_test.cc b/src/tint/lang/wgsl/resolver/materialize_test.cc
index f4b0ab5..53a6bc1 100644
--- a/src/tint/lang/wgsl/resolver/materialize_test.cc
+++ b/src/tint/lang/wgsl/resolver/materialize_test.cc
@@ -17,6 +17,7 @@
#include "src/tint/lang/core/type/helper_test.h"
#include "src/tint/lang/wgsl/resolver/resolver.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/utils/rtti/switch.h"
#include "gmock/gmock.h"
@@ -117,7 +118,7 @@
}
}
},
- [&](const core::type::Array* a) {
+ [&](const sem::Array* a) {
auto count = a->ConstantCount();
ASSERT_NE(count, 0u);
for (uint32_t i = 0; i < count; i++) {
diff --git a/src/tint/lang/wgsl/resolver/override_test.cc b/src/tint/lang/wgsl/resolver/override_test.cc
index f575a4f..575d58a 100644
--- a/src/tint/lang/wgsl/resolver/override_test.cc
+++ b/src/tint/lang/wgsl/resolver/override_test.cc
@@ -15,6 +15,7 @@
#include "src/tint/lang/wgsl/resolver/resolver.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
using namespace tint::core::number_suffixes; // NOLINT
@@ -134,15 +135,13 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
{
- auto* r = Sem().TransitivelyReferencedOverrides(Sem().Get(b));
- ASSERT_NE(r, nullptr);
- auto& refs = *r;
+ auto refs = Sem().Get(b)->TransitivelyReferencedOverrides();
ASSERT_EQ(refs.Length(), 1u);
EXPECT_EQ(refs[0], Sem().Get(a));
}
{
- auto& refs = Sem().Get(func)->TransitivelyReferencedGlobals();
+ auto refs = Sem().Get(func)->TransitivelyReferencedGlobals();
ASSERT_EQ(refs.Length(), 2u);
EXPECT_EQ(refs[0], Sem().Get(b));
EXPECT_EQ(refs[1], Sem().Get(a));
@@ -161,9 +160,7 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
{
- auto* r = Sem().TransitivelyReferencedOverrides(Sem().Get<sem::GlobalVariable>(b));
- ASSERT_NE(r, nullptr);
- auto& refs = *r;
+ auto refs = Sem().Get<sem::GlobalVariable>(b)->TransitivelyReferencedOverrides();
ASSERT_EQ(refs.Length(), 1u);
EXPECT_EQ(refs[0], Sem().Get(a));
}
@@ -201,7 +198,6 @@
auto* a = Override("a", ty.i32());
auto* b = Override("b", ty.i32(), Mul(2_a, "a"));
auto* arr = GlobalVar("arr", core::AddressSpace::kWorkgroup, ty.array(ty.i32(), Mul(2_a, "b")));
- auto arr_ty = arr->type;
Override("unused", ty.i32(), Expr(1_a));
auto* func = Func("foo", tint::Empty, ty.void_(),
Vector{
@@ -210,26 +206,25 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
+ auto* global = Sem().Get<sem::GlobalVariable>(arr);
+ ASSERT_NE(global, nullptr);
+ auto* arr_ty = global->Type()->UnwrapRef()->As<sem::Array>();
+ ASSERT_NE(arr_ty, nullptr);
+
{
- auto* r = Sem().TransitivelyReferencedOverrides(TypeOf(arr_ty));
- ASSERT_NE(r, nullptr);
- auto& refs = *r;
+ auto refs = global->TransitivelyReferencedOverrides();
ASSERT_EQ(refs.Length(), 2u);
EXPECT_EQ(refs[0], Sem().Get(b));
EXPECT_EQ(refs[1], Sem().Get(a));
}
-
{
- auto* r = Sem().TransitivelyReferencedOverrides(Sem().Get<sem::GlobalVariable>(arr));
- ASSERT_NE(r, nullptr);
- auto& refs = *r;
+ auto refs = arr_ty->TransitivelyReferencedOverrides();
ASSERT_EQ(refs.Length(), 2u);
EXPECT_EQ(refs[0], Sem().Get(b));
EXPECT_EQ(refs[1], Sem().Get(a));
}
-
{
- auto& refs = Sem().Get(func)->TransitivelyReferencedGlobals();
+ auto refs = Sem().Get(func)->TransitivelyReferencedGlobals();
ASSERT_EQ(refs.Length(), 3u);
EXPECT_EQ(refs[0], Sem().Get(arr));
EXPECT_EQ(refs[1], Sem().Get(b));
@@ -242,7 +237,6 @@
auto* b = Override("b", ty.i32(), Mul(2_a, "a"));
Alias("arr_ty", ty.array(ty.i32(), Mul(2_a, "b")));
auto* arr = GlobalVar("arr", core::AddressSpace::kWorkgroup, ty("arr_ty"));
- auto arr_ty = arr->type;
Override("unused", ty.i32(), Expr(1_a));
auto* func = Func("foo", tint::Empty, ty.void_(),
Vector{
@@ -251,26 +245,25 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
+ auto* global = Sem().Get<sem::GlobalVariable>(arr);
+ ASSERT_NE(global, nullptr);
+ auto* arr_ty = global->Type()->UnwrapRef()->As<sem::Array>();
+ ASSERT_NE(arr_ty, nullptr);
+
{
- auto* r = Sem().TransitivelyReferencedOverrides(TypeOf(arr_ty));
- ASSERT_NE(r, nullptr);
- auto& refs = *r;
+ auto refs = global->TransitivelyReferencedOverrides();
ASSERT_EQ(refs.Length(), 2u);
EXPECT_EQ(refs[0], Sem().Get(b));
EXPECT_EQ(refs[1], Sem().Get(a));
}
-
{
- auto* r = Sem().TransitivelyReferencedOverrides(Sem().Get<sem::GlobalVariable>(arr));
- ASSERT_NE(r, nullptr);
- auto& refs = *r;
+ auto refs = arr_ty->TransitivelyReferencedOverrides();
ASSERT_EQ(refs.Length(), 2u);
EXPECT_EQ(refs[0], Sem().Get(b));
EXPECT_EQ(refs[1], Sem().Get(a));
}
-
{
- auto& refs = Sem().Get(func)->TransitivelyReferencedGlobals();
+ auto refs = Sem().Get(func)->TransitivelyReferencedGlobals();
ASSERT_EQ(refs.Length(), 3u);
EXPECT_EQ(refs[0], Sem().Get(arr));
EXPECT_EQ(refs[1], Sem().Get(b));
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index bf0e9b3..9f6843f 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -61,7 +61,10 @@
#include "src/tint/lang/wgsl/ast/workgroup_attribute.h"
#include "src/tint/lang/wgsl/intrinsic/ctor_conv.h"
#include "src/tint/lang/wgsl/intrinsic/dialect.h"
+#include "src/tint/lang/wgsl/resolver/incomplete_type.h"
#include "src/tint/lang/wgsl/resolver/uniformity.h"
+#include "src/tint/lang/wgsl/resolver/unresolved_identifier.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/break_if_statement.h"
#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h"
#include "src/tint/lang/wgsl/sem/call.h"
@@ -95,13 +98,6 @@
using namespace tint::core::fluent_types; // NOLINT
-TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::Access>);
-TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::AddressSpace>);
-TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::BuiltinValue>);
-TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::InterpolationSampling>);
-TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::InterpolationType>);
-TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::TexelFormat>);
-
namespace tint::resolver {
namespace {
@@ -115,7 +111,7 @@
} // namespace
Resolver::Resolver(ProgramBuilder* builder)
- : builder_(builder),
+ : b(*builder),
diagnostics_(builder->Diagnostics()),
const_eval_(builder->constants, diagnostics_),
intrinsic_table_{builder->Types(), builder->Symbols(), builder->Diagnostics()},
@@ -133,12 +129,12 @@
return false;
}
- builder_->Sem().Reserve(builder_->LastAllocatedNodeID());
+ b.Sem().Reserve(b.LastAllocatedNodeID());
// Pre-allocate the marked bitset with the total number of AST nodes.
- marked_.Resize(builder_->ASTNodes().Count());
+ marked_.Resize(b.ASTNodes().Count());
- if (!DependencyGraph::Build(builder_->AST(), diagnostics_, dependencies_)) {
+ if (!DependencyGraph::Build(b.AST(), diagnostics_, dependencies_)) {
return false;
}
@@ -150,15 +146,15 @@
}
// Create the semantic module. Don't be tempted to std::move() these, they're used below.
- auto* mod = builder_->create<sem::Module>(dependencies_.ordered_globals, enabled_extensions_);
+ auto* mod = b.create<sem::Module>(dependencies_.ordered_globals, enabled_extensions_);
ApplyDiagnosticSeverities(mod);
- builder_->Sem().SetModule(mod);
+ b.Sem().SetModule(mod);
const bool disable_uniformity_analysis =
enabled_extensions_.Contains(wgsl::Extension::kChromiumDisableUniformityAnalysis);
if (result && !disable_uniformity_analysis) {
// Run the uniformity analysis, which requires a complete semantic module.
- if (!AnalyzeUniformity(builder_, dependencies_)) {
+ if (!AnalyzeUniformity(b, dependencies_)) {
return false;
}
}
@@ -167,7 +163,7 @@
}
bool Resolver::ResolveInternal() {
- Mark(&builder_->AST());
+ Mark(&b.AST());
// Process all module-scope declarations in dependency order.
Vector<const ast::DiagnosticControl*, 4> diagnostic_controls;
@@ -211,7 +207,7 @@
}
bool result = true;
- for (auto* node : builder_->ASTNodes().Objects()) {
+ for (auto* node : b.ASTNodes().Objects()) {
if (TINT_UNLIKELY(!marked_[node->node_id.value])) {
StringStream err;
err << "AST node '" << node->TypeInfo().name << "' was not reached by the resolver\n"
@@ -230,7 +226,7 @@
return Switch(
v, //
[&](const ast::Var* var) { return Var(var, is_global); },
- [&](const ast::Let* let) { return Let(let, is_global); },
+ [&](const ast::Let* let) { return Let(let); },
[&](const ast::Override* override) { return Override(override); },
[&](const ast::Const* const_) { return Const(const_, is_global); },
[&](Default) {
@@ -242,15 +238,18 @@
});
}
-sem::Variable* Resolver::Let(const ast::Let* v, bool is_global) {
- const core::type::Type* ty = nullptr;
+sem::Variable* Resolver::Let(const ast::Let* v) {
+ auto* sem = b.create<sem::LocalVariable>(v, current_statement_);
+ sem->SetStage(core::EvaluationStage::kRuntime);
+ b.Sem().Add(v, sem);
// If the variable has a declared type, resolve it.
if (v->type) {
- ty = Type(v->type);
- if (!ty) {
+ auto* ty = Type(v->type);
+ if (TINT_UNLIKELY(!ty)) {
return nullptr;
}
+ sem->SetType(ty);
}
for (auto* attribute : v->attributes) {
@@ -267,53 +266,49 @@
}
}
- if (!v->initializer) {
+ if (TINT_UNLIKELY(!v->initializer)) {
AddError("'let' declaration must have an initializer", v->source);
return nullptr;
}
- auto* rhs = Load(Materialize(ValueExpression(v->initializer), ty));
- if (!rhs) {
+ auto* rhs = Load(Materialize(ValueExpression(v->initializer), sem->Type()));
+ if (TINT_UNLIKELY(!rhs)) {
return nullptr;
}
+ sem->SetInitializer(rhs);
// If the variable has no declared type, infer it from the RHS
- if (!ty) {
- ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS
+ if (!sem->Type()) {
+ sem->SetType(rhs->Type()->UnwrapRef()); // Implicit load of RHS
}
- if (rhs && !validator_.VariableInitializer(v, ty, rhs)) {
+ if (TINT_UNLIKELY(rhs && !validator_.VariableInitializer(v, sem->Type(), rhs))) {
return nullptr;
}
if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined,
- const_cast<core::type::Type*>(ty), v->source)) {
+ const_cast<core::type::Type*>(sem->Type()), v->source)) {
AddNote("while instantiating 'let' " + v->name->symbol.Name(), v->source);
return nullptr;
}
- sem::Variable* sem = nullptr;
- if (is_global) {
- sem = builder_->create<sem::GlobalVariable>(
- v, ty, core::EvaluationStage::kRuntime, core::AddressSpace::kUndefined,
- core::Access::kUndefined,
- /* constant_value */ nullptr, std::nullopt, std::nullopt);
- } else {
- sem = builder_->create<sem::LocalVariable>(v, ty, core::EvaluationStage::kRuntime,
- core::AddressSpace::kUndefined,
- core::Access::kUndefined, current_statement_,
- /* constant_value */ nullptr);
- }
-
- sem->SetInitializer(rhs);
- builder_->Sem().Add(v, sem);
return sem;
}
sem::Variable* Resolver::Override(const ast::Override* v) {
- const core::type::Type* ty = nullptr;
+ auto* sem = b.create<sem::GlobalVariable>(v);
+ b.Sem().Add(v, sem);
+ sem->SetStage(core::EvaluationStage::kOverride);
+
+ on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) {
+ if (ref->Declaration()->Is<ast::Override>()) {
+ sem->AddTransitivelyReferencedOverride(ref);
+ }
+ });
+ TINT_DEFER(on_transitively_reference_global_.Pop());
// If the variable has a declared type, resolve it.
+ const core::type::Type* ty = nullptr;
if (v->type) {
ty = Type(v->type);
if (!ty) {
@@ -321,31 +316,31 @@
}
}
- const sem::ValueExpression* rhs = nullptr;
-
// Does the variable have an initializer?
+ const sem::ValueExpression* init = nullptr;
if (v->initializer) {
// Note: RHS must be a const or override expression, which excludes references.
// So there's no need to load or unwrap references here.
-
ExprEvalStageConstraint constraint{core::EvaluationStage::kOverride,
"override initializer"};
TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
- rhs = Materialize(ValueExpression(v->initializer), ty);
- if (!rhs) {
+ init = Materialize(ValueExpression(v->initializer), ty);
+ if (TINT_UNLIKELY(!init)) {
return nullptr;
}
+ sem->SetInitializer(init);
- // If the variable has no declared type, infer it from the RHS
+ // If the variable has no declared type, infer it from the initializer
if (!ty) {
- ty = rhs->Type();
+ ty = init->Type();
}
} else if (!ty) {
AddError("override declaration requires a type or initializer", v->source);
return nullptr;
}
+ sem->SetType(ty);
- if (rhs && !validator_.VariableInitializer(v, ty, rhs)) {
+ if (init && !validator_.VariableInitializer(v, ty, init)) {
return nullptr;
}
@@ -355,12 +350,6 @@
return nullptr;
}
- auto* sem = builder_->create<sem::GlobalVariable>(
- v, ty, core::EvaluationStage::kOverride, core::AddressSpace::kUndefined,
- core::Access::kUndefined,
- /* constant_value */ nullptr, std::nullopt, std::nullopt);
- sem->SetInitializer(rhs);
-
for (auto* attribute : v->attributes) {
Mark(attribute);
bool ok = Switch(
@@ -408,25 +397,19 @@
}
}
- builder_->Sem().Add(v, sem);
return sem;
}
sem::Variable* Resolver::Const(const ast::Const* c, bool is_global) {
- const core::type::Type* ty = nullptr;
-
- // If the variable has a declared type, resolve it.
- if (c->type) {
- ty = Type(c->type);
- if (!ty) {
- return nullptr;
- }
+ sem::Variable* sem = nullptr;
+ sem::GlobalVariable* global = nullptr;
+ if (is_global) {
+ global = b.create<sem::GlobalVariable>(c);
+ sem = global;
+ } else {
+ sem = b.create<sem::LocalVariable>(c, current_statement_);
}
-
- if (!c->initializer) {
- AddError("'const' declaration must have an initializer", c->source);
- return nullptr;
- }
+ b.Sem().Add(c, sem);
for (auto* attribute : c->attributes) {
Mark(attribute);
@@ -440,31 +423,47 @@
}
}
- const sem::ValueExpression* rhs = nullptr;
- {
- ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "const initializer"};
- TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
- rhs = ValueExpression(c->initializer);
- if (!rhs) {
- return nullptr;
- }
+ if (TINT_UNLIKELY(!c->initializer)) {
+ AddError("'const' declaration must have an initializer", c->source);
+ return nullptr;
+ }
+
+ ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "const initializer"};
+ TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
+ const auto* init = ValueExpression(c->initializer);
+ if (TINT_UNLIKELY(!init)) {
+ return nullptr;
}
// Note: RHS must be a const expression, which excludes references.
// So there's no need to load or unwrap references here.
+ // If the variable has a declared type, resolve it.
+ const core::type::Type* ty = nullptr;
+ if (c->type) {
+ ty = Type(c->type);
+ if (TINT_UNLIKELY(!ty)) {
+ return nullptr;
+ }
+ }
+
if (ty) {
// If an explicit type was specified, materialize to that type
- rhs = Materialize(rhs, ty);
- if (!rhs) {
+ init = Materialize(init, ty);
+ if (TINT_UNLIKELY(!init)) {
return nullptr;
}
} else {
// If no type was specified, infer it from the RHS
- ty = rhs->Type();
+ ty = init->Type();
}
- if (!validator_.VariableInitializer(c, ty, rhs)) {
+ sem->SetInitializer(init);
+ sem->SetStage(core::EvaluationStage::kConstant);
+ sem->SetConstantValue(init->ConstantValue());
+ sem->SetType(ty);
+
+ if (!validator_.VariableInitializer(c, ty, init)) {
return nullptr;
}
@@ -474,33 +473,43 @@
return nullptr;
}
- const auto value = rhs->ConstantValue();
- auto* sem = is_global
- ? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>(
- c, ty, core::EvaluationStage::kConstant, core::AddressSpace::kUndefined,
- core::Access::kUndefined, value, std::nullopt, std::nullopt))
- : static_cast<sem::Variable*>(builder_->create<sem::LocalVariable>(
- c, ty, core::EvaluationStage::kConstant, core::AddressSpace::kUndefined,
- core::Access::kUndefined, current_statement_, value));
-
- sem->SetInitializer(rhs);
- builder_->Sem().Add(c, sem);
return sem;
}
sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) {
- const core::type::Type* storage_ty = nullptr;
+ sem::Variable* sem = nullptr;
+ sem::GlobalVariable* global = nullptr;
+ if (is_global) {
+ global = b.create<sem::GlobalVariable>(var);
+ sem = global;
+ } else {
+ sem = b.create<sem::LocalVariable>(var, current_statement_);
+ }
+ sem->SetStage(core::EvaluationStage::kRuntime);
+ b.Sem().Add(var, sem);
+
+ if (is_global) {
+ on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) {
+ if (ref->Declaration()->Is<ast::Override>()) {
+ global->AddTransitivelyReferencedOverride(ref);
+ }
+ });
+ }
+ TINT_DEFER({
+ if (is_global) {
+ on_transitively_reference_global_.Pop();
+ }
+ });
// If the variable has a declared type, resolve it.
+ const core::type::Type* storage_ty = nullptr;
if (auto ty = var->type) {
storage_ty = Type(ty);
- if (!storage_ty) {
+ if (TINT_UNLIKELY(!storage_ty)) {
return nullptr;
}
}
- const sem::ValueExpression* rhs = nullptr;
-
// Does the variable have a initializer?
if (var->initializer) {
ExprEvalStageConstraint constraint{
@@ -509,13 +518,15 @@
};
TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
- rhs = Load(Materialize(ValueExpression(var->initializer), storage_ty));
- if (!rhs) {
+ auto* init = Load(Materialize(ValueExpression(var->initializer), storage_ty));
+ if (TINT_UNLIKELY(!init)) {
return nullptr;
}
+ sem->SetInitializer(init);
+
// If the variable has no declared type, infer it from the RHS
if (!storage_ty) {
- storage_ty = rhs->Type();
+ storage_ty = init->Type();
}
}
@@ -524,62 +535,61 @@
return nullptr;
}
- auto address_space = core::AddressSpace::kUndefined;
if (var->declared_address_space) {
- auto expr = AddressSpaceExpression(var->declared_address_space);
- if (TINT_UNLIKELY(!expr)) {
+ auto space = AddressSpaceExpression(var->declared_address_space);
+ if (TINT_UNLIKELY(!space)) {
return nullptr;
}
- address_space = expr->Value();
+ sem->SetAddressSpace(space->Value());
} else {
// No declared address space. Infer from usage / type.
if (!is_global) {
- address_space = core::AddressSpace::kFunction;
+ sem->SetAddressSpace(core::AddressSpace::kFunction);
} else if (storage_ty->UnwrapRef()->is_handle()) {
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
// If the store type is a texture type or a sampler type, then the
// variable declaration must not have a address space attribute. The
// address space will always be handle.
- address_space = core::AddressSpace::kHandle;
+ sem->SetAddressSpace(core::AddressSpace::kHandle);
}
}
- if (!is_global && address_space != core::AddressSpace::kFunction &&
+ if (!is_global && sem->AddressSpace() != core::AddressSpace::kFunction &&
validator_.IsValidationEnabled(var->attributes,
ast::DisabledValidation::kIgnoreAddressSpace)) {
AddError("function-scope 'var' declaration must use 'function' address space", var->source);
return nullptr;
}
- auto access = core::Access::kUndefined;
if (var->declared_access) {
auto expr = AccessExpression(var->declared_access);
if (!expr) {
return nullptr;
}
- access = expr->Value();
+ sem->SetAccess(expr->Value());
} else {
- access = DefaultAccessForAddressSpace(address_space);
+ sem->SetAccess(DefaultAccessForAddressSpace(sem->AddressSpace()));
}
- if (rhs && !validator_.VariableInitializer(var, storage_ty, rhs)) {
+ sem->SetType(b.create<core::type::Reference>(sem->AddressSpace(), storage_ty, sem->Access()));
+
+ if (sem->Initializer() &&
+ !validator_.VariableInitializer(var, storage_ty, sem->Initializer())) {
return nullptr;
}
- auto* var_ty = builder_->create<core::type::Reference>(address_space, storage_ty, access);
-
- if (!ApplyAddressSpaceUsageToType(address_space, var_ty,
+ if (!ApplyAddressSpaceUsageToType(sem->AddressSpace(),
+ const_cast<core::type::Type*>(sem->Type()),
var->type ? var->type->source : var->source)) {
AddNote("while instantiating 'var' " + var->name->symbol.Name(), var->source);
return nullptr;
}
- sem::Variable* sem = nullptr;
if (is_global) {
- bool has_io_address_space =
- address_space == core::AddressSpace::kIn || address_space == core::AddressSpace::kOut;
+ bool has_io_address_space = sem->AddressSpace() == core::AddressSpace::kIn ||
+ sem->AddressSpace() == core::AddressSpace::kOut;
- std::optional<uint32_t> group, binding, location, index;
+ std::optional<uint32_t> group, binding;
for (auto* attribute : var->attributes) {
Mark(attribute);
enum Status { kSuccess, kErrored, kInvalid };
@@ -609,7 +619,7 @@
if (!value) {
return kErrored;
}
- location = value.Get();
+ global->SetLocation(value.Get());
return kSuccess;
},
[&](const ast::IndexAttribute* attr) {
@@ -620,7 +630,7 @@
if (!value) {
return kErrored;
}
- index = value.Get();
+ global->SetIndex(value.Get());
return kSuccess;
},
[&](const ast::BuiltinAttribute* attr) {
@@ -657,13 +667,9 @@
}
}
- std::optional<BindingPoint> binding_point;
if (group && binding) {
- binding_point = BindingPoint{group.value(), binding.value()};
+ global->SetBindingPoint(BindingPoint{group.value(), binding.value()});
}
- sem = builder_->create<sem::GlobalVariable>(
- var, var_ty, core::EvaluationStage::kRuntime, address_space, access,
- /* constant_value */ nullptr, binding_point, location, index);
} else {
for (auto* attribute : var->attributes) {
@@ -679,13 +685,8 @@
return nullptr;
}
}
- sem = builder_->create<sem::LocalVariable>(var, var_ty, core::EvaluationStage::kRuntime,
- address_space, access, current_statement_,
- /* constant_value */ nullptr);
}
- sem->SetInitializer(rhs);
- builder_->Sem().Add(var, sem);
return sem;
}
@@ -694,23 +695,25 @@
uint32_t index) {
Mark(param->name);
+ auto* sem = b.create<sem::Parameter>(param, index);
+ b.Sem().Add(param, sem);
+
auto add_note = [&] {
AddNote("while instantiating parameter " + param->name->symbol.Name(), param->source);
};
- std::optional<uint32_t> location, group, binding;
-
if (func->IsEntryPoint()) {
+ std::optional<uint32_t> group, binding;
for (auto* attribute : param->attributes) {
Mark(attribute);
bool ok = Switch(
attribute, //
[&](const ast::LocationAttribute* attr) {
auto value = LocationAttribute(attr);
- if (!value) {
+ if (TINT_UNLIKELY(!value)) {
return false;
}
- location = value.Get();
+ sem->SetLocation(value.Get());
return true;
},
[&](const ast::BuiltinAttribute* attr) -> bool { return BuiltinAttribute(attr); },
@@ -728,7 +731,7 @@
return false;
}
auto value = GroupAttribute(attr);
- if (!value) {
+ if (TINT_UNLIKELY(!value)) {
return false;
}
group = value.Get();
@@ -741,7 +744,7 @@
return false;
}
auto value = BindingAttribute(attr);
- if (!value) {
+ if (TINT_UNLIKELY(!value)) {
return false;
}
binding = value.Get();
@@ -755,6 +758,9 @@
return nullptr;
}
}
+ if (group && binding) {
+ sem->SetBindingPoint(BindingPoint{group.value(), binding.value()});
+ }
} else {
for (auto* attribute : param->attributes) {
Mark(attribute);
@@ -781,9 +787,10 @@
}
core::type::Type* ty = Type(param->type);
- if (!ty) {
+ if (TINT_UNLIKELY(!ty)) {
return nullptr;
}
+ sem->SetType(ty);
if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, ty, param->type->source)) {
add_note();
@@ -801,16 +808,6 @@
}
}
- std::optional<BindingPoint> binding_point;
- if (group && binding) {
- binding_point = BindingPoint{group.value(), binding.value()};
- }
-
- auto* sem = builder_->create<sem::Parameter>(
- param, index, ty, core::AddressSpace::kUndefined, core::Access::kUndefined,
- core::ParameterUsage::kNone, binding_point, location);
- builder_->Sem().Add(param, sem);
-
if (!validator_.Parameter(sem)) {
return nullptr;
}
@@ -849,7 +846,7 @@
// deterministic.
// TODO(crbug.com/tint/1192): If a transform changes the order or removes an
// unused constant, the allocation may change on the next Resolver pass.
- for (auto* decl : builder_->AST().GlobalDeclarations()) {
+ for (auto* decl : b.AST().GlobalDeclarations()) {
auto* override = decl->As<ast::Override>();
if (!override) {
continue;
@@ -882,8 +879,8 @@
void Resolver::SetShadows() {
for (auto it : dependencies_.shadows) {
- CastableBase* b = sem_.Get(it.value);
- if (TINT_UNLIKELY(!b)) {
+ CastableBase* shadowed = sem_.Get(it.value);
+ if (TINT_UNLIKELY(!shadowed)) {
StringStream err;
err << "AST node '" << it.value->TypeInfo().name << "' had no semantic info\n"
<< "Pointer: " << it.value;
@@ -892,15 +889,12 @@
Switch(
sem_.Get(it.key), //
- [&](sem::LocalVariable* local) { local->SetShadows(b); },
- [&](sem::Parameter* param) { param->SetShadows(b); });
+ [&](sem::LocalVariable* local) { local->SetShadows(shadowed); },
+ [&](sem::Parameter* param) { param->SetShadows(shadowed); });
}
}
sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* v) {
- UniqueVector<const sem::GlobalVariable*, 4> transitively_referenced_overrides;
- TINT_SCOPED_ASSIGNMENT(resolved_overrides_, &transitively_referenced_overrides);
-
auto* sem = As<sem::GlobalVariable>(Variable(v, /* is_global */ true));
if (!sem) {
return nullptr;
@@ -914,20 +908,6 @@
return nullptr;
}
- // Track the pipeline-overridable constants that are transitively referenced by this
- // variable.
- for (auto* var : transitively_referenced_overrides) {
- builder_->Sem().AddTransitivelyReferencedOverride(sem, var);
- }
- if (auto* arr = sem->Type()->UnwrapRef()->As<core::type::Array>()) {
- auto* refs = builder_->Sem().TransitivelyReferencedOverrides(arr);
- if (refs) {
- for (auto* var : *refs) {
- builder_->Sem().AddTransitivelyReferencedOverride(sem, var);
- }
- }
- }
-
return sem;
}
@@ -948,19 +928,23 @@
AddError("const assertion failed", assertion->source);
return nullptr;
}
- auto* sem =
- builder_->create<sem::Statement>(assertion, current_compound_statement_, current_function_);
- builder_->Sem().Add(assertion, sem);
+ auto* sem = b.create<sem::Statement>(assertion, current_compound_statement_, current_function_);
+ b.Sem().Add(assertion, sem);
return sem;
}
sem::Function* Resolver::Function(const ast::Function* decl) {
Mark(decl->name);
- auto* func = builder_->create<sem::Function>(decl);
- builder_->Sem().Add(decl, func);
+ auto* func = b.create<sem::Function>(decl);
+ b.Sem().Add(decl, func);
TINT_SCOPED_ASSIGNMENT(current_function_, func);
+ on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) { //
+ func->AddDirectlyReferencedGlobal(ref);
+ });
+ TINT_DEFER(on_transitively_reference_global_.Pop());
+
validator_.DiagnosticFilters().Push();
TINT_DEFER(validator_.DiagnosticFilters().Pop());
@@ -1040,7 +1024,7 @@
return nullptr;
}
} else {
- return_type = builder_->create<core::type::Void>();
+ return_type = b.create<core::type::Void>();
}
func->SetReturnType(return_type);
@@ -1158,7 +1142,7 @@
AddICE(err.str(), decl->body->source);
return nullptr;
}
- auto* body = StatementScope(decl->body, builder_->create<sem::FunctionBlockStatement>(func),
+ auto* body = StatementScope(decl->body, b.create<sem::FunctionBlockStatement>(func),
[&] { return Statements(decl->body->statements); });
if (!body) {
return nullptr;
@@ -1227,25 +1211,25 @@
stmt,
// Compound statements. These create their own sem::CompoundStatement
// bindings.
- [&](const ast::BlockStatement* b) { return BlockStatement(b); },
- [&](const ast::ForLoopStatement* l) { return ForLoopStatement(l); },
- [&](const ast::LoopStatement* l) { return LoopStatement(l); },
- [&](const ast::WhileStatement* w) { return WhileStatement(w); },
- [&](const ast::IfStatement* i) { return IfStatement(i); },
+ [&](const ast::BlockStatement* s) { return BlockStatement(s); },
+ [&](const ast::ForLoopStatement* s) { return ForLoopStatement(s); },
+ [&](const ast::LoopStatement* s) { return LoopStatement(s); },
+ [&](const ast::WhileStatement* s) { return WhileStatement(s); },
+ [&](const ast::IfStatement* s) { return IfStatement(s); },
[&](const ast::SwitchStatement* s) { return SwitchStatement(s); },
// Non-Compound statements
- [&](const ast::AssignmentStatement* a) { return AssignmentStatement(a); },
- [&](const ast::BreakStatement* b) { return BreakStatement(b); },
- [&](const ast::BreakIfStatement* b) { return BreakIfStatement(b); },
- [&](const ast::CallStatement* c) { return CallStatement(c); },
- [&](const ast::CompoundAssignmentStatement* c) { return CompoundAssignmentStatement(c); },
- [&](const ast::ContinueStatement* c) { return ContinueStatement(c); },
- [&](const ast::DiscardStatement* d) { return DiscardStatement(d); },
- [&](const ast::IncrementDecrementStatement* i) { return IncrementDecrementStatement(i); },
- [&](const ast::ReturnStatement* r) { return ReturnStatement(r); },
- [&](const ast::VariableDeclStatement* v) { return VariableDeclStatement(v); },
- [&](const ast::ConstAssert* sa) { return ConstAssert(sa); },
+ [&](const ast::AssignmentStatement* s) { return AssignmentStatement(s); },
+ [&](const ast::BreakStatement* s) { return BreakStatement(s); },
+ [&](const ast::BreakIfStatement* s) { return BreakIfStatement(s); },
+ [&](const ast::CallStatement* s) { return CallStatement(s); },
+ [&](const ast::CompoundAssignmentStatement* s) { return CompoundAssignmentStatement(s); },
+ [&](const ast::ContinueStatement* s) { return ContinueStatement(s); },
+ [&](const ast::DiscardStatement* s) { return DiscardStatement(s); },
+ [&](const ast::IncrementDecrementStatement* s) { return IncrementDecrementStatement(s); },
+ [&](const ast::ReturnStatement* s) { return ReturnStatement(s); },
+ [&](const ast::VariableDeclStatement* s) { return VariableDeclStatement(s); },
+ [&](const ast::ConstAssert* s) { return ConstAssert(s); },
// Error cases
[&](const ast::CaseStatement*) {
@@ -1260,8 +1244,7 @@
sem::CaseStatement* Resolver::CaseStatement(const ast::CaseStatement* stmt,
const core::type::Type* ty) {
- auto* sem =
- builder_->create<sem::CaseStatement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::CaseStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
sem->Selectors().reserve(stmt->selectors.Length());
for (auto* sel : stmt->selectors) {
@@ -1289,7 +1272,7 @@
}
}
- sem->Selectors().emplace_back(builder_->create<sem::CaseSelector>(sel, const_value));
+ sem->Selectors().emplace_back(b.create<sem::CaseSelector>(sel, const_value));
}
Mark(stmt->body);
@@ -1304,8 +1287,7 @@
}
sem::IfStatement* Resolver::IfStatement(const ast::IfStatement* stmt) {
- auto* sem =
- builder_->create<sem::IfStatement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::IfStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto* cond = Load(ValueExpression(stmt->condition));
if (!cond) {
@@ -1316,8 +1298,8 @@
sem->Behaviors().Remove(sem::Behavior::kNext);
Mark(stmt->body);
- auto* body = builder_->create<sem::BlockStatement>(stmt->body, current_compound_statement_,
- current_function_);
+ auto* body = b.create<sem::BlockStatement>(stmt->body, current_compound_statement_,
+ current_function_);
if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) {
return false;
}
@@ -1342,19 +1324,18 @@
}
sem::BlockStatement* Resolver::BlockStatement(const ast::BlockStatement* stmt) {
- auto* sem = builder_->create<sem::BlockStatement>(
- stmt->As<ast::BlockStatement>(), current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::BlockStatement>(stmt->As<ast::BlockStatement>(),
+ current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] { return Statements(stmt->statements); });
}
sem::LoopStatement* Resolver::LoopStatement(const ast::LoopStatement* stmt) {
- auto* sem =
- builder_->create<sem::LoopStatement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::LoopStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
Mark(stmt->body);
- auto* body = builder_->create<sem::LoopBlockStatement>(
- stmt->body, current_compound_statement_, current_function_);
+ auto* body = b.create<sem::LoopBlockStatement>(stmt->body, current_compound_statement_,
+ current_function_);
return StatementScope(stmt->body, body, [&] {
if (!Statements(stmt->body->statements)) {
return false;
@@ -1366,7 +1347,7 @@
Mark(stmt->continuing);
auto* continuing = StatementScope(
stmt->continuing,
- builder_->create<sem::LoopContinuingBlockStatement>(
+ b.create<sem::LoopContinuingBlockStatement>(
stmt->continuing, current_compound_statement_, current_function_),
[&] { return Statements(stmt->continuing->statements); });
if (!continuing) {
@@ -1388,8 +1369,8 @@
}
sem::ForLoopStatement* Resolver::ForLoopStatement(const ast::ForLoopStatement* stmt) {
- auto* sem = builder_->create<sem::ForLoopStatement>(stmt, current_compound_statement_,
- current_function_);
+ auto* sem =
+ b.create<sem::ForLoopStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto& behaviors = sem->Behaviors();
if (auto* initializer = stmt->initializer) {
@@ -1421,8 +1402,8 @@
Mark(stmt->body);
- auto* body = builder_->create<sem::LoopBlockStatement>(
- stmt->body, current_compound_statement_, current_function_);
+ auto* body = b.create<sem::LoopBlockStatement>(stmt->body, current_compound_statement_,
+ current_function_);
if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) {
return false;
}
@@ -1440,8 +1421,7 @@
}
sem::WhileStatement* Resolver::WhileStatement(const ast::WhileStatement* stmt) {
- auto* sem =
- builder_->create<sem::WhileStatement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::WhileStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto& behaviors = sem->Behaviors();
@@ -1454,8 +1434,8 @@
Mark(stmt->body);
- auto* body = builder_->create<sem::LoopBlockStatement>(
- stmt->body, current_compound_statement_, current_function_);
+ auto* body = b.create<sem::LoopBlockStatement>(stmt->body, current_compound_statement_,
+ current_function_);
if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) {
return false;
}
@@ -1517,11 +1497,11 @@
[&](const ast::MemberAccessorExpression* member) { return MemberAccessor(member); },
[&](const ast::UnaryOpExpression* unary) { return UnaryOp(unary); },
[&](const ast::PhonyExpression*) {
- return builder_->create<sem::ValueExpression>(
- expr, builder_->create<core::type::Void>(), core::EvaluationStage::kRuntime,
- current_statement_,
- /* constant_value */ nullptr,
- /* has_side_effects */ false);
+ return b.create<sem::ValueExpression>(expr, b.create<core::type::Void>(),
+ core::EvaluationStage::kRuntime,
+ current_statement_,
+ /* constant_value */ nullptr,
+ /* has_side_effects */ false);
},
[&](Default) {
StringStream err;
@@ -1544,7 +1524,7 @@
}
}
- builder_->Sem().Add(expr, sem_expr);
+ b.Sem().Add(expr, sem_expr);
if (expr == root) {
return sem_expr;
}
@@ -1580,26 +1560,43 @@
}
sem::TypeExpression* Resolver::TypeExpression(const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "type"};
return sem_.AsTypeExpression(Expression(expr));
}
sem::FunctionExpression* Resolver::FunctionExpression(const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "call target"};
return sem_.AsFunctionExpression(Expression(expr));
}
core::type::Type* Resolver::Type(const ast::Expression* ast) {
+ Vector<const sem::GlobalVariable*, 4> referenced_overrides;
+ on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) {
+ if (ref->Declaration()->Is<ast::Override>()) {
+ referenced_overrides.Push(ref);
+ }
+ });
+ TINT_DEFER(on_transitively_reference_global_.Pop());
+
auto* type_expr = TypeExpression(ast);
- if (!type_expr) {
+ if (TINT_UNLIKELY(!type_expr)) {
return nullptr;
}
- return const_cast<core::type::Type*>(type_expr->Type());
+
+ auto* type = const_cast<core::type::Type*>(type_expr->Type());
+ if (TINT_UNLIKELY(!type)) {
+ return nullptr;
+ }
+
+ if (auto* arr = type->As<sem::Array>()) {
+ for (auto* ref : referenced_overrides) {
+ arr->AddTransitivelyReferencedOverride(ref);
+ }
+ }
+
+ return type;
}
sem::BuiltinEnumExpression<core::AddressSpace>* Resolver::AddressSpaceExpression(
const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "address space", core::kAddressSpaceStrings};
auto address_space_expr = sem_.AsAddressSpace(Expression(expr));
if (TINT_UNLIKELY(!address_space_expr)) {
return nullptr;
@@ -1618,31 +1615,25 @@
sem::BuiltinEnumExpression<core::BuiltinValue>* Resolver::BuiltinValueExpression(
const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "builtin value", core::kBuiltinValueStrings};
return sem_.AsBuiltinValue(Expression(expr));
}
sem::BuiltinEnumExpression<core::TexelFormat>* Resolver::TexelFormatExpression(
const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "texel format", core::kTexelFormatStrings};
return sem_.AsTexelFormat(Expression(expr));
}
sem::BuiltinEnumExpression<core::Access>* Resolver::AccessExpression(const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "access", core::kAccessStrings};
return sem_.AsAccess(Expression(expr));
}
sem::BuiltinEnumExpression<core::InterpolationSampling>* Resolver::InterpolationSampling(
const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "interpolation sampling",
- core::kInterpolationSamplingStrings};
return sem_.AsInterpolationSampling(Expression(expr));
}
sem::BuiltinEnumExpression<core::InterpolationType>* Resolver::InterpolationType(
const ast::Expression* expr) {
- identifier_resolve_hint_ = {expr, "interpolation type", core::kInterpolationTypeStrings};
return sem_.AsInterpolationType(Expression(expr));
}
@@ -1768,12 +1759,12 @@
const core::type::Type* Resolver::ConcreteType(const core::type::Type* ty,
const core::type::Type* target_ty,
const Source& source) {
- auto i32 = [&] { return builder_->create<core::type::I32>(); };
- auto f32 = [&] { return builder_->create<core::type::F32>(); };
- auto i32v = [&](uint32_t width) { return builder_->create<core::type::Vector>(i32(), width); };
- auto f32v = [&](uint32_t width) { return builder_->create<core::type::Vector>(f32(), width); };
+ auto i32 = [&] { return b.create<core::type::I32>(); };
+ auto f32 = [&] { return b.create<core::type::F32>(); };
+ auto i32v = [&](uint32_t width) { return b.create<core::type::Vector>(i32(), width); };
+ auto f32v = [&](uint32_t width) { return b.create<core::type::Vector>(f32(), width); };
auto f32m = [&](uint32_t columns, uint32_t rows) {
- return builder_->create<core::type::Matrix>(f32v(rows), columns);
+ return b.create<core::type::Matrix>(f32v(rows), columns);
};
return Switch(
@@ -1796,9 +1787,9 @@
return target_ty ? target_ty : f32m(m->columns(), m->rows());
});
},
- [&](const core::type::Array* a) -> const core::type::Type* {
+ [&](const sem::Array* a) -> const core::type::Type* {
const core::type::Type* target_el_ty = nullptr;
- if (auto* target_arr_ty = As<core::type::Array>(target_ty)) {
+ if (auto* target_arr_ty = As<sem::Array>(target_ty)) {
target_el_ty = target_arr_ty->ElemType();
}
if (auto* el_ty = ConcreteType(a->ElemType(), target_el_ty, source)) {
@@ -1825,9 +1816,9 @@
return expr;
}
- auto* load = builder_->create<sem::Load>(expr, current_statement_);
+ auto* load = b.create<sem::Load>(expr, current_statement_);
load->Behaviors() = expr->Behaviors();
- builder_->Sem().Replace(expr->Declaration(), load);
+ b.Sem().Replace(expr->Declaration(), load);
// Track the load for the alias analysis.
auto& alias_info = alias_analysis_infos_[current_function_];
@@ -1887,10 +1878,9 @@
}
}
- auto* m =
- builder_->create<sem::Materialize>(expr, current_statement_, concrete_ty, materialized_val);
+ auto* m = b.create<sem::Materialize>(expr, current_statement_, concrete_ty, materialized_val);
m->Behaviors() = expr->Behaviors();
- builder_->Sem().Replace(decl, m);
+ b.Sem().Replace(decl, m);
return m;
}
@@ -1966,10 +1956,10 @@
auto* obj_ty = obj_raw_ty->UnwrapRef();
auto* ty = Switch(
obj_ty, //
- [&](const core::type::Array* arr) { return arr->ElemType(); },
+ [&](const sem::Array* arr) { return arr->ElemType(); },
[&](const core::type::Vector* vec) { return vec->type(); },
[&](const core::type::Matrix* mat) {
- return builder_->create<core::type::Vector>(mat->type(), mat->rows());
+ return b.create<core::type::Vector>(mat->type(), mat->rows());
},
[&](Default) {
AddError("cannot index type '" + sem_.TypeNameOf(obj_ty) + "'", expr->source);
@@ -1988,7 +1978,7 @@
// If we're extracting from a reference, we return a reference.
if (auto* ref = obj_raw_ty->As<core::type::Reference>()) {
- ty = builder_->create<core::type::Reference>(ref->AddressSpace(), ty, ref->Access());
+ ty = b.create<core::type::Reference>(ref->AddressSpace(), ty, ref->Access());
}
const core::constant::Value* val = nullptr;
@@ -2006,9 +1996,9 @@
}
}
bool has_side_effects = idx->HasSideEffects() || obj->HasSideEffects();
- auto* sem = builder_->create<sem::IndexAccessorExpression>(
- expr, ty, stage, obj, idx, current_statement_, std::move(val), has_side_effects,
- obj->RootIdentifier());
+ auto* sem = b.create<sem::IndexAccessorExpression>(expr, ty, stage, obj, idx,
+ current_statement_, std::move(val),
+ has_side_effects, obj->RootIdentifier());
sem->Behaviors() = idx->Behaviors() + obj->Behaviors();
return sem;
}
@@ -2040,8 +2030,8 @@
}
}
- auto* sem = builder_->create<sem::ValueExpression>(expr, ty, stage, current_statement_,
- std::move(value), inner->HasSideEffects());
+ auto* sem = b.create<sem::ValueExpression>(expr, ty, stage, current_statement_,
+ std::move(value), inner->HasSideEffects());
sem->Behaviors() = inner->Behaviors();
return sem;
}
@@ -2052,11 +2042,10 @@
// * A builtin call.
// * A value constructor.
// * A value conversion.
- auto* target = expr->target;
- Mark(target);
-
- auto* ident = target->identifier;
- Mark(ident);
+ auto* target = sem_.Get(expr->target);
+ if (TINT_UNLIKELY(!target)) {
+ return nullptr;
+ }
// Resolve all of the arguments, their types and the set of behaviors.
Vector<const sem::ValueExpression*, 8> args;
@@ -2097,22 +2086,18 @@
if (match->info->flags.Contains(OverloadFlag::kIsConstructor)) {
// Type constructor
auto params = Transform(match->parameters, [&](auto& p, size_t i) {
- return builder_->create<sem::Parameter>(nullptr, static_cast<uint32_t>(i), p.type,
- core::AddressSpace::kUndefined,
- core::Access::kUndefined, p.usage);
+ return b.create<sem::Parameter>(nullptr, static_cast<uint32_t>(i), p.type, p.usage);
});
target_sem = constructors_.GetOrCreate(match.Get(), [&] {
- return builder_->create<sem::ValueConstructor>(match->return_type,
- std::move(params), overload_stage);
+ return b.create<sem::ValueConstructor>(match->return_type, std::move(params),
+ overload_stage);
});
} else {
// Type conversion
target_sem = converters_.GetOrCreate(match.Get(), [&] {
- auto param = builder_->create<sem::Parameter>(
- nullptr, 0u, match->parameters[0].type, core::AddressSpace::kUndefined,
- core::Access::kUndefined, match->parameters[0].usage);
- return builder_->create<sem::ValueConversion>(match->return_type, param,
- overload_stage);
+ auto* param = b.create<sem::Parameter>(nullptr, 0u, match->parameters[0].type,
+ match->parameters[0].usage);
+ return b.create<sem::ValueConversion>(match->return_type, param, overload_stage);
});
}
@@ -2138,26 +2123,25 @@
return nullptr;
}
}
- return builder_->create<sem::Call>(expr, target_sem, stage, std::move(args),
- current_statement_, value, has_side_effects);
+ return b.create<sem::Call>(expr, target_sem, stage, std::move(args), current_statement_,
+ value, has_side_effects);
};
// arr_or_str_init is a helper for building a sem::ValueConstructor for an array or structure
// constructor call target.
auto arr_or_str_init = [&](const core::type::Type* ty,
const sem::CallTarget* call_target) -> sem::Call* {
- if (!MaybeMaterializeAndLoadArguments(args, call_target)) {
- return nullptr;
- }
-
auto stage = args_stage; // The evaluation stage of the call
const core::constant::Value* value = nullptr; // The constant value for the call
if (stage == core::EvaluationStage::kConstant && skip_const_eval_.Contains(expr)) {
stage = core::EvaluationStage::kNotEvaluated;
}
if (stage == core::EvaluationStage::kConstant) {
- auto els = tint::Transform(args, [&](auto* arg) { return arg->ConstantValue(); });
- if (auto r = const_eval_.ArrayOrStructCtor(ty, std::move(els))) {
+ auto const_args = ConvertArguments(args, call_target);
+ if (!const_args) {
+ return nullptr;
+ }
+ if (auto r = const_eval_.ArrayOrStructCtor(ty, std::move(const_args.Get()))) {
value = r.Get();
} else {
return nullptr;
@@ -2172,8 +2156,8 @@
}
}
- return builder_->create<sem::Call>(expr, call_target, stage, std::move(args),
- current_statement_, value, has_side_effects);
+ return b.create<sem::Call>(expr, call_target, stage, std::move(args), current_statement_,
+ value, has_side_effects);
};
auto ty_init_or_conv = [&](const core::type::Type* type) {
@@ -2201,32 +2185,27 @@
return ctor_or_conv(wgsl::intrinsic::MatrixCtorConv(m->columns(), m->rows()),
m->type());
},
- [&](const core::type::Array* arr) -> sem::Call* {
+ [&](const sem::Array* arr) -> sem::Call* {
auto* call_target = array_ctors_.GetOrCreate(
ArrayConstructorSig{{arr, args.Length(), args_stage}},
[&]() -> sem::ValueConstructor* {
auto params = tint::Transform(args, [&](auto, size_t i) {
- return builder_->create<sem::Parameter>(
- nullptr, // declaration
- static_cast<uint32_t>(i), // index
- arr->ElemType(), // type
- core::AddressSpace::kUndefined, // address_space
- core::Access::kUndefined);
+ return b.create<sem::Parameter>(nullptr, // declaration
+ static_cast<uint32_t>(i), // index
+ arr->ElemType());
});
- return builder_->create<sem::ValueConstructor>(arr, std::move(params),
- args_stage);
+ return b.create<sem::ValueConstructor>(arr, std::move(params), args_stage);
});
- auto* call = arr_or_str_init(arr, call_target);
- if (!call) {
+ if (TINT_UNLIKELY(!MaybeMaterializeAndLoadArguments(args, call_target))) {
return nullptr;
}
- // Validation must occur after argument materialization in arr_or_str_init().
- if (!validator_.ArrayConstructor(expr, arr)) {
+ if (TINT_UNLIKELY(!validator_.ArrayConstructor(expr, arr))) {
return nullptr;
}
- return call;
+
+ return arr_or_str_init(arr, call_target);
},
[&](const core::type::Struct* str) -> sem::Call* {
auto* call_target = struct_ctors_.GetOrCreate(
@@ -2235,27 +2214,23 @@
Vector<sem::Parameter*, 8> params;
params.Resize(std::min(args.Length(), str->Members().Length()));
for (size_t i = 0, n = params.Length(); i < n; i++) {
- params[i] = builder_->create<sem::Parameter>(
- nullptr, // declaration
- static_cast<uint32_t>(i), // index
- str->Members()[i]->Type(), // type
- core::AddressSpace::kUndefined, // address_space
- core::Access::kUndefined); // access
+ params[i] =
+ b.create<sem::Parameter>(nullptr, // declaration
+ static_cast<uint32_t>(i), // index
+ str->Members()[i]->Type()); // type
}
- return builder_->create<sem::ValueConstructor>(str, std::move(params),
- args_stage);
+ return b.create<sem::ValueConstructor>(str, std::move(params), args_stage);
});
- auto* call = arr_or_str_init(str, call_target);
- if (!call) {
+ if (TINT_UNLIKELY(!MaybeMaterializeAndLoadArguments(args, call_target))) {
return nullptr;
}
- // Validation must occur after argument materialization in arr_or_str_init().
- if (!validator_.StructureInitializer(expr, str)) {
+ if (TINT_UNLIKELY(!validator_.StructureInitializer(expr, str))) {
return nullptr;
}
- return call;
+
+ return arr_or_str_init(str, call_target);
},
[&](Default) {
AddError("type is not constructible", expr->source);
@@ -2263,137 +2238,99 @@
});
};
- auto inferred_array = [&]() -> tint::sem::Call* {
- auto el_count =
- builder_->create<core::type::ConstantArrayCount>(static_cast<uint32_t>(args.Length()));
- auto arg_tys = tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
- auto el_ty = core::type::Type::Common(arg_tys);
- if (!el_ty) {
- AddError("cannot infer common array element type from constructor arguments",
- expr->source);
- Hashset<const core::type::Type*, 8> types;
- for (size_t i = 0; i < args.Length(); i++) {
- if (types.Add(args[i]->Type())) {
- AddNote("argument " + std::to_string(i) + " is of type '" +
- sem_.TypeNameOf(args[i]->Type()) + "'",
- args[i]->Declaration()->source);
+ auto incomplete_type = [&](const IncompleteType* t) -> sem::Call* {
+ // A type without template arguments.
+ // Examples: vec3(...), array(...)
+ switch (t->builtin) {
+ case core::BuiltinType::kVec2:
+ return ctor_or_conv(CtorConvIntrinsic::kVec2, nullptr);
+ case core::BuiltinType::kVec3:
+ return ctor_or_conv(CtorConvIntrinsic::kVec3, nullptr);
+ case core::BuiltinType::kVec4:
+ return ctor_or_conv(CtorConvIntrinsic::kVec4, nullptr);
+ case core::BuiltinType::kMat2X2:
+ return ctor_or_conv(CtorConvIntrinsic::kMat2x2, nullptr);
+ case core::BuiltinType::kMat2X3:
+ return ctor_or_conv(CtorConvIntrinsic::kMat2x3, nullptr);
+ case core::BuiltinType::kMat2X4:
+ return ctor_or_conv(CtorConvIntrinsic::kMat2x4, nullptr);
+ case core::BuiltinType::kMat3X2:
+ return ctor_or_conv(CtorConvIntrinsic::kMat3x2, nullptr);
+ case core::BuiltinType::kMat3X3:
+ return ctor_or_conv(CtorConvIntrinsic::kMat3x3, nullptr);
+ case core::BuiltinType::kMat3X4:
+ return ctor_or_conv(CtorConvIntrinsic::kMat3x4, nullptr);
+ case core::BuiltinType::kMat4X2:
+ return ctor_or_conv(CtorConvIntrinsic::kMat4x2, nullptr);
+ case core::BuiltinType::kMat4X3:
+ return ctor_or_conv(CtorConvIntrinsic::kMat4x3, nullptr);
+ case core::BuiltinType::kMat4X4:
+ return ctor_or_conv(CtorConvIntrinsic::kMat4x4, nullptr);
+ case core::BuiltinType::kArray: {
+ auto el_count =
+ b.create<core::type::ConstantArrayCount>(static_cast<uint32_t>(args.Length()));
+ auto arg_tys =
+ tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
+ auto el_ty = core::type::Type::Common(arg_tys);
+ if (TINT_UNLIKELY(!el_ty)) {
+ AddError("cannot infer common array element type from constructor arguments",
+ expr->source);
+ Hashset<const core::type::Type*, 8> types;
+ for (size_t i = 0; i < args.Length(); i++) {
+ if (types.Add(args[i]->Type())) {
+ AddNote("argument " + std::to_string(i) + " is of type '" +
+ sem_.TypeNameOf(args[i]->Type()) + "'",
+ args[i]->Declaration()->source);
+ }
+ }
+ return nullptr;
}
+ auto* arr = Array(expr->source, expr->source, expr->source, el_ty, el_count,
+ /* explicit_stride */ 0);
+ if (TINT_UNLIKELY(!arr)) {
+ return nullptr;
+ }
+ return ty_init_or_conv(arr);
}
- return nullptr;
+ default: {
+ TINT_ICE() << "unhandled IncompleteType builtin: " << t->builtin;
+ return nullptr;
+ }
}
- auto* arr = Array(expr->source, expr->source, expr->source, el_ty, el_count,
- /* explicit_stride */ 0);
- if (!arr) {
- return nullptr;
- }
- return ty_init_or_conv(arr);
};
- auto call = [&]() -> sem::Call* {
- auto resolved = dependencies_.resolved_identifiers.Get(ident);
- if (!resolved) {
- StringStream err;
- err << "identifier '" << ident->symbol.Name() << "' was not resolved";
- AddICE(err.str(), ident->source);
- return nullptr;
- }
-
- if (auto* ast_node = resolved->Node()) {
+ auto* call = Switch(
+ target, //
+ [&](const sem::FunctionExpression* fn_expr) {
+ return FunctionCall(expr, const_cast<sem::Function*>(fn_expr->Function()),
+ std::move(args), arg_behaviors);
+ },
+ [&](const sem::TypeExpression* ty_expr) {
return Switch(
- sem_.Get(ast_node), //
- [&](core::type::Type* t) -> tint::sem::Call* {
- // User declared types cannot be templated.
- if (!TINT_LIKELY(CheckNotTemplated("type", ident))) {
+ ty_expr->Type(), //
+ [&](const IncompleteType* t) -> sem::Call* {
+ auto* ctor = incomplete_type(t);
+ if (TINT_UNLIKELY(!ctor)) {
return nullptr;
}
- return ty_init_or_conv(t);
+ // Replace incomplete type with resolved type
+ const_cast<sem::TypeExpression*>(ty_expr)->SetType(ctor->Type());
+ return ctor;
},
- [&](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;
- },
- [&](Default) {
- ErrorMismatchedResolvedIdentifier(ident->source, *resolved, "call target");
- return nullptr;
- });
- }
-
- if (auto f = resolved->BuiltinFn(); f != wgsl::BuiltinFn::kNone) {
- if (!TINT_LIKELY(CheckNotTemplated("builtin", ident))) {
- return nullptr;
- }
- return BuiltinCall(expr, f, args);
- }
-
- if (auto b = resolved->BuiltinType(); b != core::BuiltinType::kUndefined) {
- if (!ident->Is<ast::TemplatedIdentifier>()) {
- // No template arguments provided.
- // Check to see if this is an inferred-element-type call.
- switch (b) {
- case core::BuiltinType::kArray:
- return inferred_array();
- case core::BuiltinType::kVec2:
- return ctor_or_conv(CtorConvIntrinsic::kVec2, nullptr);
- case core::BuiltinType::kVec3:
- return ctor_or_conv(CtorConvIntrinsic::kVec3, nullptr);
- case core::BuiltinType::kVec4:
- return ctor_or_conv(CtorConvIntrinsic::kVec4, nullptr);
- case core::BuiltinType::kMat2X2:
- return ctor_or_conv(CtorConvIntrinsic::kMat2x2, nullptr);
- case core::BuiltinType::kMat2X3:
- return ctor_or_conv(CtorConvIntrinsic::kMat2x3, nullptr);
- case core::BuiltinType::kMat2X4:
- return ctor_or_conv(CtorConvIntrinsic::kMat2x4, nullptr);
- case core::BuiltinType::kMat3X2:
- return ctor_or_conv(CtorConvIntrinsic::kMat3x2, nullptr);
- case core::BuiltinType::kMat3X3:
- return ctor_or_conv(CtorConvIntrinsic::kMat3x3, nullptr);
- case core::BuiltinType::kMat3X4:
- return ctor_or_conv(CtorConvIntrinsic::kMat3x4, nullptr);
- case core::BuiltinType::kMat4X2:
- return ctor_or_conv(CtorConvIntrinsic::kMat4x2, nullptr);
- case core::BuiltinType::kMat4X3:
- return ctor_or_conv(CtorConvIntrinsic::kMat4x3, nullptr);
- case core::BuiltinType::kMat4X4:
- return ctor_or_conv(CtorConvIntrinsic::kMat4x4, nullptr);
- default:
- break;
- }
- }
- auto* ty = BuiltinType(b, ident);
- if (TINT_UNLIKELY(!ty)) {
- return nullptr;
- }
- return ty_init_or_conv(ty);
- }
-
- if (auto* unresolved = resolved->Unresolved()) {
- AddError("unresolved call target '" + unresolved->name + "'", expr->source);
+ [&](Default) { return ty_init_or_conv(ty_expr->Type()); });
+ },
+ [&](const sem::BuiltinEnumExpression<wgsl::BuiltinFn>* fn_expr) {
+ return BuiltinCall(expr, fn_expr->Value(), args);
+ },
+ [&](Default) {
+ sem_.ErrorUnexpectedExprKind(target, "call target");
return nullptr;
- }
-
- ErrorMismatchedResolvedIdentifier(ident->source, *resolved, "call target");
- return nullptr;
- }();
+ });
if (!call) {
return nullptr;
}
- if (call->Target()->IsAnyOf<sem::ValueConstructor, sem::ValueConversion>()) {
- // The target of the call was a type.
- // Associate the target identifier expression with the resolved type.
- auto* ty_expr =
- builder_->create<sem::TypeExpression>(target, current_statement_, call->Type());
- builder_->Sem().Add(target, ty_expr);
- }
-
return validator_.Call(call, current_statement_) ? call : nullptr;
}
@@ -2415,9 +2352,7 @@
// De-duplicate builtins that are identical.
auto* target = builtins_.GetOrCreate(std::make_pair(overload.Get(), fn), [&] {
auto params = Transform(overload->parameters, [&](auto& p, size_t i) {
- return builder_->create<sem::Parameter>(nullptr, static_cast<uint32_t>(i), p.type,
- core::AddressSpace::kUndefined,
- core::Access::kUndefined, p.usage);
+ return b.create<sem::Parameter>(nullptr, static_cast<uint32_t>(i), p.type, p.usage);
});
sem::PipelineStageSet supported_stages;
auto flags = overload->info->flags;
@@ -2432,7 +2367,7 @@
}
auto eval_stage = overload->const_eval_fn ? core::EvaluationStage::kConstant
: core::EvaluationStage::kRuntime;
- return builder_->create<sem::BuiltinFn>(
+ return b.create<sem::BuiltinFn>(
fn, overload->return_type, std::move(params), eval_stage, supported_stages,
flags.Contains(OverloadFlag::kIsDeprecated), flags.Contains(OverloadFlag::kMustUse));
});
@@ -2477,8 +2412,8 @@
bool has_side_effects =
target->HasSideEffects() ||
std::any_of(args.begin(), args.end(), [](auto* e) { return e->HasSideEffects(); });
- auto* call = builder_->create<sem::Call>(expr, target, stage, std::move(args),
- current_statement_, value, has_side_effects);
+ auto* call = b.create<sem::Call>(expr, target, stage, std::move(args), current_statement_,
+ value, has_side_effects);
if (current_function_) {
current_function_->AddDirectlyCalledBuiltin(target);
@@ -2517,491 +2452,210 @@
core::type::Type* Resolver::BuiltinType(core::BuiltinType builtin_ty,
const ast::Identifier* ident) {
- auto& b = *builder_;
-
auto check_no_tmpl_args = [&](core::type::Type* ty) -> core::type::Type* {
return TINT_LIKELY(CheckNotTemplated("type", ident)) ? ty : nullptr;
};
- auto af = [&] { return b.create<core::type::AbstractFloat>(); };
- auto f32 = [&] { return b.create<core::type::F32>(); };
- auto i32 = [&] { return b.create<core::type::I32>(); };
- auto u32 = [&] { return b.create<core::type::U32>(); };
- auto f16 = [&] {
- return validator_.CheckF16Enabled(ident->source) ? b.create<core::type::F16>() : nullptr;
- };
- auto templated_identifier =
- [&](size_t min_args, size_t max_args = /* use min */ 0) -> const ast::TemplatedIdentifier* {
- if (max_args == 0) {
- max_args = min_args;
- }
- auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
- if (!tmpl_ident) {
- if (TINT_UNLIKELY(min_args != 0)) {
- AddError("expected '<' for '" + ident->symbol.Name() + "'",
- Source{ident->source.range.end});
- }
- return nullptr;
- }
- if (min_args == max_args) {
- if (TINT_UNLIKELY(tmpl_ident->arguments.Length() != min_args)) {
- AddError("'" + ident->symbol.Name() + "' requires " + std::to_string(min_args) +
- " template arguments",
- ident->source);
- return nullptr;
- }
- } else {
- if (TINT_UNLIKELY(tmpl_ident->arguments.Length() < min_args)) {
- AddError("'" + ident->symbol.Name() + "' requires at least " +
- std::to_string(min_args) + " template arguments",
- ident->source);
- return nullptr;
- }
- if (TINT_UNLIKELY(tmpl_ident->arguments.Length() > max_args)) {
- AddError("'" + ident->symbol.Name() + "' requires at most " +
- std::to_string(max_args) + " template arguments",
- ident->source);
- return nullptr;
- }
- }
- return tmpl_ident;
- };
- auto vec = [&](core::type::Type* el, uint32_t n) -> core::type::Vector* {
- if (TINT_UNLIKELY(!el)) {
- return nullptr;
- }
- if (TINT_UNLIKELY(!validator_.Vector(el, ident->source))) {
- return nullptr;
- }
- return b.create<core::type::Vector>(el, n);
- };
- auto mat = [&](core::type::Type* el, uint32_t num_columns,
- uint32_t num_rows) -> core::type::Matrix* {
- if (TINT_UNLIKELY(!el)) {
- return nullptr;
- }
- if (TINT_UNLIKELY(!validator_.Matrix(el, ident->source))) {
- return nullptr;
- }
- auto* column = vec(el, num_rows);
- if (!column) {
- return nullptr;
- }
- return b.create<core::type::Matrix>(column, num_columns);
- };
- auto vec_t = [&](uint32_t n) -> core::type::Vector* {
- auto* tmpl_ident = templated_identifier(1);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
- auto* ty = Type(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!ty)) {
- return nullptr;
- }
- return vec(const_cast<core::type::Type*>(ty), n);
- };
- auto mat_t = [&](uint32_t num_columns, uint32_t num_rows) -> core::type::Matrix* {
- auto* tmpl_ident = templated_identifier(1);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
- auto* ty = Type(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!ty)) {
- return nullptr;
- }
- return mat(const_cast<core::type::Type*>(ty), num_columns, num_rows);
- };
- auto array = [&]() -> core::type::Array* {
- UniqueVector<const sem::GlobalVariable*, 4> transitively_referenced_overrides;
- TINT_SCOPED_ASSIGNMENT(resolved_overrides_, &transitively_referenced_overrides);
-
- auto* tmpl_ident = templated_identifier(1, 2);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
- auto* ast_el_ty = tmpl_ident->arguments[0];
- auto* ast_count = (tmpl_ident->arguments.Length() > 1) ? tmpl_ident->arguments[1] : nullptr;
-
- auto* el_ty = Type(ast_el_ty);
- if (!el_ty) {
- return nullptr;
- }
-
- const core::type::ArrayCount* el_count =
- ast_count ? ArrayCount(ast_count) : builder_->create<core::type::RuntimeArrayCount>();
- if (!el_count) {
- return nullptr;
- }
-
- // Look for explicit stride via @stride(n) attribute
- uint32_t explicit_stride = 0;
- if (!ArrayAttributes(tmpl_ident->attributes, el_ty, explicit_stride)) {
- return nullptr;
- }
-
- auto* out = Array(tmpl_ident->source, //
- ast_el_ty->source, //
- ast_count ? ast_count->source : ident->source, //
- el_ty, el_count, explicit_stride);
- if (!out) {
- return nullptr;
- }
-
- if (el_ty->Is<core::type::Atomic>()) {
- atomic_composite_info_.Add(out, &ast_el_ty->source);
- } else {
- if (auto found = atomic_composite_info_.Get(el_ty)) {
- atomic_composite_info_.Add(out, *found);
- }
- }
-
- // Track the pipeline-overridable constants that are transitively referenced by this
- // array type.
- for (auto* var : transitively_referenced_overrides) {
- builder_->Sem().AddTransitivelyReferencedOverride(out, var);
- }
- return out;
- };
- auto atomic = [&]() -> core::type::Atomic* {
- auto* tmpl_ident = templated_identifier(1); // atomic<type>
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
-
- auto* ty_expr = TypeExpression(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!ty_expr)) {
- return nullptr;
- }
- auto* ty = ty_expr->Type();
-
- auto* out = builder_->create<core::type::Atomic>(ty);
- if (!validator_.Atomic(tmpl_ident, out)) {
- return nullptr;
- }
- return out;
- };
- auto ptr = [&]() -> core::type::Pointer* {
- auto* tmpl_ident = templated_identifier(2, 3); // ptr<address, type [, access]>
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
-
- auto* address_space_expr = AddressSpaceExpression(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!address_space_expr)) {
- return nullptr;
- }
- auto address_space = address_space_expr->Value();
-
- auto* store_ty_expr = TypeExpression(tmpl_ident->arguments[1]);
- if (TINT_UNLIKELY(!store_ty_expr)) {
- return nullptr;
- }
- auto* store_ty = const_cast<core::type::Type*>(store_ty_expr->Type());
-
- auto access = DefaultAccessForAddressSpace(address_space);
- if (tmpl_ident->arguments.Length() > 2) {
- auto* access_expr = AccessExpression(tmpl_ident->arguments[2]);
- if (TINT_UNLIKELY(!access_expr)) {
- return nullptr;
- }
- access = access_expr->Value();
- }
-
- auto* out = b.create<core::type::Pointer>(address_space, store_ty, access);
- if (!validator_.Pointer(tmpl_ident, out)) {
- return nullptr;
- }
- if (!ApplyAddressSpaceUsageToType(address_space, store_ty,
- store_ty_expr->Declaration()->source)) {
- AddNote("while instantiating " + out->FriendlyName(), ident->source);
- return nullptr;
- }
- return out;
- };
- auto sampled_texture = [&](core::type::TextureDimension dim) -> core::type::SampledTexture* {
- auto* tmpl_ident = templated_identifier(1);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
-
- auto* ty_expr = TypeExpression(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!ty_expr)) {
- return nullptr;
- }
- auto* out = b.create<core::type::SampledTexture>(dim, ty_expr->Type());
- return validator_.SampledTexture(out, ident->source) ? out : nullptr;
- };
- auto multisampled_texture =
- [&](core::type::TextureDimension dim) -> core::type::MultisampledTexture* {
- auto* tmpl_ident = templated_identifier(1);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
-
- auto* ty_expr = TypeExpression(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!ty_expr)) {
- return nullptr;
- }
- auto* out = b.create<core::type::MultisampledTexture>(dim, ty_expr->Type());
- return validator_.MultisampledTexture(out, ident->source) ? out : nullptr;
- };
- auto storage_texture = [&](core::type::TextureDimension dim) -> core::type::StorageTexture* {
- auto* tmpl_ident = templated_identifier(2);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
-
- auto* format = TexelFormatExpression(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!format)) {
- return nullptr;
- }
- auto* access = AccessExpression(tmpl_ident->arguments[1]);
- if (TINT_UNLIKELY(!access)) {
- return nullptr;
- }
- auto* subtype = core::type::StorageTexture::SubtypeFor(format->Value(), builder_->Types());
- auto* tex =
- b.create<core::type::StorageTexture>(dim, format->Value(), access->Value(), subtype);
- if (!validator_.StorageTexture(tex, ident->source)) {
- return nullptr;
- }
- return tex;
- };
- auto packed_vec3_t = [&]() -> core::type::Vector* {
- auto* tmpl_ident = templated_identifier(1);
- if (TINT_UNLIKELY(!tmpl_ident)) {
- return nullptr;
- }
- auto* el_ty = Type(tmpl_ident->arguments[0]);
- if (TINT_UNLIKELY(!el_ty)) {
- return nullptr;
- }
-
- if (TINT_UNLIKELY(!validator_.Vector(el_ty, ident->source))) {
- return nullptr;
- }
- return b.create<core::type::Vector>(el_ty, 3u, true);
- };
switch (builtin_ty) {
case core::BuiltinType::kBool:
return check_no_tmpl_args(b.create<core::type::Bool>());
case core::BuiltinType::kI32:
- return check_no_tmpl_args(i32());
+ return check_no_tmpl_args(I32());
case core::BuiltinType::kU32:
- return check_no_tmpl_args(u32());
+ return check_no_tmpl_args(U32());
case core::BuiltinType::kF16:
- return check_no_tmpl_args(f16());
+ return check_no_tmpl_args(F16(ident));
case core::BuiltinType::kF32:
return check_no_tmpl_args(b.create<core::type::F32>());
case core::BuiltinType::kVec2:
- return vec_t(2);
+ return VecT(ident, builtin_ty, 2);
case core::BuiltinType::kVec3:
- return vec_t(3);
+ return VecT(ident, builtin_ty, 3);
case core::BuiltinType::kVec4:
- return vec_t(4);
+ return VecT(ident, builtin_ty, 4);
case core::BuiltinType::kMat2X2:
- return mat_t(2, 2);
+ return MatT(ident, builtin_ty, 2, 2);
case core::BuiltinType::kMat2X3:
- return mat_t(2, 3);
+ return MatT(ident, builtin_ty, 2, 3);
case core::BuiltinType::kMat2X4:
- return mat_t(2, 4);
+ return MatT(ident, builtin_ty, 2, 4);
case core::BuiltinType::kMat3X2:
- return mat_t(3, 2);
+ return MatT(ident, builtin_ty, 3, 2);
case core::BuiltinType::kMat3X3:
- return mat_t(3, 3);
+ return MatT(ident, builtin_ty, 3, 3);
case core::BuiltinType::kMat3X4:
- return mat_t(3, 4);
+ return MatT(ident, builtin_ty, 3, 4);
case core::BuiltinType::kMat4X2:
- return mat_t(4, 2);
+ return MatT(ident, builtin_ty, 4, 2);
case core::BuiltinType::kMat4X3:
- return mat_t(4, 3);
+ return MatT(ident, builtin_ty, 4, 3);
case core::BuiltinType::kMat4X4:
- return mat_t(4, 4);
+ return MatT(ident, builtin_ty, 4, 4);
case core::BuiltinType::kMat2X2F:
- return check_no_tmpl_args(mat(f32(), 2u, 2u));
+ return check_no_tmpl_args(Mat(ident, F32(), 2u, 2u));
case core::BuiltinType::kMat2X3F:
- return check_no_tmpl_args(mat(f32(), 2u, 3u));
+ return check_no_tmpl_args(Mat(ident, F32(), 2u, 3u));
case core::BuiltinType::kMat2X4F:
- return check_no_tmpl_args(mat(f32(), 2u, 4u));
+ return check_no_tmpl_args(Mat(ident, F32(), 2u, 4u));
case core::BuiltinType::kMat3X2F:
- return check_no_tmpl_args(mat(f32(), 3u, 2u));
+ return check_no_tmpl_args(Mat(ident, F32(), 3u, 2u));
case core::BuiltinType::kMat3X3F:
- return check_no_tmpl_args(mat(f32(), 3u, 3u));
+ return check_no_tmpl_args(Mat(ident, F32(), 3u, 3u));
case core::BuiltinType::kMat3X4F:
- return check_no_tmpl_args(mat(f32(), 3u, 4u));
+ return check_no_tmpl_args(Mat(ident, F32(), 3u, 4u));
case core::BuiltinType::kMat4X2F:
- return check_no_tmpl_args(mat(f32(), 4u, 2u));
+ return check_no_tmpl_args(Mat(ident, F32(), 4u, 2u));
case core::BuiltinType::kMat4X3F:
- return check_no_tmpl_args(mat(f32(), 4u, 3u));
+ return check_no_tmpl_args(Mat(ident, F32(), 4u, 3u));
case core::BuiltinType::kMat4X4F:
- return check_no_tmpl_args(mat(f32(), 4u, 4u));
+ return check_no_tmpl_args(Mat(ident, F32(), 4u, 4u));
case core::BuiltinType::kMat2X2H:
- return check_no_tmpl_args(mat(f16(), 2u, 2u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 2u, 2u));
case core::BuiltinType::kMat2X3H:
- return check_no_tmpl_args(mat(f16(), 2u, 3u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 2u, 3u));
case core::BuiltinType::kMat2X4H:
- return check_no_tmpl_args(mat(f16(), 2u, 4u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 2u, 4u));
case core::BuiltinType::kMat3X2H:
- return check_no_tmpl_args(mat(f16(), 3u, 2u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 3u, 2u));
case core::BuiltinType::kMat3X3H:
- return check_no_tmpl_args(mat(f16(), 3u, 3u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 3u, 3u));
case core::BuiltinType::kMat3X4H:
- return check_no_tmpl_args(mat(f16(), 3u, 4u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 3u, 4u));
case core::BuiltinType::kMat4X2H:
- return check_no_tmpl_args(mat(f16(), 4u, 2u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 4u, 2u));
case core::BuiltinType::kMat4X3H:
- return check_no_tmpl_args(mat(f16(), 4u, 3u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 4u, 3u));
case core::BuiltinType::kMat4X4H:
- return check_no_tmpl_args(mat(f16(), 4u, 4u));
+ return check_no_tmpl_args(Mat(ident, F16(ident), 4u, 4u));
case core::BuiltinType::kVec2F:
- return check_no_tmpl_args(vec(f32(), 2u));
+ return check_no_tmpl_args(Vec(ident, F32(), 2u));
case core::BuiltinType::kVec3F:
- return check_no_tmpl_args(vec(f32(), 3u));
+ return check_no_tmpl_args(Vec(ident, F32(), 3u));
case core::BuiltinType::kVec4F:
- return check_no_tmpl_args(vec(f32(), 4u));
+ return check_no_tmpl_args(Vec(ident, F32(), 4u));
case core::BuiltinType::kVec2H:
- return check_no_tmpl_args(vec(f16(), 2u));
+ return check_no_tmpl_args(Vec(ident, F16(ident), 2u));
case core::BuiltinType::kVec3H:
- return check_no_tmpl_args(vec(f16(), 3u));
+ return check_no_tmpl_args(Vec(ident, F16(ident), 3u));
case core::BuiltinType::kVec4H:
- return check_no_tmpl_args(vec(f16(), 4u));
+ return check_no_tmpl_args(Vec(ident, F16(ident), 4u));
case core::BuiltinType::kVec2I:
- return check_no_tmpl_args(vec(i32(), 2u));
+ return check_no_tmpl_args(Vec(ident, I32(), 2u));
case core::BuiltinType::kVec3I:
- return check_no_tmpl_args(vec(i32(), 3u));
+ return check_no_tmpl_args(Vec(ident, I32(), 3u));
case core::BuiltinType::kVec4I:
- return check_no_tmpl_args(vec(i32(), 4u));
+ return check_no_tmpl_args(Vec(ident, I32(), 4u));
case core::BuiltinType::kVec2U:
- return check_no_tmpl_args(vec(u32(), 2u));
+ return check_no_tmpl_args(Vec(ident, U32(), 2u));
case core::BuiltinType::kVec3U:
- return check_no_tmpl_args(vec(u32(), 3u));
+ return check_no_tmpl_args(Vec(ident, U32(), 3u));
case core::BuiltinType::kVec4U:
- return check_no_tmpl_args(vec(u32(), 4u));
+ return check_no_tmpl_args(Vec(ident, U32(), 4u));
case core::BuiltinType::kArray:
- return array();
+ return Array(ident);
case core::BuiltinType::kAtomic:
- return atomic();
+ return Atomic(ident);
case core::BuiltinType::kPtr:
- return ptr();
+ return Ptr(ident);
case core::BuiltinType::kSampler:
return check_no_tmpl_args(
- builder_->create<core::type::Sampler>(core::type::SamplerKind::kSampler));
+ b.create<core::type::Sampler>(core::type::SamplerKind::kSampler));
case core::BuiltinType::kSamplerComparison:
return check_no_tmpl_args(
- builder_->create<core::type::Sampler>(core::type::SamplerKind::kComparisonSampler));
+ b.create<core::type::Sampler>(core::type::SamplerKind::kComparisonSampler));
case core::BuiltinType::kTexture1D:
- return sampled_texture(core::type::TextureDimension::k1d);
+ return SampledTexture(ident, core::type::TextureDimension::k1d);
case core::BuiltinType::kTexture2D:
- return sampled_texture(core::type::TextureDimension::k2d);
+ return SampledTexture(ident, core::type::TextureDimension::k2d);
case core::BuiltinType::kTexture2DArray:
- return sampled_texture(core::type::TextureDimension::k2dArray);
+ return SampledTexture(ident, core::type::TextureDimension::k2dArray);
case core::BuiltinType::kTexture3D:
- return sampled_texture(core::type::TextureDimension::k3d);
+ return SampledTexture(ident, core::type::TextureDimension::k3d);
case core::BuiltinType::kTextureCube:
- return sampled_texture(core::type::TextureDimension::kCube);
+ return SampledTexture(ident, core::type::TextureDimension::kCube);
case core::BuiltinType::kTextureCubeArray:
- return sampled_texture(core::type::TextureDimension::kCubeArray);
+ return SampledTexture(ident, core::type::TextureDimension::kCubeArray);
case core::BuiltinType::kTextureDepth2D:
return check_no_tmpl_args(
- builder_->create<core::type::DepthTexture>(core::type::TextureDimension::k2d));
+ b.create<core::type::DepthTexture>(core::type::TextureDimension::k2d));
case core::BuiltinType::kTextureDepth2DArray:
return check_no_tmpl_args(
- builder_->create<core::type::DepthTexture>(core::type::TextureDimension::k2dArray));
+ b.create<core::type::DepthTexture>(core::type::TextureDimension::k2dArray));
case core::BuiltinType::kTextureDepthCube:
return check_no_tmpl_args(
- builder_->create<core::type::DepthTexture>(core::type::TextureDimension::kCube));
+ b.create<core::type::DepthTexture>(core::type::TextureDimension::kCube));
case core::BuiltinType::kTextureDepthCubeArray:
- return check_no_tmpl_args(builder_->create<core::type::DepthTexture>(
- core::type::TextureDimension::kCubeArray));
+ return check_no_tmpl_args(
+ b.create<core::type::DepthTexture>(core::type::TextureDimension::kCubeArray));
case core::BuiltinType::kTextureDepthMultisampled2D:
- return check_no_tmpl_args(builder_->create<core::type::DepthMultisampledTexture>(
- core::type::TextureDimension::k2d));
+ return check_no_tmpl_args(
+ b.create<core::type::DepthMultisampledTexture>(core::type::TextureDimension::k2d));
case core::BuiltinType::kTextureExternal:
- return check_no_tmpl_args(builder_->create<core::type::ExternalTexture>());
+ return check_no_tmpl_args(b.create<core::type::ExternalTexture>());
case core::BuiltinType::kTextureMultisampled2D:
- return multisampled_texture(core::type::TextureDimension::k2d);
+ return MultisampledTexture(ident, core::type::TextureDimension::k2d);
case core::BuiltinType::kTextureStorage1D:
- return storage_texture(core::type::TextureDimension::k1d);
+ return StorageTexture(ident, core::type::TextureDimension::k1d);
case core::BuiltinType::kTextureStorage2D:
- return storage_texture(core::type::TextureDimension::k2d);
+ return StorageTexture(ident, core::type::TextureDimension::k2d);
case core::BuiltinType::kTextureStorage2DArray:
- return storage_texture(core::type::TextureDimension::k2dArray);
+ return StorageTexture(ident, core::type::TextureDimension::k2dArray);
case core::BuiltinType::kTextureStorage3D:
- return storage_texture(core::type::TextureDimension::k3d);
+ return StorageTexture(ident, core::type::TextureDimension::k3d);
case core::BuiltinType::kPackedVec3:
- return packed_vec3_t();
+ return PackedVec3T(ident);
case core::BuiltinType::kAtomicCompareExchangeResultI32:
- return core::type::CreateAtomicCompareExchangeResult(builder_->Types(),
- builder_->Symbols(), i32());
+ return core::type::CreateAtomicCompareExchangeResult(b.Types(), b.Symbols(), I32());
case core::BuiltinType::kAtomicCompareExchangeResultU32:
- return core::type::CreateAtomicCompareExchangeResult(builder_->Types(),
- builder_->Symbols(), u32());
+ return core::type::CreateAtomicCompareExchangeResult(b.Types(), b.Symbols(), U32());
case core::BuiltinType::kFrexpResultAbstract:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(), af());
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), AF());
case core::BuiltinType::kFrexpResultF16:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(), f16());
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), F16(ident));
case core::BuiltinType::kFrexpResultF32:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(), f32());
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), F32());
case core::BuiltinType::kFrexpResultVec2Abstract:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(af(), 2));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, AF(), 2));
case core::BuiltinType::kFrexpResultVec2F16:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(f16(), 2));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 2));
case core::BuiltinType::kFrexpResultVec2F32:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(f32(), 2));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F32(), 2));
case core::BuiltinType::kFrexpResultVec3Abstract:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(af(), 3));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, AF(), 3));
case core::BuiltinType::kFrexpResultVec3F16:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(f16(), 3));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 3));
case core::BuiltinType::kFrexpResultVec3F32:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(f32(), 3));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F32(), 3));
case core::BuiltinType::kFrexpResultVec4Abstract:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(af(), 4));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, AF(), 4));
case core::BuiltinType::kFrexpResultVec4F16:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(f16(), 4));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 4));
case core::BuiltinType::kFrexpResultVec4F32:
- return core::type::CreateFrexpResult(builder_->Types(), builder_->Symbols(),
- vec(f32(), 4));
+ return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F32(), 4));
case core::BuiltinType::kModfResultAbstract:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(), af());
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), AF());
case core::BuiltinType::kModfResultF16:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(), f16());
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), F16(ident));
case core::BuiltinType::kModfResultF32:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(), f32());
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), F32());
case core::BuiltinType::kModfResultVec2Abstract:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(af(), 2));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, AF(), 2));
case core::BuiltinType::kModfResultVec2F16:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(f16(), 2));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 2));
case core::BuiltinType::kModfResultVec2F32:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(f32(), 2));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F32(), 2));
case core::BuiltinType::kModfResultVec3Abstract:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(af(), 3));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, AF(), 3));
case core::BuiltinType::kModfResultVec3F16:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(f16(), 3));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 3));
case core::BuiltinType::kModfResultVec3F32:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(f32(), 3));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F32(), 3));
case core::BuiltinType::kModfResultVec4Abstract:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(af(), 4));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, AF(), 4));
case core::BuiltinType::kModfResultVec4F16:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(f16(), 4));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 4));
case core::BuiltinType::kModfResultVec4F32:
- return core::type::CreateModfResult(builder_->Types(), builder_->Symbols(),
- vec(f32(), 4));
+ return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F32(), 4));
case core::BuiltinType::kUndefined:
break;
}
@@ -3013,6 +2667,320 @@
return nullptr;
}
+core::type::AbstractFloat* Resolver::AF() {
+ return b.create<core::type::AbstractFloat>();
+}
+
+core::type::F32* Resolver::F32() {
+ return b.create<core::type::F32>();
+}
+
+core::type::I32* Resolver::I32() {
+ return b.create<core::type::I32>();
+}
+
+core::type::U32* Resolver::U32() {
+ return b.create<core::type::U32>();
+}
+
+core::type::F16* Resolver::F16(const ast::Identifier* ident) {
+ return validator_.CheckF16Enabled(ident->source) ? b.create<core::type::F16>() : nullptr;
+}
+
+core::type::Vector* Resolver::Vec(const ast::Identifier* ident, core::type::Type* el, uint32_t n) {
+ if (TINT_UNLIKELY(!el)) {
+ return nullptr;
+ }
+ if (TINT_UNLIKELY(!validator_.Vector(el, ident->source))) {
+ return nullptr;
+ }
+ return b.create<core::type::Vector>(el, n);
+}
+
+core::type::Type* Resolver::VecT(const ast::Identifier* ident,
+ core::BuiltinType builtin,
+ uint32_t n) {
+ auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
+ if (!tmpl_ident) {
+ // 'vecN' has no template arguments, so return an incomplete type.
+ return b.create<IncompleteType>(builtin);
+ }
+
+ if (TINT_UNLIKELY(!CheckTemplatedIdentifierArgs(tmpl_ident, 1))) {
+ return nullptr;
+ }
+
+ auto* ty = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!ty)) {
+ return nullptr;
+ }
+
+ return Vec(ident, const_cast<core::type::Type*>(ty), n);
+}
+
+core::type::Matrix* Resolver::Mat(const ast::Identifier* ident,
+ core::type::Type* el,
+ uint32_t num_columns,
+ uint32_t num_rows) {
+ if (TINT_UNLIKELY(!el)) {
+ return nullptr;
+ }
+ if (TINT_UNLIKELY(!validator_.Matrix(el, ident->source))) {
+ return nullptr;
+ }
+ auto* column = Vec(ident, el, num_rows);
+ if (!column) {
+ return nullptr;
+ }
+ return b.create<core::type::Matrix>(column, num_columns);
+}
+
+core::type::Type* Resolver::MatT(const ast::Identifier* ident,
+ core::BuiltinType builtin,
+ uint32_t num_columns,
+ uint32_t num_rows) {
+ auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
+ if (!tmpl_ident) {
+ // 'vecN' has no template arguments, so return an incomplete type.
+ return b.create<IncompleteType>(builtin);
+ }
+
+ if (TINT_UNLIKELY(!CheckTemplatedIdentifierArgs(tmpl_ident, 1))) {
+ return nullptr;
+ }
+
+ auto* el_ty = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!el_ty)) {
+ return nullptr;
+ }
+
+ return Mat(ident, const_cast<core::type::Type*>(el_ty), num_columns, num_rows);
+}
+
+core::type::Type* Resolver::Array(const ast::Identifier* ident) {
+ auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
+ if (!tmpl_ident) {
+ // 'array' has no template arguments, so return an incomplete type.
+ return b.create<IncompleteType>(core::BuiltinType::kArray);
+ }
+
+ if (TINT_UNLIKELY(!CheckTemplatedIdentifierArgs(tmpl_ident, 1, 2))) {
+ return nullptr;
+ }
+ auto* ast_el_ty = tmpl_ident->arguments[0];
+ auto* ast_count = (tmpl_ident->arguments.Length() > 1) ? tmpl_ident->arguments[1] : nullptr;
+
+ auto* el_ty = sem_.GetType(ast_el_ty);
+ if (!el_ty) {
+ return nullptr;
+ }
+
+ const core::type::ArrayCount* el_count =
+ ast_count ? ArrayCount(ast_count) : b.create<core::type::RuntimeArrayCount>();
+ if (!el_count) {
+ return nullptr;
+ }
+
+ // Look for explicit stride via @stride(n) attribute
+ uint32_t explicit_stride = 0;
+ if (!ArrayAttributes(tmpl_ident->attributes, el_ty, explicit_stride)) {
+ return nullptr;
+ }
+
+ auto* out = Array(tmpl_ident->source, //
+ ast_el_ty->source, //
+ ast_count ? ast_count->source : ident->source, //
+ el_ty, el_count, explicit_stride);
+ if (!out) {
+ return nullptr;
+ }
+
+ if (el_ty->Is<core::type::Atomic>()) {
+ atomic_composite_info_.Add(out, &ast_el_ty->source);
+ } else {
+ if (auto found = atomic_composite_info_.Get(el_ty)) {
+ atomic_composite_info_.Add(out, *found);
+ }
+ }
+
+ return out;
+}
+
+core::type::Atomic* Resolver::Atomic(const ast::Identifier* ident) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 1); // atomic<type>
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto* el_ty = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!el_ty)) {
+ return nullptr;
+ }
+
+ auto* out = b.create<core::type::Atomic>(el_ty);
+ if (TINT_UNLIKELY(!validator_.Atomic(tmpl_ident, out))) {
+ return nullptr;
+ }
+ return out;
+}
+
+core::type::Pointer* Resolver::Ptr(const ast::Identifier* ident) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 2, 3); // ptr<address, type [, access]>
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto address_space = sem_.GetAddressSpace(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(address_space == core::AddressSpace::kUndefined)) {
+ return nullptr;
+ }
+
+ auto* store_ty = const_cast<core::type::Type*>(sem_.GetType(tmpl_ident->arguments[1]));
+ if (TINT_UNLIKELY(!store_ty)) {
+ return nullptr;
+ }
+
+ core::Access access = core::Access::kUndefined;
+ if (tmpl_ident->arguments.Length() > 2) {
+ access = sem_.GetAccess(tmpl_ident->arguments[2]);
+ if (TINT_UNLIKELY(access == core::Access::kUndefined)) {
+ return nullptr;
+ }
+ } else {
+ access = DefaultAccessForAddressSpace(address_space);
+ }
+
+ auto* out = b.create<core::type::Pointer>(address_space, store_ty, access);
+ if (TINT_UNLIKELY(!validator_.Pointer(tmpl_ident, out))) {
+ return nullptr;
+ }
+
+ if (!ApplyAddressSpaceUsageToType(address_space, store_ty, tmpl_ident->arguments[1]->source)) {
+ AddNote("while instantiating " + out->FriendlyName(), ident->source);
+ return nullptr;
+ }
+ return out;
+}
+
+core::type::SampledTexture* Resolver::SampledTexture(const ast::Identifier* ident,
+ core::type::TextureDimension dim) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 1);
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!ty_expr)) {
+ return nullptr;
+ }
+
+ auto* out = b.create<core::type::SampledTexture>(dim, ty_expr);
+ return validator_.SampledTexture(out, ident->source) ? out : nullptr;
+}
+
+core::type::MultisampledTexture* Resolver::MultisampledTexture(const ast::Identifier* ident,
+ core::type::TextureDimension dim) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 1);
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!ty_expr)) {
+ return nullptr;
+ }
+
+ auto* out = b.create<core::type::MultisampledTexture>(dim, ty_expr);
+ return validator_.MultisampledTexture(out, ident->source) ? out : nullptr;
+}
+
+core::type::StorageTexture* Resolver::StorageTexture(const ast::Identifier* ident,
+ core::type::TextureDimension dim) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 2);
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto format = sem_.GetTexelFormat(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(format == core::TexelFormat::kUndefined)) {
+ return nullptr;
+ }
+
+ auto access = sem_.GetAccess(tmpl_ident->arguments[1]);
+ if (TINT_UNLIKELY(access == core::Access::kUndefined)) {
+ return nullptr;
+ }
+
+ auto* subtype = core::type::StorageTexture::SubtypeFor(format, b.Types());
+ auto* tex = b.create<core::type::StorageTexture>(dim, format, access, subtype);
+ if (!validator_.StorageTexture(tex, ident->source)) {
+ return nullptr;
+ }
+
+ return tex;
+}
+
+core::type::Vector* Resolver::PackedVec3T(const ast::Identifier* ident) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 1);
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto* el_ty = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!el_ty)) {
+ return nullptr;
+ }
+
+ if (TINT_UNLIKELY(!validator_.Vector(el_ty, ident->source))) {
+ return nullptr;
+ }
+ return b.create<core::type::Vector>(el_ty, 3u, true);
+}
+
+const ast::TemplatedIdentifier* Resolver::TemplatedIdentifier(const ast::Identifier* ident,
+ size_t min_args,
+ size_t max_args /* = use min 0 */) {
+ auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
+ if (!tmpl_ident) {
+ if (TINT_UNLIKELY(min_args != 0)) {
+ AddError("expected '<' for '" + ident->symbol.Name() + "'",
+ Source{ident->source.range.end});
+ }
+ return nullptr;
+ }
+ return CheckTemplatedIdentifierArgs(tmpl_ident, min_args, max_args) ? tmpl_ident : nullptr;
+}
+
+bool Resolver::CheckTemplatedIdentifierArgs(const ast::TemplatedIdentifier* ident,
+ size_t min_args,
+ size_t max_args /* = use min 0 */) {
+ if (max_args == 0) {
+ max_args = min_args;
+ }
+ if (min_args == max_args) {
+ if (TINT_UNLIKELY(ident->arguments.Length() != min_args)) {
+ AddError("'" + ident->symbol.Name() + "' requires " + std::to_string(min_args) +
+ " template arguments",
+ ident->source);
+ return false;
+ }
+ } else {
+ if (TINT_UNLIKELY(ident->arguments.Length() < min_args)) {
+ AddError("'" + ident->symbol.Name() + "' requires at least " +
+ std::to_string(min_args) + " template arguments",
+ ident->source);
+ return false;
+ }
+ if (TINT_UNLIKELY(ident->arguments.Length() > max_args)) {
+ AddError("'" + ident->symbol.Name() + "' requires at most " + std::to_string(max_args) +
+ " template arguments",
+ ident->source);
+ return false;
+ }
+ }
+ return ident;
+}
+
size_t Resolver::NestDepth(const core::type::Type* ty) const {
return Switch(
ty, //
@@ -3053,21 +3021,20 @@
}
}
-template <size_t N>
sem::Call* Resolver::FunctionCall(const ast::CallExpression* expr,
sem::Function* target,
- Vector<const sem::ValueExpression*, N>& args,
+ VectorRef<const sem::ValueExpression*> args_in,
sem::Behaviors arg_behaviors) {
+ Vector<const sem::ValueExpression*, 8> args = std::move(args_in);
if (!MaybeMaterializeAndLoadArguments(args, target)) {
return nullptr;
}
- // TODO(crbug.com/tint/1420): For now, assume all function calls have side
- // effects.
+ // TODO(crbug.com/tint/1420): For now, assume all function calls have side effects.
bool has_side_effects = true;
- auto* call = builder_->create<sem::Call>(expr, target, core::EvaluationStage::kRuntime,
- std::move(args), current_statement_,
- /* constant_value */ nullptr, has_side_effects);
+ auto* call = b.create<sem::Call>(expr, target, core::EvaluationStage::kRuntime, std::move(args),
+ current_statement_,
+ /* constant_value */ nullptr, has_side_effects);
target->AddCallSite(call);
@@ -3100,11 +3067,6 @@
CollectTextureSamplerPairs(target, call->Arguments());
}
- // Associate the target identifier expression with the resolved function.
- auto* fn_expr =
- builder_->create<sem::FunctionExpression>(expr->target, current_statement_, target);
- builder_->Sem().Add(expr->target, fn_expr);
-
return call;
}
@@ -3116,19 +3078,48 @@
// argument passed to the current function. Leave global variables
// as-is. Then add the mapped pair to the current function's list of
// texture/sampler pairs.
+
+ Hashset<const sem::Variable*, 4> texture_sampler_set;
+
for (sem::VariablePair pair : func->TextureSamplerPairs()) {
const sem::Variable* texture = pair.first;
const sem::Variable* sampler = pair.second;
- if (auto* param = texture->As<sem::Parameter>()) {
+ if (auto* param = As<sem::Parameter>(texture)) {
texture = args[param->Index()]->UnwrapLoad()->As<sem::VariableUser>()->Variable();
+ texture_sampler_set.Add(texture);
}
- if (sampler) {
- if (auto* param = sampler->As<sem::Parameter>()) {
- sampler = args[param->Index()]->UnwrapLoad()->As<sem::VariableUser>()->Variable();
- }
+ if (auto* param = As<sem::Parameter>(sampler)) {
+ sampler = args[param->Index()]->UnwrapLoad()->As<sem::VariableUser>()->Variable();
+ texture_sampler_set.Add(sampler);
}
current_function_->AddTextureSamplerPair(texture, sampler);
}
+
+ // Add any possible texture/sampler not essentially passed to builtins from the function param.
+ // This could be unused texture/sampler or texture/sampler passed to builtins that are emulated.
+
+ const auto& signature = func->Signature();
+
+ for (size_t i = 0; i < signature.parameters.Length(); i++) {
+ auto* param = signature.parameters[i];
+ if (param->Type()->Is<core::type::Texture>()) {
+ auto* user = args[i]->UnwrapLoad()->As<sem::VariableUser>();
+ auto* texture = user->Variable();
+ if (!texture_sampler_set.Contains(texture)) {
+ current_function_->AddTextureSamplerPair(texture, nullptr);
+ func->AddTextureSamplerPair(texture, nullptr);
+ texture_sampler_set.Add(texture);
+ }
+ } else if (param->Type()->Is<core::type::Sampler>()) {
+ auto* user = args[i]->UnwrapLoad()->As<sem::VariableUser>();
+ auto* sampler = user->Variable();
+ if (!texture_sampler_set.Contains(sampler)) {
+ current_function_->AddTextureSamplerPair(nullptr, sampler);
+ func->AddTextureSamplerPair(nullptr, sampler);
+ texture_sampler_set.Add(sampler);
+ }
+ }
+ }
}
sem::ValueExpression* Resolver::Literal(const ast::LiteralExpression* literal) {
@@ -3137,11 +3128,11 @@
[&](const ast::IntLiteralExpression* i) -> core::type::Type* {
switch (i->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
- return builder_->create<core::type::AbstractInt>();
+ return b.create<core::type::AbstractInt>();
case ast::IntLiteralExpression::Suffix::kI:
- return builder_->create<core::type::I32>();
+ return b.create<core::type::I32>();
case ast::IntLiteralExpression::Suffix::kU:
- return builder_->create<core::type::U32>();
+ return b.create<core::type::U32>();
}
TINT_UNREACHABLE() << "Unhandled integer literal suffix: " << i->suffix;
return nullptr;
@@ -3149,18 +3140,17 @@
[&](const ast::FloatLiteralExpression* f) -> core::type::Type* {
switch (f->suffix) {
case ast::FloatLiteralExpression::Suffix::kNone:
- return builder_->create<core::type::AbstractFloat>();
+ return b.create<core::type::AbstractFloat>();
case ast::FloatLiteralExpression::Suffix::kF:
- return builder_->create<core::type::F32>();
+ return b.create<core::type::F32>();
case ast::FloatLiteralExpression::Suffix::kH:
- return validator_.CheckF16Enabled(literal->source)
- ? builder_->create<core::type::F16>()
- : nullptr;
+ return validator_.CheckF16Enabled(literal->source) ? b.create<core::type::F16>()
+ : nullptr;
}
TINT_UNREACHABLE() << "Unhandled float literal suffix: " << f->suffix;
return nullptr;
},
- [&](const ast::BoolLiteralExpression*) { return builder_->create<core::type::Bool>(); },
+ [&](const ast::BoolLiteralExpression*) { return b.create<core::type::Bool>(); },
[&](Default) {
TINT_UNREACHABLE() << "Unhandled literal type: " << literal->TypeInfo().name;
return nullptr;
@@ -3178,35 +3168,32 @@
if (stage == core::EvaluationStage::kConstant) {
val = Switch(
literal,
- [&](const ast::BoolLiteralExpression* lit) {
- return builder_->constants.Get(lit->value);
- },
+ [&](const ast::BoolLiteralExpression* lit) { return b.constants.Get(lit->value); },
[&](const ast::IntLiteralExpression* lit) -> const core::constant::Value* {
switch (lit->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
- return builder_->constants.Get(AInt(lit->value));
+ return b.constants.Get(AInt(lit->value));
case ast::IntLiteralExpression::Suffix::kI:
- return builder_->constants.Get(i32(lit->value));
+ return b.constants.Get(i32(lit->value));
case ast::IntLiteralExpression::Suffix::kU:
- return builder_->constants.Get(u32(lit->value));
+ return b.constants.Get(u32(lit->value));
}
return nullptr;
},
[&](const ast::FloatLiteralExpression* lit) -> const core::constant::Value* {
switch (lit->suffix) {
case ast::FloatLiteralExpression::Suffix::kNone:
- return builder_->constants.Get(AFloat(lit->value));
+ return b.constants.Get(AFloat(lit->value));
case ast::FloatLiteralExpression::Suffix::kF:
- return builder_->constants.Get(f32(lit->value));
+ return b.constants.Get(f32(lit->value));
case ast::FloatLiteralExpression::Suffix::kH:
- return builder_->constants.Get(f16(lit->value));
+ return b.constants.Get(f16(lit->value));
}
return nullptr;
});
}
- return builder_->create<sem::ValueExpression>(literal, ty, stage, current_statement_,
- std::move(val),
- /* has_side_effects */ false);
+ return b.create<sem::ValueExpression>(literal, ty, stage, current_statement_, std::move(val),
+ /* has_side_effects */ false);
}
sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
@@ -3238,8 +3225,8 @@
stage = core::EvaluationStage::kNotEvaluated;
value = nullptr;
}
- auto* user = builder_->create<sem::VariableUser>(expr, stage, current_statement_,
- value, variable);
+ auto* user =
+ b.create<sem::VariableUser>(expr, stage, current_statement_, value, variable);
if (current_statement_) {
// If identifier is part of a loop continuing block, make sure it
@@ -3271,38 +3258,17 @@
}
}
- auto* global = variable->As<sem::GlobalVariable>();
- if (current_function_) {
- if (global) {
- current_function_->AddDirectlyReferencedGlobal(global);
- auto* refs = builder_->Sem().TransitivelyReferencedOverrides(global);
- if (refs) {
- for (auto* var : *refs) {
- current_function_->AddTransitivelyReferencedGlobal(var);
- }
- }
+ if (auto* global = variable->As<sem::GlobalVariable>()) {
+ for (auto& fn : on_transitively_reference_global_) {
+ fn(global);
}
- } else if (variable->Declaration()->Is<ast::Override>()) {
- if (resolved_overrides_) {
- // Track the reference to this pipeline-overridable constant and any other
- // pipeline-overridable constants that it references.
- resolved_overrides_->Add(global);
- auto* refs = builder_->Sem().TransitivelyReferencedOverrides(global);
- if (refs) {
- for (auto* var : *refs) {
- resolved_overrides_->Add(var);
- }
- }
+ if (!current_function_ && variable->Declaration()->Is<ast::Var>()) {
+ // Use of a module-scope 'var' outside of a function.
+ std::string desc = "var '" + ident->symbol.Name() + "' ";
+ AddError(desc + "cannot be referenced at module-scope", expr->source);
+ AddNote(desc + "declared here", variable->Declaration()->source);
+ return nullptr;
}
- } else if (variable->Declaration()->Is<ast::Var>()) {
- // Use of a module-scope 'var' outside of a function.
- // Note: The spec is currently vague around the rules here. See
- // https://github.com/gpuweb/gpuweb/issues/3081. Remove this comment when
- // resolved.
- std::string desc = "var '" + ident->symbol.Name() + "' ";
- AddError(desc + "cannot be referenced at module-scope", expr->source);
- AddNote(desc + "declared here", variable->Declaration()->source);
- return nullptr;
}
variable->AddUser(user);
@@ -3313,13 +3279,23 @@
if (!TINT_LIKELY(CheckNotTemplated("type", ident))) {
return nullptr;
}
- return builder_->create<sem::TypeExpression>(expr, current_statement_, ty);
+
+ // Notify callers of all transitively referenced globals.
+ if (auto* arr = ty->As<sem::Array>()) {
+ for (auto& fn : on_transitively_reference_global_) {
+ for (auto* ref : arr->TransitivelyReferencedOverrides()) {
+ fn(ref);
+ }
+ }
+ }
+
+ return b.create<sem::TypeExpression>(expr, current_statement_, ty);
},
[&](const sem::Function* fn) -> sem::FunctionExpression* {
if (!TINT_LIKELY(CheckNotTemplated("function", ident))) {
return nullptr;
}
- return builder_->create<sem::FunctionExpression>(expr, current_statement_, fn);
+ return b.create<sem::FunctionExpression>(expr, current_statement_, fn);
});
}
@@ -3328,31 +3304,33 @@
if (!ty) {
return nullptr;
}
- return builder_->create<sem::TypeExpression>(expr, current_statement_, ty);
+ return b.create<sem::TypeExpression>(expr, current_statement_, ty);
}
- if (resolved->BuiltinFn() != wgsl::BuiltinFn::kNone) {
- AddError("missing '(' for builtin function call", expr->source.End());
- return nullptr;
+ if (auto fn = resolved->BuiltinFn(); fn != wgsl::BuiltinFn::kNone) {
+ return CheckNotTemplated("builtin function", ident)
+ ? b.create<sem::BuiltinEnumExpression<wgsl::BuiltinFn>>(expr, current_statement_,
+ fn)
+ : nullptr;
}
if (auto access = resolved->Access(); access != core::Access::kUndefined) {
return CheckNotTemplated("access", ident)
- ? builder_->create<sem::BuiltinEnumExpression<core::Access>>(
- expr, current_statement_, access)
+ ? b.create<sem::BuiltinEnumExpression<core::Access>>(expr, current_statement_,
+ access)
: nullptr;
}
if (auto addr = resolved->AddressSpace(); addr != core::AddressSpace::kUndefined) {
return CheckNotTemplated("address space", ident)
- ? builder_->create<sem::BuiltinEnumExpression<core::AddressSpace>>(
+ ? b.create<sem::BuiltinEnumExpression<core::AddressSpace>>(
expr, current_statement_, addr)
: nullptr;
}
if (auto builtin = resolved->BuiltinValue(); builtin != core::BuiltinValue::kUndefined) {
return CheckNotTemplated("builtin value", ident)
- ? builder_->create<sem::BuiltinEnumExpression<core::BuiltinValue>>(
+ ? b.create<sem::BuiltinEnumExpression<core::BuiltinValue>>(
expr, current_statement_, builtin)
: nullptr;
}
@@ -3360,7 +3338,7 @@
if (auto i_smpl = resolved->InterpolationSampling();
i_smpl != core::InterpolationSampling::kUndefined) {
return CheckNotTemplated("interpolation sampling", ident)
- ? builder_->create<sem::BuiltinEnumExpression<core::InterpolationSampling>>(
+ ? b.create<sem::BuiltinEnumExpression<core::InterpolationSampling>>(
expr, current_statement_, i_smpl)
: nullptr;
}
@@ -3368,40 +3346,20 @@
if (auto i_type = resolved->InterpolationType();
i_type != core::InterpolationType::kUndefined) {
return CheckNotTemplated("interpolation type", ident)
- ? builder_->create<sem::BuiltinEnumExpression<core::InterpolationType>>(
+ ? b.create<sem::BuiltinEnumExpression<core::InterpolationType>>(
expr, current_statement_, i_type)
: nullptr;
}
if (auto fmt = resolved->TexelFormat(); fmt != core::TexelFormat::kUndefined) {
return CheckNotTemplated("texel format", ident)
- ? builder_->create<sem::BuiltinEnumExpression<core::TexelFormat>>(
+ ? b.create<sem::BuiltinEnumExpression<core::TexelFormat>>(
expr, current_statement_, fmt)
: nullptr;
}
- if (auto* unresolved = resolved->Unresolved()) {
- if (identifier_resolve_hint_.expression == expr) {
- AddError("unresolved " + std::string(identifier_resolve_hint_.usage) + " '" +
- unresolved->name + "'",
- expr->source);
- if (!identifier_resolve_hint_.suggestions.IsEmpty()) {
- // Filter out suggestions that have a leading underscore.
- Vector<const char*, 8> filtered;
- for (auto* str : identifier_resolve_hint_.suggestions) {
- if (str[0] != '_') {
- filtered.Push(str);
- }
- }
- StringStream msg;
- tint::SuggestAlternatives(unresolved->name,
- filtered.Slice().Reinterpret<char const* const>(), msg);
- AddNote(msg.str(), expr->source);
- }
- } else {
- AddError("unresolved identifier '" + unresolved->name + "'", expr->source);
- }
- return nullptr;
+ if (resolved->Unresolved()) {
+ return b.create<UnresolvedIdentifier>(expr, current_statement_);
}
TINT_UNREACHABLE() << "unhandled resolved identifier: " << resolved->String();
@@ -3448,16 +3406,15 @@
// If we're extracting from a reference, we return a reference.
if (auto* ref = object_ty->As<core::type::Reference>()) {
- ty =
- builder_->create<core::type::Reference>(ref->AddressSpace(), ty, ref->Access());
+ ty = b.create<core::type::Reference>(ref->AddressSpace(), ty, ref->Access());
}
const core::constant::Value* val = nullptr;
if (auto* obj_val = object->ConstantValue()) {
val = obj_val->Index(static_cast<size_t>(member->Index()));
}
- return builder_->create<sem::StructMemberAccess>(
- expr, ty, current_statement_, val, object, member, has_side_effects, root_ident);
+ return b.create<sem::StructMemberAccess>(expr, ty, current_statement_, val, object,
+ member, has_side_effects, root_ident);
},
[&](const core::type::Vector* vec) -> sem::ValueExpression* {
@@ -3517,13 +3474,12 @@
ty = vec->type();
// If we're extracting from a reference, we return a reference.
if (auto* ref = object_ty->As<core::type::Reference>()) {
- ty = builder_->create<core::type::Reference>(ref->AddressSpace(), ty,
- ref->Access());
+ ty = b.create<core::type::Reference>(ref->AddressSpace(), ty, ref->Access());
}
} else {
// The vector will have a number of components equal to the length of
// the swizzle.
- ty = builder_->create<core::type::Vector>(vec->type(), static_cast<uint32_t>(size));
+ ty = b.create<core::type::Vector>(vec->type(), static_cast<uint32_t>(size));
// The load rule is invoked before the swizzle, if necessary.
obj_expr = Load(object);
@@ -3536,8 +3492,8 @@
}
val = res.Get();
}
- return builder_->create<sem::Swizzle>(expr, ty, current_statement_, val, obj_expr,
- std::move(swizzle), has_side_effects, root_ident);
+ return b.create<sem::Swizzle>(expr, ty, current_statement_, val, obj_expr,
+ std::move(swizzle), has_side_effects, root_ident);
},
[&](Default) {
@@ -3627,8 +3583,8 @@
}
bool has_side_effects = lhs->HasSideEffects() || rhs->HasSideEffects();
- auto* sem = builder_->create<sem::ValueExpression>(expr, res_ty, stage, current_statement_,
- value, has_side_effects);
+ auto* sem = b.create<sem::ValueExpression>(expr, res_ty, stage, current_statement_, value,
+ has_side_effects);
sem->Behaviors() = lhs->Behaviors() + rhs->Behaviors();
return sem;
@@ -3664,8 +3620,8 @@
return nullptr;
}
- ty = builder_->create<core::type::Pointer>(ref->AddressSpace(), ref->StoreType(),
- ref->Access());
+ ty = b.create<core::type::Pointer>(ref->AddressSpace(), ref->StoreType(),
+ ref->Access());
root_ident = expr->RootIdentifier();
} else {
@@ -3676,8 +3632,8 @@
case core::UnaryOp::kIndirection:
if (auto* ptr = expr_ty->As<core::type::Pointer>()) {
- ty = builder_->create<core::type::Reference>(ptr->AddressSpace(), ptr->StoreType(),
- ptr->Access());
+ ty = b.create<core::type::Reference>(ptr->AddressSpace(), ptr->StoreType(),
+ ptr->Access());
root_ident = expr->RootIdentifier();
} else {
AddError("cannot dereference expression of type '" + sem_.TypeNameOf(expr_ty) + "'",
@@ -3724,8 +3680,8 @@
}
}
- auto* sem = builder_->create<sem::ValueExpression>(unary, ty, stage, current_statement_, value,
- expr->HasSideEffects(), root_ident);
+ auto* sem = b.create<sem::ValueExpression>(unary, ty, stage, current_statement_, value,
+ expr->HasSideEffects(), root_ident);
sem->Behaviors() = expr->Behaviors();
return sem;
}
@@ -3873,7 +3829,7 @@
// If all arguments are abstract-integers, then materialize to i32.
if (common_ty->Is<core::type::AbstractInt>()) {
- common_ty = builder_->create<core::type::I32>();
+ common_ty = b.create<core::type::I32>();
}
for (size_t i = 0; i < args.Length(); i++) {
@@ -3912,7 +3868,7 @@
}
// Apply the resolved tint::sem::BuiltinEnumExpression<tint::core::BuiltinValue> to the
// attribute.
- builder_->Sem().Add(attr, builtin_expr);
+ b.Sem().Add(attr, builtin_expr);
return builtin_expr->Value();
}
@@ -4022,50 +3978,62 @@
return nullptr;
}
- builder_->Sem().Add(named_type, result);
+ b.Sem().Add(named_type, result);
return result;
}
const core::type::ArrayCount* Resolver::ArrayCount(const ast::Expression* count_expr) {
// Evaluate the constant array count expression.
- const auto* count_sem = Materialize(ValueExpression(count_expr));
+ const auto* count_sem = Materialize(sem_.GetVal(count_expr));
if (!count_sem) {
return nullptr;
}
- if (count_sem->Stage() == core::EvaluationStage::kOverride) {
- // array count is an override expression.
- // Is the count a named 'override'?
- if (auto* user = count_sem->UnwrapMaterialize()->As<sem::VariableUser>()) {
- if (auto* global = user->Variable()->As<sem::GlobalVariable>()) {
- return builder_->create<sem::NamedOverrideArrayCount>(global);
+ switch (count_sem->Stage()) {
+ case core::EvaluationStage::kNotEvaluated:
+ // Happens in expressions like:
+ // false && array<T, N>()[i]
+ // The end result will not be used, so just make N=1.
+ return b.create<core::type::ConstantArrayCount>(static_cast<uint32_t>(1));
+
+ case core::EvaluationStage::kOverride: {
+ // array count is an override expression.
+ // Is the count a named 'override'?
+ if (auto* user = count_sem->UnwrapMaterialize()->As<sem::VariableUser>()) {
+ if (auto* global = user->Variable()->As<sem::GlobalVariable>()) {
+ return b.create<sem::NamedOverrideArrayCount>(global);
+ }
}
+ return b.create<sem::UnnamedOverrideArrayCount>(count_sem);
}
- return builder_->create<sem::UnnamedOverrideArrayCount>(count_sem);
- }
- auto* count_val = count_sem->ConstantValue();
- if (!count_val) {
- AddError("array count must evaluate to a constant integer expression or override variable",
- count_expr->source);
- return nullptr;
- }
+ case core::EvaluationStage::kConstant: {
+ auto* count_val = count_sem->ConstantValue();
+ if (auto* ty = count_val->Type(); !ty->is_integer_scalar()) {
+ AddError(
+ "array count must evaluate to a constant integer expression, but is type '" +
+ ty->FriendlyName() + "'",
+ count_expr->source);
+ return nullptr;
+ }
- if (auto* ty = count_val->Type(); !ty->is_integer_scalar()) {
- AddError("array count must evaluate to a constant integer expression, but is type '" +
- ty->FriendlyName() + "'",
- count_expr->source);
- return nullptr;
- }
+ int64_t count = count_val->ValueAs<AInt>();
+ if (count < 1) {
+ AddError("array count (" + std::to_string(count) + ") must be greater than 0",
+ count_expr->source);
+ return nullptr;
+ }
- int64_t count = count_val->ValueAs<AInt>();
- if (count < 1) {
- AddError("array count (" + std::to_string(count) + ") must be greater than 0",
- count_expr->source);
- return nullptr;
- }
+ return b.create<core::type::ConstantArrayCount>(static_cast<uint32_t>(count));
+ }
- return builder_->create<core::type::ConstantArrayCount>(static_cast<uint32_t>(count));
+ default: {
+ AddError(
+ "array count must evaluate to a constant integer expression or override variable",
+ count_expr->source);
+ return nullptr;
+ }
+ }
}
bool Resolver::ArrayAttributes(VectorRef<const ast::Attribute*> attributes,
@@ -4104,12 +4072,12 @@
return true;
}
-core::type::Array* Resolver::Array(const Source& array_source,
- const Source& el_source,
- const Source& count_source,
- const core::type::Type* el_ty,
- const core::type::ArrayCount* el_count,
- uint32_t explicit_stride) {
+sem::Array* Resolver::Array(const Source& array_source,
+ const Source& el_source,
+ const Source& count_source,
+ const core::type::Type* el_ty,
+ const core::type::ArrayCount* el_count,
+ uint32_t explicit_stride) {
uint32_t el_align = el_ty->Align();
uint32_t el_size = el_ty->Size();
uint64_t implicit_stride = el_size ? tint::RoundUp<uint64_t>(el_align, el_size) : 0;
@@ -4128,9 +4096,9 @@
} else if (el_count->Is<core::type::RuntimeArrayCount>()) {
size = stride;
}
- auto* out = builder_->create<core::type::Array>(
- el_ty, el_count, el_align, static_cast<uint32_t>(size), static_cast<uint32_t>(stride),
- static_cast<uint32_t>(implicit_stride));
+ auto* out =
+ b.create<sem::Array>(el_ty, el_count, el_align, static_cast<uint32_t>(size),
+ static_cast<uint32_t>(stride), static_cast<uint32_t>(implicit_stride));
// Maximum nesting depth of composite types
// https://gpuweb.github.io/gpuweb/wgsl/#limits
@@ -4152,10 +4120,10 @@
core::type::Type* Resolver::Alias(const ast::Alias* alias) {
auto* ty = Type(alias->type);
- if (!ty) {
+ if (TINT_UNLIKELY(!ty)) {
return nullptr;
}
- if (!validator_.Alias(alias)) {
+ if (TINT_UNLIKELY(!validator_.Alias(alias))) {
return nullptr;
}
return ty;
@@ -4412,11 +4380,11 @@
return nullptr;
}
- auto* sem_member = builder_->create<sem::StructMember>(
+ auto* sem_member = b.create<sem::StructMember>(
member, member->name->symbol, type, static_cast<uint32_t>(sem_members.Length()),
static_cast<uint32_t>(offset), static_cast<uint32_t>(align),
static_cast<uint32_t>(size), attributes);
- builder_->Sem().Add(member, sem_member);
+ b.Sem().Add(member, sem_member);
sem_members.Push(sem_member);
struct_size = offset + size;
@@ -4437,7 +4405,7 @@
return nullptr;
}
- auto* out = builder_->create<sem::Struct>(
+ auto* out = b.create<sem::Struct>(
str, str->name->symbol, std::move(sem_members), static_cast<uint32_t>(struct_align),
static_cast<uint32_t>(struct_size), static_cast<uint32_t>(size_no_padding));
@@ -4478,8 +4446,7 @@
}
sem::Statement* Resolver::ReturnStatement(const ast::ReturnStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto& behaviors = current_statement_->Behaviors();
behaviors = sem::Behavior::kReturn;
@@ -4500,7 +4467,7 @@
value_ty = expr->Type();
} else {
- value_ty = builder_->create<core::type::Void>();
+ value_ty = b.create<core::type::Void>();
}
// Validate after processing the return value expression so that its type
@@ -4511,8 +4478,8 @@
}
sem::SwitchStatement* Resolver::SwitchStatement(const ast::SwitchStatement* stmt) {
- auto* sem = builder_->create<sem::SwitchStatement>(stmt, current_compound_statement_,
- current_function_);
+ auto* sem =
+ b.create<sem::SwitchStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto& behaviors = sem->Behaviors();
@@ -4544,7 +4511,7 @@
if (!common_ty || !common_ty->is_integer_scalar()) {
// No common type found or the common type was abstract.
// Pick i32 and let validation deal with any mismatches.
- common_ty = builder_->create<core::type::I32>();
+ common_ty = b.create<core::type::I32>();
}
cond = Materialize(cond, common_ty);
if (!cond) {
@@ -4594,8 +4561,7 @@
}
sem::Statement* Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
Mark(stmt->variable);
@@ -4615,8 +4581,7 @@
}
sem::Statement* Resolver::AssignmentStatement(const ast::AssignmentStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto* lhs = ValueExpression(stmt->lhs);
if (!lhs) {
@@ -4657,8 +4622,7 @@
}
sem::Statement* Resolver::BreakStatement(const ast::BreakStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
sem->Behaviors() = sem::Behavior::kBreak;
@@ -4667,8 +4631,8 @@
}
sem::Statement* Resolver::BreakIfStatement(const ast::BreakIfStatement* stmt) {
- auto* sem = builder_->create<sem::BreakIfStatement>(stmt, current_compound_statement_,
- current_function_);
+ auto* sem =
+ b.create<sem::BreakIfStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto* cond = Load(ValueExpression(stmt->condition));
if (!cond) {
@@ -4683,8 +4647,7 @@
}
sem::Statement* Resolver::CallStatement(const ast::CallStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
if (auto* expr = ValueExpression(stmt->expr)) {
sem->Behaviors() = expr->Behaviors();
@@ -4696,8 +4659,7 @@
sem::Statement* Resolver::CompoundAssignmentStatement(
const ast::CompoundAssignmentStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto* lhs = ValueExpression(stmt->lhs);
if (!lhs) {
@@ -4733,8 +4695,7 @@
}
sem::Statement* Resolver::ContinueStatement(const ast::ContinueStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
sem->Behaviors() = sem::Behavior::kContinue;
@@ -4751,8 +4712,7 @@
}
sem::Statement* Resolver::DiscardStatement(const ast::DiscardStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
current_function_->SetDiscardStatement(sem);
return true;
@@ -4761,8 +4721,7 @@
sem::Statement* Resolver::IncrementDecrementStatement(
const ast::IncrementDecrementStatement* stmt) {
- auto* sem =
- builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
+ auto* sem = b.create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
auto* lhs = ValueExpression(stmt->lhs);
if (!lhs) {
@@ -4803,7 +4762,7 @@
return true;
}
- if (auto* arr = ty->As<core::type::Array>()) {
+ if (auto* arr = ty->As<sem::Array>()) {
if (address_space != core::AddressSpace::kStorage) {
if (arr->Count()->Is<core::type::RuntimeArrayCount>()) {
AddError("runtime-sized arrays can only be used in the <storage> address space",
@@ -4836,7 +4795,7 @@
template <typename SEM, typename F>
SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback) {
- builder_->Sem().Add(ast, sem);
+ b.Sem().Add(ast, sem);
auto* as_compound =
As<sem::CompoundStatement, tint::CastFlags::kDontErrorOnImpossibleCast>(sem);
@@ -4949,13 +4908,6 @@
return true;
}
-void Resolver::ErrorMismatchedResolvedIdentifier(const Source& source,
- const ResolvedIdentifier& resolved,
- std::string_view wanted) {
- AddError("cannot use " + resolved.String() + " as " + std::string(wanted), source);
- sem_.NoteDeclarationSource(resolved.Node());
-}
-
void Resolver::ErrorInvalidAttribute(const ast::Attribute* attr, std::string_view use) {
AddError("@" + attr->Name() + " is not valid for " + std::string(use), attr->source);
}
diff --git a/src/tint/lang/wgsl/resolver/resolver.h b/src/tint/lang/wgsl/resolver/resolver.h
index 3846d1a..2e1cbde 100644
--- a/src/tint/lang/wgsl/resolver/resolver.h
+++ b/src/tint/lang/wgsl/resolver/resolver.h
@@ -145,6 +145,83 @@
/// @returns the resolved type from an expression, or nullptr on error
core::type::Type* Type(const ast::Expression* ast);
+ /// @returns a new abstract-float
+ core::type::AbstractFloat* AF();
+
+ /// @returns a new f32
+ core::type::F32* F32();
+
+ /// @returns a new i32
+ core::type::I32* I32();
+
+ /// @returns a new u32
+ core::type::U32* U32();
+
+ /// @returns a new f16, if the f16 extension is enabled, otherwise nullptr
+ core::type::F16* F16(const ast::Identifier* ident);
+
+ /// @returns a vector with the element type @p el of width @p n resolved from the identifier @p
+ /// ident.
+ core::type::Vector* Vec(const ast::Identifier* ident, core::type::Type* el, uint32_t n);
+
+ /// @returns a vector of width @p n resolved from the templated identifier @p ident, or an
+ /// IncompleteType if the identifier is not templated.
+ core::type::Type* VecT(const ast::Identifier* ident, core::BuiltinType builtin, uint32_t n);
+
+ /// @returns a matrix with the element type @p el of dimensions @p num_columns x @p num_rows
+ /// resolved from the identifier @p ident.
+ core::type::Matrix* Mat(const ast::Identifier* ident,
+ core::type::Type* el,
+ uint32_t num_columns,
+ uint32_t num_rows);
+
+ /// @returns a matrix of dimensions @p num_columns x @p num_rows resolved from the templated
+ /// identifier @p ident, or an IncompleteType if the identifier is not templated.
+ core::type::Type* MatT(const ast::Identifier* ident,
+ core::BuiltinType builtin,
+ uint32_t num_columns,
+ uint32_t num_rows);
+
+ /// @returns an array resolved from the templated identifier @p ident, or an IncompleteType if
+ /// the identifier is not templated.
+ core::type::Type* Array(const ast::Identifier* ident);
+
+ /// @returns an atomic resolved from the templated identifier @p ident.
+ core::type::Atomic* Atomic(const ast::Identifier* ident);
+
+ /// @returns a pointer resolved from the templated identifier @p ident.
+ core::type::Pointer* Ptr(const ast::Identifier* ident);
+
+ /// @returns a sampled texture resolved from the templated identifier @p ident with the
+ /// dimensions @p dim.
+ core::type::SampledTexture* SampledTexture(const ast::Identifier* ident,
+ core::type::TextureDimension dim);
+
+ /// @returns a multisampled texture resolved from the templated identifier @p ident with the
+ /// dimensions @p dim.
+ core::type::MultisampledTexture* MultisampledTexture(const ast::Identifier* ident,
+ core::type::TextureDimension dim);
+
+ /// @returns a storage texture resolved from the templated identifier @p ident with the
+ /// dimensions @p dim.
+ core::type::StorageTexture* StorageTexture(const ast::Identifier* ident,
+ core::type::TextureDimension dim);
+
+ /// @returns a packed vec3 resolved from the templated identifier @p ident.
+ core::type::Vector* PackedVec3T(const ast::Identifier* ident);
+
+ /// @returns @p ident cast to an ast::TemplatedIdentifier, if the identifier is templated and
+ /// the number of templated arguments are between @p min_args and @p max_args.
+ const ast::TemplatedIdentifier* TemplatedIdentifier(const ast::Identifier* ident,
+ size_t min_args,
+ size_t max_args = /* use min */ 0);
+
+ /// @returns true if the number of templated arguments are between @p min_args and @p max_args
+ /// otherwise raises an error and returns false.
+ bool CheckTemplatedIdentifierArgs(const ast::TemplatedIdentifier* ident,
+ size_t min_args,
+ size_t max_args = /* use min */ 0);
+
/// @returns the call of Expression() cast to a
/// sem::BuiltinEnumExpression<core::AddressSpace>. If the sem::Expression is not a
/// sem::BuiltinEnumExpression<core::AddressSpace>, then an error diagnostic is raised and
@@ -205,10 +282,9 @@
sem::ValueExpression* Bitcast(const ast::BitcastExpression*);
sem::Call* Call(const ast::CallExpression*);
sem::Function* Function(const ast::Function*);
- template <size_t N>
sem::Call* FunctionCall(const ast::CallExpression*,
sem::Function* target,
- Vector<const sem::ValueExpression*, N>& args,
+ VectorRef<const sem::ValueExpression*> args,
sem::Behaviors arg_behaviors);
sem::Expression* Identifier(const ast::IdentifierExpression*);
template <size_t N>
@@ -408,12 +484,12 @@
/// @param el_ty the Array element type
/// @param el_count the number of elements in the array.
/// @param explicit_stride the explicit byte stride of the array. Zero means implicit stride.
- core::type::Array* Array(const Source& array_source,
- const Source& el_source,
- const Source& count_source,
- const core::type::Type* el_ty,
- const core::type::ArrayCount* el_count,
- uint32_t explicit_stride);
+ sem::Array* Array(const Source& array_source,
+ const Source& el_source,
+ const Source& count_source,
+ const core::type::Type* el_ty,
+ const core::type::ArrayCount* el_count,
+ uint32_t explicit_stride);
/// Builds and returns the semantic information for the alias `alias`.
/// This method does not mark the ast::Alias node, nor attach the generated
@@ -441,8 +517,7 @@
/// @note this method does not resolve the attributes as these are context-dependent (global,
/// local)
/// @param var the variable
- /// @param is_global true if this is module scope, otherwise function scope
- sem::Variable* Let(const ast::Let* var, bool is_global);
+ sem::Variable* Let(const ast::Let* var);
/// @returns the semantic info for the module-scope `ast::Override` `v`. If an error is raised,
/// nullptr is returned.
@@ -531,15 +606,6 @@
/// @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
- /// @param resolved the resolved identifier
- /// @param wanted the expected kind
- void ErrorMismatchedResolvedIdentifier(const Source& source,
- const ResolvedIdentifier& resolved,
- std::string_view wanted);
-
/// Raises an error that the attribute is not valid for the given use.
/// @param attr the invalue attribute
/// @param use the thing that the attribute was applied to
@@ -568,8 +634,8 @@
// ArrayConstructorSig represents a unique array constructor signature.
// It is a tuple of the array type, number of arguments provided and earliest evaluation stage.
- using ArrayConstructorSig = tint::UnorderedKeyWrapper<
- std::tuple<const core::type::Array*, size_t, core::EvaluationStage>>;
+ using ArrayConstructorSig =
+ tint::UnorderedKeyWrapper<std::tuple<const sem::Array*, size_t, core::EvaluationStage>>;
// StructConstructorSig represents a unique structure constructor signature.
// It is a tuple of the structure type, number of arguments provided and earliest evaluation
@@ -599,18 +665,7 @@
std::unordered_set<const sem::Variable*> parameter_reads;
};
- /// A hint for the usage of an identifier expression.
- /// Used to provide more informative error diagnostics on resolution failure.
- struct IdentifierResolveHint {
- /// The expression this hint applies to
- const ast::Expression* expression = nullptr;
- /// The usage of the identifier.
- const char* usage = "identifier";
- /// Suggested strings if the identifier failed to resolve
- tint::Slice<char const* const> suggestions = tint::Empty;
- };
-
- ProgramBuilder* const builder_;
+ ProgramBuilder& b;
diag::List& diagnostics_;
core::constant::Eval const_eval_;
core::intrinsic::Table<wgsl::intrinsic::Dialect> intrinsic_table_;
@@ -629,12 +684,11 @@
sem::Function* current_function_ = nullptr;
sem::Statement* current_statement_ = nullptr;
sem::CompoundStatement* current_compound_statement_ = nullptr;
+ Vector<std::function<void(const sem::GlobalVariable*)>, 4> on_transitively_reference_global_;
uint32_t current_scoping_depth_ = 0;
- UniqueVector<const sem::GlobalVariable*, 4>* resolved_overrides_ = nullptr;
Hashset<TypeAndAddressSpace, 8> valid_type_storage_layouts_;
Hashmap<const ast::Expression*, const ast::BinaryExpression*, 8> logical_binary_lhs_to_parent_;
Hashset<const ast::Expression*, 8> skip_const_eval_;
- IdentifierResolveHint identifier_resolve_hint_;
Hashmap<const core::type::Type*, size_t, 8> nest_depth_;
Hashmap<std::pair<core::intrinsic::Overload, wgsl::BuiltinFn>, sem::BuiltinFn*, 64> builtins_;
Hashmap<core::intrinsic::Overload, sem::ValueConstructor*, 16> constructors_;
diff --git a/src/tint/lang/wgsl/resolver/resolver_helper_test.h b/src/tint/lang/wgsl/resolver/resolver_helper_test.h
index 7daf352..f15027c 100644
--- a/src/tint/lang/wgsl/resolver/resolver_helper_test.h
+++ b/src/tint/lang/wgsl/resolver/resolver_helper_test.h
@@ -28,6 +28,7 @@
#include "src/tint/lang/core/type/abstract_int.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolver.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/statement.h"
#include "src/tint/lang/wgsl/sem/value_expression.h"
#include "src/tint/lang/wgsl/sem/variable.h"
@@ -141,14 +142,47 @@
template <typename TO>
using alias3 = alias<TO, 3>;
-/// A scalar value
-using Scalar =
- std::variant<core::i32, core::u32, core::f32, core::f16, core::AInt, core::AFloat, bool>;
+/// Scalar represents a scalar value
+struct Scalar {
+ /// The possible types of a scalar value.
+ using Value =
+ std::variant<core::i32, core::u32, core::f32, core::f16, core::AInt, core::AFloat, bool>;
-/// Returns current variant value in `s` cast to type `T`
+ /// Constructor
+ /// @param val the value used to construct this Scalar
+ template <typename T>
+ Scalar(T&& val) : value(std::forward<T>(val)) {} // NOLINT
+
+ /// @returns the Value
+ operator Value&() { return value; }
+
+ /// Equality operator
+ /// @param other the other Scalar
+ /// @return true if this Scalar is equal to @p other
+ bool operator==(const Scalar& other) const { return value == other.value; }
+
+ /// Inequality operator
+ /// @param other the other Scalar
+ /// @return true if this Scalar is not equal to @p other
+ bool operator!=(const Scalar& other) const { return value != other.value; }
+
+ /// The scalar value
+ Value value;
+};
+
+/// @param out the stream to write to
+/// @param s the Scalar
+/// @returns @p out so calls can be chained
+template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
+STREAM& operator<<(STREAM& out, const Scalar& s) {
+ std::visit([&](auto&& v) { out << v; }, s.value);
+ return out;
+}
+
+/// @return current variant value in @p s cast to type `T`
template <typename T>
T As(const Scalar& s) {
- return std::visit([](auto&& v) { return static_cast<T>(v); }, s);
+ return std::visit([](auto&& v) { return static_cast<T>(v); }, s.value);
}
using ast_type_func_ptr = ast::Type (*)(ProgramBuilder& b);
@@ -199,7 +233,7 @@
/// @param args args of size 1 with the boolean value to init with
/// @return a new AST expression of the bool type
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<bool>(args[0]));
+ return b.Expr(std::get<bool>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to bool.
@@ -232,7 +266,7 @@
/// @param args args of size 1 with the i32 value to init with
/// @return a new AST i32 literal value expression
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<core::i32>(args[0]));
+ return b.Expr(std::get<core::i32>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to i32.
@@ -265,7 +299,7 @@
/// @param args args of size 1 with the u32 value to init with
/// @return a new AST u32 literal value expression
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<core::u32>(args[0]));
+ return b.Expr(std::get<core::u32>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to u32.
@@ -298,7 +332,7 @@
/// @param args args of size 1 with the f32 value to init with
/// @return a new AST f32 literal value expression
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<core::f32>(args[0]));
+ return b.Expr(std::get<core::f32>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to f32.
@@ -331,7 +365,7 @@
/// @param args args of size 1 with the f16 value to init with
/// @return a new AST f16 literal value expression
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<core::f16>(args[0]));
+ return b.Expr(std::get<core::f16>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to f16.
@@ -363,7 +397,7 @@
/// @param args args of size 1 with the abstract-float value to init with
/// @return a new AST abstract-float literal value expression
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<core::AFloat>(args[0]));
+ return b.Expr(std::get<core::AFloat>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to AFloat.
@@ -395,7 +429,7 @@
/// @param args args of size 1 with the abstract-int value to init with
/// @return a new AST abstract-int literal value expression
static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
- return b.Expr(std::get<core::AInt>(args[0]));
+ return b.Expr(std::get<core::AInt>(args[0].value));
}
/// @param b the ProgramBuilder
/// @param v arg of type double that will be cast to AInt.
@@ -649,7 +683,7 @@
} else {
count = b.create<core::type::ConstantArrayCount>(N);
}
- return b.create<core::type::Array>(
+ return b.create<sem::Array>(
/* element */ el,
/* count */ count,
/* align */ el->Align(),
@@ -773,7 +807,7 @@
std::ostream& Print(std::ostream& o) const {
o << type_name << "(";
for (auto& a : args) {
- std::visit([&](auto& v) { o << v; }, a);
+ o << a;
if (&a != &args.Back()) {
o << ", ";
}
@@ -806,7 +840,7 @@
/// Creates a Value of DataType<T> from a scalar `v`
template <typename T>
Value Val(T v) {
- static_assert(tint::traits::IsTypeIn<T, Scalar>, "v must be a Number of bool");
+ static_assert(tint::traits::IsTypeIn<T, Scalar::Value>, "v must be a Number of bool");
return Value::Create<T>(Vector<Scalar, 1>{v});
}
diff --git a/src/tint/lang/wgsl/resolver/resolver_test.cc b/src/tint/lang/wgsl/resolver/resolver_test.cc
index 43cf3ec..3fc4a87 100644
--- a/src/tint/lang/wgsl/resolver/resolver_test.cc
+++ b/src/tint/lang/wgsl/resolver/resolver_test.cc
@@ -39,6 +39,7 @@
#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
#include "src/tint/lang/wgsl/ast/workgroup_attribute.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/call.h"
#include "src/tint/lang/wgsl/sem/function.h"
#include "src/tint/lang/wgsl/sem/member_accessor_expression.h"
@@ -423,7 +424,7 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref, nullptr);
- auto* ary = ref->StoreType()->As<core::type::Array>();
+ auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), create<core::type::ConstantArrayCount>(10u));
}
@@ -436,7 +437,7 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref, nullptr);
- auto* ary = ref->StoreType()->As<core::type::Array>();
+ auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), create<core::type::ConstantArrayCount>(10u));
}
@@ -451,7 +452,7 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref, nullptr);
- auto* ary = ref->StoreType()->As<core::type::Array>();
+ auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), create<core::type::ConstantArrayCount>(10u));
}
@@ -466,7 +467,7 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref, nullptr);
- auto* ary = ref->StoreType()->As<core::type::Array>();
+ auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), create<core::type::ConstantArrayCount>(10u));
}
@@ -481,7 +482,7 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref, nullptr);
- auto* ary = ref->StoreType()->As<core::type::Array>();
+ auto* ary = ref->StoreType()->As<sem::Array>();
auto* sem_override = Sem().Get(override);
ASSERT_NE(sem_override, nullptr);
EXPECT_EQ(ary->Count(), create<sem::NamedOverrideArrayCount>(sem_override));
@@ -500,12 +501,12 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref_a = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref_a, nullptr);
- auto* ary_a = ref_a->StoreType()->As<core::type::Array>();
+ auto* ary_a = ref_a->StoreType()->As<sem::Array>();
ASSERT_NE(TypeOf(b), nullptr);
auto* ref_b = TypeOf(b)->As<core::type::Reference>();
ASSERT_NE(ref_b, nullptr);
- auto* ary_b = ref_b->StoreType()->As<core::type::Array>();
+ auto* ary_b = ref_b->StoreType()->As<sem::Array>();
auto* sem_override = Sem().Get(override);
ASSERT_NE(sem_override, nullptr);
@@ -526,7 +527,7 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref, nullptr);
- auto* ary = ref->StoreType()->As<core::type::Array>();
+ auto* ary = ref->StoreType()->As<sem::Array>();
auto* sem_override = Sem().Get(override);
ASSERT_NE(sem_override, nullptr);
EXPECT_EQ(ary->Count(), create<sem::UnnamedOverrideArrayCount>(Sem().Get(cnt)));
@@ -547,12 +548,12 @@
ASSERT_NE(TypeOf(a), nullptr);
auto* ref_a = TypeOf(a)->As<core::type::Reference>();
ASSERT_NE(ref_a, nullptr);
- auto* ary_a = ref_a->StoreType()->As<core::type::Array>();
+ auto* ary_a = ref_a->StoreType()->As<sem::Array>();
ASSERT_NE(TypeOf(b), nullptr);
auto* ref_b = TypeOf(b)->As<core::type::Reference>();
ASSERT_NE(ref_b, nullptr);
- auto* ary_b = ref_b->StoreType()->As<core::type::Array>();
+ auto* ary_b = ref_b->StoreType()->As<sem::Array>();
auto* sem_override = Sem().Get(override);
ASSERT_NE(sem_override, nullptr);
@@ -1225,7 +1226,7 @@
EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), R"(12:34 error: cannot use type 'f32' as value
-12:34 note: are you missing '()' for value constructor?)");
+12:34 note: are you missing '()'?)");
}
TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
diff --git a/src/tint/lang/wgsl/resolver/sem_helper.cc b/src/tint/lang/wgsl/resolver/sem_helper.cc
index ce4c0d6..a921ad1 100644
--- a/src/tint/lang/wgsl/resolver/sem_helper.cc
+++ b/src/tint/lang/wgsl/resolver/sem_helper.cc
@@ -14,6 +14,8 @@
#include "src/tint/lang/wgsl/resolver/sem_helper.h"
+#include "src/tint/lang/wgsl/resolver/incomplete_type.h"
+#include "src/tint/lang/wgsl/resolver/unresolved_identifier.h"
#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h"
#include "src/tint/lang/wgsl/sem/function.h"
#include "src/tint/lang/wgsl/sem/function_expression.h"
@@ -40,6 +42,27 @@
return sem ? const_cast<core::type::Type*>(sem->Type()) : nullptr;
}
+sem::TypeExpression* SemHelper::AsTypeExpression(sem::Expression* expr) const {
+ if (TINT_UNLIKELY(!expr)) {
+ return nullptr;
+ }
+
+ auto* ty_expr = expr->As<sem::TypeExpression>();
+ if (TINT_UNLIKELY(!ty_expr)) {
+ ErrorUnexpectedExprKind(expr, "type");
+ return nullptr;
+ }
+
+ auto* type = ty_expr->Type();
+ if (auto* incomplete = type->As<IncompleteType>(); TINT_UNLIKELY(incomplete)) {
+ AddError("expected '<' for '" + std::string(ToString(incomplete->builtin)) + "'",
+ expr->Declaration()->source.End());
+ return nullptr;
+ }
+
+ return ty_expr;
+}
+
std::string SemHelper::Describe(const sem::Expression* expr) const {
return Switch(
expr, //
@@ -69,6 +92,9 @@
auto name = fn->name->symbol.Name();
return "function '" + name + "'";
},
+ [&](const sem::BuiltinEnumExpression<wgsl::BuiltinFn>* fn) {
+ return "builtin function '" + tint::ToString(fn->Value()) + "'";
+ },
[&](const sem::BuiltinEnumExpression<core::Access>* access) {
return "access '" + tint::ToString(access->Value()) + "'";
},
@@ -87,6 +113,10 @@
[&](const sem::BuiltinEnumExpression<core::TexelFormat>* fmt) {
return "texel format '" + tint::ToString(fmt->Value()) + "'";
},
+ [&](const UnresolvedIdentifier* ui) {
+ auto name = ui->Identifier()->identifier->symbol.Name();
+ return "unresolved identifier '" + name + "'";
+ },
[&](Default) -> std::string {
TINT_ICE() << "unhandled sem::Expression type: "
<< (expr ? expr->TypeInfo().name : "<null>");
@@ -94,8 +124,29 @@
});
}
-void SemHelper::ErrorUnexpectedExprKind(const sem::Expression* expr,
- std::string_view wanted) const {
+void SemHelper::ErrorUnexpectedExprKind(
+ const sem::Expression* expr,
+ std::string_view wanted,
+ tint::Slice<char const* const> suggestions /* = Empty */) const {
+ if (auto* ui = expr->As<UnresolvedIdentifier>()) {
+ auto* ident = ui->Identifier();
+ auto name = ident->identifier->symbol.Name();
+ AddError("unresolved " + std::string(wanted) + " '" + name + "'", ident->source);
+ if (!suggestions.IsEmpty()) {
+ // Filter out suggestions that have a leading underscore.
+ Vector<const char*, 8> filtered;
+ for (auto* str : suggestions) {
+ if (str[0] != '_') {
+ filtered.Push(str);
+ }
+ }
+ StringStream msg;
+ tint::SuggestAlternatives(name, filtered.Slice().Reinterpret<char const* const>(), msg);
+ AddNote(msg.str(), ident->source);
+ }
+ return;
+ }
+
AddError("cannot use " + Describe(expr) + " as " + std::string(wanted),
expr->Declaration()->source);
NoteDeclarationSource(expr->Declaration());
@@ -103,9 +154,10 @@
void SemHelper::ErrorExpectedValueExpr(const sem::Expression* expr) const {
ErrorUnexpectedExprKind(expr, "value");
- if (auto* ty_expr = expr->As<sem::TypeExpression>()) {
- if (auto* ident = ty_expr->Declaration()->As<ast::IdentifierExpression>()) {
- AddNote("are you missing '()' for value constructor?", ident->source.End());
+ if (auto* ident = expr->Declaration()->As<ast::IdentifierExpression>()) {
+ if (expr->IsAnyOf<sem::FunctionExpression, sem::TypeExpression,
+ sem::BuiltinEnumExpression<wgsl::BuiltinFn>>()) {
+ AddNote("are you missing '()'?", ident->source.End());
}
}
}
diff --git a/src/tint/lang/wgsl/resolver/sem_helper.h b/src/tint/lang/wgsl/resolver/sem_helper.h
index 4dfbe64..bbd7943 100644
--- a/src/tint/lang/wgsl/resolver/sem_helper.h
+++ b/src/tint/lang/wgsl/resolver/sem_helper.h
@@ -55,8 +55,8 @@
return const_cast<T*>(As<T>(sem));
}
- /// GetVal is a helper for obtaining the semantic sem::ValueExpression for the given AST node.
- /// Raises an error diagnostic and returns `nullptr` if the semantic node is not a
+ /// GetVal is a helper for obtaining the semantic sem::ValueExpression for the given AST
+ /// expression. Raises an error diagnostic and returns `nullptr` if the semantic node is not a
/// sem::ValueExpression.
/// @param ast the ast node to get the sem for
/// @returns the sem node for @p ast
@@ -81,12 +81,17 @@
/// @param expr the semantic node
/// @returns nullptr if @p expr is nullptr, or @p expr cast to type::Type if the cast is
/// successful, otherwise an error diagnostic is raised.
- sem::TypeExpression* AsTypeExpression(sem::Expression* expr) const {
+ sem::TypeExpression* AsTypeExpression(sem::Expression* expr) const;
+
+ /// GetType is a helper for obtaining the semantic type for the given AST expression.
+ /// Raises an error diagnostic and returns `nullptr` if the semantic node is not a
+ /// sem::TypeExpression
+ /// @param ast the ast node to get the sem for
+ /// @returns the sem node for @p ast
+ const core::type::Type* GetType(const ast::Expression* ast) const {
+ auto* expr = AsTypeExpression(Get(ast));
if (TINT_LIKELY(expr)) {
- if (auto* ty_expr = expr->As<sem::TypeExpression>(); TINT_LIKELY(ty_expr)) {
- return ty_expr;
- }
- ErrorUnexpectedExprKind(expr, "type");
+ return expr->Type();
}
return nullptr;
}
@@ -115,11 +120,24 @@
if (TINT_LIKELY(enum_expr)) {
return enum_expr;
}
- ErrorUnexpectedExprKind(expr, "address space");
+ ErrorUnexpectedExprKind(expr, "address space", core::kAddressSpaceStrings);
}
return nullptr;
}
+ /// GetAddressSpace is a helper for obtaining the address space for the given AST expression.
+ /// Raises an error diagnostic and returns core::AddressSpace::kUndefined if the semantic node
+ /// is not a sem::BuiltinEnumExpression<core::AddressSpace>
+ /// @param ast the ast node to get the address space
+ /// @returns the sem node for @p ast
+ core::AddressSpace GetAddressSpace(const ast::Expression* ast) const {
+ auto* expr = AsAddressSpace(Get(ast));
+ if (TINT_LIKELY(expr)) {
+ return expr->Value();
+ }
+ return core::AddressSpace::kUndefined;
+ }
+
/// @param expr the semantic node
/// @returns nullptr if @p expr is nullptr, or @p expr cast to
/// sem::BuiltinEnumExpression<core::BuiltinValue> if the cast is successful, otherwise an
@@ -130,7 +148,7 @@
if (TINT_LIKELY(enum_expr)) {
return enum_expr;
}
- ErrorUnexpectedExprKind(expr, "builtin value");
+ ErrorUnexpectedExprKind(expr, "builtin value", core::kBuiltinValueStrings);
}
return nullptr;
}
@@ -145,11 +163,24 @@
if (TINT_LIKELY(enum_expr)) {
return enum_expr;
}
- ErrorUnexpectedExprKind(expr, "texel format");
+ ErrorUnexpectedExprKind(expr, "texel format", core::kTexelFormatStrings);
}
return nullptr;
}
+ /// GetTexelFormat is a helper for obtaining the texel format for the given AST expression.
+ /// Raises an error diagnostic and returns core::TexelFormat::kUndefined if the semantic node
+ /// is not a sem::BuiltinEnumExpression<core::TexelFormat>
+ /// @param ast the ast node to get the texel format
+ /// @returns the sem node for @p ast
+ core::TexelFormat GetTexelFormat(const ast::Expression* ast) const {
+ auto* expr = AsTexelFormat(Get(ast));
+ if (TINT_LIKELY(expr)) {
+ return expr->Value();
+ }
+ return core::TexelFormat::kUndefined;
+ }
+
/// @param expr the semantic node
/// @returns nullptr if @p expr is nullptr, or @p expr cast to
/// sem::BuiltinEnumExpression<core::Access> if the cast is successful, otherwise an error
@@ -160,11 +191,24 @@
if (TINT_LIKELY(enum_expr)) {
return enum_expr;
}
- ErrorUnexpectedExprKind(expr, "access");
+ ErrorUnexpectedExprKind(expr, "access", core::kAccessStrings);
}
return nullptr;
}
+ /// GetAccess is a helper for obtaining the access mode for the given AST expression.
+ /// Raises an error diagnostic and returns core::Access::kUndefined if the semantic node
+ /// is not a sem::BuiltinEnumExpression<core::Access>
+ /// @param ast the ast node to get the access mode
+ /// @returns the sem node for @p ast
+ core::Access GetAccess(const ast::Expression* ast) const {
+ auto* expr = AsAccess(Get(ast));
+ if (TINT_LIKELY(expr)) {
+ return expr->Value();
+ }
+ return core::Access::kUndefined;
+ }
+
/// @param expr the semantic node
/// @returns nullptr if @p expr is nullptr, or @p expr cast to
/// sem::BuiltinEnumExpression<core::InterpolationSampling> if the cast is successful,
@@ -176,7 +220,8 @@
if (TINT_LIKELY(enum_expr)) {
return enum_expr;
}
- ErrorUnexpectedExprKind(expr, "interpolation sampling");
+ ErrorUnexpectedExprKind(expr, "interpolation sampling",
+ core::kInterpolationSamplingStrings);
}
return nullptr;
}
@@ -192,7 +237,7 @@
if (TINT_LIKELY(enum_expr)) {
return enum_expr;
}
- ErrorUnexpectedExprKind(expr, "interpolation type");
+ ErrorUnexpectedExprKind(expr, "interpolation type", core::kInterpolationTypeStrings);
}
return nullptr;
}
@@ -217,7 +262,10 @@
/// Raises an error diagnostic that the expression @p got was not of the kind @p wanted.
/// @param expr the expression
/// @param wanted the expected expression kind
- void ErrorUnexpectedExprKind(const sem::Expression* expr, std::string_view wanted) const;
+ /// @param suggestions suggested valid identifiers
+ void ErrorUnexpectedExprKind(const sem::Expression* expr,
+ std::string_view wanted,
+ tint::Slice<char const* const> suggestions = Empty) const;
/// If @p node is a module-scope type, variable or function declaration, then appends a note
/// diagnostic where this declaration was declared, otherwise the function does nothing.
diff --git a/src/tint/lang/wgsl/resolver/type_validation_test.cc b/src/tint/lang/wgsl/resolver/type_validation_test.cc
index 46284e1..b5b07d6 100644
--- a/src/tint/lang/wgsl/resolver/type_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/type_validation_test.cc
@@ -579,7 +579,20 @@
56:78 note: while instantiating 'var' a)");
}
-TEST_F(ResolverTypeValidationTest, Struct_Member_VectorNoType) {
+TEST_F(ResolverTypeValidationTest, PtrType_ArrayIncomplete) {
+ // fn f(l: ptr<function, array>) {}
+
+ Func("f",
+ Vector{
+ Param("l", ty.ptr(function, ty(Source{{12, 34}}, "array"))),
+ },
+ ty.void_(), Empty);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'array'");
+}
+
+TEST_F(ResolverTypeValidationTest, Struct_Member_VectorIncomplete) {
// struct S {
// a: vec3;
// };
@@ -592,7 +605,7 @@
EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'vec3'");
}
-TEST_F(ResolverTypeValidationTest, Struct_Member_MatrixNoType) {
+TEST_F(ResolverTypeValidationTest, Struct_Member_MatrixIncomplete) {
// struct S {
// a: mat3x3;
// };
@@ -768,6 +781,21 @@
56:78 note: while instantiating parameter a)");
}
+TEST_F(ResolverTypeValidationTest, PtrToPtr_Fail) {
+ // fn func(a : ptr<workgroup, ptr<workgroup, u32>>) {}
+ auto* param = Param("a", ty.ptr(workgroup, ty.ptr<workgroup, u32>(Source{{12, 34}})));
+
+ Func("func", Vector{param}, ty.void_(),
+ Vector{
+ Return(),
+ });
+
+ EXPECT_FALSE(r()->Resolve()) << r()->error();
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: ptr<workgroup, u32, read_write> cannot be used as the store type of a pointer)");
+}
+
TEST_F(ResolverTypeValidationTest, PtrToRuntimeArrayAsPointerParameter_Fail) {
// fn func(a : ptr<workgroup, array<u32>>) {}
diff --git a/src/tint/lang/wgsl/resolver/uniformity.cc b/src/tint/lang/wgsl/resolver/uniformity.cc
index 506a20b..aa7190b 100644
--- a/src/tint/lang/wgsl/resolver/uniformity.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity.cc
@@ -176,8 +176,8 @@
struct FunctionInfo {
/// Constructor
/// @param func the AST function
- /// @param builder the program builder
- FunctionInfo(const ast::Function* func, const ProgramBuilder* builder) {
+ /// @param b the program builder
+ FunctionInfo(const ast::Function* func, const ProgramBuilder& b) {
name = func->name->symbol.Name();
callsite_tag = {CallSiteTag::CallSiteNoRestriction};
function_tag = NoRestriction;
@@ -197,7 +197,7 @@
for (size_t i = 0; i < func->params.Length(); i++) {
auto* param = func->params[i];
auto param_name = param->name->symbol.Name();
- auto* sem = builder->Sem().Get<sem::Parameter>(param);
+ auto* sem = b.Sem().Get<sem::Parameter>(param);
parameters[i].sem = sem;
parameters[i].value = CreateNode({"param_", param_name});
@@ -339,8 +339,8 @@
public:
/// Constructor.
/// @param builder the program to analyze
- explicit UniformityGraph(ProgramBuilder* builder)
- : builder_(builder), sem_(builder->Sem()), diagnostics_(builder->Diagnostics()) {}
+ explicit UniformityGraph(ProgramBuilder& builder)
+ : b(builder), sem_(b.Sem()), diagnostics_(builder.Diagnostics()) {}
/// Destructor.
~UniformityGraph() {}
@@ -374,7 +374,7 @@
}
private:
- const ProgramBuilder* builder_;
+ const ProgramBuilder& b;
const sem::Info& sem_;
diag::List& diagnostics_;
@@ -418,7 +418,7 @@
/// @param func the function to process
/// @returns true if there are no uniformity issues, false otherwise
bool ProcessFunction(const ast::Function* func) {
- current_function_ = functions_.Add(func, FunctionInfo(func, builder_)).value;
+ current_function_ = functions_.Add(func, FunctionInfo(func, b)).value;
// Process function body.
if (func->body) {
@@ -565,21 +565,22 @@
return cf_r;
},
- [&](const ast::BlockStatement* b) {
+ [&](const ast::BlockStatement* block) {
Hashmap<const sem::Variable*, Node*, 4> scoped_assignments;
+ auto* sem = sem_.Get(block);
{
// Push a new scope for variable assignments in the block.
current_function_->variables.Push();
TINT_DEFER(current_function_->variables.Pop());
- for (auto* s : b->statements) {
+ for (auto* s : block->statements) {
cf = ProcessStatement(cf, s);
if (!sem_.Get(s)->Behaviors().Contains(sem::Behavior::kNext)) {
break;
}
}
- auto* parent = sem_.Get(b)->Parent();
+ auto* parent = sem->Parent();
auto* loop = parent ? parent->As<sem::LoopStatement>() : nullptr;
if (loop) {
// We've reached the end of a loop body. If there is a continuing block,
@@ -587,7 +588,7 @@
// loop body are visible to the continuing block.
if (auto* continuing =
loop->Declaration()->As<ast::LoopStatement>()->continuing) {
- auto& loop_body_behavior = sem_.Get(b)->Behaviors();
+ auto& loop_body_behavior = sem->Behaviors();
if (loop_body_behavior.Contains(sem::Behavior::kNext) ||
loop_body_behavior.Contains(sem::Behavior::kContinue)) {
cf = ProcessStatement(cf, continuing);
@@ -595,7 +596,7 @@
}
}
- if (sem_.Get<sem::FunctionBlockStatement>(b)) {
+ if (sem_.Get<sem::FunctionBlockStatement>(block)) {
// We've reached the end of the function body.
// Add edges from pointer parameter outputs to their current value.
for (auto& param : current_function_->parameters) {
@@ -611,7 +612,7 @@
// Propagate all variables assignments to the containing scope if the behavior is
// 'Next'.
- auto& behaviors = sem_.Get(b)->Behaviors();
+ auto& behaviors = sem->Behaviors();
if (behaviors.Contains(sem::Behavior::kNext)) {
for (auto var : scoped_assignments) {
current_function_->variables.Set(var.key, var.value);
@@ -619,16 +620,16 @@
}
// Remove any variables declared in this scope from the set of in-scope variables.
- for (auto decl : sem_.Get<sem::BlockStatement>(b)->Decls()) {
+ for (auto decl : sem->Decls()) {
current_function_->local_var_decls.Remove(decl.value.variable);
}
return cf;
},
- [&](const ast::BreakStatement* b) {
+ [&](const ast::BreakStatement* brk) {
// Find the loop or switch statement that we are in.
- auto* parent = sem_.Get(b)
+ auto* parent = sem_.Get(brk)
->FindFirstParent<sem::SwitchStatement, sem::LoopStatement,
sem::ForLoopStatement, sem::WhileStatement>();
@@ -654,20 +655,21 @@
return cf;
},
- [&](const ast::BreakIfStatement* b) {
+ [&](const ast::BreakIfStatement* brk) {
// This works very similar to the IfStatement uniformity below, execpt instead of
// processing the body, we directly inline the BreakStatement uniformity from
// above.
+ auto* sem = sem_.Get(brk);
- auto [_, v_cond] = ProcessExpression(cf, b->condition);
+ auto [_, v_cond] = ProcessExpression(cf, brk->condition);
// Add a diagnostic node to capture the control flow change.
- auto* v = CreateNode({"break_if_stmt"}, b);
+ auto* v = CreateNode({"break_if_stmt"}, brk);
v->affects_control_flow = true;
v->AddEdge(v_cond);
{
- auto* parent = sem_.Get(b)->FindFirstParent<sem::LoopStatement>();
+ auto* parent = sem->FindFirstParent<sem::LoopStatement>();
auto& info = current_function_->LoopSwitchInfoFor(parent);
// Propagate variable values to the loop exit nodes.
@@ -689,8 +691,7 @@
}
}
- auto* sem_break_if = sem_.Get(b);
- if (sem_break_if->Behaviors() != sem::Behaviors{sem::Behavior::kNext}) {
+ if (sem->Behaviors() != sem::Behaviors{sem::Behavior::kNext}) {
auto* cf_end = CreateNode({"break_if_CFend"});
cf_end->AddEdge(v);
return cf_end;
@@ -1178,7 +1179,7 @@
auto has_nonuniform_entry_point_attribute = [&](auto* obj) {
// Only the num_workgroups and workgroup_id builtins are uniform.
if (auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(obj->attributes)) {
- auto builtin = builder_->Sem().Get(builtin_attr)->Value();
+ auto builtin = b.Sem().Get(builtin_attr)->Value();
if (builtin == core::BuiltinValue::kNumWorkgroups ||
builtin == core::BuiltinValue::kWorkgroupId) {
return false;
@@ -1316,29 +1317,29 @@
return Switch(
expr,
- [&](const ast::BinaryExpression* b) {
- if (b->IsLogical()) {
+ [&](const ast::BinaryExpression* e) {
+ if (e->IsLogical()) {
// Short-circuiting binary operators are a special case.
- auto [cf1, v1] = ProcessExpression(cf, b->lhs);
+ auto [cf1, v1] = ProcessExpression(cf, e->lhs);
// Add a diagnostic node to capture the control flow change.
- auto* v1_cf = CreateNode({"short_circuit_op"}, b);
+ auto* v1_cf = CreateNode({"short_circuit_op"}, e);
v1_cf->affects_control_flow = true;
v1_cf->AddEdge(v1);
- auto [cf2, v2] = ProcessExpression(v1_cf, b->rhs);
+ auto [cf2, v2] = ProcessExpression(v1_cf, e->rhs);
return std::pair<Node*, Node*>(cf, v2);
} else {
- auto [cf1, v1] = ProcessExpression(cf, b->lhs);
- auto [cf2, v2] = ProcessExpression(cf1, b->rhs);
- auto* result = CreateNode({"binary_expr_result"}, b);
+ auto [cf1, v1] = ProcessExpression(cf, e->lhs);
+ auto [cf2, v2] = ProcessExpression(cf1, e->rhs);
+ auto* result = CreateNode({"binary_expr_result"}, e);
result->AddEdge(v1);
result->AddEdge(v2);
return std::pair<Node*, Node*>(cf2, result);
}
},
- [&](const ast::BitcastExpression* b) { return ProcessExpression(cf, b->expr); },
+ [&](const ast::BitcastExpression* e) { return ProcessExpression(cf, e->expr); },
[&](const ast::CallExpression* c) { return ProcessCall(cf, c); },
@@ -1977,7 +1978,7 @@
} // namespace
-bool AnalyzeUniformity(ProgramBuilder* builder, const DependencyGraph& dependency_graph) {
+bool AnalyzeUniformity(ProgramBuilder& builder, const DependencyGraph& dependency_graph) {
UniformityGraph graph(builder);
return graph.Build(dependency_graph);
}
diff --git a/src/tint/lang/wgsl/resolver/uniformity.h b/src/tint/lang/wgsl/resolver/uniformity.h
index 7fa7e04..93e8a70 100644
--- a/src/tint/lang/wgsl/resolver/uniformity.h
+++ b/src/tint/lang/wgsl/resolver/uniformity.h
@@ -32,7 +32,7 @@
/// @param builder the program to analyze
/// @param dependency_graph the dependency-ordered module-scope declarations
/// @returns true if there are no uniformity issues, false otherwise
-bool AnalyzeUniformity(ProgramBuilder* builder, const resolver::DependencyGraph& dependency_graph);
+bool AnalyzeUniformity(ProgramBuilder& builder, const resolver::DependencyGraph& dependency_graph);
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/uniformity_test.cc b/src/tint/lang/wgsl/resolver/uniformity_test.cc
index 36568e9..dbad0bb 100644
--- a/src/tint/lang/wgsl/resolver/uniformity_test.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity_test.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// GEN_BUILD:CONDITION(tint_build_wgsl_reader)
+
#include <memory>
#include <string>
#include <tuple>
diff --git a/src/tint/lang/wgsl/resolver/unresolved_identifier.cc b/src/tint/lang/wgsl/resolver/unresolved_identifier.cc
new file mode 100644
index 0000000..54305f2
--- /dev/null
+++ b/src/tint/lang/wgsl/resolver/unresolved_identifier.cc
@@ -0,0 +1,27 @@
+// 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/lang/wgsl/resolver/unresolved_identifier.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::resolver::UnresolvedIdentifier);
+
+namespace tint::resolver {
+
+UnresolvedIdentifier::UnresolvedIdentifier(const ast::IdentifierExpression* i,
+ const sem::Statement* stmt)
+ : Base(i, stmt) {}
+
+UnresolvedIdentifier::~UnresolvedIdentifier() = default;
+
+} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/unresolved_identifier.h b/src/tint/lang/wgsl/resolver/unresolved_identifier.h
new file mode 100644
index 0000000..ec3be23
--- /dev/null
+++ b/src/tint/lang/wgsl/resolver/unresolved_identifier.h
@@ -0,0 +1,42 @@
+// 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_LANG_WGSL_RESOLVER_UNRESOLVED_IDENTIFIER_H_
+#define SRC_TINT_LANG_WGSL_RESOLVER_UNRESOLVED_IDENTIFIER_H_
+
+#include "src/tint/lang/wgsl/ast/identifier_expression.h"
+#include "src/tint/lang/wgsl/sem/expression.h"
+
+namespace tint::resolver {
+
+/// Represents an identifier that could not be resolved.
+class UnresolvedIdentifier : public Castable<UnresolvedIdentifier, sem::Expression> {
+ public:
+ /// Constructor
+ /// @param i the identifier that could not be resolved
+ /// @param statement the statement that owns this expression
+ UnresolvedIdentifier(const ast::IdentifierExpression* i, const sem::Statement* statement);
+
+ /// Destructor
+ ~UnresolvedIdentifier() override;
+
+ /// @returns the identifier that could not be resolved
+ const ast::IdentifierExpression* Identifier() const {
+ return static_cast<const ast::IdentifierExpression*>(declaration_);
+ }
+};
+
+} // namespace tint::resolver
+
+#endif // SRC_TINT_LANG_WGSL_RESOLVER_UNRESOLVED_IDENTIFIER_H_
diff --git a/src/tint/lang/wgsl/resolver/validation_test.cc b/src/tint/lang/wgsl/resolver/validation_test.cc
index 0634f94..ce98dac 100644
--- a/src/tint/lang/wgsl/resolver/validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/validation_test.cc
@@ -170,7 +170,7 @@
WrapInFunction(assign);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: unresolved identifier 'b')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: unresolved value 'b')");
}
TEST_F(ResolverValidationTest, UsingUndefinedVariableInBlockStatement_Fail) {
@@ -185,7 +185,7 @@
WrapInFunction(body);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: unresolved identifier 'b')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: unresolved value 'b')");
}
TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) {
@@ -225,7 +225,7 @@
WrapInFunction(outer_body);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: unresolved identifier 'a')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: unresolved value 'a')");
}
TEST_F(ResolverValidationTest, UsingUndefinedVariableOuterScope_Pass) {
@@ -265,7 +265,7 @@
WrapInFunction(outer_body);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: unresolved identifier 'a')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: unresolved value 'a')");
}
TEST_F(ResolverValidationTest, AddressSpace_FunctionVariableWorkgroupClass) {
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 67aed69..de7befe 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -21,7 +21,6 @@
#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/core/type/abstract_numeric.h"
-#include "src/tint/lang/core/type/array.h"
#include "src/tint/lang/core/type/atomic.h"
#include "src/tint/lang/core/type/depth_multisampled_texture.h"
#include "src/tint/lang/core/type/depth_texture.h"
@@ -53,6 +52,7 @@
#include "src/tint/lang/wgsl/ast/unary_op_expression.h"
#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
#include "src/tint/lang/wgsl/ast/workgroup_attribute.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/break_if_statement.h"
#include "src/tint/lang/wgsl/sem/call.h"
#include "src/tint/lang/wgsl/sem/for_loop_statement.h"
@@ -202,7 +202,7 @@
// https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
bool Validator::IsPlain(const core::type::Type* type) const {
return type->IsAnyOf<core::type::Scalar, core::type::Atomic, core::type::Vector,
- core::type::Matrix, core::type::Array, core::type::Struct>();
+ core::type::Matrix, sem::Array, core::type::Struct>();
}
// https://gpuweb.github.io/gpuweb/wgsl/#fixed-footprint-types
@@ -212,7 +212,7 @@
[&](const core::type::Vector*) { return true; }, //
[&](const core::type::Matrix*) { return true; }, //
[&](const core::type::Atomic*) { return true; },
- [&](const core::type::Array* arr) {
+ [&](const sem::Array* arr) {
return !arr->Count()->Is<core::type::RuntimeArrayCount>() &&
IsFixedFootprint(arr->ElemType());
},
@@ -236,7 +236,7 @@
type, //
[&](const core::type::Vector* vec) { return IsHostShareable(vec->type()); },
[&](const core::type::Matrix* mat) { return IsHostShareable(mat->type()); },
- [&](const core::type::Array* arr) { return IsHostShareable(arr->ElemType()); },
+ [&](const sem::Array* arr) { return IsHostShareable(arr->ElemType()); },
[&](const core::type::Struct* str) {
for (auto* member : str->Members()) {
if (!IsHostShareable(member->Type())) {
@@ -307,6 +307,12 @@
}
}
+ if (auto* store_ty = s->StoreType(); !IsStorable(store_ty)) {
+ AddError(sem_.TypeNameOf(store_ty) + " cannot be used as the store type of a pointer",
+ a->arguments[1]->source);
+ return false;
+ }
+
return CheckTypeAccessAddressSpace(s->StoreType(), s->Access(), s->AddressSpace(), tint::Empty,
a->source);
}
@@ -416,7 +422,7 @@
auto is_uniform_struct_or_array = [address_space](const core::type::Type* ty) {
return address_space == core::AddressSpace::kUniform &&
- ty->IsAnyOf<core::type::Array, core::type::Struct>();
+ ty->IsAnyOf<sem::Array, core::type::Struct>();
};
auto is_uniform_struct = [address_space](const core::type::Type* ty) {
@@ -523,7 +529,7 @@
}
// For uniform buffer array members, validate that array elements are aligned to 16 bytes
- if (auto* arr = store_ty->As<core::type::Array>()) {
+ if (auto* arr = store_ty->As<sem::Array>()) {
// Recurse into the element type.
// TODO(crbug.com/tint/1388): Ideally we'd pass the source for nested element type here, but
// we can't easily get that from the semantic node. We should consider recursing through the
@@ -1635,7 +1641,8 @@
// used instead.
auto* builtin = call->Target()->As<sem::BuiltinFn>();
auto name = tint::ToString(builtin->Fn());
- AddError("builtin '" + name + "' does not return a value", call->Declaration()->source);
+ AddError("builtin function '" + name + "' does not return a value",
+ call->Declaration()->source);
return false;
}
}
@@ -1888,7 +1895,7 @@
}
bool Validator::ArrayConstructor(const ast::CallExpression* ctor,
- const core::type::Array* array_type) const {
+ const sem::Array* array_type) const {
auto& values = ctor->args;
auto* elem_ty = array_type->ElemType();
for (auto* value : values) {
@@ -2068,7 +2075,7 @@
return true;
}
-bool Validator::Array(const core::type::Array* arr, const Source& el_source) const {
+bool Validator::Array(const sem::Array* arr, const Source& el_source) const {
auto* el_ty = arr->ElemType();
if (!IsPlain(el_ty)) {
@@ -2122,7 +2129,7 @@
auto has_index = false;
Hashset<std::pair<uint32_t, uint32_t>, 8> locationsAndIndexes;
for (auto* member : str->Members()) {
- if (auto* r = member->Type()->As<core::type::Array>()) {
+ if (auto* r = member->Type()->As<sem::Array>()) {
if (r->Count()->Is<core::type::RuntimeArrayCount>()) {
if (member != str->Members().Back()) {
AddError("runtime arrays may only appear as the last member of a struct",
@@ -2606,7 +2613,7 @@
}
bool Validator::IsArrayWithOverrideCount(const core::type::Type* ty) const {
- if (auto* arr = ty->UnwrapRef()->As<core::type::Array>()) {
+ if (auto* arr = ty->UnwrapRef()->As<sem::Array>()) {
if (arr->Count()->IsAnyOf<sem::NamedOverrideArrayCount, sem::UnnamedOverrideArrayCount>()) {
return true;
}
@@ -2714,7 +2721,7 @@
return true;
},
[&](const core::type::Struct*) { return check_sub_atomics(); }, //
- [&](const core::type::Array*) { return check_sub_atomics(); }, //
+ [&](const sem::Array*) { return check_sub_atomics(); }, //
[&](Default) { return true; });
}
diff --git a/src/tint/lang/wgsl/resolver/validator.h b/src/tint/lang/wgsl/resolver/validator.h
index ecce5ba..e5df0f1 100644
--- a/src/tint/lang/wgsl/resolver/validator.h
+++ b/src/tint/lang/wgsl/resolver/validator.h
@@ -173,7 +173,7 @@
/// @param el_source the source of the array element, or the array if the array does not have a
/// locally-declared element AST node.
/// @returns true on success, false otherwise.
- bool Array(const core::type::Array* arr, const Source& el_source) const;
+ bool Array(const sem::Array* arr, const Source& el_source) const;
/// Validates an array stride attribute
/// @param attr the stride attribute to validate
@@ -452,7 +452,7 @@
/// @param ctor the call expresion to validate
/// @param arr_type the type of the array
/// @returns true on success, false otherwise
- bool ArrayConstructor(const ast::CallExpression* ctor, const core::type::Array* arr_type) const;
+ bool ArrayConstructor(const ast::CallExpression* ctor, const sem::Array* arr_type) const;
/// Validates a texture builtin function
/// @param call the builtin call to validate
diff --git a/src/tint/lang/wgsl/resolver/validator_is_storeable_test.cc b/src/tint/lang/wgsl/resolver/validator_is_storeable_test.cc
index 8674a75..0290231 100644
--- a/src/tint/lang/wgsl/resolver/validator_is_storeable_test.cc
+++ b/src/tint/lang/wgsl/resolver/validator_is_storeable_test.cc
@@ -17,6 +17,7 @@
#include "gmock/gmock.h"
#include "src/tint/lang/core/type/atomic.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
namespace tint::resolver {
namespace {
@@ -89,14 +90,14 @@
}
TEST_F(ValidatorIsStorableTest, ArraySizedOfStorable) {
- auto* arr = create<core::type::Array>(
- create<core::type::I32>(), create<core::type::ConstantArrayCount>(5u), 4u, 20u, 4u, 4u);
+ auto* arr = create<sem::Array>(create<core::type::I32>(),
+ create<core::type::ConstantArrayCount>(5u), 4u, 20u, 4u, 4u);
EXPECT_TRUE(v()->IsStorable(arr));
}
TEST_F(ValidatorIsStorableTest, ArrayUnsizedOfStorable) {
- auto* arr = create<core::type::Array>(create<core::type::I32>(),
- create<core::type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
+ auto* arr = create<sem::Array>(create<core::type::I32>(),
+ create<core::type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
EXPECT_TRUE(v()->IsStorable(arr));
}
diff --git a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
index 0dcd3a1..c962e18 100644
--- a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
@@ -15,6 +15,7 @@
#include "gmock/gmock.h"
#include "src/tint/lang/core/type/reference.h"
#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/value_constructor.h"
#include "src/tint/lang/wgsl/sem/value_conversion.h"
#include "src/tint/utils/text/string_stream.h"
@@ -489,7 +490,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -505,7 +506,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -524,7 +525,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -543,7 +544,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -562,7 +563,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -581,7 +582,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -600,7 +601,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -621,7 +622,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
@@ -645,7 +646,7 @@
auto* call = Sem().Get<sem::Call>(tc);
ASSERT_NE(call, nullptr);
- EXPECT_TRUE(call->Type()->Is<core::type::Array>());
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
auto* ctor = call->Target()->As<sem::ValueConstructor>();
ASSERT_NE(ctor, nullptr);
EXPECT_EQ(call->Type(), ctor->ReturnType());
diff --git a/src/tint/lang/wgsl/resolver/variable_validation_test.cc b/src/tint/lang/wgsl/resolver/variable_validation_test.cc
index cfcc146..8fcbaf0 100644
--- a/src/tint/lang/wgsl/resolver/variable_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/variable_validation_test.cc
@@ -47,7 +47,8 @@
WrapInFunction(Var("a", NoReturnValueBuiltin));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: builtin 'storageBarrier' does not return a value");
+ EXPECT_EQ(r()->error(),
+ "12:34 error: builtin function 'storageBarrier' does not return a value");
}
TEST_F(ResolverVariableValidationTest, GlobalVarInitializerNoReturnValueBuiltin) {
@@ -56,7 +57,8 @@
GlobalVar("a", NoReturnValueBuiltin);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: builtin 'storageBarrier' does not return a value");
+ EXPECT_EQ(r()->error(),
+ "12:34 error: builtin function 'storageBarrier' does not return a value");
}
TEST_F(ResolverVariableValidationTest, GlobalVarNoAddressSpace) {
diff --git a/src/tint/lang/wgsl/sem/BUILD.bazel b/src/tint/lang/wgsl/sem/BUILD.bazel
index a014edf..a7abdd6 100644
--- a/src/tint/lang/wgsl/sem/BUILD.bazel
+++ b/src/tint/lang/wgsl/sem/BUILD.bazel
@@ -27,6 +27,7 @@
name = "sem",
srcs = [
"accessor_expression.cc",
+ "array.cc",
"array_count.cc",
"behavior.cc",
"block_statement.cc",
@@ -60,6 +61,7 @@
],
hdrs = [
"accessor_expression.h",
+ "array.h",
"array_count.h",
"behavior.h",
"block_statement.h",
diff --git a/src/tint/lang/wgsl/sem/BUILD.cmake b/src/tint/lang/wgsl/sem/BUILD.cmake
index 6e545fa..29749a5 100644
--- a/src/tint/lang/wgsl/sem/BUILD.cmake
+++ b/src/tint/lang/wgsl/sem/BUILD.cmake
@@ -28,6 +28,8 @@
tint_add_target(tint_lang_wgsl_sem lib
lang/wgsl/sem/accessor_expression.cc
lang/wgsl/sem/accessor_expression.h
+ lang/wgsl/sem/array.cc
+ lang/wgsl/sem/array.h
lang/wgsl/sem/array_count.cc
lang/wgsl/sem/array_count.h
lang/wgsl/sem/behavior.cc
diff --git a/src/tint/lang/wgsl/sem/BUILD.gn b/src/tint/lang/wgsl/sem/BUILD.gn
index 2e87dae..f0465ba 100644
--- a/src/tint/lang/wgsl/sem/BUILD.gn
+++ b/src/tint/lang/wgsl/sem/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -33,6 +33,8 @@
sources = [
"accessor_expression.cc",
"accessor_expression.h",
+ "array.cc",
+ "array.h",
"array_count.cc",
"array_count.h",
"behavior.cc",
@@ -121,7 +123,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"builtin_fn_test.cc",
"diagnostic_severity_test.cc",
diff --git a/src/tint/lang/wgsl/sem/array.cc b/src/tint/lang/wgsl/sem/array.cc
new file mode 100644
index 0000000..a2aae60
--- /dev/null
+++ b/src/tint/lang/wgsl/sem/array.cc
@@ -0,0 +1,40 @@
+// 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.
+
+#include "src/tint/lang/wgsl/sem/array.h"
+
+#include "src/tint/lang/wgsl/sem/variable.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::sem::Array);
+
+namespace tint::sem {
+
+Array::Array(core::type::Type const* element,
+ const core::type::ArrayCount* count,
+ uint32_t align,
+ uint32_t size,
+ uint32_t stride,
+ uint32_t implicit_stride)
+ : Base(element, count, align, size, stride, implicit_stride) {}
+
+Array::~Array() = default;
+
+void Array::AddTransitivelyReferencedOverride(const GlobalVariable* var) {
+ transitively_referenced_overrides_.Add(var);
+ for (auto* ref : var->TransitivelyReferencedOverrides()) {
+ AddTransitivelyReferencedOverride(ref);
+ }
+}
+
+} // namespace tint::sem
diff --git a/src/tint/lang/wgsl/sem/array.h b/src/tint/lang/wgsl/sem/array.h
new file mode 100644
index 0000000..e634a0f
--- /dev/null
+++ b/src/tint/lang/wgsl/sem/array.h
@@ -0,0 +1,67 @@
+// 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_LANG_WGSL_SEM_ARRAY_H_
+#define SRC_TINT_LANG_WGSL_SEM_ARRAY_H_
+
+#include "src/tint/lang/core/type/array.h"
+#include "src/tint/utils/containers/unique_vector.h"
+
+/// Forward declarations
+namespace tint::sem {
+class GlobalVariable;
+}
+
+namespace tint::sem {
+
+/// Array holds the semantic information for Arrays.
+class Array final : public Castable<Array, core::type::Array> {
+ public:
+ /// Constructor
+ /// @param element the array element type
+ /// @param count the number of elements in the array.
+ /// @param align the byte alignment of the array
+ /// @param size the byte size of the array. The size will be 0 if the array element count is
+ /// pipeline overridable.
+ /// @param stride the number of bytes from the start of one element of the
+ /// array to the start of the next element
+ /// @param implicit_stride the number of bytes from the start of one element
+ /// of the array to the start of the next element, if there was no `@stride`
+ /// attribute applied.
+ Array(core::type::Type const* element,
+ const core::type::ArrayCount* count,
+ uint32_t align,
+ uint32_t size,
+ uint32_t stride,
+ uint32_t implicit_stride);
+
+ /// Destructor
+ ~Array() override;
+
+ /// Records that this variable (transitively) references the given override variable.
+ /// @param var the module-scope override variable
+ void AddTransitivelyReferencedOverride(const GlobalVariable* var);
+
+ /// @returns all transitively referenced override variables
+ VectorRef<const GlobalVariable*> TransitivelyReferencedOverrides() const {
+ return transitively_referenced_overrides_;
+ }
+
+ private:
+ UniqueVector<const GlobalVariable*, 4> transitively_referenced_overrides_;
+};
+
+} // namespace tint::sem
+
+#endif // SRC_TINT_LANG_WGSL_SEM_ARRAY_H_
diff --git a/src/tint/lang/wgsl/sem/builtin_enum_expression.cc b/src/tint/lang/wgsl/sem/builtin_enum_expression.cc
index fe5bff6..55081b8 100644
--- a/src/tint/lang/wgsl/sem/builtin_enum_expression.cc
+++ b/src/tint/lang/wgsl/sem/builtin_enum_expression.cc
@@ -14,8 +14,25 @@
#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h"
+#include "src/tint/lang/core/access.h"
+#include "src/tint/lang/core/address_space.h"
+#include "src/tint/lang/core/builtin_value.h"
+#include "src/tint/lang/core/interpolation_sampling.h"
+#include "src/tint/lang/core/interpolation_type.h"
+#include "src/tint/lang/core/texel_format.h"
+#include "src/tint/lang/wgsl/builtin_fn.h"
+
TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpressionBase);
+// Specializations
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::Access>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::AddressSpace>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::BuiltinValue>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::InterpolationSampling>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::InterpolationType>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::core::TexelFormat>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::wgsl::BuiltinFn>);
+
namespace tint::sem {
BuiltinEnumExpressionBase::BuiltinEnumExpressionBase(const ast::Expression* declaration,
diff --git a/src/tint/lang/wgsl/sem/function.cc b/src/tint/lang/wgsl/sem/function.cc
index 1d1b9e3..bb6a8a2 100644
--- a/src/tint/lang/wgsl/sem/function.cc
+++ b/src/tint/lang/wgsl/sem/function.cc
@@ -52,6 +52,14 @@
return ret;
}
+void Function::AddTransitivelyReferencedGlobal(const sem::GlobalVariable* global) {
+ if (transitively_referenced_globals_.Add(global)) {
+ for (auto* ref : global->TransitivelyReferencedOverrides()) {
+ AddTransitivelyReferencedGlobal(ref);
+ }
+ }
+}
+
Function::VariableBindings Function::TransitivelyReferencedUniformVariables() const {
VariableBindings ret;
diff --git a/src/tint/lang/wgsl/sem/function.h b/src/tint/lang/wgsl/sem/function.h
index 585ede0..8d01a14 100644
--- a/src/tint/lang/wgsl/sem/function.h
+++ b/src/tint/lang/wgsl/sem/function.h
@@ -86,11 +86,11 @@
}
/// Records that this function directly references the given global variable.
- /// Note: Implicitly adds this global to the transtively-called globals.
+ /// Note: Implicitly adds this global to the transitively-called globals.
/// @param global the module-scope variable
void AddDirectlyReferencedGlobal(const sem::GlobalVariable* global) {
directly_referenced_globals_.Add(global);
- transitively_referenced_globals_.Add(global);
+ AddTransitivelyReferencedGlobal(global);
}
/// @returns all transitively referenced global variables
@@ -101,9 +101,7 @@
/// Records that this function transitively references the given global
/// variable.
/// @param global the module-scoped variable
- void AddTransitivelyReferencedGlobal(const sem::GlobalVariable* global) {
- transitively_referenced_globals_.Add(global);
- }
+ void AddTransitivelyReferencedGlobal(const sem::GlobalVariable* global);
/// @returns the list of functions that this function transitively calls.
const UniqueVector<const Function*, 8>& TransitivelyCalledFunctions() const {
@@ -131,9 +129,10 @@
/// that this function uses (directly or indirectly). These can only
/// be parameters to this function or global variables. Uniqueness is
/// ensured by texture_sampler_pairs_ being a UniqueVector.
- /// @param texture the texture (must be non-null)
+ /// @param texture the texture (null indicates a sampler-only reference)
/// @param sampler the sampler (null indicates a texture-only reference)
void AddTextureSamplerPair(const sem::Variable* texture, const sem::Variable* sampler) {
+ TINT_ASSERT(texture || sampler);
texture_sampler_pairs_.Add(VariablePair(texture, sampler));
}
diff --git a/src/tint/lang/wgsl/sem/helper_test.h b/src/tint/lang/wgsl/sem/helper_test.h
index ece8694..fb45117 100644
--- a/src/tint/lang/wgsl/sem/helper_test.h
+++ b/src/tint/lang/wgsl/sem/helper_test.h
@@ -36,8 +36,11 @@
return resolver::Resolve(*this);
}
};
+
+/// An alias to TestHelper templated without a test parameter
using TestHelper = TestHelperBase<testing::Test>;
+/// An alias to TestHelper templated with the parameter type T
template <typename T>
using TestParamHelper = TestHelperBase<testing::TestWithParam<T>>;
diff --git a/src/tint/lang/wgsl/sem/info.h b/src/tint/lang/wgsl/sem/info.h
index 5a41a3f..a4ab07c 100644
--- a/src/tint/lang/wgsl/sem/info.h
+++ b/src/tint/lang/wgsl/sem/info.h
@@ -51,9 +51,6 @@
using GetResultType =
std::conditional_t<std::is_same<SEM, InferFromAST>::value, SemanticNodeTypeFor<AST>, SEM>;
- /// Alias to a unique vector of transitively referenced global variables
- using TransitivelyReferenced = UniqueVector<const GlobalVariable*, 4>;
-
/// Constructor
Info();
@@ -138,25 +135,6 @@
/// @returns the semantic module.
const sem::Module* Module() const { return module_; }
- /// Records that this variable (transitively) references the given override variable.
- /// @param from the item the variable is referenced from
- /// @param var the module-scope override variable
- void AddTransitivelyReferencedOverride(const CastableBase* from, const GlobalVariable* var) {
- if (referenced_overrides_.count(from) == 0) {
- referenced_overrides_.insert({from, TransitivelyReferenced{}});
- }
- referenced_overrides_[from].Add(var);
- }
-
- /// @param from the key to look up
- /// @returns all transitively referenced override variables or nullptr if none set
- const TransitivelyReferenced* TransitivelyReferencedOverrides(const CastableBase* from) const {
- if (referenced_overrides_.count(from) == 0) {
- return nullptr;
- }
- return &referenced_overrides_.at(from);
- }
-
/// Determines the severity of a filterable diagnostic rule for the AST node `ast_node`.
/// @param ast_node the AST node
/// @param rule the diagnostic rule
@@ -167,8 +145,6 @@
private:
// AST node index to semantic node
std::vector<const CastableBase*> nodes_;
- // Lists transitively referenced overrides for the given item
- std::unordered_map<const CastableBase*, TransitivelyReferenced> referenced_overrides_;
// The semantic module
sem::Module* module_ = nullptr;
};
diff --git a/src/tint/lang/wgsl/sem/pipeline_stage_set.h b/src/tint/lang/wgsl/sem/pipeline_stage_set.h
index c21796f..417235b 100644
--- a/src/tint/lang/wgsl/sem/pipeline_stage_set.h
+++ b/src/tint/lang/wgsl/sem/pipeline_stage_set.h
@@ -20,6 +20,7 @@
namespace tint::sem {
+/// A set of PipelineStage
using PipelineStageSet = tint::EnumSet<ast::PipelineStage>;
} // namespace tint::sem
diff --git a/src/tint/lang/wgsl/sem/type_expression.h b/src/tint/lang/wgsl/sem/type_expression.h
index c8f9563..4114b63 100644
--- a/src/tint/lang/wgsl/sem/type_expression.h
+++ b/src/tint/lang/wgsl/sem/type_expression.h
@@ -41,8 +41,12 @@
/// @return the type that the expression resolved to
const core::type::Type* Type() const { return type_; }
+ /// Sets the type that this expression resolved to
+ /// @param type the new type
+ void SetType(const core::type::Type* type) { type_ = type; }
+
private:
- core::type::Type const* const type_;
+ const core::type::Type* type_ = nullptr;
};
} // namespace tint::sem
diff --git a/src/tint/lang/wgsl/sem/type_mappings.h b/src/tint/lang/wgsl/sem/type_mappings.h
index 2dfb6ac..7518167 100644
--- a/src/tint/lang/wgsl/sem/type_mappings.h
+++ b/src/tint/lang/wgsl/sem/type_mappings.h
@@ -27,6 +27,7 @@
class AccessorExpression;
class BinaryExpression;
class BitcastExpression;
+class BlockStatement;
class BuiltinAttribute;
class CallExpression;
class Expression;
@@ -42,14 +43,15 @@
class StructMember;
class SwitchStatement;
class TypeDecl;
+class UnaryOpExpression;
class Variable;
class WhileStatement;
-class UnaryOpExpression;
} // namespace tint::ast
namespace tint::core {
enum class BuiltinValue : uint8_t;
}
namespace tint::sem {
+class BlockStatement;
class Expression;
class ForLoopStatement;
class Function;
@@ -77,6 +79,7 @@
/// rules will be used to infer the return type based on the argument type.
struct TypeMappings {
//! @cond Doxygen_Suppress
+ BlockStatement* operator()(ast::BlockStatement*);
BuiltinEnumExpression<core::BuiltinValue>* operator()(ast::BuiltinAttribute*);
CastableBase* operator()(ast::Node*);
Expression* operator()(ast::Expression*);
diff --git a/src/tint/lang/wgsl/sem/variable.cc b/src/tint/lang/wgsl/sem/variable.cc
index bfff38f..54849f2 100644
--- a/src/tint/lang/wgsl/sem/variable.cc
+++ b/src/tint/lang/wgsl/sem/variable.cc
@@ -28,62 +28,34 @@
TINT_INSTANTIATE_TYPEINFO(tint::sem::VariableUser);
namespace tint::sem {
-Variable::Variable(const ast::Variable* declaration,
- const core::type::Type* type,
- core::EvaluationStage stage,
- core::AddressSpace address_space,
- core::Access access,
- const core::constant::Value* constant_value)
- : declaration_(declaration),
- type_(type),
- stage_(stage),
- address_space_(address_space),
- access_(access),
- constant_value_(constant_value) {}
+Variable::Variable(const ast::Variable* declaration) : declaration_(declaration) {}
Variable::~Variable() = default;
-LocalVariable::LocalVariable(const ast::Variable* declaration,
- const core::type::Type* type,
- core::EvaluationStage stage,
- core::AddressSpace address_space,
- core::Access access,
- const sem::Statement* statement,
- const core::constant::Value* constant_value)
- : Base(declaration, type, stage, address_space, access, constant_value),
- statement_(statement) {}
+LocalVariable::LocalVariable(const ast::Variable* declaration, const sem::Statement* statement)
+ : Base(declaration), statement_(statement) {}
LocalVariable::~LocalVariable() = default;
-GlobalVariable::GlobalVariable(const ast::Variable* declaration,
- const core::type::Type* type,
- core::EvaluationStage stage,
- core::AddressSpace address_space,
- core::Access access,
- const core::constant::Value* constant_value,
- std::optional<tint::BindingPoint> binding_point,
- std::optional<uint32_t> location,
- std::optional<uint32_t> index)
- : Base(declaration, type, stage, address_space, access, constant_value),
- binding_point_(binding_point),
- location_(location),
- index_(index) {}
+GlobalVariable::GlobalVariable(const ast::Variable* declaration) : Base(declaration) {}
GlobalVariable::~GlobalVariable() = default;
+void GlobalVariable::AddTransitivelyReferencedOverride(const GlobalVariable* var) {
+ if (transitively_referenced_overrides_.Add(var)) {
+ for (auto* ref : var->TransitivelyReferencedOverrides()) {
+ AddTransitivelyReferencedOverride(ref);
+ }
+ }
+}
+
Parameter::Parameter(const ast::Parameter* declaration,
- uint32_t index,
- const core::type::Type* type,
- core::AddressSpace address_space,
- core::Access access,
- const core::ParameterUsage usage /* = ParameterUsage::kNone */,
- std::optional<tint::BindingPoint> binding_point /* = {} */,
- std::optional<uint32_t> location /* = std::nullopt */)
- : Base(declaration, type, core::EvaluationStage::kRuntime, address_space, access, nullptr),
- index_(index),
- usage_(usage),
- binding_point_(binding_point),
- location_(location) {}
+ uint32_t index /* = 0 */,
+ const core::type::Type* type /* = nullptr */,
+ core::ParameterUsage usage /* = core::ParameterUsage::kNone */)
+ : Base(declaration), index_(index), usage_(usage) {
+ SetType(type);
+}
Parameter::~Parameter() = default;
diff --git a/src/tint/lang/wgsl/sem/variable.h b/src/tint/lang/wgsl/sem/variable.h
index a894a83..7a7b826 100644
--- a/src/tint/lang/wgsl/sem/variable.h
+++ b/src/tint/lang/wgsl/sem/variable.h
@@ -49,17 +49,7 @@
public:
/// Constructor
/// @param declaration the AST declaration node
- /// @param type the variable type
- /// @param stage the evaluation stage for an expression of this variable type
- /// @param address_space the variable address space
- /// @param access the variable access control type
- /// @param constant_value the constant value for the variable. May be null
- Variable(const ast::Variable* declaration,
- const core::type::Type* type,
- core::EvaluationStage stage,
- core::AddressSpace address_space,
- core::Access access,
- const core::constant::Value* constant_value);
+ explicit Variable(const ast::Variable* declaration);
/// Destructor
~Variable() override;
@@ -67,29 +57,44 @@
/// @returns the AST declaration node
const ast::Variable* Declaration() const { return declaration_; }
+ /// @param type the variable type
+ void SetType(const core::type::Type* type) { type_ = type; }
+
/// @returns the canonical type for the variable
const core::type::Type* Type() const { return type_; }
+ /// @param stage the evaluation stage for an expression of this variable type
+ void SetStage(core::EvaluationStage stage) { stage_ = stage; }
+
/// @returns the evaluation stage for an expression of this variable type
core::EvaluationStage Stage() const { return stage_; }
+ /// @param space the variable address space
+ void SetAddressSpace(core::AddressSpace space) { address_space_ = space; }
+
/// @returns the address space for the variable
core::AddressSpace AddressSpace() const { return address_space_; }
+ /// @param access the variable access control type
+ void SetAccess(core::Access access) { access_ = access; }
+
/// @returns the access control for the variable
core::Access Access() const { return access_; }
+ /// @param value the constant value for the variable. May be null
+ void SetConstantValue(const core::constant::Value* value) { constant_value_ = value; }
+
/// @return the constant value of this expression
const core::constant::Value* ConstantValue() const { return constant_value_; }
- /// @returns the variable initializer expression, or nullptr if the variable
- /// does not have one.
- const ValueExpression* Initializer() const { return initializer_; }
-
/// Sets the variable initializer expression.
/// @param initializer the initializer expression to assign to this variable.
void SetInitializer(const ValueExpression* initializer) { initializer_ = initializer; }
+ /// @returns the variable initializer expression, or nullptr if the variable
+ /// does not have one.
+ const ValueExpression* Initializer() const { return initializer_; }
+
/// @returns the expressions that use the variable
VectorRef<const VariableUser*> Users() const { return users_; }
@@ -97,12 +102,12 @@
void AddUser(const VariableUser* user) { users_.Push(user); }
private:
- const ast::Variable* const declaration_;
- const core::type::Type* const type_;
- const core::EvaluationStage stage_;
- const core::AddressSpace address_space_;
- const core::Access access_;
- const core::constant::Value* constant_value_;
+ const ast::Variable* const declaration_ = nullptr;
+ const core::type::Type* type_ = nullptr;
+ core::EvaluationStage stage_ = core::EvaluationStage::kRuntime;
+ core::AddressSpace address_space_ = core::AddressSpace::kUndefined;
+ core::Access access_ = core::Access::kUndefined;
+ const core::constant::Value* constant_value_ = nullptr;
const ValueExpression* initializer_ = nullptr;
tint::Vector<const VariableUser*, 8> users_;
};
@@ -112,19 +117,8 @@
public:
/// Constructor
/// @param declaration the AST declaration node
- /// @param type the variable type
- /// @param stage the evaluation stage for an expression of this variable type
- /// @param address_space the variable address space
- /// @param access the variable access control type
/// @param statement the statement that declared this local variable
- /// @param constant_value the constant value for the variable. May be null
- LocalVariable(const ast::Variable* declaration,
- const core::type::Type* type,
- core::EvaluationStage stage,
- core::AddressSpace address_space,
- core::Access access,
- const sem::Statement* statement,
- const core::constant::Value* constant_value);
+ LocalVariable(const ast::Variable* declaration, const sem::Statement* statement);
/// Destructor
~LocalVariable() override;
@@ -132,13 +126,13 @@
/// @returns the statement that declares this local variable
const sem::Statement* Statement() const { return statement_; }
- /// @returns the Type, Function or Variable that this local variable shadows
- const CastableBase* Shadows() const { return shadows_; }
-
/// Sets the Type, Function or Variable that this local variable shadows
/// @param shadows the Type, Function or Variable that this variable shadows
void SetShadows(const CastableBase* shadows) { shadows_ = shadows; }
+ /// @returns the Type, Function or Variable that this local variable shadows
+ const CastableBase* Shadows() const { return shadows_; }
+
private:
const sem::Statement* const statement_;
const CastableBase* shadows_ = nullptr;
@@ -149,30 +143,16 @@
public:
/// Constructor
/// @param declaration the AST declaration node
- /// @param type the variable type
- /// @param stage the evaluation stage for an expression of this variable type
- /// @param address_space the variable address space
- /// @param access the variable access control type
- /// @param constant_value the constant value for the variable. May be null
- /// @param binding_point the optional resource binding point of the variable
- /// @param location the location value if provided
- /// @param index the index value if provided
- ///
- /// Note, a GlobalVariable generally doesn't have a `location` in WGSL, as it isn't allowed by
- /// the spec. The location maybe attached by transforms such as CanonicalizeEntryPointIO.
- GlobalVariable(const ast::Variable* declaration,
- const core::type::Type* type,
- core::EvaluationStage stage,
- core::AddressSpace address_space,
- core::Access access,
- const core::constant::Value* constant_value,
- std::optional<tint::BindingPoint> binding_point = std::nullopt,
- std::optional<uint32_t> location = std::nullopt,
- std::optional<uint32_t> index = std::nullopt);
+ explicit GlobalVariable(const ast::Variable* declaration);
/// Destructor
~GlobalVariable() override;
+ /// @param binding_point the resource binding point for the parameter
+ void SetBindingPoint(std::optional<tint::BindingPoint> binding_point) {
+ binding_point_ = binding_point;
+ }
+
/// @returns the resource binding point for the variable
std::optional<tint::BindingPoint> BindingPoint() const { return binding_point_; }
@@ -182,40 +162,49 @@
/// @returns the pipeline constant ID associated with the variable
tint::OverrideId OverrideId() const { return override_id_; }
+ /// @param location the location value for the parameter, if set
+ /// @note a GlobalVariable generally doesn't have a `location` in WGSL, as it isn't allowed by
+ /// the spec. The location maybe attached by transforms such as CanonicalizeEntryPointIO.
+ void SetLocation(std::optional<uint32_t> location) { location_ = location; }
+
/// @returns the location value for the parameter, if set
std::optional<uint32_t> Location() const { return location_; }
+ /// @param index the index value for the parameter, if set
+ void SetIndex(std::optional<uint32_t> index) { index_ = index; }
+
/// @returns the index value for the parameter, if set
std::optional<uint32_t> Index() const { return index_; }
- private:
- const std::optional<tint::BindingPoint> binding_point_;
+ /// Records that this variable (transitively) references the given override variable.
+ /// @param var the module-scope override variable
+ void AddTransitivelyReferencedOverride(const GlobalVariable* var);
+ /// @returns all transitively referenced override variables
+ VectorRef<const GlobalVariable*> TransitivelyReferencedOverrides() const {
+ return transitively_referenced_overrides_;
+ }
+
+ private:
+ std::optional<tint::BindingPoint> binding_point_;
tint::OverrideId override_id_;
std::optional<uint32_t> location_;
std::optional<uint32_t> index_;
+ UniqueVector<const GlobalVariable*, 4> transitively_referenced_overrides_;
};
/// Parameter is a function parameter
class Parameter final : public Castable<Parameter, Variable> {
public:
- /// Constructor for function parameters
+ /// Constructor
/// @param declaration the AST declaration node
- /// @param index the index of the parmeter in the function
+ /// @param index the index of the parameter in the function
/// @param type the variable type
- /// @param address_space the variable address space
- /// @param access the variable access control type
- /// @param usage the semantic usage for the parameter
- /// @param binding_point the optional resource binding point of the parameter
- /// @param location the location value, if set
+ /// @param usage the parameter usage
Parameter(const ast::Parameter* declaration,
- uint32_t index,
- const core::type::Type* type,
- core::AddressSpace address_space,
- core::Access access,
- const core::ParameterUsage usage = core::ParameterUsage::kNone,
- std::optional<tint::BindingPoint> binding_point = {},
- std::optional<uint32_t> location = std::nullopt);
+ uint32_t index = 0,
+ const core::type::Type* type = nullptr,
+ core::ParameterUsage usage = core::ParameterUsage::kNone);
/// Destructor
~Parameter() override;
@@ -225,38 +214,52 @@
return static_cast<const ast::Parameter*>(Variable::Declaration());
}
+ /// @param index the index value for the parameter, if set
+ void SetIndex(uint32_t index) { index_ = index; }
+
/// @return the index of the parameter in the function
uint32_t Index() const { return index_; }
+ /// @param usage the semantic usage for the parameter
+ void SetUsage(core::ParameterUsage usage) { usage_ = usage; }
+
/// @returns the semantic usage for the parameter
core::ParameterUsage Usage() const { return usage_; }
- /// @returns the CallTarget owner of this parameter
- CallTarget const* Owner() const { return owner_; }
-
/// @param owner the CallTarget owner of this parameter
- void SetOwner(CallTarget const* owner) { owner_ = owner; }
+ void SetOwner(const CallTarget* owner) { owner_ = owner; }
- /// @returns the Type, Function or Variable that this local variable shadows
- const CastableBase* Shadows() const { return shadows_; }
+ /// @returns the CallTarget owner of this parameter
+ const CallTarget* Owner() const { return owner_; }
/// Sets the Type, Function or Variable that this local variable shadows
/// @param shadows the Type, Function or Variable that this variable shadows
void SetShadows(const CastableBase* shadows) { shadows_ = shadows; }
+ /// @returns the Type, Function or Variable that this local variable shadows
+ const CastableBase* Shadows() const { return shadows_; }
+
+ /// @param binding_point the resource binding point for the parameter
+ void SetBindingPoint(std::optional<tint::BindingPoint> binding_point) {
+ binding_point_ = binding_point;
+ }
+
/// @returns the resource binding point for the parameter
std::optional<tint::BindingPoint> BindingPoint() const { return binding_point_; }
+ /// @param location the location value for the parameter, if set
+ void SetLocation(std::optional<uint32_t> location) { location_ = location; }
+
/// @returns the location value for the parameter, if set
std::optional<uint32_t> Location() const { return location_; }
private:
- const uint32_t index_;
- const core::ParameterUsage usage_;
+ uint32_t index_ = 0;
+ core::ParameterUsage usage_ = core::ParameterUsage::kNone;
CallTarget const* owner_ = nullptr;
const CastableBase* shadows_ = nullptr;
- const std::optional<tint::BindingPoint> binding_point_;
- const std::optional<uint32_t> location_;
+ std::optional<tint::BindingPoint> binding_point_;
+ std::optional<uint32_t> location_;
};
/// VariableUser holds the semantic information for an identifier expression
diff --git a/src/tint/lang/wgsl/writer/BUILD.bazel b/src/tint/lang/wgsl/writer/BUILD.bazel
index 36cadd8..262e529 100644
--- a/src/tint/lang/wgsl/writer/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/BUILD.bazel
@@ -45,7 +45,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer/ast_printer",
"//src/tint/lang/wgsl/writer/ir_to_program",
"//src/tint/lang/wgsl/writer/raise",
"//src/tint/lang/wgsl/writer/syntax_tree_printer",
@@ -63,17 +62,23 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
- ],
+ ] + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer/ast_printer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"writer_bench.cc",
],
deps = [
- "//src/tint/cmd/bench",
+ "//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
@@ -81,7 +86,6 @@
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
@@ -95,8 +99,19 @@
"//src/tint/utils/symbol",
"//src/tint/utils/text",
"//src/tint/utils/traits",
- ],
+ "@benchmark",
+ ] + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
diff --git a/src/tint/lang/wgsl/writer/BUILD.cfg b/src/tint/lang/wgsl/writer/BUILD.cfg
new file mode 100644
index 0000000..80e6a14
--- /dev/null
+++ b/src/tint/lang/wgsl/writer/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_wgsl_writer"
+}
diff --git a/src/tint/lang/wgsl/writer/BUILD.cmake b/src/tint/lang/wgsl/writer/BUILD.cmake
index c9893f6..014df3e 100644
--- a/src/tint/lang/wgsl/writer/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/BUILD.cmake
@@ -26,9 +26,11 @@
include(lang/wgsl/writer/raise/BUILD.cmake)
include(lang/wgsl/writer/syntax_tree_printer/BUILD.cmake)
+if(TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_wgsl_writer
# Kind: lib
+# Condition: TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_wgsl_writer lib
lang/wgsl/writer/options.cc
@@ -49,7 +51,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_program
tint_lang_wgsl_sem
- tint_lang_wgsl_writer_ast_printer
tint_lang_wgsl_writer_ir_to_program
tint_lang_wgsl_writer_raise
tint_lang_wgsl_writer_syntax_tree_printer
@@ -69,16 +70,25 @@
tint_utils_traits
)
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_wgsl_writer lib
+ tint_lang_wgsl_writer_ast_printer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_WGSL_WRITER)
+if(TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_wgsl_writer_bench
# Kind: bench
+# Condition: TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_wgsl_writer_bench bench
lang/wgsl/writer/writer_bench.cc
)
tint_target_add_dependencies(tint_lang_wgsl_writer_bench bench
- tint_cmd_bench
+ tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
@@ -86,7 +96,6 @@
tint_lang_wgsl_ast
tint_lang_wgsl_program
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -101,3 +110,15 @@
tint_utils_text
tint_utils_traits
)
+
+tint_target_add_external_dependencies(tint_lang_wgsl_writer_bench bench
+ "google-benchmark"
+)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_wgsl_writer_bench bench
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/writer/BUILD.gn b/src/tint/lang/wgsl/writer/BUILD.gn
index 21b27a4..2c531db 100644
--- a/src/tint/lang/wgsl/writer/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/BUILD.gn
@@ -25,42 +25,85 @@
import("${tint_src_dir}/tint.gni")
-libtint_source_set("writer") {
- sources = [
- "options.cc",
- "options.h",
- "output.cc",
- "output.h",
- "writer.cc",
- "writer.h",
- ]
- deps = [
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer/ast_printer",
- "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
- "${tint_src_dir}/lang/wgsl/writer/raise",
- "${tint_src_dir}/lang/wgsl/writer/syntax_tree_printer",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/generator",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
+if (tint_build_wgsl_writer) {
+ libtint_source_set("writer") {
+ sources = [
+ "options.cc",
+ "options.h",
+ "output.cc",
+ "output.h",
+ "writer.cc",
+ "writer.h",
+ ]
+ deps = [
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
+ "${tint_src_dir}/lang/wgsl/writer/raise",
+ "${tint_src_dir}/lang/wgsl/writer/syntax_tree_printer",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/generator",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer/ast_printer" ]
+ }
+ }
+}
+if (tint_build_benchmarks) {
+ if (tint_build_wgsl_writer) {
+ tint_unittests_source_set("bench") {
+ sources = [ "writer_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/cmd/bench:bench",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
+ }
+ }
}
diff --git a/src/tint/lang/wgsl/writer/ast_printer/BUILD.bazel b/src/tint/lang/wgsl/writer/ast_printer/BUILD.bazel
index b80b144..f40c5b2 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/ast_printer/BUILD.bazel
@@ -103,7 +103,6 @@
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/resolver",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer/ast_printer",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/generator",
@@ -119,8 +118,18 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer/ast_printer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
diff --git a/src/tint/lang/wgsl/writer/ast_printer/BUILD.cfg b/src/tint/lang/wgsl/writer/ast_printer/BUILD.cfg
new file mode 100644
index 0000000..80e6a14
--- /dev/null
+++ b/src/tint/lang/wgsl/writer/ast_printer/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+ "condition": "tint_build_wgsl_writer"
+}
diff --git a/src/tint/lang/wgsl/writer/ast_printer/BUILD.cmake b/src/tint/lang/wgsl/writer/ast_printer/BUILD.cmake
index 96beb17..92526ed 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/ast_printer/BUILD.cmake
@@ -21,9 +21,11 @@
# Do not modify this file directly
################################################################################
+if(TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_wgsl_writer_ast_printer
# Kind: lib
+# Condition: TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_wgsl_writer_ast_printer lib
lang/wgsl/writer/ast_printer/ast_printer.cc
@@ -54,9 +56,12 @@
tint_utils_traits
)
+endif(TINT_BUILD_WGSL_WRITER)
+if(TINT_BUILD_WGSL_WRITER)
################################################################################
# Target: tint_lang_wgsl_writer_ast_printer_test
# Kind: test
+# Condition: TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_wgsl_writer_ast_printer_test test
lang/wgsl/writer/ast_printer/alias_type_test.cc
@@ -102,7 +107,6 @@
tint_lang_wgsl_program
tint_lang_wgsl_resolver
tint_lang_wgsl_sem
- tint_lang_wgsl_writer_ast_printer
tint_utils_containers
tint_utils_diagnostic
tint_utils_generator
@@ -122,3 +126,11 @@
tint_target_add_external_dependencies(tint_lang_wgsl_writer_ast_printer_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_dependencies(tint_lang_wgsl_writer_ast_printer_test test
+ tint_lang_wgsl_writer_ast_printer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
+
+endif(TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/wgsl/writer/ast_printer/BUILD.gn b/src/tint/lang/wgsl/writer/ast_printer/BUILD.gn
index dcdec55..7a31589 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/ast_printer/BUILD.gn
@@ -25,87 +25,23 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
-
-libtint_source_set("ast_printer") {
- sources = [
- "ast_printer.cc",
- "ast_printer.h",
- ]
- deps = [
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/generator",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/strconv",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
-}
-if (tint_build_unittests) {
- tint_unittests_source_set("unittests") {
- testonly = true
+if (tint_build_wgsl_writer) {
+ libtint_source_set("ast_printer") {
sources = [
- "alias_type_test.cc",
- "array_accessor_test.cc",
- "assign_test.cc",
- "ast_printer_test.cc",
- "binary_test.cc",
- "bitcast_test.cc",
- "block_test.cc",
- "break_test.cc",
- "call_test.cc",
- "case_test.cc",
- "cast_test.cc",
- "const_assert_test.cc",
- "constructor_test.cc",
- "continue_test.cc",
- "diagnostic_test.cc",
- "discard_test.cc",
- "enable_test.cc",
- "function_test.cc",
- "global_decl_test.cc",
- "helper_test.h",
- "identifier_test.cc",
- "if_test.cc",
- "literal_test.cc",
- "loop_test.cc",
- "member_accessor_test.cc",
- "return_test.cc",
- "switch_test.cc",
- "type_test.cc",
- "unary_op_test.cc",
- "variable_decl_statement_test.cc",
- "variable_test.cc",
+ "ast_printer.cc",
+ "ast_printer.h",
]
deps = [
- "${tint_src_dir}:gmock_and_gtest",
- "${tint_src_dir}/api/common",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/resolver",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer/ast_printer",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/generator",
@@ -114,12 +50,81 @@
"${tint_src_dir}/utils/macros",
"${tint_src_dir}/utils/math",
"${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
"${tint_src_dir}/utils/result",
"${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/strconv",
"${tint_src_dir}/utils/symbol",
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
}
}
+if (tint_build_unittests) {
+ if (tint_build_wgsl_writer) {
+ tint_unittests_source_set("unittests") {
+ sources = [
+ "alias_type_test.cc",
+ "array_accessor_test.cc",
+ "assign_test.cc",
+ "ast_printer_test.cc",
+ "binary_test.cc",
+ "bitcast_test.cc",
+ "block_test.cc",
+ "break_test.cc",
+ "call_test.cc",
+ "case_test.cc",
+ "cast_test.cc",
+ "const_assert_test.cc",
+ "constructor_test.cc",
+ "continue_test.cc",
+ "diagnostic_test.cc",
+ "discard_test.cc",
+ "enable_test.cc",
+ "function_test.cc",
+ "global_decl_test.cc",
+ "helper_test.h",
+ "identifier_test.cc",
+ "if_test.cc",
+ "literal_test.cc",
+ "loop_test.cc",
+ "member_accessor_test.cc",
+ "return_test.cc",
+ "switch_test.cc",
+ "type_test.cc",
+ "unary_op_test.cc",
+ "variable_decl_statement_test.cc",
+ "variable_test.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/resolver",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
+ "${tint_src_dir}/utils/generator",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/id",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/result",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/symbol",
+ "${tint_src_dir}/utils/text",
+ "${tint_src_dir}/utils/traits",
+ ]
+
+ if (tint_build_wgsl_writer) {
+ deps += [ "${tint_src_dir}/lang/wgsl/writer/ast_printer" ]
+ }
+ }
+ }
+}
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
index c67c82f..4e76e72 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
@@ -68,11 +68,15 @@
name = "test",
alwayslink = True,
srcs = [
- "inlining_test.cc",
- "ir_to_program_test.cc",
"ir_to_program_test.h",
"rename_conflicts_test.cc",
- ],
+ ] + select({
+ ":tint_build_wgsl_writer": [
+ "inlining_test.cc",
+ "ir_to_program_test.cc",
+ ],
+ "//conditions:default": [],
+ }),
deps = [
"//src/tint/api/common",
"//src/tint/lang/core",
@@ -83,9 +87,10 @@
"//src/tint/lang/core/type",
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
+ "//src/tint/lang/wgsl/intrinsic",
+ "//src/tint/lang/wgsl/ir",
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer",
"//src/tint/lang/wgsl/writer/ir_to_program",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -101,8 +106,18 @@
"//src/tint/utils/text",
"//src/tint/utils/traits",
"@gtest",
- ],
+ ] + select({
+ ":tint_build_wgsl_writer": [
+ "//src/tint/lang/wgsl/writer",
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
+alias(
+ name = "tint_build_wgsl_writer",
+ actual = "//src/tint:tint_build_wgsl_writer_true",
+)
+
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
index 1fa4481..b9b7546 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
@@ -66,8 +66,6 @@
# Kind: test
################################################################################
tint_add_target(tint_lang_wgsl_writer_ir_to_program_test test
- lang/wgsl/writer/ir_to_program/inlining_test.cc
- lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
lang/wgsl/writer/ir_to_program/ir_to_program_test.h
lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
)
@@ -82,9 +80,10 @@
tint_lang_core_type
tint_lang_wgsl
tint_lang_wgsl_ast
+ tint_lang_wgsl_intrinsic
+ tint_lang_wgsl_ir
tint_lang_wgsl_program
tint_lang_wgsl_sem
- tint_lang_wgsl_writer
tint_lang_wgsl_writer_ir_to_program
tint_utils_containers
tint_utils_diagnostic
@@ -104,3 +103,13 @@
tint_target_add_external_dependencies(tint_lang_wgsl_writer_ir_to_program_test test
"gtest"
)
+
+if(TINT_BUILD_WGSL_WRITER)
+ tint_target_add_sources(tint_lang_wgsl_writer_ir_to_program_test test
+ "lang/wgsl/writer/ir_to_program/inlining_test.cc"
+ "lang/wgsl/writer/ir_to_program/ir_to_program_test.cc"
+ )
+ tint_target_add_dependencies(tint_lang_wgsl_writer_ir_to_program_test test
+ tint_lang_wgsl_writer
+ )
+endif(TINT_BUILD_WGSL_WRITER)
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
index c823bb4..89fdd01 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -67,10 +67,7 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
- "inlining_test.cc",
- "ir_to_program_test.cc",
"ir_to_program_test.h",
"rename_conflicts_test.cc",
]
@@ -85,9 +82,10 @@
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/intrinsic",
+ "${tint_src_dir}/lang/wgsl/ir",
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/lang/wgsl/writer/ir_to_program",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -103,5 +101,13 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_wgsl_writer) {
+ sources += [
+ "inlining_test.cc",
+ "ir_to_program_test.cc",
+ ]
+ deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
+ }
}
}
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
index ae49eb3..65f748c 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// GEN_BUILD:CONDITION(tint_build_wgsl_writer)
+
#include <string>
#include "src/tint/lang/core/ir/disassembler.h"
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index faaacf4..43d5ce7 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -596,6 +596,18 @@
disabled_derivative_uniformity_ = true;
}
+ switch (c->Func()) {
+ case wgsl::BuiltinFn::kTextureBarrier:
+ Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
+ break;
+ case wgsl::BuiltinFn::kSubgroupBallot:
+ case wgsl::BuiltinFn::kSubgroupBroadcast:
+ Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
+ break;
+ default:
+ break;
+ }
+
auto* expr = b.Call(c->Func(), std::move(args));
if (!call->HasResults() || call->Result()->Type()->Is<core::type::Void>()) {
Append(b.CallStmt(expr));
@@ -925,6 +937,9 @@
return b.ty.sampled_texture(t->dim(), el);
},
[&](const core::type::StorageTexture* t) {
+ if (t->access() == core::Access::kRead || t->access() == core::Access::kReadWrite) {
+ Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
+ }
return b.ty.storage_texture(t->dim(), t->texel_format(), t->access());
},
[&](const core::type::Sampler* s) { return b.ty.sampler(s->kind()); },
@@ -968,6 +983,9 @@
ast_attrs.Push(b.Index(u32(*index)));
}
if (auto builtin = ir_attrs.builtin) {
+ if (RequiresSubgroups(*builtin)) {
+ Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
+ }
ast_attrs.Push(b.Builtin(*builtin));
}
if (auto interpolation = ir_attrs.interpolation) {
@@ -1171,6 +1189,18 @@
}
}
+ /// @returns true if the builtin value requires the kChromiumExperimentalSubgroups extension to
+ /// be enabled.
+ bool RequiresSubgroups(core::BuiltinValue builtin) {
+ switch (builtin) {
+ case core::BuiltinValue::kSubgroupInvocationId:
+ case core::BuiltinValue::kSubgroupSize:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/// @returns true if a parameter of the type @p ty requires the
/// kChromiumExperimentalFullPtrParameters extension to be enabled.
bool ParamRequiresFullPtrParameters(const core::type::Type* ty) {
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 537c11a..a189e4e 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -12,10 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// GEN_BUILD:CONDITION(tint_build_wgsl_writer)
+
#include <sstream>
#include <string>
#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/type/storage_texture.h"
+#include "src/tint/lang/wgsl/ir/builtin_call.h"
#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h"
#include "src/tint/lang/wgsl/writer/writer.h"
@@ -29,8 +33,7 @@
IRToProgramTest::Result IRToProgramTest::Run() {
Result result;
- tint::core::ir::Disassembler d{mod};
- result.ir = d.Disassemble();
+ result.ir = tint::core::ir::Disassemble(mod);
auto output_program = IRToProgram(mod);
if (!output_program.IsValid()) {
@@ -3195,5 +3198,142 @@
)");
}
+////////////////////////////////////////////////////////////////////////////////
+// chromium_experimental_read_write_storage_texture
+////////////////////////////////////////////////////////////////////////////////
+TEST_F(IRToProgramTest, Enable_ChromiumExperimentalReadWriteStorageTexture_TextureBarrier) {
+ auto* fn = b.Function("f", ty.void_());
+ b.Append(fn->Block(), [&] {
+ b.Append(mod.instructions.Create<wgsl::ir::BuiltinCall>(
+ b.InstructionResult(ty.void_()), wgsl::BuiltinFn::kTextureBarrier, Empty));
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_read_write_storage_texture;
+
+fn f() {
+ textureBarrier();
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Enable_ChromiumExperimentalReadWriteStorageTexture_ReadOnlyStorageTexture) {
+ auto* T = b.Var("T", ty.ptr<handle>(ty.Get<core::type::StorageTexture>(
+ core::type::TextureDimension::k2d, core::TexelFormat::kR32Float,
+ core::Access::kRead, ty.f32())));
+ T->SetBindingPoint(0, 0);
+ b.ir.root_block->Append(T);
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_read_write_storage_texture;
+
+@group(0) @binding(0) var T : texture_storage_2d<r32float, read>;
+)");
+}
+
+TEST_F(IRToProgramTest,
+ Enable_ChromiumExperimentalReadWriteStorageTexture_ReadWriteOnlyStorageTexture) {
+ auto* T = b.Var("T", ty.ptr<handle>(ty.Get<core::type::StorageTexture>(
+ core::type::TextureDimension::k2d, core::TexelFormat::kR32Float,
+ core::Access::kReadWrite, ty.f32())));
+ T->SetBindingPoint(0, 0);
+ b.ir.root_block->Append(T);
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_read_write_storage_texture;
+
+@group(0) @binding(0) var T : texture_storage_2d<r32float, read_write>;
+)");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// chromium_experimental_subgroups
+////////////////////////////////////////////////////////////////////////////////
+TEST_F(IRToProgramTest, Enable_ChromiumExperimentalSubgroups_SubgroupBallot) {
+ auto* fn = b.Function("f", ty.void_());
+ b.Append(fn->Block(), [&] {
+ b.Append(mod.instructions.Create<wgsl::ir::BuiltinCall>(
+ b.InstructionResult(ty.vec4<u32>()), wgsl::BuiltinFn::kSubgroupBallot, Empty));
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_subgroups;
+
+fn f() {
+ _ = subgroupBallot();
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Enable_ChromiumExperimentalSubgroups_SubgroupBroadcast) {
+ auto* fn = b.Function("f", ty.void_());
+ b.Append(fn->Block(), [&] {
+ auto* one = b.Value(1_u);
+ b.Append(mod.instructions.Create<wgsl::ir::BuiltinCall>(
+ b.InstructionResult(ty.u32()), wgsl::BuiltinFn::kSubgroupBroadcast, Vector{one, one}));
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_subgroups;
+
+fn f() {
+ _ = subgroupBroadcast(1u, 1u);
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Enable_ChromiumExperimentalSubgroups_StructBuiltin_SubgroupInvocationId) {
+ core::type::Manager::StructMemberDesc member;
+ member.name = mod.symbols.New("a");
+ member.type = ty.u32();
+ member.attributes.builtin = core::BuiltinValue::kSubgroupInvocationId;
+
+ auto* S = ty.Struct(mod.symbols.New("S"), {member});
+
+ auto* fn = b.Function("f", ty.void_());
+ fn->SetParams({b.FunctionParam(S)});
+ b.Append(fn->Block(), [&] { b.Return(fn); });
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_subgroups;
+
+struct S {
+ @builtin(subgroup_invocation_id)
+ a : u32,
+}
+
+fn f(v : S) {
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Enable_ChromiumExperimentalSubgroups_StructBuiltin_SubgroupSize) {
+ core::type::Manager::StructMemberDesc member;
+ member.name = mod.symbols.New("a");
+ member.type = ty.u32();
+ member.attributes.builtin = core::BuiltinValue::kSubgroupSize;
+
+ auto* S = ty.Struct(mod.symbols.New("S"), {member});
+
+ auto* fn = b.Function("f", ty.void_());
+ fn->SetParams({b.FunctionParam(S)});
+ b.Append(fn->Block(), [&] { b.Return(fn); });
+
+ EXPECT_WGSL(R"(
+enable chromium_experimental_subgroups;
+
+struct S {
+ @builtin(subgroup_size)
+ a : u32,
+}
+
+fn f(v : S) {
+}
+)");
+}
+
} // namespace
} // namespace tint::wgsl::writer
diff --git a/src/tint/lang/wgsl/writer/raise/BUILD.gn b/src/tint/lang/wgsl/writer/raise/BUILD.gn
index 7dc51e0..219ad43 100644
--- a/src/tint/lang/wgsl/writer/raise/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/raise/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -61,7 +61,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "raise_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/lang/wgsl/writer/raise/raise.cc b/src/tint/lang/wgsl/writer/raise/raise.cc
index 5843d5f..53ffb6c 100644
--- a/src/tint/lang/wgsl/writer/raise/raise.cc
+++ b/src/tint/lang/wgsl/writer/raise/raise.cc
@@ -18,6 +18,8 @@
#include "src/tint/lang/core/builtin_fn.h"
#include "src/tint/lang/core/ir/core_builtin_call.h"
+#include "src/tint/lang/core/ir/load.h"
+#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/wgsl/builtin_fn.h"
#include "src/tint/lang/wgsl/ir/builtin_call.h"
@@ -116,7 +118,6 @@
CASE(kUnpack4X8Snorm)
CASE(kUnpack4X8Unorm)
CASE(kWorkgroupBarrier)
- CASE(kWorkgroupUniformLoad)
CASE(kTextureBarrier)
CASE(kTextureDimensions)
CASE(kTextureGather)
@@ -152,15 +153,66 @@
}
}
+void ReplaceBuiltinFnCall(core::ir::Module& mod, core::ir::CoreBuiltinCall* call) {
+ Vector<core::ir::Value*, 8> args(call->Args());
+ auto* replacement = mod.instructions.Create<wgsl::ir::BuiltinCall>(
+ call->Result(), Convert(call->Func()), std::move(args));
+ call->ReplaceWith(replacement);
+ call->ClearResults();
+ call->Destroy();
+}
+
+void ReplaceWorkgroupBarrier(core::ir::Module& mod, core::ir::CoreBuiltinCall* call) {
+ // Pattern match:
+ // call workgroupBarrier
+ // %value = load &ptr
+ // call workgroupBarrier
+ // And replace with:
+ // %value = call workgroupUniformLoad %ptr
+
+ auto* load = As<core::ir::Load>(call->next);
+ if (!load || load->From()->Type()->As<core::type::Pointer>()->AddressSpace() !=
+ core::AddressSpace::kWorkgroup) {
+ // No match
+ ReplaceBuiltinFnCall(mod, call);
+ return;
+ }
+
+ auto* post_load = As<core::ir::CoreBuiltinCall>(load->next);
+ if (!post_load || post_load->Func() != core::BuiltinFn::kWorkgroupBarrier) {
+ // No match
+ ReplaceBuiltinFnCall(mod, call);
+ return;
+ }
+
+ // Remove both calls to workgroupBarrier
+ post_load->Destroy();
+ call->Destroy();
+
+ // Replace load with workgroupUniformLoad
+ auto* replacement = mod.instructions.Create<wgsl::ir::BuiltinCall>(
+ load->Result(), wgsl::BuiltinFn::kWorkgroupUniformLoad, Vector{load->From()});
+ load->ReplaceWith(replacement);
+ load->ClearResults();
+ load->Destroy();
+}
+
} // namespace
Result<SuccessType> Raise(core::ir::Module& mod) {
for (auto* inst : mod.instructions.Objects()) {
+ if (!inst->Alive()) {
+ continue;
+ }
if (auto* call = inst->As<core::ir::CoreBuiltinCall>()) {
- Vector<core::ir::Value*, 8> args(call->Args());
- auto* replacement = mod.instructions.Create<wgsl::ir::BuiltinCall>(
- call->Result(), Convert(call->Func()), std::move(args));
- call->ReplaceWith(replacement);
+ switch (call->Func()) {
+ case core::BuiltinFn::kWorkgroupBarrier:
+ ReplaceWorkgroupBarrier(mod, call);
+ break;
+ default:
+ ReplaceBuiltinFnCall(mod, call);
+ break;
+ }
}
}
return Success;
diff --git a/src/tint/lang/wgsl/writer/raise/raise_test.cc b/src/tint/lang/wgsl/writer/raise/raise_test.cc
index a4f9b05..6928dd4 100644
--- a/src/tint/lang/wgsl/writer/raise/raise_test.cc
+++ b/src/tint/lang/wgsl/writer/raise/raise_test.cc
@@ -57,5 +57,100 @@
EXPECT_EQ(expect, str());
}
+TEST_F(WgslWriter_RaiseTest, WorkgroupBarrier) {
+ auto* W = b.Var<workgroup, i32, read_write>("W");
+ b.ir.root_block->Append(W);
+ auto* f = b.Function("f", ty.i32());
+ b.Append(f->Block(), [&] { //
+ b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
+ auto* load = b.Load(W);
+ b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
+ b.Return(f, load);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %W:ptr<workgroup, i32, read_write> = var
+}
+
+%f = func():i32 -> %b2 {
+ %b2 = block {
+ %3:void = workgroupBarrier
+ %4:i32 = load %W
+ %5:void = workgroupBarrier
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %W:ptr<workgroup, i32, read_write> = var
+}
+
+%f = func():i32 -> %b2 {
+ %b2 = block {
+ %3:i32 = wgsl.workgroupUniformLoad %W
+ ret %3
+ }
+}
+)";
+
+ Run(Raise);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(WgslWriter_RaiseTest, WorkgroupBarrier_NoMatch) {
+ auto* W = b.Var<workgroup, i32, read_write>("W");
+ b.ir.root_block->Append(W);
+ auto* f = b.Function("f", ty.i32());
+ b.Append(f->Block(), [&] { //
+ b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
+ b.Store(W, 42_i); // Prevents pattern match
+ auto* load = b.Load(W);
+ b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier);
+ b.Return(f, load);
+ });
+
+ auto* src = R"(
+%b1 = block { # root
+ %W:ptr<workgroup, i32, read_write> = var
+}
+
+%f = func():i32 -> %b2 {
+ %b2 = block {
+ %3:void = workgroupBarrier
+ store %W, 42i
+ %4:i32 = load %W
+ %5:void = workgroupBarrier
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%b1 = block { # root
+ %W:ptr<workgroup, i32, read_write> = var
+}
+
+%f = func():i32 -> %b2 {
+ %b2 = block {
+ %3:void = wgsl.workgroupBarrier
+ store %W, 42i
+ %4:i32 = load %W
+ %5:void = wgsl.workgroupBarrier
+ ret %4
+ }
+}
+)";
+
+ Run(Raise);
+
+ EXPECT_EQ(expect, str());
+}
+
} // namespace
} // namespace tint::wgsl::writer::raise
diff --git a/src/tint/lang/wgsl/writer/writer_bench.cc b/src/tint/lang/wgsl/writer/writer_bench.cc
index 05f349a..3a4157d 100644
--- a/src/tint/lang/wgsl/writer/writer_bench.cc
+++ b/src/tint/lang/wgsl/writer/writer_bench.cc
@@ -22,15 +22,14 @@
void GenerateWGSL(benchmark::State& state, std::string input_name) {
auto res = bench::LoadProgram(input_name);
- if (auto err = std::get_if<bench::Error>(&res)) {
- state.SkipWithError(err->msg.c_str());
+ if (!res) {
+ state.SkipWithError(res.Failure().reason.str());
return;
}
- auto& program = std::get<bench::ProgramAndFile>(res).program;
for (auto _ : state) {
- auto res = Generate(program, {});
- if (!res) {
- state.SkipWithError(res.Failure().reason.str());
+ auto gen_res = Generate(res->program, {});
+ if (!gen_res) {
+ state.SkipWithError(gen_res.Failure().reason.str());
}
}
}
diff --git a/src/tint/tint.gni b/src/tint/tint.gni
index 6d6bd8c..9693090 100644
--- a/src/tint/tint.gni
+++ b/src/tint/tint.gni
@@ -43,11 +43,27 @@
}
}
+###############################################################################
+# Executables - only built when tint_build_cmds is enabled
+###############################################################################
+template("tint_executable") {
+ if (tint_build_cmds) {
+ executable(target_name) {
+ forward_variables_from(invoker, "*")
+ }
+ }
+}
+
+###############################################################################
+# Unit tests - only built when tint_build_unittests is enabled
+###############################################################################
template("tint_unittests_source_set") {
if (tint_build_unittests) {
source_set(target_name) {
forward_variables_from(invoker, "*", [ "configs" ])
+ testonly = true
+
if (defined(invoker.configs)) {
configs += invoker.configs
}
@@ -59,8 +75,6 @@
configs += [ "//build/config/compiler:no_chromium_code" ]
}
- testonly = true
-
if (!defined(invoker.deps)) {
deps = []
}
@@ -69,3 +83,65 @@
}
}
}
+
+###############################################################################
+# Fuzzers - only built when tint_has_fuzzers is enabled
+###############################################################################
+if (tint_has_fuzzers) {
+ import("//testing/libfuzzer/fuzzer_test.gni")
+ fuzzer_corpus_wgsl_dir = "${root_gen_dir}/fuzzers/wgsl_corpus"
+ fuzzer_corpus_wgsl_stamp = "${fuzzer_corpus_wgsl_dir}.stamp"
+
+ template("tint_fuzz_source_set") {
+ source_set(target_name) {
+ forward_variables_from(invoker, "*", [ "configs" ])
+
+ testonly = true
+
+ if (!defined(invoker.deps)) {
+ deps = []
+ }
+
+ if (defined(invoker.configs)) {
+ configs += invoker.configs
+ }
+
+ configs += [ "${tint_src_dir}:tint_common_config" ]
+
+ if (build_with_chromium) {
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
+ }
+
+ if (!defined(invoker.public_configs)) {
+ public_configs = []
+ }
+
+ public_configs += [ "${tint_src_dir}:tint_public_config" ]
+ }
+ }
+
+ template("tint_fuzzer_test") {
+ fuzzer_test(target_name) {
+ forward_variables_from(invoker, "*")
+ exclude_main = false
+
+ if (target_name == "wgsl") {
+ dict = "dictionary.txt"
+ libfuzzer_options = [
+ "only_ascii=1", # TODO(bclayton): Remove this to fuzz unicode?
+ "max_len=10000",
+ ]
+ seed_corpus = fuzzer_corpus_wgsl_dir
+ seed_corpus_deps = [ "${tint_src_dir}:tint_generate_wgsl_corpus" ]
+ } else {
+ assert(false, "unsupported tint fuzzer target")
+ }
+ }
+ }
+} else {
+ template("tint_fuzz_source_set") {
+ }
+ template("tint_fuzzer_test") {
+ }
+}
diff --git a/src/tint/utils/cli/BUILD.gn b/src/tint/utils/cli/BUILD.gn
index 2306667..495eb17 100644
--- a/src/tint/utils/cli/BUILD.gn
+++ b/src/tint/utils/cli/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -50,7 +50,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "cli_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/command/BUILD.gn b/src/tint/utils/command/BUILD.gn
index c9b9d86..57bd6e6 100644
--- a/src/tint/utils/command/BUILD.gn
+++ b/src/tint/utils/command/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -50,7 +50,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "command_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/containers/BUILD.gn b/src/tint/utils/containers/BUILD.gn
index b7cbe13..4c79c02 100644
--- a/src/tint/utils/containers/BUILD.gn
+++ b/src/tint/utils/containers/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -58,7 +58,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"bitset_test.cc",
"enum_set_test.cc",
diff --git a/src/tint/utils/containers/hashmap_base.h b/src/tint/utils/containers/hashmap_base.h
index e1ea31e..403dd22 100644
--- a/src/tint/utils/containers/hashmap_base.h
+++ b/src/tint/utils/containers/hashmap_base.h
@@ -228,7 +228,7 @@
if (current == end) {
return *this;
}
- current++;
+ ++current;
SkipToNextValue();
return *this;
}
@@ -261,9 +261,11 @@
using SLOT = std::conditional_t<IS_CONST, const Slot, Slot>;
- IteratorT(SLOT* c, SLOT* e, [[maybe_unused]] const HashmapBase& m)
- : current(c),
- end(e)
+ IteratorT(VectorIterator<SLOT> c,
+ VectorIterator<SLOT> e,
+ [[maybe_unused]] const HashmapBase& m)
+ : current(std::move(c)),
+ end(std::move(e))
#ifdef TINT_ASSERT_ITERATORS_NOT_INVALIDATED
,
map(m),
@@ -276,12 +278,12 @@
/// Moves the iterator forward, stopping at the next slot that is not empty.
void SkipToNextValue() {
while (current != end && !current->entry.has_value()) {
- current++;
+ ++current;
}
}
- SLOT* current; /// The slot the iterator is pointing to
- SLOT* end; /// One past the last slot in the map
+ VectorIterator<SLOT> current; /// The slot the iterator is pointing to
+ VectorIterator<SLOT> end; /// One past the last slot in the map
#ifdef TINT_ASSERT_ITERATORS_NOT_INVALIDATED
const HashmapBase& map; /// The hashmap that is being iterated over.
diff --git a/src/tint/utils/containers/vector.h b/src/tint/utils/containers/vector.h
index 8ba1677..9320346 100644
--- a/src/tint/utils/containers/vector.h
+++ b/src/tint/utils/containers/vector.h
@@ -18,6 +18,7 @@
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
+#include <atomic>
#include <iterator>
#include <new>
#include <utility>
@@ -29,6 +30,20 @@
#include "src/tint/utils/math/hash.h"
#include "src/tint/utils/memory/bitcast.h"
+#ifndef TINT_VECTOR_MUTATION_CHECKS_ENABLED
+#ifdef NDEBUG
+#define TINT_VECTOR_MUTATION_CHECKS_ENABLED 0
+#else
+#define TINT_VECTOR_MUTATION_CHECKS_ENABLED 1
+#endif
+#endif
+
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+#define TINT_VECTOR_MUTATION_CHECK_ASSERT(x) TINT_ASSERT(x)
+#else
+#define TINT_VECTOR_MUTATION_CHECK_ASSERT(x)
+#endif
+
/// Forward declarations
namespace tint {
template <typename>
@@ -37,6 +52,228 @@
namespace tint {
+/// VectorIterator is a forward iterator of Vector elements.
+template <typename T, bool FORWARD = true>
+class VectorIterator {
+ public:
+ /// The iterator trait
+ using iterator_category = std::random_access_iterator_tag;
+ /// The type of an element that this iterator points to
+ using value_type = T;
+ /// The type of the difference of two iterators
+ using difference_type = std::ptrdiff_t;
+ /// A pointer of the element type
+ using pointer = T*;
+ /// A reference of the element type
+ using reference = T&;
+
+ /// Constructor
+ VectorIterator() = default;
+
+ /// Destructor
+ ~VectorIterator() {
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ if (iterator_count_) {
+ TINT_ASSERT(*iterator_count_ > 0);
+ (*iterator_count_)--;
+ }
+#endif
+ }
+
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ /// Constructor
+ /// @param p the pointer to the vector element
+ /// @param it_cnt a pointer to an iterator count
+ VectorIterator(T* p, std::atomic<uint32_t>* it_cnt) : ptr_(p), iterator_count_(it_cnt) {
+ (*iterator_count_)++;
+ }
+
+ /// Copy constructor
+ /// @param other the VectorIterator to copy
+ VectorIterator(const VectorIterator& other)
+ : ptr_(other.ptr_), iterator_count_(other.iterator_count_) {
+ if (iterator_count_) {
+ (*iterator_count_)++;
+ }
+ }
+
+ /// Move constructor
+ /// @param other the VectorIterator to move
+ VectorIterator(VectorIterator&& other)
+ : ptr_(other.ptr_), iterator_count_(other.iterator_count_) {
+ other.ptr_ = nullptr;
+ other.iterator_count_ = nullptr;
+ }
+#else
+ /// Constructor
+ /// @param p the pointer to the vector element
+ explicit VectorIterator(T* p) : ptr_(p) {}
+
+ /// Copy constructor
+ /// @param other the VectorIterator to copy
+ VectorIterator(const VectorIterator& other) : ptr_(other.ptr_) {}
+
+ /// Move constructor
+ /// @param other the VectorIterator to move
+ VectorIterator(VectorIterator&& other) : ptr_(other.ptr_) { other.ptr_ = nullptr; }
+#endif
+
+ /// Assignment operator
+ /// @param other the VectorIterator to copy
+ /// @return this VectorIterator
+ VectorIterator& operator=(const VectorIterator& other) {
+ ptr_ = other.ptr_;
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ if (iterator_count_ != other.iterator_count_) {
+ if (iterator_count_) {
+ (*iterator_count_)--;
+ }
+ iterator_count_ = other.iterator_count_;
+ if (iterator_count_) {
+ (*iterator_count_)++;
+ }
+ }
+#endif
+ return *this;
+ }
+
+ /// Move-assignment operator
+ /// @param other the VectorIterator to move
+ /// @return this VectorIterator
+ VectorIterator& operator=(VectorIterator&& other) {
+ ptr_ = other.ptr_;
+ other.ptr_ = nullptr;
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ if (iterator_count_) {
+ (*iterator_count_)--;
+ }
+ iterator_count_ = other.iterator_count_;
+ other.iterator_count_ = nullptr;
+#endif
+ return *this;
+ }
+
+ /// @return the element this iterator currently points at
+ operator T*() const { return ptr_; }
+
+ /// @return the element this iterator currently points at
+ T& operator*() const { return *ptr_; }
+
+ /// @return the element this iterator currently points at
+ T* operator->() const { return ptr_; }
+
+ /// Equality operator
+ /// @param other the other VectorIterator
+ /// @return true if this iterator is equal to @p other
+ bool operator==(const VectorIterator& other) const { return ptr_ == other.ptr_; }
+
+ /// Inequality operator
+ /// @param other the other VectorIterator
+ /// @return true if this iterator is not equal to @p other
+ bool operator!=(const VectorIterator& other) const { return ptr_ != other.ptr_; }
+
+ /// Less-than operator
+ /// @param other the other iterator
+ /// @returns true if this iterator comes before @p other
+ bool operator<(const VectorIterator& other) const { return other - *this > 0; }
+
+ /// Greater-than operator
+ /// @param other the other iterator
+ /// @returns true if this iterator comes after @p other
+ bool operator>(const VectorIterator& other) const { return *this - other > 0; }
+
+ /// Index operator
+ /// @param i the number of elements from the element this iterator points to
+ /// @return the element
+ T& operator[](std::ptrdiff_t i) const { return *(*this + i); }
+
+ /// Increments the iterator (prefix)
+ /// @returns this VectorIterator
+ VectorIterator& operator++() {
+ this->ptr_ = FORWARD ? this->ptr_ + 1 : this->ptr_ - 1;
+ return *this;
+ }
+
+ /// Decrements the iterator (prefix)
+ /// @returns this VectorIterator
+ VectorIterator& operator--() {
+ this->ptr_ = FORWARD ? this->ptr_ - 1 : this->ptr_ + 1;
+ return *this;
+ }
+
+ /// Increments the iterator (postfix)
+ /// @returns a VectorIterator that points to the element before the increment
+ VectorIterator operator++(int) {
+ VectorIterator res = *this;
+ this->ptr_ = FORWARD ? this->ptr_ + 1 : this->ptr_ - 1;
+ return res;
+ }
+
+ /// Decrements the iterator (postfix)
+ /// @returns a VectorIterator that points to the element before the decrement
+ VectorIterator operator--(int) {
+ VectorIterator res = *this;
+ this->ptr_ = FORWARD ? this->ptr_ - 1 : this->ptr_ + 1;
+ return res;
+ }
+
+ /// Moves the iterator forward by @p n elements
+ /// @param n the number of elements
+ /// @returns this VectorIterator
+ VectorIterator operator+=(std::ptrdiff_t n) {
+ this->ptr_ = FORWARD ? this->ptr_ + n : this->ptr_ - n;
+ return *this;
+ }
+
+ /// Moves the iterator backwards by @p n elements
+ /// @param n the number of elements
+ /// @returns this VectorIterator
+ VectorIterator operator-=(std::ptrdiff_t n) {
+ this->ptr_ = FORWARD ? this->ptr_ - n : this->ptr_ + n;
+ return *this;
+ }
+
+ /// @param n the number of elements
+ /// @returns a new VectorIterator progressed by @p n elements
+ VectorIterator operator+(std::ptrdiff_t n) const {
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ return VectorIterator{FORWARD ? ptr_ + n : ptr_ - n, iterator_count_};
+#else
+ return VectorIterator{FORWARD ? ptr_ + n : ptr_ - n};
+#endif
+ }
+
+ /// @param n the number of elements
+ /// @returns a new VectorIterator regressed by @p n elements
+ VectorIterator operator-(std::ptrdiff_t n) const {
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ return VectorIterator{FORWARD ? ptr_ - n : ptr_ + n, iterator_count_};
+#else
+ return VectorIterator{FORWARD ? ptr_ - n : ptr_ + n};
+#endif
+ }
+
+ /// @param other the other iterator
+ /// @returns the number of elements between this iterator and @p other
+ std::ptrdiff_t operator-(const VectorIterator& other) const {
+ return FORWARD ? ptr_ - other.ptr_ : other.ptr_ - ptr_;
+ }
+
+ private:
+ T* ptr_ = nullptr;
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ std::atomic<uint32_t>* iterator_count_ = nullptr;
+#endif
+};
+
+/// @param out the stream to write to
+/// @param it the VectorIterator
+/// @returns @p out so calls can be chained
+template <typename STREAM, typename T, bool FORWARD, typename = traits::EnableIfIsOStream<STREAM>>
+auto& operator<<(STREAM& out, const VectorIterator<T, FORWARD>& it) {
+ return out << *it;
+}
+
/// Vector is a small-object-optimized, dynamically-sized vector of contigious elements of type T.
///
/// Vector will fit `N` elements internally before spilling to heap allocations. If `N` is greater
@@ -59,10 +296,14 @@
template <typename T, size_t N>
class Vector {
public:
- /// Alias to `T*`.
- using iterator = T*;
- /// Alias to `const T*`.
- using const_iterator = const T*;
+ /// Alias to the non-const forward iterator
+ using iterator = VectorIterator<T, /* forward */ true>;
+ /// Alias to the const forward iterator
+ using const_iterator = VectorIterator<const T, /* forward */ true>;
+ /// Alias to the non-const reverse iterator
+ using reverse_iterator = VectorIterator<T, /* forward */ false>;
+ /// Alias to the const reverse iterator
+ using const_reverse_iterator = VectorIterator<const T, /* forward */ false>;
/// Alias to `T`.
using value_type = T;
/// Value of `N`
@@ -211,18 +452,12 @@
/// Index operator
/// @param i the element index. Must be less than `len`.
/// @returns a reference to the i'th element.
- T& operator[](size_t i) {
- TINT_ASSERT(i < Length());
- return impl_.slice[i];
- }
+ T& operator[](size_t i) { return impl_.slice[i]; }
/// Index operator
/// @param i the element index. Must be less than `len`.
/// @returns a reference to the i'th element.
- const T& operator[](size_t i) const {
- TINT_ASSERT(i < Length());
- return impl_.slice[i];
- }
+ const T& operator[](size_t i) const { return impl_.slice[i]; }
/// @return the number of elements in the vector
size_t Length() const { return impl_.slice.len; }
@@ -234,6 +469,7 @@
/// Reserves memory to hold at least `new_cap` elements
/// @param new_cap the new vector capacity
void Reserve(size_t new_cap) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
if (new_cap > impl_.slice.cap) {
auto* old_data = impl_.slice.data;
impl_.Allocate(new_cap);
@@ -282,17 +518,17 @@
/// Clears all elements from the vector, keeping the capacity the same.
void Clear() {
- TINT_BEGIN_DISABLE_WARNING(MAYBE_UNINITIALIZED);
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
for (size_t i = 0; i < impl_.slice.len; i++) {
impl_.slice.data[i].~T();
}
impl_.slice.len = 0;
- TINT_END_DISABLE_WARNING(MAYBE_UNINITIALIZED);
}
/// Appends a new element to the vector.
/// @param el the element to copy to the vector.
void Push(const T& el) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
if (impl_.slice.len >= impl_.slice.cap) {
Grow();
}
@@ -302,6 +538,7 @@
/// Appends a new element to the vector.
/// @param el the element to move to the vector.
void Push(T&& el) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
if (impl_.slice.len >= impl_.slice.cap) {
Grow();
}
@@ -312,6 +549,7 @@
/// @param args the arguments to pass to the element constructor.
template <typename... ARGS>
void Emplace(ARGS&&... args) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
if (impl_.slice.len >= impl_.slice.cap) {
Grow();
}
@@ -321,6 +559,7 @@
/// Removes and returns the last element from the vector.
/// @returns the popped element
T Pop() {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
TINT_ASSERT(!IsEmpty());
auto& el = impl_.slice.data[--impl_.slice.len];
auto val = std::move(el);
@@ -333,6 +572,7 @@
/// @param element the element to insert
template <typename EL>
void Insert(size_t before, EL&& element) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
TINT_ASSERT(before <= Length());
size_t n = Length();
Resize(Length() + 1);
@@ -350,6 +590,7 @@
/// @param start the index of the first element to remove
/// @param count the number of elements to remove
void Erase(size_t start, size_t count = 1) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
TINT_ASSERT(start < Length());
TINT_ASSERT((start + count) <= Length());
// Shuffle
@@ -370,6 +611,7 @@
/// should return `true` for elements that should be removed from the vector.
template <typename PREDICATE>
void EraseIf(PREDICATE&& predicate) {
+ TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0);
// Shuffle
size_t num_removed = 0;
for (size_t i = 0; i < impl_.slice.len; i++) {
@@ -444,29 +686,65 @@
/// @returns a reference to the last element in the vector
const T& Back() const { return impl_.slice.Back(); }
- /// @returns a pointer to the first element in the vector
- T* begin() { return impl_.slice.begin(); }
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+ /// @returns a forward iterator to the first element of the vector
+ iterator begin() { return iterator{impl_.slice.begin(), &iterator_count_}; }
- /// @returns a pointer to the first element in the vector
- const T* begin() const { return impl_.slice.begin(); }
+ /// @returns a forward iterator to the first element of the vector
+ const const_iterator begin() const {
+ return const_iterator{impl_.slice.begin(), &iterator_count_};
+ }
- /// @returns a pointer to one past the last element in the vector
- T* end() { return impl_.slice.end(); }
+ /// @returns a forward iterator to one-pass the last element of the vector
+ iterator end() { return iterator{impl_.slice.end(), &iterator_count_}; }
- /// @returns a pointer to one past the last element in the vector
- const T* end() const { return impl_.slice.end(); }
+ /// @returns a forward iterator to one-pass the last element of the vector
+ const const_iterator end() const { return const_iterator{impl_.slice.end(), &iterator_count_}; }
- /// @returns a reverse iterator starting with the last element in the vector
- auto rbegin() { return impl_.slice.rbegin(); }
+ /// @returns a reverse iterator to the last element of the vector
+ reverse_iterator rbegin() { return reverse_iterator{impl_.slice.end(), &iterator_count_} + 1; }
- /// @returns a reverse iterator starting with the last element in the vector
- auto rbegin() const { return impl_.slice.rbegin(); }
+ /// @returns a reverse iterator to the last element of the vector
+ const const_reverse_iterator rbegin() const {
+ return const_reverse_iterator{impl_.slice.end(), &iterator_count_} + 1;
+ }
- /// @returns the end for a reverse iterator
- auto rend() { return impl_.slice.rend(); }
+ /// @returns a reverse iterator to one element before the first element of the vector
+ reverse_iterator rend() { return reverse_iterator{impl_.slice.begin(), &iterator_count_} + 1; }
- /// @returns the end for a reverse iterator
- auto rend() const { return impl_.slice.rend(); }
+ /// @returns a reverse iterator to one element before the first element of the vector
+ const const_reverse_iterator rend() const {
+ return const_reverse_iterator{impl_.slice.begin(), &iterator_count_} + 1;
+ }
+#else
+ /// @returns a forward iterator to the first element of the vector
+ iterator begin() { return iterator{impl_.slice.begin()}; }
+
+ /// @returns a forward iterator to the first element of the vector
+ const const_iterator begin() const { return const_iterator{impl_.slice.begin()}; }
+
+ /// @returns a forward iterator to one-pass the last element of the vector
+ iterator end() { return iterator{impl_.slice.end()}; }
+
+ /// @returns a forward iterator to one-pass the last element of the vector
+ const const_iterator end() const { return const_iterator{impl_.slice.end()}; }
+
+ /// @returns a reverse iterator to the last element of the vector
+ reverse_iterator rbegin() { return reverse_iterator{impl_.slice.end()} + 1; }
+
+ /// @returns a reverse iterator to the last element of the vector
+ const const_reverse_iterator rbegin() const {
+ return const_reverse_iterator{impl_.slice.end()} + 1;
+ }
+
+ /// @returns a reverse iterator to one element before the first element of the vector
+ reverse_iterator rend() { return reverse_iterator{impl_.slice.begin()} + 1; }
+
+ /// @returns a reverse iterator to one element before the first element of the vector
+ const const_reverse_iterator rend() const {
+ return const_reverse_iterator{impl_.slice.begin()} + 1;
+ }
+#endif
/// @returns a hash code for this Vector
size_t HashCode() const {
@@ -626,6 +904,9 @@
/// Either a ImplWithSmallArray or ImplWithoutSmallArray based on N.
std::conditional_t<HasSmallArray, ImplWithSmallArray, ImplWithoutSmallArray> impl_;
+
+ /// The current number of iterators referring to this vector
+ mutable std::atomic<uint32_t> iterator_count_ = 0;
};
namespace detail {
diff --git a/src/tint/utils/containers/vector_test.cc b/src/tint/utils/containers/vector_test.cc
index b276564..d40f2e5 100644
--- a/src/tint/utils/containers/vector_test.cc
+++ b/src/tint/utils/containers/vector_test.cc
@@ -18,8 +18,10 @@
#include <tuple>
#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
#include "src/tint/utils/containers/predicates.h"
+#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/memory/bitcast.h"
#include "src/tint/utils/text/string_stream.h"
@@ -1954,32 +1956,64 @@
Vector<std::string, 3> vec{"front", "mid", "back"};
static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.begin())>>);
static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.end())>>);
- EXPECT_EQ(vec.begin(), &vec[0]);
- EXPECT_EQ(vec.end(), &vec[0] + 3);
+ EXPECT_EQ(&*vec.begin(), &vec[0]);
+ EXPECT_EQ(&*vec.end(), &vec[0] + 3);
+}
+
+TEST(TintVectorTest, RbeginRend_NoSpill) {
+ Vector<std::string, 3> vec{"front", "mid", "back"};
+ static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.rbegin())>>);
+ static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.rend())>>);
+ EXPECT_EQ(&*vec.rbegin(), &vec[0] + 2);
+ EXPECT_EQ(&*vec.rend(), &vec[0] - 1);
}
TEST(TintVectorTest, BeginEnd_WithSpill) {
Vector<std::string, 2> vec{"front", "mid", "back"};
static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.begin())>>);
static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.end())>>);
- EXPECT_EQ(vec.begin(), &vec[0]);
- EXPECT_EQ(vec.end(), &vec[0] + 3);
+ EXPECT_EQ(&*vec.begin(), &vec[0]);
+ EXPECT_EQ(&*vec.end(), &vec[0] + 3);
+}
+
+TEST(TintVectorTest, RbeginRend_WithSpill) {
+ Vector<std::string, 2> vec{"front", "mid", "back"};
+ static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.rbegin())>>);
+ static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec.rend())>>);
+ EXPECT_EQ(&*vec.rbegin(), &vec[0] + 2);
+ EXPECT_EQ(&*vec.rend(), &vec[0] - 1);
}
TEST(TintVectorTest, ConstBeginEnd_NoSpill) {
const Vector<std::string, 3> vec{"front", "mid", "back"};
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.begin())>>);
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.end())>>);
- EXPECT_EQ(vec.begin(), &vec[0]);
- EXPECT_EQ(vec.end(), &vec[0] + 3);
+ EXPECT_EQ(&*vec.begin(), &vec[0]);
+ EXPECT_EQ(&*vec.end(), &vec[0] + 3);
+}
+
+TEST(TintVectorTest, ConstRbeginRend_NoSpill) {
+ const Vector<std::string, 3> vec{"front", "mid", "back"};
+ static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.rbegin())>>);
+ static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.rend())>>);
+ EXPECT_EQ(&*vec.rbegin(), &vec[0] + 2);
+ EXPECT_EQ(&*vec.rend(), &vec[0] - 1);
}
TEST(TintVectorTest, ConstBeginEnd_WithSpill) {
const Vector<std::string, 2> vec{"front", "mid", "back"};
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.begin())>>);
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.end())>>);
- EXPECT_EQ(vec.begin(), &vec[0]);
- EXPECT_EQ(vec.end(), &vec[0] + 3);
+ EXPECT_EQ(&*vec.begin(), &vec[0]);
+ EXPECT_EQ(&*vec.end(), &vec[0] + 3);
+}
+
+TEST(TintVectorTest, ConstRbeginRend_WithSpill) {
+ const Vector<std::string, 2> vec{"front", "mid", "back"};
+ static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.rbegin())>>);
+ static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec.rend())>>);
+ EXPECT_EQ(&*vec.rbegin(), &vec[0] + 2);
+ EXPECT_EQ(&*vec.rend(), &vec[0] - 1);
}
TEST(TintVectorTest, Equality) {
@@ -2059,6 +2093,70 @@
EXPECT_EQ(ss.str(), "[1, 2, 3]");
}
+TEST(TintVectorTest, AssertOOBs) {
+ TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
+ EXPECT_FATAL_FAILURE(
+ {
+ Vector vec{1};
+ [[maybe_unused]] int i = vec[1];
+ },
+ "internal compiler error");
+ TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
+}
+
+#if TINT_VECTOR_MUTATION_CHECKS_ENABLED
+TEST(TintVectorTest, AssertPushWhileIterating) {
+ TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
+ using V = Vector<int, 4>;
+ EXPECT_FATAL_FAILURE(
+ {
+ V vec;
+ vec.Push(1);
+ vec.Push(2);
+ for ([[maybe_unused]] int i : vec) {
+ vec.Push(3);
+ break;
+ }
+ },
+ "internal compiler error");
+ TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
+}
+
+TEST(TintVectorTest, AssertPopWhileIterating) {
+ TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
+ using V = Vector<int, 4>;
+ EXPECT_FATAL_FAILURE(
+ {
+ V vec;
+ vec.Push(1);
+ vec.Push(2);
+ for ([[maybe_unused]] int i : vec) {
+ vec.Pop();
+ break;
+ }
+ },
+ "internal compiler error");
+ TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
+}
+
+TEST(TintVectorTest, AssertClearWhileIterating) {
+ TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
+ using V = Vector<int, 4>;
+ EXPECT_FATAL_FAILURE(
+ {
+ V vec;
+ vec.Push(1);
+ vec.Push(2);
+ for ([[maybe_unused]] int i : vec) {
+ vec.Clear();
+ break;
+ }
+ },
+ "internal compiler error");
+ TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
+}
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// TintVectorRefTest
////////////////////////////////////////////////////////////////////////////////
@@ -2320,8 +2418,15 @@
const VectorRef<std::string> vec_ref(vec);
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec_ref.begin())>>);
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec_ref.end())>>);
- EXPECT_EQ(vec_ref.begin(), &vec[0]);
- EXPECT_EQ(vec_ref.end(), &vec[0] + 3);
+ EXPECT_EQ(&*vec_ref.begin(), &vec[0]);
+ EXPECT_EQ(&*vec_ref.end(), &vec[0] + 3);
+}
+
+TEST(TintVectorRefTest, RbeginRend) {
+ Vector<std::string, 3> vec{"front", "mid", "back"};
+ const VectorRef<std::string> vec_ref(vec);
+ EXPECT_EQ(&*vec_ref.rbegin(), &vec[0] + 2);
+ EXPECT_EQ(&*vec_ref.rend(), &vec[0] - 1);
}
TEST(TintVectorRefTest, ostream) {
@@ -2332,6 +2437,16 @@
EXPECT_EQ(ss.str(), "[1, 2, 3]");
}
+TEST(TintVectorRefTest, AssertOOBs) {
+ EXPECT_FATAL_FAILURE(
+ {
+ Vector vec{1};
+ const VectorRef<int> vec_ref(vec);
+ [[maybe_unused]] int i = vec_ref[1];
+ },
+ "internal compiler error");
+}
+
} // namespace
} // namespace tint
diff --git a/src/tint/utils/diagnostic/BUILD.gn b/src/tint/utils/diagnostic/BUILD.gn
index 90735ad..de2eeb3 100644
--- a/src/tint/utils/diagnostic/BUILD.gn
+++ b/src/tint/utils/diagnostic/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -65,7 +65,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"diagnostic_test.cc",
"formatter_test.cc",
diff --git a/src/tint/utils/diagnostic/diagnostic.h b/src/tint/utils/diagnostic/diagnostic.h
index 1b40cae..fac58ac 100644
--- a/src/tint/utils/diagnostic/diagnostic.h
+++ b/src/tint/utils/diagnostic/diagnostic.h
@@ -89,8 +89,8 @@
/// List is a container of Diagnostic messages.
class List {
public:
- /// iterator is the type used for range based iteration.
- using iterator = const Diagnostic*;
+ /// The iterator type for this List
+ using iterator = VectorIterator<const Diagnostic>;
/// Constructs the list with no elements.
List();
diff --git a/src/tint/utils/diagnostic/source.cc b/src/tint/utils/diagnostic/source.cc
index f223d62..0ea43bb 100644
--- a/src/tint/utils/diagnostic/source.cc
+++ b/src/tint/utils/diagnostic/source.cc
@@ -113,7 +113,7 @@
} // namespace
-Source::FileContent::FileContent(const std::string& body) : data(body), lines(SplitLines(data)) {}
+Source::FileContent::FileContent(std::string_view body) : data(body), lines(SplitLines(data)) {}
Source::FileContent::FileContent(const FileContent& rhs)
: data(rhs.data), lines(CopyRelativeStringViews(rhs.lines, rhs.data, data)) {}
diff --git a/src/tint/utils/diagnostic/source.h b/src/tint/utils/diagnostic/source.h
index ac3497c..6795dca 100644
--- a/src/tint/utils/diagnostic/source.h
+++ b/src/tint/utils/diagnostic/source.h
@@ -34,7 +34,7 @@
public:
/// Constructs the FileContent with the given file content.
/// @param data the file contents
- explicit FileContent(const std::string& data);
+ explicit FileContent(std::string_view data);
/// Copy constructor
/// @param rhs the FileContent to copy
@@ -55,7 +55,7 @@
/// Constructs the File with the given file path and content.
/// @param p the path for this file
/// @param c the file contents
- inline File(const std::string& p, const std::string& c) : path(p), content(c) {}
+ inline File(const std::string& p, std::string_view c) : path(p), content(c) {}
/// Copy constructor
File(const File&) = default;
diff --git a/src/tint/utils/file/BUILD.gn b/src/tint/utils/file/BUILD.gn
index cfca680..a7267e8 100644
--- a/src/tint/utils/file/BUILD.gn
+++ b/src/tint/utils/file/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -51,7 +51,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "tmpfile_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/ice/BUILD.gn b/src/tint/utils/ice/BUILD.gn
index d151d2f..e7f69a0 100644
--- a/src/tint/utils/ice/BUILD.gn
+++ b/src/tint/utils/ice/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -41,7 +41,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "ice_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/macros/BUILD.bazel b/src/tint/utils/macros/BUILD.bazel
index e3a081b..57ac024 100644
--- a/src/tint/utils/macros/BUILD.bazel
+++ b/src/tint/utils/macros/BUILD.bazel
@@ -34,6 +34,7 @@
"defer.h",
"foreach.h",
"scoped_assignment.h",
+ "static_init.h",
],
deps = [
],
@@ -46,6 +47,7 @@
srcs = [
"defer_test.cc",
"scoped_assignment_test.cc",
+ "static_init_test.cc",
],
deps = [
"//src/tint/utils/macros",
diff --git a/src/tint/utils/macros/BUILD.cmake b/src/tint/utils/macros/BUILD.cmake
index 39242f1..175c753 100644
--- a/src/tint/utils/macros/BUILD.cmake
+++ b/src/tint/utils/macros/BUILD.cmake
@@ -32,6 +32,7 @@
utils/macros/foreach.h
utils/macros/macros.cc
utils/macros/scoped_assignment.h
+ utils/macros/static_init.h
)
################################################################################
@@ -41,6 +42,7 @@
tint_add_target(tint_utils_macros_test test
utils/macros/defer_test.cc
utils/macros/scoped_assignment_test.cc
+ utils/macros/static_init_test.cc
)
tint_target_add_dependencies(tint_utils_macros_test test
diff --git a/src/tint/utils/macros/BUILD.gn b/src/tint/utils/macros/BUILD.gn
index 7b85feb..75705d3 100644
--- a/src/tint/utils/macros/BUILD.gn
+++ b/src/tint/utils/macros/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -37,15 +37,16 @@
"foreach.h",
"macros.cc",
"scoped_assignment.h",
+ "static_init.h",
]
deps = []
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"defer_test.cc",
"scoped_assignment_test.cc",
+ "static_init_test.cc",
]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/macros/scoped_assignment.h b/src/tint/utils/macros/scoped_assignment.h
index 9d4e98b..af3a25b 100644
--- a/src/tint/utils/macros/scoped_assignment.h
+++ b/src/tint/utils/macros/scoped_assignment.h
@@ -1,4 +1,3 @@
-
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/src/tint/utils/macros/static_init.h b/src/tint/utils/macros/static_init.h
new file mode 100644
index 0000000..e1b69fb
--- /dev/null
+++ b/src/tint/utils/macros/static_init.h
@@ -0,0 +1,31 @@
+// 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_UTILS_MACROS_STATIC_INIT_H_
+#define SRC_TINT_UTILS_MACROS_STATIC_INIT_H_
+
+#include "src/tint/utils/macros/concat.h"
+
+/// A helper macro that executes STATEMENT the first time the macro comes into scope - typically
+/// used at global scope to call a function before main() is run.
+/// For example: `TINT_STATIC_INIT(CallAtStartup(1,2,3));`
+/// @note: This must not be used at global scope in production code, as this violates the Chromium
+/// rules around static initializers. Attempting to do this will result in a compilation error.
+#define TINT_STATIC_INIT(STATEMENT) \
+ [[maybe_unused]] static const bool TINT_CONCAT(tint_static_init_, __COUNTER__) = [] { \
+ STATEMENT; \
+ return true; \
+ }()
+
+#endif // SRC_TINT_UTILS_MACROS_STATIC_INIT_H_
diff --git a/src/tint/cmd/bench/benchmark.cc b/src/tint/utils/macros/static_init_test.cc
similarity index 65%
copy from src/tint/cmd/bench/benchmark.cc
copy to src/tint/utils/macros/static_init_test.cc
index ad8658b..2f71a78 100644
--- a/src/tint/cmd/bench/benchmark.cc
+++ b/src/tint/utils/macros/static_init_test.cc
@@ -12,9 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
-#endif
+#include "src/tint/utils/macros/static_init.h"
-// A placeholder symbol used to emit a symbol for this lib target.
-int tint_cmd_bench_symbol = 1;
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace {
+
+int global_var = 0;
+
+void SetGlobalVar(int i) {
+ global_var = i;
+}
+
+TINT_STATIC_INIT(SetGlobalVar(42));
+
+TEST(TestStaticInit, Global) {
+ EXPECT_EQ(global_var, 42);
+}
+
+} // namespace
+} // namespace tint
diff --git a/src/tint/utils/math/BUILD.gn b/src/tint/utils/math/BUILD.gn
index 2498c65..594f07d 100644
--- a/src/tint/utils/math/BUILD.gn
+++ b/src/tint/utils/math/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -40,7 +40,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"crc32_test.cc",
"hash_test.cc",
diff --git a/src/tint/utils/memory/BUILD.bazel b/src/tint/utils/memory/BUILD.bazel
index e419f7b..2d91e3c 100644
--- a/src/tint/utils/memory/BUILD.bazel
+++ b/src/tint/utils/memory/BUILD.bazel
@@ -34,6 +34,7 @@
"bump_allocator.h",
],
deps = [
+ "//src/tint/utils/macros",
"//src/tint/utils/math",
],
copts = COPTS,
@@ -48,6 +49,7 @@
"bump_allocator_test.cc",
],
deps = [
+ "//src/tint/utils/macros",
"//src/tint/utils/math",
"//src/tint/utils/memory",
"@gtest",
diff --git a/src/tint/utils/memory/BUILD.cmake b/src/tint/utils/memory/BUILD.cmake
index a29c41c..1b07cd1 100644
--- a/src/tint/utils/memory/BUILD.cmake
+++ b/src/tint/utils/memory/BUILD.cmake
@@ -33,6 +33,7 @@
)
tint_target_add_dependencies(tint_utils_memory lib
+ tint_utils_macros
tint_utils_math
)
@@ -47,6 +48,7 @@
)
tint_target_add_dependencies(tint_utils_memory_test test
+ tint_utils_macros
tint_utils_math
tint_utils_memory
)
diff --git a/src/tint/utils/memory/BUILD.gn b/src/tint/utils/memory/BUILD.gn
index 36728c7..79a3a1c 100644
--- a/src/tint/utils/memory/BUILD.gn
+++ b/src/tint/utils/memory/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -36,11 +36,13 @@
"bump_allocator.h",
"memory.cc",
]
- deps = [ "${tint_src_dir}/utils/math" ]
+ deps = [
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ ]
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"bitcast_test.cc",
"block_allocator_test.cc",
@@ -48,6 +50,7 @@
]
deps = [
"${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/utils/macros",
"${tint_src_dir}/utils/math",
"${tint_src_dir}/utils/memory",
]
diff --git a/src/tint/utils/memory/block_allocator.h b/src/tint/utils/memory/block_allocator.h
index 2ee1296..978950a 100644
--- a/src/tint/utils/memory/block_allocator.h
+++ b/src/tint/utils/memory/block_allocator.h
@@ -40,6 +40,7 @@
std::array<T*, kMax> ptrs;
Pointers* next;
Pointers* prev;
+ size_t count;
};
/// Block is linked list of memory blocks.
@@ -48,7 +49,7 @@
/// Note: We're not using std::aligned_storage here as this warns / errors on MSVC.
struct alignas(BLOCK_ALIGNMENT) Block {
uint8_t data[BLOCK_SIZE];
- Block* next;
+ Block* next = nullptr;
};
// Forward declaration
@@ -56,7 +57,7 @@
class TView;
/// An iterator for the objects owned by the BlockAllocator.
- template <bool IS_CONST, bool FORWARD>
+ template <bool IS_CONST>
class TIterator {
using PointerTy = std::conditional_t<IS_CONST, const T*, T*>;
@@ -76,10 +77,12 @@
/// Progress the iterator forward one element
/// @returns this iterator
TIterator& operator++() {
- if (FORWARD) {
- ProgressForward();
- } else {
- ProgressBackwards();
+ if (ptrs != nullptr) {
+ ++idx;
+ if (idx >= ptrs->count) {
+ idx = 0;
+ ptrs = ptrs->next;
+ }
}
return *this;
}
@@ -87,44 +90,27 @@
/// Progress the iterator backwards one element
/// @returns this iterator
TIterator& operator--() {
- if (FORWARD) {
- ProgressBackwards();
- } else {
- ProgressForward();
+ if (ptrs != nullptr) {
+ if (idx == 0) {
+ ptrs = ptrs->prev;
+ idx = ptrs->count - 1;
+ }
+ --idx;
}
return *this;
}
/// @returns the pointer to the object at the current iterator position
- PointerTy operator*() const { return ptrs ? ptrs->ptrs[idx] : nullptr; }
+ PointerTy operator*() const { return ptrs->ptrs[idx]; }
private:
friend TView<IS_CONST>; // Keep internal iterator impl private.
explicit TIterator(const Pointers* p, size_t i) : ptrs(p), idx(i) {}
- /// Progresses the iterator forwards
- void ProgressForward() {
- if (ptrs != nullptr) {
- ++idx;
- if (idx == Pointers::kMax) {
- idx = 0;
- ptrs = ptrs->next;
- }
- }
- }
- /// Progresses the iterator backwards
- void ProgressBackwards() {
- if (ptrs != nullptr) {
- if (idx == 0) {
- idx = Pointers::kMax - 1;
- ptrs = ptrs->prev;
- }
- --idx;
- }
- }
-
- const Pointers* ptrs;
- size_t idx;
+ /// The current Pointers
+ const Pointers* ptrs = nullptr;
+ /// The current index within #ptrs
+ size_t idx = 0;
};
/// View provides begin() and end() methods for looping over the objects owned by the
@@ -133,26 +119,12 @@
class TView {
public:
/// @returns an iterator to the beginning of the view
- TIterator<IS_CONST, true> begin() const {
- return TIterator<IS_CONST, true>{allocator_->data.pointers.root, 0};
+ TIterator<IS_CONST> begin() const {
+ return TIterator<IS_CONST>{allocator_->data.pointers.root, 0};
}
/// @returns an iterator to the end of the view
- TIterator<IS_CONST, true> end() const {
- return allocator_->data.pointers.current_index >= Pointers::kMax
- ? TIterator<IS_CONST, true>{nullptr, 0}
- : TIterator<IS_CONST, true>{allocator_->data.pointers.current,
- allocator_->data.pointers.current_index};
- }
-
- /// @returns an iterator to the beginning of the view
- TIterator<IS_CONST, false> rbegin() const { return TIterator<IS_CONST, false>{nullptr, 0}; }
-
- /// @returns an iterator to the end of the view
- TIterator<IS_CONST, false> rend() const {
- return TIterator<IS_CONST, false>{allocator_->data.pointers.current,
- allocator_->data.pointers.current_index};
- }
+ TIterator<IS_CONST> end() const { return TIterator<IS_CONST>{nullptr, 0}; }
private:
friend BlockAllocator; // For BlockAllocator::operator View()
@@ -162,16 +134,10 @@
public:
/// A forward-iterator type over the objects of the BlockAllocator
- using Iterator = TIterator</* const */ false, /* forward */ true>;
+ using Iterator = TIterator</* const */ false>;
/// An immutable forward-iterator type over the objects of the BlockAllocator
- using ConstIterator = TIterator</* const */ true, /* forward */ true>;
-
- /// A reverse-iterator type over the objects of the BlockAllocator
- using ReverseIterator = TIterator</* const */ false, /* forward */ false>;
-
- /// An immutable reverse-iterator type over the objects of the BlockAllocator
- using ReverseConstIterator = TIterator</* const */ true, /* forward */ false>;
+ using ConstIterator = TIterator</* const */ true>;
/// View provides begin() and end() methods for looping over the objects owned by the
/// BlockAllocator.
@@ -287,7 +253,7 @@
void AddObjectPointer(T* ptr) {
auto& pointers = data.pointers;
- if (pointers.current_index >= Pointers::kMax) {
+ if (!pointers.current || pointers.current->count == Pointers::kMax) {
auto* prev_pointers = pointers.current;
pointers.current = Allocate<Pointers>();
if (!pointers.current) {
@@ -295,7 +261,7 @@
}
pointers.current->next = nullptr;
pointers.current->prev = prev_pointers;
- pointers.current_index = 0;
+ pointers.current->count = 0;
if (prev_pointers) {
prev_pointers->next = pointers.current;
@@ -304,7 +270,7 @@
}
}
- pointers.current->ptrs[pointers.current_index++] = ptr;
+ pointers.current->ptrs[pointers.current->count++] = ptr;
}
struct {
@@ -326,10 +292,6 @@
/// The current (end) Pointers structure of the pointers linked list.
/// AddObjectPointer() adds to this structure.
Pointers* current = nullptr;
- /// The array index in #current for the next append.
- /// Initialized with Pointers::kMax so that the first append triggers a allocation of
- /// the Pointers structure.
- size_t current_index = Pointers::kMax;
} pointers;
size_t count = 0;
diff --git a/src/tint/utils/memory/block_allocator_test.cc b/src/tint/utils/memory/block_allocator_test.cc
index d6da564..821e150 100644
--- a/src/tint/utils/memory/block_allocator_test.cc
+++ b/src/tint/utils/memory/block_allocator_test.cc
@@ -14,6 +14,8 @@
#include "src/tint/utils/memory/block_allocator.h"
+#include <vector>
+
#include "gtest/gtest.h"
namespace tint {
@@ -160,5 +162,30 @@
}
}
+TEST_F(BlockAllocatorTest, AddWhileIterating) {
+ using Allocator = BlockAllocator<size_t>;
+
+ Allocator allocator;
+ for (int i = 0; i < 20; i++) {
+ allocator.Create(allocator.Count());
+
+ std::vector<size_t*> seen;
+ for (auto* j : allocator.Objects()) {
+ if (*j % 3 == 0) {
+ allocator.Create(allocator.Count());
+ }
+ seen.push_back(j);
+ }
+
+ // Check that iteration-while-adding saw the same list of objects as an
+ // iteration-without-adding.
+ size_t n = 0;
+ for (auto* obj : allocator.Objects()) {
+ ASSERT_TRUE(n < seen.size());
+ EXPECT_EQ(seen[n++], obj);
+ }
+ }
+}
+
} // namespace
} // namespace tint
diff --git a/src/tint/utils/memory/bump_allocator.h b/src/tint/utils/memory/bump_allocator.h
index 5d4f594..c1df71a 100644
--- a/src/tint/utils/memory/bump_allocator.h
+++ b/src/tint/utils/memory/bump_allocator.h
@@ -15,10 +15,12 @@
#ifndef SRC_TINT_UTILS_MEMORY_BUMP_ALLOCATOR_H_
#define SRC_TINT_UTILS_MEMORY_BUMP_ALLOCATOR_H_
+#include <algorithm>
#include <array>
#include <cstring>
#include <utility>
+#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/math/math.h"
#include "src/tint/utils/memory/bitcast.h"
@@ -27,16 +29,17 @@
/// A allocator for chunks of memory. The memory is owned by the BumpAllocator. When the
/// BumpAllocator is freed all of the allocated memory is freed.
class BumpAllocator {
- static constexpr size_t kBlockSize = 64 * 1024;
-
- /// Block is linked list of memory blocks.
+ /// BlockHeader is linked list of memory blocks.
/// Blocks are allocated out of heap memory.
- struct Block {
- uint8_t data[kBlockSize];
- Block* next;
+ struct BlockHeader {
+ BlockHeader* next;
};
public:
+ /// The default size for a block's data. Allocations can be greater than this, but smaller
+ /// allocations will use this size.
+ static constexpr size_t kDefaultBlockDataSize = 64 * 1024;
+
/// Constructor
BumpAllocator() = default;
@@ -61,38 +64,42 @@
/// Allocates @p size_in_bytes from the current block, or from a newly allocated block if the
/// current block is full.
/// @param size_in_bytes the number of bytes to allocate
- /// @returns the pointer to the allocated memory or |nullptr| if the memory can not be allocated
- char* Allocate(size_t size_in_bytes) {
- auto& block = data.block;
- if (block.current_offset + size_in_bytes > kBlockSize) {
+ /// @returns the pointer to the allocated memory or `nullptr` if the memory can not be allocated
+ uint8_t* Allocate(size_t size_in_bytes) {
+ if (TINT_UNLIKELY(data.current_offset + size_in_bytes < size_in_bytes)) {
+ return nullptr; // integer overflow
+ }
+ if (data.current_offset + size_in_bytes > data.current_data_size) {
// Allocate a new block from the heap
- auto* prev_block = block.current;
- block.current = new Block;
- if (!block.current) {
+ auto* prev_block = data.current;
+ data.current_data_size = std::max(size_in_bytes, kDefaultBlockDataSize);
+ data.current =
+ Bitcast<BlockHeader*>(new uint8_t[sizeof(BlockHeader) + data.current_data_size]);
+ if (!data.current) {
return nullptr; // out of memory
}
- block.current->next = nullptr;
- block.current_offset = 0;
+ data.current->next = nullptr;
+ data.current_offset = 0;
if (prev_block) {
- prev_block->next = block.current;
+ prev_block->next = data.current;
} else {
- block.root = block.current;
+ data.root = data.current;
}
}
- auto* base = &block.current->data[0];
- auto* ptr = reinterpret_cast<char*>(base + block.current_offset);
- block.current_offset += size_in_bytes;
+ auto* base = Bitcast<uint8_t*>(data.current) + sizeof(BlockHeader);
+ auto* ptr = base + data.current_offset;
+ data.current_offset += size_in_bytes;
data.count++;
return ptr;
}
/// Frees all allocations from the allocator.
void Reset() {
- auto* block = data.block.root;
+ auto* block = data.root;
while (block != nullptr) {
auto* next = block->next;
- delete block;
+ delete[] Bitcast<uint8_t*>(block);
block = next;
}
data = {};
@@ -106,18 +113,16 @@
BumpAllocator& operator=(const BumpAllocator&) = delete;
struct {
- struct {
- /// The root block of the block linked list
- Block* root = nullptr;
- /// The current (end) block of the blocked linked list.
- /// New allocations come from this block
- Block* current = nullptr;
- /// The byte offset in #current for the next allocation.
- /// Initialized with kBlockSize so that the first allocation triggers a block
- /// allocation.
- size_t current_offset = kBlockSize;
- } block;
-
+ /// The root block of the block linked list
+ BlockHeader* root = nullptr;
+ /// The current (end) block of the blocked linked list.
+ /// New allocations come from this block
+ BlockHeader* current = nullptr;
+ /// The byte offset in #current for the next allocation.
+ size_t current_offset = 0;
+ /// The size of the #current, excluding the header size
+ size_t current_data_size = 0;
+ /// Total number of allocations
size_t count = 0;
} data;
};
diff --git a/src/tint/utils/memory/bump_allocator_test.cc b/src/tint/utils/memory/bump_allocator_test.cc
index 4241699..31f3809 100644
--- a/src/tint/utils/memory/bump_allocator_test.cc
+++ b/src/tint/utils/memory/bump_allocator_test.cc
@@ -21,6 +21,29 @@
using BumpAllocatorTest = testing::Test;
+TEST_F(BumpAllocatorTest, AllocationSizes) {
+ BumpAllocator allocator;
+ for (size_t n : {1u, 0x10u, 0x100u, 0x1000u, 0x10000u, 0x100000u, //
+ 2u, 0x34u, 0x567u, 0x8912u, 0x34567u, 0x891234u}) {
+ auto ptr = allocator.Allocate(n);
+ memset(ptr, 0x42, n);
+ }
+}
+
+TEST_F(BumpAllocatorTest, AllocationSizesAroundBlockSize) {
+ for (size_t n : {
+ BumpAllocator::kDefaultBlockDataSize - sizeof(void*),
+ BumpAllocator::kDefaultBlockDataSize - 4,
+ BumpAllocator::kDefaultBlockDataSize,
+ BumpAllocator::kDefaultBlockDataSize + 4,
+ BumpAllocator::kDefaultBlockDataSize + sizeof(void*),
+ }) {
+ BumpAllocator allocator;
+ auto ptr = allocator.Allocate(n);
+ memset(ptr, 0x42, n);
+ }
+}
+
TEST_F(BumpAllocatorTest, Count) {
for (size_t n : {0u, 1u, 10u, 16u, 20u, 32u, 50u, 64u, 100u, 256u, 300u, 512u, 500u, 512u}) {
BumpAllocator allocator;
diff --git a/src/tint/utils/reflection/BUILD.gn b/src/tint/utils/reflection/BUILD.gn
index 86c94c2..4be79b1 100644
--- a/src/tint/utils/reflection/BUILD.gn
+++ b/src/tint/utils/reflection/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -38,7 +38,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "reflection_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/result/BUILD.gn b/src/tint/utils/result/BUILD.gn
index f607347..27838cc 100644
--- a/src/tint/utils/result/BUILD.gn
+++ b/src/tint/utils/result/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -48,7 +48,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "result_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/rtti/BUILD.bazel b/src/tint/utils/rtti/BUILD.bazel
index e724929..893a78a 100644
--- a/src/tint/utils/rtti/BUILD.bazel
+++ b/src/tint/utils/rtti/BUILD.bazel
@@ -61,6 +61,7 @@
)
cc_library(
name = "bench",
+ alwayslink = True,
srcs = [
"switch_bench.cc",
],
@@ -70,6 +71,7 @@
"//src/tint/utils/memory",
"//src/tint/utils/rtti",
"//src/tint/utils/traits",
+ "@benchmark",
],
copts = COPTS,
visibility = ["//visibility:public"],
diff --git a/src/tint/utils/rtti/BUILD.cmake b/src/tint/utils/rtti/BUILD.cmake
index 9b256ff..c06aae6 100644
--- a/src/tint/utils/rtti/BUILD.cmake
+++ b/src/tint/utils/rtti/BUILD.cmake
@@ -74,3 +74,7 @@
tint_utils_rtti
tint_utils_traits
)
+
+tint_target_add_external_dependencies(tint_utils_rtti_bench bench
+ "google-benchmark"
+)
diff --git a/src/tint/utils/rtti/BUILD.gn b/src/tint/utils/rtti/BUILD.gn
index cd23285..c54b499 100644
--- a/src/tint/utils/rtti/BUILD.gn
+++ b/src/tint/utils/rtti/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -44,7 +44,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"castable_test.cc",
"switch_test.cc",
@@ -59,3 +58,16 @@
]
}
}
+if (tint_build_benchmarks) {
+ tint_unittests_source_set("bench") {
+ sources = [ "switch_bench.cc" ]
+ deps = [
+ "${tint_src_dir}:google_benchmark",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/traits",
+ ]
+ }
+}
diff --git a/src/tint/utils/strconv/BUILD.gn b/src/tint/utils/strconv/BUILD.gn
index e386dcb..aefde2c 100644
--- a/src/tint/utils/strconv/BUILD.gn
+++ b/src/tint/utils/strconv/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -52,7 +52,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "float_to_string_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/src/tint/utils/symbol/BUILD.gn b/src/tint/utils/symbol/BUILD.gn
index 4eec052..1be7d46 100644
--- a/src/tint/utils/symbol/BUILD.gn
+++ b/src/tint/utils/symbol/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -50,7 +50,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"symbol_table_test.cc",
"symbol_test.cc",
diff --git a/src/tint/utils/symbol/symbol_table.cc b/src/tint/utils/symbol/symbol_table.cc
index f541b6a..2830a41 100644
--- a/src/tint/utils/symbol/symbol_table.cc
+++ b/src/tint/utils/symbol/symbol_table.cc
@@ -37,7 +37,7 @@
}
Symbol SymbolTable::RegisterInternal(std::string_view name) {
- char* name_mem = name_allocator_.Allocate(name.length() + 1);
+ char* name_mem = Bitcast<char*>(name_allocator_.Allocate(name.length() + 1));
if (name_mem == nullptr) {
return Symbol();
}
diff --git a/src/tint/utils/text/BUILD.gn b/src/tint/utils/text/BUILD.gn
index 6c0b1a1..b2df428 100644
--- a/src/tint/utils/text/BUILD.gn
+++ b/src/tint/utils/text/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -50,7 +50,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [
"string_stream_test.cc",
"string_test.cc",
diff --git a/src/tint/utils/traits/BUILD.gn b/src/tint/utils/traits/BUILD.gn
index 215b58e..69f793b 100644
--- a/src/tint/utils/traits/BUILD.gn
+++ b/src/tint/utils/traits/BUILD.gn
@@ -25,7 +25,7 @@
import("${tint_src_dir}/tint.gni")
-if (tint_build_unittests) {
+if (tint_build_unittests || tint_build_benchmarks) {
import("//testing/test.gni")
}
@@ -38,7 +38,6 @@
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
- testonly = true
sources = [ "traits_test.cc" ]
deps = [
"${tint_src_dir}:gmock_and_gtest",
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index e8b1165..5df49a4 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -14,7 +14,7 @@
if (${TINT_BUILD_BENCHMARKS})
set(BENCHMARK_ENABLE_TESTING FALSE CACHE BOOL FALSE FORCE)
- add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/benchmark EXCLUDE_FROM_ALL)
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/google_benchmark/src EXCLUDE_FROM_ALL)
endif()
if (${TINT_BUILD_TESTS} AND NOT TARGET gmock)
diff --git a/third_party/google_benchmark/BUILD.gn b/third_party/google_benchmark/BUILD.gn
new file mode 100644
index 0000000..779cf2a
--- /dev/null
+++ b/third_party/google_benchmark/BUILD.gn
@@ -0,0 +1,91 @@
+# Copyright 2019 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build_overrides/build.gni")
+
+config("benchmark_config") {
+ include_dirs = [ "src/include" ]
+
+ if (!is_component_build) {
+ defines = [ "BENCHMARK_STATIC_DEFINE" ]
+ }
+}
+
+component("google_benchmark") {
+ testonly = true
+
+ public = [
+ "src/include/benchmark/benchmark.h",
+ "src/include/benchmark/export.h",
+ ]
+
+ sources = [
+ "src/src/arraysize.h",
+ "src/src/benchmark.cc",
+ "src/src/benchmark_api_internal.cc",
+ "src/src/benchmark_api_internal.h",
+ "src/src/benchmark_name.cc",
+ "src/src/benchmark_register.cc",
+ "src/src/benchmark_register.h",
+ "src/src/benchmark_runner.cc",
+ "src/src/benchmark_runner.h",
+ "src/src/check.cc",
+ "src/src/check.h",
+ "src/src/colorprint.cc",
+ "src/src/colorprint.h",
+ "src/src/commandlineflags.cc",
+ "src/src/commandlineflags.h",
+ "src/src/complexity.cc",
+ "src/src/complexity.h",
+ "src/src/console_reporter.cc",
+ "src/src/counter.cc",
+ "src/src/counter.h",
+ "src/src/csv_reporter.cc",
+ "src/src/cycleclock.h",
+ "src/src/internal_macros.h",
+ "src/src/json_reporter.cc",
+ "src/src/log.h",
+ "src/src/mutex.h",
+ "src/src/perf_counters.cc",
+ "src/src/perf_counters.h",
+ "src/src/re.h",
+ "src/src/reporter.cc",
+ "src/src/statistics.cc",
+ "src/src/statistics.h",
+ "src/src/string_util.cc",
+ "src/src/string_util.h",
+ "src/src/sysinfo.cc",
+ "src/src/thread_manager.h",
+ "src/src/thread_timer.h",
+ "src/src/timers.cc",
+ "src/src/timers.h",
+ ]
+
+ all_dependent_configs = [ ":benchmark_config" ]
+
+ if (build_with_chromium) {
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
+ }
+
+ if (is_win) {
+ configs -= [ "//build/config/win:nominmax" ]
+ }
+
+ defines = [
+ "benchmark_EXPORTS=1",
+
+ # Tell gtest to always use standard regular expressions.
+ "HAVE_GNU_POSIX_REGEX=0",
+ "HAVE_POSIX_REGEX=0",
+ "HAVE_STD_REGEX=1",
+ ]
+}
+
+component("benchmark_main") {
+ testonly = true
+ sources = [ "src/src/benchmark_main.cc" ]
+ defines = [ "benchmark_EXPORTS=1" ]
+ deps = [ ":google_benchmark" ]
+}
diff --git a/third_party/google_benchmark/README.chromium b/third_party/google_benchmark/README.chromium
new file mode 100644
index 0000000..637538b
--- /dev/null
+++ b/third_party/google_benchmark/README.chromium
@@ -0,0 +1,13 @@
+Name: Google Benchmark
+Short Name: benchmark
+URL: https://github.com/google/benchmark
+Version: efc89f0b524780b1994d5dddd83a92718e5be492
+License: Apache 2.0
+Security Critical: no
+Shipped: no
+
+Description:
+A microbenchmark support library.
+
+Local Additions:
+* gn file for building in chromium