Import Tint changes from Dawn
Changes:
- f55d13b7544c04210550d51ec20d3f6ef81ba835 [ir] Add increment and decrement statements. by dan sinclair <dsinclair@chromium.org>
- 0e6534e44d2c3c77ac409d787d9d5b3d449a2d0a [tint] Make Transform base class by James Price <jrprice@google.com>
- a6d8e8137101746de775c45915b43c5b4730715e [ir][spirv-writer] Implement binary subtract by James Price <jrprice@google.com>
- 9940c7bdccca0826cf27b2a20da5b590200c811a [tint][ir][ToProgram] Stub ToProgram() by Ben Clayton <bclayton@google.com>
- 0df7f8bccd74f2c9fd07e5bc65f08bfabc2f3845 [ir] Update disassembly output. by dan sinclair <dsinclair@chromium.org>
- 11bd8a012faa4a56a272f73109908c2720f2e329 [ir] Fix scope stack for loops. by dan sinclair <dsinclair@chromium.org>
- 055de2744101630570b257d8a1583cabaa986c24 [ir][spirv-writer] Emit vector constants by James Price <jrprice@google.com>
- 2f324c59ffbec46a5c5e3b3f21b7dace177f0907 [ir] Remove list of entry points from module by James Price <jrprice@google.com>
- f59547fb7f1ca6d7cc3fc357020af02d94d68a8b [ir] Add optional CreateFunction parameters. by dan sinclair <dsinclair@chromium.org>
- 69b5900c88bbc478c2a03d395b42593e833e609c [ir] Use the branch helper in the spirv tests. by dan sinclair <dsinclair@chromium.org>
- 34c794e2e9476bd5338bc1ba548d7dc3dc59352b [tint][ir] Shuffle and refactor from_program.cc by Ben Clayton <bclayton@google.com>
- 8d98977a30b7c00ffacad47322a1ba0f896b3ad8 [tint][ir] Make the ir::BuilderImpl PIMPL by Ben Clayton <bclayton@google.com>
- c9dd75a0e9cd6597539c8b2d06a73636905ab266 clang-format by Ben Clayton <bclayton@google.com>
- c9923d2ee3bc5ae541052176320e30aa3d8d6d43 [ir] Set default flow node values. by dan sinclair <dsinclair@chromium.org>
- 809187c57968e5ee1748fb1b661e46cc9f691093 [ir] Move ir::Builder to hold module reference by dan sinclair <dsinclair@chromium.org>
- 36aa48ce36053a10993f6eae1ad1224b7a912abf [tint][ir] Clean up tests by Ben Clayton <bclayton@google.com>
- 8370ddddc58a6fdc5a3e9f688da909352164351b [ir][spirv-writer] Emit vector types by James Price <jrprice@google.com>
GitOrigin-RevId: f55d13b7544c04210550d51ec20d3f6ef81ba835
Change-Id: Icb27f15ec5162714de7d909637103f195a4b6194
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/133040
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 5d04077..7e85a38 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -356,6 +356,43 @@
libtint_source_set("libtint_transform_src") {
sources = [
+ "transform/transform.cc",
+ "transform/transform.h",
+ ]
+ deps = [
+ ":libtint_program_src",
+ ":libtint_utils_src",
+ ]
+}
+
+libtint_source_set("libtint_ast_transform_base_src") {
+ sources = [
+ "ast/transform/transform.cc",
+ "ast/transform/transform.h",
+ ]
+ public_deps = [ ":libtint_transform_src" ]
+ deps = [
+ ":libtint_builtins_src",
+ ":libtint_program_src",
+ ":libtint_sem_src",
+ ":libtint_type_src",
+ ":libtint_utils_src",
+ ]
+}
+
+libtint_source_set("libtint_transform_manager_src") {
+ sources = [
+ "transform/manager.cc",
+ "transform/manager.h",
+ ]
+ deps = [
+ ":libtint_ast_transform_base_src",
+ ":libtint_program_src",
+ ]
+}
+
+libtint_source_set("libtint_ast_transform_src") {
+ sources = [
"ast/transform/add_block_attribute.cc",
"ast/transform/add_block_attribute.h",
"ast/transform/add_empty_entry_point.cc",
@@ -434,8 +471,6 @@
"ast/transform/substitute_override.h",
"ast/transform/texture_1d_to_2d.cc",
"ast/transform/texture_1d_to_2d.h",
- "ast/transform/transform.cc",
- "ast/transform/transform.h",
"ast/transform/truncate_interstage_variables.cc",
"ast/transform/truncate_interstage_variables.h",
"ast/transform/unshadow.cc",
@@ -456,15 +491,15 @@
"ast/transform/while_to_loop.h",
"ast/transform/zero_init_workgroup_memory.cc",
"ast/transform/zero_init_workgroup_memory.h",
- "transform/manager.cc",
- "transform/manager.h",
]
+ public_deps = [ ":libtint_ast_transform_base_src" ]
deps = [
":libtint_ast_src",
":libtint_builtins_src",
":libtint_program_src",
":libtint_sem_src",
":libtint_symbols_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
]
@@ -860,10 +895,7 @@
"reader/reader.h",
]
- public_deps = [
- ":libtint_program_src",
- ":libtint_transform_src",
- ]
+ public_deps = [ ":libtint_program_src" ]
}
libtint_source_set("libtint_spv_reader_src") {
@@ -892,11 +924,13 @@
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
":libtint_program_src",
":libtint_reader_src",
":libtint_sem_src",
":libtint_symbols_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
"${tint_spirv_tools_dir}/:spvtools_opt",
@@ -932,11 +966,12 @@
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
":libtint_inspector_src",
":libtint_program_src",
":libtint_sem_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
]
@@ -965,12 +1000,13 @@
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
":libtint_constant_src",
":libtint_program_src",
":libtint_sem_src",
":libtint_symbols_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
":libtint_writer_src",
@@ -1044,12 +1080,13 @@
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
":libtint_constant_src",
":libtint_program_src",
":libtint_sem_src",
":libtint_symbols_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
":libtint_writer_src",
@@ -1066,12 +1103,13 @@
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
":libtint_constant_src",
":libtint_program_src",
":libtint_sem_src",
":libtint_symbols_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
":libtint_writer_src",
@@ -1088,12 +1126,13 @@
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
":libtint_constant_src",
":libtint_program_src",
":libtint_sem_src",
":libtint_symbols_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_type_src",
":libtint_utils_src",
":libtint_writer_src",
@@ -1121,10 +1160,10 @@
libtint_source_set("libtint_ir_builder_src") {
sources = [
- "ir/builder_impl.cc",
- "ir/builder_impl.h",
"ir/from_program.cc",
"ir/from_program.h",
+ "ir/to_program.cc",
+ "ir/to_program.h",
]
deps = [
":libtint_ast_src",
@@ -1206,13 +1245,13 @@
source_set("libtint") {
public_deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_constant_src",
":libtint_initializer_src",
":libtint_inspector_src",
":libtint_program_src",
":libtint_sem_src",
":libtint_symbols_src",
- ":libtint_transform_src",
":libtint_type_src",
":libtint_utils_src",
":libtint_writer_src",
@@ -1470,8 +1509,8 @@
]
deps = [
":libtint_ast_src",
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
- ":libtint_transform_src",
":libtint_unittests_ast_helper",
":libtint_utils_src",
]
@@ -1587,8 +1626,8 @@
"resolver/variable_validation_test.cc",
]
deps = [
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
- ":libtint_transform_src",
":libtint_utils_src",
":tint_unittests_ast_src",
]
@@ -1638,7 +1677,7 @@
deps = [ ":libtint_builtins_src" ]
}
- tint_unittests_source_set("tint_unittests_transform_src") {
+ tint_unittests_source_set("tint_unittests_ast_transform_src") {
sources = [
"ast/transform/add_block_attribute_test.cc",
"ast/transform/add_empty_entry_point_test.cc",
@@ -1697,8 +1736,9 @@
]
deps = [
+ ":libtint_ast_transform_src",
":libtint_builtins_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_unittests_ast_helper",
":libtint_utils_src",
":libtint_wgsl_reader_src",
@@ -2071,8 +2111,9 @@
]
deps = [
+ ":libtint_ast_transform_src",
":libtint_hlsl_writer_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_utils_src",
":tint_unittests_ast_src",
]
@@ -2115,9 +2156,10 @@
]
deps = [
+ ":libtint_ast_transform_src",
":libtint_glsl_writer_src",
":libtint_symbols_src",
- ":libtint_transform_src",
+ ":libtint_transform_manager_src",
":libtint_utils_src",
":tint_unittests_ast_src",
]
@@ -2151,19 +2193,20 @@
sources = [
"ir/binary_test.cc",
"ir/bitcast_test.cc",
- "ir/builder_impl_binary_test.cc",
- "ir/builder_impl_call_test.cc",
- "ir/builder_impl_literal_test.cc",
- "ir/builder_impl_materialize_test.cc",
- "ir/builder_impl_store_test.cc",
- "ir/builder_impl_test.cc",
- "ir/builder_impl_unary_test.cc",
- "ir/builder_impl_var_test.cc",
"ir/constant_test.cc",
"ir/discard_test.cc",
+ "ir/from_program_binary_test.cc",
+ "ir/from_program_call_test.cc",
+ "ir/from_program_literal_test.cc",
+ "ir/from_program_materialize_test.cc",
+ "ir/from_program_store_test.cc",
+ "ir/from_program_test.cc",
+ "ir/from_program_unary_test.cc",
+ "ir/from_program_var_test.cc",
"ir/module_test.cc",
"ir/store_test.cc",
"ir/test_helper.h",
+ "ir/to_program_roundtrip_test.cc",
"ir/unary_test.cc",
]
@@ -2191,6 +2234,7 @@
":libtint_wgsl_reader_src",
":libtint_wgsl_writer_src",
":tint_unittests_ast_src",
+ ":tint_unittests_ast_transform_src",
":tint_unittests_builtins_src",
":tint_unittests_cmd_src",
":tint_unittests_constant_src",
@@ -2200,7 +2244,6 @@
":tint_unittests_resolver_src",
":tint_unittests_sem_src",
":tint_unittests_symbols_src",
- ":tint_unittests_transform_src",
":tint_unittests_type_src",
":tint_unittests_utils_src",
":tint_unittests_writer_src",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index ea69d50..7d12ae2 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -452,6 +452,8 @@
ast/transform/zero_init_workgroup_memory.h
transform/manager.cc
transform/manager.h
+ transform/transform.cc
+ transform/transform.h
type/abstract_float.cc
type/abstract_float.h
type/abstract_int.cc
@@ -716,8 +718,6 @@
ir/block.h
ir/builder.cc
ir/builder.h
- ir/builder_impl.cc
- ir/builder_impl.h
ir/builtin.cc
ir/builtin.h
ir/call.cc
@@ -756,6 +756,8 @@
ir/store.h
ir/switch.cc
ir/switch.h
+ ir/to_program.cc
+ ir/to_program.h
ir/unary.cc
ir/unary.h
ir/user_call.cc
@@ -1447,16 +1449,16 @@
list(APPEND TINT_TEST_SRCS
ir/binary_test.cc
ir/bitcast_test.cc
- ir/builder_impl_binary_test.cc
- ir/builder_impl_call_test.cc
- ir/builder_impl_literal_test.cc
- ir/builder_impl_materialize_test.cc
- ir/builder_impl_store_test.cc
- ir/builder_impl_test.cc
- ir/builder_impl_unary_test.cc
- ir/builder_impl_var_test.cc
ir/constant_test.cc
ir/discard_test.cc
+ ir/from_program_binary_test.cc
+ ir/from_program_call_test.cc
+ ir/from_program_literal_test.cc
+ ir/from_program_materialize_test.cc
+ ir/from_program_store_test.cc
+ ir/from_program_test.cc
+ ir/from_program_unary_test.cc
+ ir/from_program_var_test.cc
ir/module_test.cc
ir/store_test.cc
ir/test_helper.h
@@ -1464,6 +1466,13 @@
)
endif()
+ if (${TINT_BUILD_IR} AND ${TINT_BUILD_WGSL_READER} AND ${TINT_BUILD_WGSL_WRITER})
+ list(APPEND TINT_TEST_SRCS
+ ir/to_program_roundtrip_test.cc
+ )
+ endif()
+
+
if (${TINT_BUILD_FUZZERS})
list(APPEND TINT_TEST_SRCS
fuzzers/mersenne_twister_engine.cc
diff --git a/src/tint/ast/transform/array_length_from_uniform_test.cc b/src/tint/ast/transform/array_length_from_uniform_test.cc
index b734630..8441655 100644
--- a/src/tint/ast/transform/array_length_from_uniform_test.cc
+++ b/src/tint/ast/transform/array_length_from_uniform_test.cc
@@ -31,7 +31,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
EXPECT_FALSE(ShouldRun<ArrayLengthFromUniform>(src, data));
@@ -54,7 +54,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
EXPECT_FALSE(ShouldRun<ArrayLengthFromUniform>(src, data));
@@ -78,7 +78,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
EXPECT_TRUE(ShouldRun<ArrayLengthFromUniform>(src, data));
@@ -134,7 +134,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
@@ -183,7 +183,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
@@ -275,7 +275,7 @@
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{3u, 2u}, 3);
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{4u, 2u}, 4);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
@@ -361,7 +361,7 @@
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{3u, 2u}, 3);
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{4u, 2u}, 4);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
@@ -389,7 +389,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
@@ -454,7 +454,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 2}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
@@ -502,7 +502,7 @@
ArrayLengthFromUniform::Config cfg({0, 30u});
cfg.bindpoint_to_size_index.emplace(sem::BindingPoint{0, 0}, 0);
- DataMap data;
+ Transform::DataMap data;
data.Add<ArrayLengthFromUniform::Config>(std::move(cfg));
auto got = Run<Unshadow, SimplifyPointers, ArrayLengthFromUniform>(src, data);
diff --git a/src/tint/ast/transform/binding_remapper_test.cc b/src/tint/ast/transform/binding_remapper_test.cc
index 296bd7c..023b919 100644
--- a/src/tint/ast/transform/binding_remapper_test.cc
+++ b/src/tint/ast/transform/binding_remapper_test.cc
@@ -26,7 +26,7 @@
TEST_F(BindingRemapperTest, ShouldRunEmptyRemappings) {
auto* src = R"()";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(BindingRemapper::BindingPoints{},
BindingRemapper::AccessControls{});
@@ -36,7 +36,7 @@
TEST_F(BindingRemapperTest, ShouldRunBindingPointRemappings) {
auto* src = R"()";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(
BindingRemapper::BindingPoints{
{{2, 1}, {1, 2}},
@@ -49,7 +49,7 @@
TEST_F(BindingRemapperTest, ShouldRunAccessControlRemappings) {
auto* src = R"()";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(BindingRemapper::BindingPoints{},
BindingRemapper::AccessControls{
{{2, 1}, builtin::Access::kWrite},
@@ -75,7 +75,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(BindingRemapper::BindingPoints{},
BindingRemapper::AccessControls{});
auto got = Run<BindingRemapper>(src, data);
@@ -112,7 +112,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(
BindingRemapper::BindingPoints{
{{2, 1}, {1, 2}}, // Remap
@@ -158,7 +158,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(
BindingRemapper::BindingPoints{},
BindingRemapper::AccessControls{
@@ -200,7 +200,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(
BindingRemapper::BindingPoints{
{{2, 1}, {4, 5}},
@@ -254,7 +254,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(
BindingRemapper::BindingPoints{
{{2, 1}, {1, 1}},
@@ -316,7 +316,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<BindingRemapper::Remappings>(
BindingRemapper::BindingPoints{
{{2, 1}, {1, 1}},
diff --git a/src/tint/ast/transform/builtin_polyfill_test.cc b/src/tint/ast/transform/builtin_polyfill_test.cc
index e48ab70..668c4fc 100644
--- a/src/tint/ast/transform/builtin_polyfill_test.cc
+++ b/src/tint/ast/transform/builtin_polyfill_test.cc
@@ -41,10 +41,10 @@
////////////////////////////////////////////////////////////////////////////////
// acosh
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillAcosh(Level level) {
+Transform::DataMap polyfillAcosh(Level level) {
BuiltinPolyfill::Builtins builtins;
builtins.acosh = level;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -172,10 +172,10 @@
////////////////////////////////////////////////////////////////////////////////
// asinh
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillSinh() {
+Transform::DataMap polyfillSinh() {
BuiltinPolyfill::Builtins builtins;
builtins.asinh = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -253,10 +253,10 @@
////////////////////////////////////////////////////////////////////////////////
// atanh
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillAtanh(Level level) {
+Transform::DataMap polyfillAtanh(Level level) {
BuiltinPolyfill::Builtins builtins;
builtins.atanh = level;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -384,10 +384,10 @@
////////////////////////////////////////////////////////////////////////////////
// bgra8unorm
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillBgra8unorm() {
+Transform::DataMap polyfillBgra8unorm() {
BuiltinPolyfill::Builtins builtins;
builtins.bgra8unorm = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -505,7 +505,7 @@
BuiltinPolyfill::Builtins builtins;
builtins.atanh = BuiltinPolyfill::Level::kFull;
builtins.bgra8unorm = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
auto got = Run<BuiltinPolyfill>(src, std::move(data));
@@ -516,10 +516,10 @@
////////////////////////////////////////////////////////////////////////////////
// bitshiftModulo
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillBitshiftModulo() {
+Transform::DataMap polyfillBitshiftModulo() {
BuiltinPolyfill::Builtins builtins;
builtins.bitshift_modulo = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -655,10 +655,10 @@
////////////////////////////////////////////////////////////////////////////////
// clampInteger
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillClampInteger() {
+Transform::DataMap polyfillClampInteger() {
BuiltinPolyfill::Builtins builtins;
builtins.clamp_int = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -818,10 +818,10 @@
////////////////////////////////////////////////////////////////////////////////
// conv_f32_to_iu32
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillConvF32ToIU32() {
+Transform::DataMap polyfillConvF32ToIU32() {
BuiltinPolyfill::Builtins builtins;
builtins.conv_f32_to_iu32 = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -969,10 +969,10 @@
////////////////////////////////////////////////////////////////////////////////
// countLeadingZeros
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillCountLeadingZeros() {
+Transform::DataMap polyfillCountLeadingZeros() {
BuiltinPolyfill::Builtins builtins;
builtins.count_leading_zeros = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -1142,10 +1142,10 @@
////////////////////////////////////////////////////////////////////////////////
// countTrailingZeros
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillCountTrailingZeros() {
+Transform::DataMap polyfillCountTrailingZeros() {
BuiltinPolyfill::Builtins builtins;
builtins.count_trailing_zeros = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -1315,10 +1315,10 @@
////////////////////////////////////////////////////////////////////////////////
// extractBits
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillExtractBits(Level level) {
+Transform::DataMap polyfillExtractBits(Level level) {
BuiltinPolyfill::Builtins builtins;
builtins.extract_bits = level;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -1570,10 +1570,10 @@
////////////////////////////////////////////////////////////////////////////////
// firstLeadingBit
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillFirstLeadingBit() {
+Transform::DataMap polyfillFirstLeadingBit() {
BuiltinPolyfill::Builtins builtins;
builtins.first_leading_bit = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -1743,10 +1743,10 @@
////////////////////////////////////////////////////////////////////////////////
// firstTrailingBit
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillFirstTrailingBit() {
+Transform::DataMap polyfillFirstTrailingBit() {
BuiltinPolyfill::Builtins builtins;
builtins.first_trailing_bit = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -1916,10 +1916,10 @@
////////////////////////////////////////////////////////////////////////////////
// insertBits
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillInsertBits(Level level) {
+Transform::DataMap polyfillInsertBits(Level level) {
BuiltinPolyfill::Builtins builtins;
builtins.insert_bits = level;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -2159,10 +2159,10 @@
////////////////////////////////////////////////////////////////////////////////
// precise_float_mod
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillPreciseFloatMod() {
+Transform::DataMap polyfillPreciseFloatMod() {
BuiltinPolyfill::Builtins builtins;
builtins.precise_float_mod = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -2385,10 +2385,10 @@
////////////////////////////////////////////////////////////////////////////////
// int_div_mod
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillIntDivMod() {
+Transform::DataMap polyfillIntDivMod() {
BuiltinPolyfill::Builtins builtins;
builtins.int_div_mod = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -3199,10 +3199,10 @@
////////////////////////////////////////////////////////////////////////////////
// reflect for vec2<f32>
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillReflectVec2F32() {
+Transform::DataMap polyfillReflectVec2F32() {
BuiltinPolyfill::Builtins builtins;
builtins.reflect_vec2_f32 = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -3370,10 +3370,10 @@
////////////////////////////////////////////////////////////////////////////////
// saturate
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillSaturate() {
+Transform::DataMap polyfillSaturate() {
BuiltinPolyfill::Builtins builtins;
builtins.saturate = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -3507,10 +3507,10 @@
////////////////////////////////////////////////////////////////////////////////
// sign_int
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillSignInt() {
+Transform::DataMap polyfillSignInt() {
BuiltinPolyfill::Builtins builtins;
builtins.sign_int = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -3600,10 +3600,10 @@
////////////////////////////////////////////////////////////////////////////////
// textureSampleBaseClampToEdge
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillTextureSampleBaseClampToEdge_2d_f32() {
+Transform::DataMap polyfillTextureSampleBaseClampToEdge_2d_f32() {
BuiltinPolyfill::Builtins builtins;
builtins.texture_sample_base_clamp_to_edge_2d_f32 = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -3671,18 +3671,18 @@
////////////////////////////////////////////////////////////////////////////////
// workgroupUniformLoad
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillWorkgroupUniformLoad() {
+Transform::DataMap polyfillWorkgroupUniformLoad() {
BuiltinPolyfill::Builtins builtins;
builtins.workgroup_uniform_load = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
-DataMap polyfillWorkgroupUniformLoadWithDirectVariableAccess() {
- DataMap data;
+Transform::DataMap polyfillWorkgroupUniformLoadWithDirectVariableAccess() {
+ Transform::DataMap data;
BuiltinPolyfill::Builtins builtins;
builtins.workgroup_uniform_load = true;
@@ -3893,10 +3893,10 @@
////////////////////////////////////////////////////////////////////////////////
// quantizeToF16
////////////////////////////////////////////////////////////////////////////////
-DataMap polyfillQuantizeToF16_2d_f32() {
+Transform::DataMap polyfillQuantizeToF16_2d_f32() {
BuiltinPolyfill::Builtins builtins;
builtins.quantize_to_vec_f16 = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
return data;
}
@@ -4021,7 +4021,7 @@
BuiltinPolyfill::Builtins builtins;
builtins.bitshift_modulo = true;
builtins.int_div_mod = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<BuiltinPolyfill::Config>(builtins);
auto got = Run<BuiltinPolyfill>(src, std::move(data));
diff --git a/src/tint/ast/transform/canonicalize_entry_point_io_test.cc b/src/tint/ast/transform/canonicalize_entry_point_io_test.cc
index 98af3a7..454fb3b 100644
--- a/src/tint/ast/transform/canonicalize_entry_point_io_test.cc
+++ b/src/tint/ast/transform/canonicalize_entry_point_io_test.cc
@@ -48,7 +48,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -82,7 +82,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -117,7 +117,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -154,7 +154,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -189,7 +189,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -224,7 +224,7 @@
alias myf32 = f32;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -277,7 +277,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -330,7 +330,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -384,7 +384,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -438,7 +438,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -494,7 +494,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -550,7 +550,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -579,7 +579,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -613,7 +613,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -647,7 +647,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -702,7 +702,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -757,7 +757,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -817,7 +817,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -877,7 +877,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -937,7 +937,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -997,7 +997,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1063,7 +1063,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1129,7 +1129,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1201,7 +1201,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1273,7 +1273,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1345,7 +1345,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1417,7 +1417,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1484,7 +1484,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1551,7 +1551,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1637,7 +1637,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1723,7 +1723,7 @@
alias myf32 = f32;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1814,7 +1814,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -1905,7 +1905,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2035,7 +2035,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2165,7 +2165,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2229,7 +2229,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2293,7 +2293,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2360,7 +2360,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2427,7 +2427,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2531,7 +2531,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2635,7 +2635,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2664,7 +2664,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2696,7 +2696,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2730,7 +2730,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2764,7 +2764,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2801,7 +2801,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2853,7 +2853,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2905,7 +2905,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -2955,7 +2955,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3005,7 +3005,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3094,7 +3094,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03u);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3144,7 +3144,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl, 0x03);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3176,7 +3176,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3214,7 +3214,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3255,7 +3255,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3296,7 +3296,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3342,7 +3342,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3388,7 +3388,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3466,7 +3466,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3544,7 +3544,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3620,7 +3620,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3696,7 +3696,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kMsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3772,7 +3772,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3848,7 +3848,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl,
0xFFFFFFFF, true);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3884,7 +3884,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kSpirv);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3919,7 +3919,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kGlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
@@ -3956,7 +3956,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kGlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO>(src, data);
diff --git a/src/tint/ast/transform/combine_samplers_test.cc b/src/tint/ast/transform/combine_samplers_test.cc
index f658493..fa74b8a 100644
--- a/src/tint/ast/transform/combine_samplers_test.cc
+++ b/src/tint/ast/transform/combine_samplers_test.cc
@@ -28,7 +28,7 @@
auto* src = "";
auto* expect = "";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -55,7 +55,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -82,7 +82,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -117,7 +117,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -152,7 +152,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -179,7 +179,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
CombineSamplers::BindingMap map;
sem::SamplerTexturePair pair;
pair.texture_binding_point.group = 0;
@@ -214,7 +214,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
CombineSamplers::BindingMap map;
sem::SamplerTexturePair pair;
pair.texture_binding_point.group = 3;
@@ -262,7 +262,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -300,7 +300,7 @@
alias Tex2d = texture_2d<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -343,7 +343,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -385,7 +385,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -428,7 +428,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -491,7 +491,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -538,7 +538,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -585,7 +585,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -624,7 +624,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -661,7 +661,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -700,7 +700,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -737,7 +737,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -776,7 +776,7 @@
pair.sampler_binding_point.binding = placeholder.binding;
CombineSamplers::BindingMap map;
map[pair] = "fred";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(map, placeholder);
auto got = Run<CombineSamplers>(src, data);
@@ -820,7 +820,7 @@
CombineSamplers::BindingMap map;
map[pair] = "barney";
map[placeholder_pair] = "fred";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(map, placeholder);
auto got = Run<CombineSamplers>(src, data);
@@ -847,7 +847,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -882,7 +882,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -916,7 +916,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -947,7 +947,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
@@ -977,7 +977,7 @@
@internal(disable_validation__binding_point_collision) @group(0) @binding(0) var<uniform> gcoords : vec2<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CombineSamplers::BindingInfo>(CombineSamplers::BindingMap(), sem::BindingPoint());
auto got = Run<CombineSamplers>(src, data);
diff --git a/src/tint/ast/transform/decompose_memory_access.cc b/src/tint/ast/transform/decompose_memory_access.cc
index f80fd56..bd48606 100644
--- a/src/tint/ast/transform/decompose_memory_access.cc
+++ b/src/tint/ast/transform/decompose_memory_access.cc
@@ -313,8 +313,8 @@
/// Store describes a single storage or uniform buffer write
struct Store {
- const AssignmentStatement* assignment; // The AST assignment statement
- BufferAccess target; // The target for the write
+ const AssignmentStatement* assignment; // The AST assignment statement
+ BufferAccess target; // The target for the write
};
} // namespace
diff --git a/src/tint/ast/transform/direct_variable_access_test.cc b/src/tint/ast/transform/direct_variable_access_test.cc
index b735991..ecc8843 100644
--- a/src/tint/ast/transform/direct_variable_access_test.cc
+++ b/src/tint/ast/transform/direct_variable_access_test.cc
@@ -23,22 +23,22 @@
namespace tint::ast::transform {
namespace {
-/// @returns a DataMap with DirectVariableAccess::Config::transform_private enabled.
-static DataMap EnablePrivate() {
+/// @returns a Transform::DataMap with DirectVariableAccess::Config::transform_private enabled.
+static Transform::DataMap EnablePrivate() {
DirectVariableAccess::Options opts;
opts.transform_private = true;
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<DirectVariableAccess::Config>(opts);
return inputs;
}
-/// @returns a DataMap with DirectVariableAccess::Config::transform_function enabled.
-static DataMap EnableFunction() {
+/// @returns a Transform::DataMap with DirectVariableAccess::Config::transform_function enabled.
+static Transform::DataMap EnableFunction() {
DirectVariableAccess::Options opts;
opts.transform_function = true;
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<DirectVariableAccess::Config>(opts);
return inputs;
}
diff --git a/src/tint/ast/transform/first_index_offset.h b/src/tint/ast/transform/first_index_offset.h
index cb5e3f3..44a3a63 100644
--- a/src/tint/ast/transform/first_index_offset.h
+++ b/src/tint/ast/transform/first_index_offset.h
@@ -62,7 +62,7 @@
/// BindingPoint is consumed by the FirstIndexOffset transform.
/// BindingPoint specifies the binding point of the first index uniform
/// buffer.
- struct BindingPoint final : public utils::Castable<BindingPoint, transform::Data> {
+ struct BindingPoint final : public utils::Castable<BindingPoint, Transform::Data> {
/// Constructor
BindingPoint();
@@ -82,7 +82,7 @@
/// Data is outputted by the FirstIndexOffset transform.
/// Data holds information about shader usage and constant buffer offsets.
- struct Data final : public utils::Castable<Data, transform::Data> {
+ struct Data final : public utils::Castable<Data, Transform::Data> {
/// Constructor
/// @param has_vtx_or_inst_index True if the shader uses vertex_index or
/// instance_index
diff --git a/src/tint/ast/transform/first_index_offset_test.cc b/src/tint/ast/transform/first_index_offset_test.cc
index 1be6474..8dc441f 100644
--- a/src/tint/ast/transform/first_index_offset_test.cc
+++ b/src/tint/ast/transform/first_index_offset_test.cc
@@ -57,7 +57,7 @@
auto* src = "";
auto* expect = "";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(0, 0);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -77,7 +77,7 @@
)";
auto* expect = src;
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(0, 0);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -121,7 +121,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -165,7 +165,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -209,7 +209,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 7);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -253,7 +253,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 7);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -309,7 +309,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -365,7 +365,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -417,7 +417,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -469,7 +469,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -537,7 +537,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
@@ -605,7 +605,7 @@
}
)";
- DataMap config;
+ Transform::DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
diff --git a/src/tint/ast/transform/multiplanar_external_texture_test.cc b/src/tint/ast/transform/multiplanar_external_texture_test.cc
index 25c7765..8acf254 100644
--- a/src/tint/ast/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/ast/transform/multiplanar_external_texture_test.cc
@@ -23,7 +23,7 @@
TEST_F(MultiplanarExternalTextureTest, ShouldRunEmptyModule) {
auto* src = R"()";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
@@ -35,7 +35,7 @@
alias ET = texture_external;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
@@ -46,7 +46,7 @@
@group(0) @binding(0) var ext_tex : texture_external;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
@@ -58,7 +58,7 @@
fn f(ext_tex : texture_external) {}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
@@ -98,7 +98,7 @@
auto* expect = R"(error: missing new binding points for texture_external at binding {0,1})";
- DataMap data;
+ Transform::DataMap data;
// This bindings map specifies 0,0 as the location of the texture_external,
// which is incorrect.
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
@@ -156,7 +156,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -212,7 +212,7 @@
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -296,7 +296,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 1}, {{0, 2}, {0, 3}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -380,7 +380,7 @@
@group(0) @binding(0) var s : sampler;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 1}, {{0, 2}, {0, 3}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -475,7 +475,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -570,7 +570,7 @@
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -670,7 +670,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 1}, {{0, 2}, {0, 3}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -770,7 +770,7 @@
@group(0) @binding(1) var ext_tex : texture_2d<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 1}, {{0, 2}, {0, 3}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -878,7 +878,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 1}, {{0, 4}, {0, 5}}},
{{0, 2}, {{0, 6}, {0, 7}}},
@@ -974,7 +974,7 @@
f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
@@ -1067,7 +1067,7 @@
@group(0) @binding(1) var smp : sampler;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
@@ -1160,7 +1160,7 @@
f(smp, ext_tex, ext_tex_plane_1, ext_tex_params);
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
@@ -1262,7 +1262,7 @@
f(ext_tex, ext_tex_plane_1, ext_tex_params, smp, ext_tex2, ext_tex_plane_1_1, ext_tex_params_1);
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 3}, {0, 4}}},
{{0, 2}, {{0, 5}, {0, 6}}},
@@ -1366,7 +1366,7 @@
@group(0) @binding(2) var ext_tex2 : texture_2d<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 3}, {0, 4}}},
{{0, 2}, {{0, 5}, {0, 6}}},
@@ -1468,7 +1468,7 @@
f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
@@ -1569,7 +1569,7 @@
f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
@@ -1613,7 +1613,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(
MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
auto got = Run<MultiplanarExternalTexture>(src, data);
@@ -1708,7 +1708,7 @@
f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
@@ -1804,7 +1804,7 @@
alias ET = texture_external;
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<MultiplanarExternalTexture::NewBindingPoints>(MultiplanarExternalTexture::BindingsMap{
{{0, 0}, {{0, 2}, {0, 3}}},
});
diff --git a/src/tint/ast/transform/num_workgroups_from_uniform_test.cc b/src/tint/ast/transform/num_workgroups_from_uniform_test.cc
index b46f6ab..2910655 100644
--- a/src/tint/ast/transform/num_workgroups_from_uniform_test.cc
+++ b/src/tint/ast/transform/num_workgroups_from_uniform_test.cc
@@ -28,7 +28,7 @@
TEST_F(NumWorkgroupsFromUniformTest, ShouldRunEmptyModule) {
auto* src = R"()";
- DataMap data;
+ Transform::DataMap data;
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
EXPECT_FALSE(ShouldRun<NumWorkgroupsFromUniform>(src, data));
}
@@ -40,7 +40,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
EXPECT_TRUE(ShouldRun<NumWorkgroupsFromUniform>(src, data));
}
@@ -55,7 +55,7 @@
auto* expect =
"error: missing transform data for tint::ast::transform::NumWorkgroupsFromUniform";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
EXPECT_EQ(expect, str(got));
@@ -90,7 +90,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -134,7 +134,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -178,7 +178,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -233,7 +233,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -289,7 +289,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -388,7 +388,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -429,7 +429,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<NumWorkgroupsFromUniform::Config>(sem::BindingPoint{0, 30u});
auto got = Run<Unshadow, CanonicalizeEntryPointIO, NumWorkgroupsFromUniform>(src, data);
@@ -530,7 +530,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
// Make binding point unspecified.
data.Add<NumWorkgroupsFromUniform::Config>(std::nullopt);
@@ -684,7 +684,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
// Make binding point unspecified.
data.Add<NumWorkgroupsFromUniform::Config>(std::nullopt);
diff --git a/src/tint/ast/transform/packed_vec3_test.cc b/src/tint/ast/transform/packed_vec3_test.cc
index 29d9919..6ad0b0a 100644
--- a/src/tint/ast/transform/packed_vec3_test.cc
+++ b/src/tint/ast/transform/packed_vec3_test.cc
@@ -218,7 +218,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -243,7 +243,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -268,7 +268,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -293,7 +293,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -321,7 +321,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -346,7 +346,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -371,7 +371,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -409,7 +409,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -439,7 +439,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -469,7 +469,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -499,7 +499,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -537,7 +537,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -570,7 +570,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -600,7 +600,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -638,7 +638,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -668,7 +668,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -698,7 +698,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -736,7 +736,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -766,7 +766,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -796,7 +796,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -826,7 +826,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -864,7 +864,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -897,7 +897,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -927,7 +927,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -965,7 +965,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -995,7 +995,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1025,7 +1025,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1071,7 +1071,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1109,7 +1109,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1139,7 +1139,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1169,7 +1169,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1199,7 +1199,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1245,7 +1245,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1278,7 +1278,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1316,7 +1316,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1354,7 +1354,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1384,7 +1384,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1427,7 +1427,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1457,7 +1457,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1487,7 +1487,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1531,7 +1531,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1569,7 +1569,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1607,7 +1607,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1645,7 +1645,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1689,7 +1689,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1730,7 +1730,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1768,7 +1768,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1818,7 +1818,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1856,7 +1856,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1894,7 +1894,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1951,7 +1951,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2002,7 +2002,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2045,7 +2045,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2088,7 +2088,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2131,7 +2131,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2189,7 +2189,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2235,7 +2235,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2286,7 +2286,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2341,7 +2341,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2384,7 +2384,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2440,7 +2440,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2483,7 +2483,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2526,7 +2526,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2583,7 +2583,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2634,7 +2634,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2677,7 +2677,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2720,7 +2720,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2763,7 +2763,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2821,7 +2821,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2867,7 +2867,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2918,7 +2918,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2973,7 +2973,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3016,7 +3016,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3072,7 +3072,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3115,7 +3115,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3158,7 +3158,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3223,7 +3223,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3282,7 +3282,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3333,7 +3333,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3376,7 +3376,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3419,7 +3419,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3462,7 +3462,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3528,7 +3528,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3574,7 +3574,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3633,7 +3633,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3688,7 +3688,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3739,7 +3739,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3795,7 +3795,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3838,7 +3838,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3899,7 +3899,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3942,7 +3942,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3985,7 +3985,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4039,7 +4039,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4089,7 +4089,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4144,7 +4144,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4211,7 +4211,7 @@
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(std::move(src), data);
EXPECT_EQ(expect, str(got));
@@ -4264,7 +4264,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4317,7 +4317,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
auto& vars = got.program.AST().GlobalVariables();
@@ -4436,7 +4436,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4485,7 +4485,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4517,7 +4517,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4578,7 +4578,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4671,7 +4671,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4791,7 +4791,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4885,7 +4885,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4958,7 +4958,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5047,7 +5047,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5172,7 +5172,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5288,7 +5288,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5390,7 +5390,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5477,7 +5477,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5580,7 +5580,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5722,7 +5722,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5790,7 +5790,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5881,7 +5881,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -5978,7 +5978,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6084,7 +6084,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6190,7 +6190,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6263,7 +6263,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6336,7 +6336,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6414,7 +6414,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6482,7 +6482,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6550,7 +6550,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6647,7 +6647,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6672,7 +6672,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6697,7 +6697,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6743,7 +6743,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6795,7 +6795,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6860,7 +6860,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -6937,7 +6937,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7002,7 +7002,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7075,7 +7075,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7197,7 +7197,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7320,7 +7320,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7466,7 +7466,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7513,7 +7513,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7559,7 +7559,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7619,7 +7619,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7683,7 +7683,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7748,7 +7748,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7788,7 +7788,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7870,7 +7870,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -7944,7 +7944,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -8038,7 +8038,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
@@ -8085,7 +8085,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
diff --git a/src/tint/ast/transform/pad_structs_test.cc b/src/tint/ast/transform/pad_structs_test.cc
index 89ce34c..f7dc437 100644
--- a/src/tint/ast/transform/pad_structs_test.cc
+++ b/src/tint/ast/transform/pad_structs_test.cc
@@ -28,7 +28,7 @@
auto* src = "";
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -61,7 +61,7 @@
let x = u.x;
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -97,7 +97,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -137,7 +137,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -179,7 +179,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -219,7 +219,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -254,7 +254,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -300,7 +300,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -350,7 +350,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -396,7 +396,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -433,7 +433,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -477,7 +477,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -524,7 +524,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -561,7 +561,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
@@ -598,7 +598,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PadStructs>(src, data);
EXPECT_EQ(expect, str(got));
diff --git a/src/tint/ast/transform/promote_side_effects_to_decl.cc b/src/tint/ast/transform/promote_side_effects_to_decl.cc
index 345caf1..19136dd 100644
--- a/src/tint/ast/transform/promote_side_effects_to_decl.cc
+++ b/src/tint/ast/transform/promote_side_effects_to_decl.cc
@@ -672,7 +672,7 @@
tint::transform::Manager manager;
manager.Add<SimplifySideEffectStatements>();
manager.Add<DecomposeSideEffects>();
- return manager.Apply(src, inputs, outputs);
+ return manager.Run(src, inputs, outputs);
}
} // namespace tint::ast::transform
diff --git a/src/tint/ast/transform/promote_side_effects_to_decl_test.cc b/src/tint/ast/transform/promote_side_effects_to_decl_test.cc
index 9cd2e0f..f8ce860 100644
--- a/src/tint/ast/transform/promote_side_effects_to_decl_test.cc
+++ b/src/tint/ast/transform/promote_side_effects_to_decl_test.cc
@@ -25,7 +25,7 @@
auto* src = "";
auto* expect = "";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -44,7 +44,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -81,7 +81,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -111,7 +111,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -142,7 +142,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -176,7 +176,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -211,7 +211,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -248,7 +248,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -278,7 +278,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -306,7 +306,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -338,7 +338,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -370,7 +370,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -401,7 +401,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -433,7 +433,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -467,7 +467,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -489,7 +489,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -532,7 +532,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -566,7 +566,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -608,7 +608,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -645,7 +645,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -679,7 +679,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -716,7 +716,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -757,7 +757,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -789,7 +789,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -820,7 +820,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -861,7 +861,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -900,7 +900,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -944,7 +944,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -998,7 +998,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1037,7 +1037,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1077,7 +1077,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1137,7 +1137,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1168,7 +1168,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1205,7 +1205,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1238,7 +1238,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1271,7 +1271,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1302,7 +1302,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1347,7 +1347,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1384,7 +1384,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1429,7 +1429,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1468,7 +1468,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1509,7 +1509,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1548,7 +1548,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1585,7 +1585,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1628,7 +1628,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1685,7 +1685,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1732,7 +1732,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1779,7 +1779,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1818,7 +1818,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1859,7 +1859,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1906,7 +1906,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1946,7 +1946,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -1984,7 +1984,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2031,7 +2031,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2079,7 +2079,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2113,7 +2113,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2146,7 +2146,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2190,7 +2190,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2232,7 +2232,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2279,7 +2279,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2342,7 +2342,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2384,7 +2384,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2427,7 +2427,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2492,7 +2492,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2517,7 +2517,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2555,7 +2555,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2593,7 +2593,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2634,7 +2634,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2680,7 +2680,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2712,7 +2712,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2747,7 +2747,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2778,7 +2778,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2805,7 +2805,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2835,7 +2835,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2866,7 +2866,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2898,7 +2898,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2933,7 +2933,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2963,7 +2963,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -2995,7 +2995,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3027,7 +3027,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3069,7 +3069,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3099,7 +3099,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3132,7 +3132,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3161,7 +3161,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3200,7 +3200,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3264,7 +3264,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3295,7 +3295,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3325,7 +3325,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3355,7 +3355,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3385,7 +3385,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3417,7 +3417,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3450,7 +3450,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3484,7 +3484,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3515,7 +3515,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3547,7 +3547,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3580,7 +3580,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3614,7 +3614,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3651,7 +3651,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3688,7 +3688,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3724,7 +3724,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3760,7 +3760,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3806,7 +3806,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3824,7 +3824,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3873,7 +3873,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3922,7 +3922,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -3970,7 +3970,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4018,7 +4018,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4079,7 +4079,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
@@ -4127,7 +4127,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<PromoteSideEffectsToDecl>(src, data);
EXPECT_EQ(expect, str(got));
diff --git a/src/tint/ast/transform/remove_continue_in_switch_test.cc b/src/tint/ast/transform/remove_continue_in_switch_test.cc
index 84ad5cd..237ceea 100644
--- a/src/tint/ast/transform/remove_continue_in_switch_test.cc
+++ b/src/tint/ast/transform/remove_continue_in_switch_test.cc
@@ -101,7 +101,7 @@
auto* src = "";
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -163,7 +163,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -247,7 +247,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -332,7 +332,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -423,7 +423,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -501,7 +501,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -553,7 +553,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
@@ -607,7 +607,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
diff --git a/src/tint/ast/transform/renamer.h b/src/tint/ast/transform/renamer.h
index fb839c2..5e7c92d 100644
--- a/src/tint/ast/transform/renamer.h
+++ b/src/tint/ast/transform/renamer.h
@@ -27,7 +27,7 @@
public:
/// Data is outputted by the Renamer transform.
/// Data holds information about shader usage and constant buffer offsets.
- struct Data final : public utils::Castable<Data, transform::Data> {
+ struct Data final : public utils::Castable<Data, tint::transform::Data> {
/// Remappings is a map of old symbol name to new symbol name
using Remappings = std::unordered_map<std::string, std::string>;
@@ -59,7 +59,7 @@
/// Optional configuration options for the transform.
/// If omitted, then the renamer will use Target::kAll.
- struct Config final : public utils::Castable<Config, transform::Data> {
+ struct Config final : public utils::Castable<Config, tint::transform::Data> {
/// Constructor
/// @param tgt the targets to rename
/// @param keep_unicode if false, symbols with non-ascii code-points are
diff --git a/src/tint/ast/transform/renamer_test.cc b/src/tint/ast/transform/renamer_test.cc
index fe7e845..4e97c6f 100644
--- a/src/tint/ast/transform/renamer_test.cc
+++ b/src/tint/ast/transform/renamer_test.cc
@@ -245,7 +245,7 @@
auto expect = src;
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<Renamer::Config>(Renamer::Target::kMslKeywords,
/* preserve_unicode */ true);
auto got = Run<Renamer>(src, inputs);
@@ -269,7 +269,7 @@
}
)";
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<Renamer::Config>(Renamer::Target::kAll,
/* preserve_unicode */ true);
auto got = Run<Renamer>(src, inputs);
@@ -379,7 +379,7 @@
}
)";
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<Renamer::Config>(Renamer::Target::kGlslKeywords,
/* preserve_unicode */ false);
auto got = Run<Renamer>(src, inputs);
@@ -405,7 +405,7 @@
}
)";
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<Renamer::Config>(Renamer::Target::kHlslKeywords,
/* preserve_unicode */ false);
auto got = Run<Renamer>(src, inputs);
@@ -431,7 +431,7 @@
}
)";
- DataMap inputs;
+ Transform::DataMap inputs;
inputs.Add<Renamer::Config>(Renamer::Target::kMslKeywords,
/* preserve_unicode */ false);
auto got = Run<Renamer>(src, inputs);
diff --git a/src/tint/ast/transform/robustness_test.cc b/src/tint/ast/transform/robustness_test.cc
index 1200bb4..ebe7dc2 100644
--- a/src/tint/ast/transform/robustness_test.cc
+++ b/src/tint/ast/transform/robustness_test.cc
@@ -32,7 +32,7 @@
namespace {
-DataMap Config(Robustness::Action action) {
+Transform::DataMap Config(Robustness::Action action) {
Robustness::Config cfg;
cfg.value_action = action;
cfg.texture_action = action;
@@ -42,7 +42,7 @@
cfg.storage_action = action;
cfg.uniform_action = action;
cfg.workgroup_action = action;
- DataMap data;
+ Transform::DataMap data;
data.Add<Robustness::Config>(cfg);
return data;
}
diff --git a/src/tint/ast/transform/single_entry_point_test.cc b/src/tint/ast/transform/single_entry_point_test.cc
index 54c730f..6a4ebf2 100644
--- a/src/tint/ast/transform/single_entry_point_test.cc
+++ b/src/tint/ast/transform/single_entry_point_test.cc
@@ -38,7 +38,7 @@
auto* expect = "error: entry point 'main' not found";
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>("main");
auto got = Run<SingleEntryPoint>(src, data);
@@ -57,7 +57,7 @@
SingleEntryPoint::Config cfg("_");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -76,7 +76,7 @@
SingleEntryPoint::Config cfg("foo");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -92,7 +92,7 @@
SingleEntryPoint::Config cfg("main");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -127,7 +127,7 @@
SingleEntryPoint::Config cfg("comp_main1");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -177,7 +177,7 @@
SingleEntryPoint::Config cfg("comp_main1");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -233,7 +233,7 @@
SingleEntryPoint::Config cfg("comp_main1");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -253,7 +253,7 @@
SingleEntryPoint::Config cfg("main");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -303,7 +303,7 @@
let local_d = c1;
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -321,7 +321,7 @@
let local_d = c2;
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -337,7 +337,7 @@
let local_d = c3;
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -353,7 +353,7 @@
let local_d = c4;
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -367,7 +367,7 @@
let local_d = 1u;
}
)";
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -403,7 +403,7 @@
auto* expect = src;
SingleEntryPoint::Config cfg("main");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -440,7 +440,7 @@
)";
SingleEntryPoint::Config cfg("main");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
EXPECT_EQ(expect, str(got));
@@ -498,7 +498,7 @@
SingleEntryPoint::Config cfg("comp_main1");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -581,7 +581,7 @@
SingleEntryPoint::Config cfg("comp_main1");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -604,7 +604,7 @@
SingleEntryPoint::Config cfg("main");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
@@ -624,7 +624,7 @@
SingleEntryPoint::Config cfg("main");
- DataMap data;
+ Transform::DataMap data;
data.Add<SingleEntryPoint::Config>(cfg);
auto got = Run<SingleEntryPoint>(src, data);
diff --git a/src/tint/ast/transform/substitute_override.cc b/src/tint/ast/transform/substitute_override.cc
index fed559b..f0d7717 100644
--- a/src/tint/ast/transform/substitute_override.cc
+++ b/src/tint/ast/transform/substitute_override.cc
@@ -101,20 +101,19 @@
// Ensure that objects that are indexed with an override-expression are materialized.
// If the object is not materialized, and the 'override' variable is turned to a 'const', the
// resulting type of the index may change. See: crbug.com/tint/1697.
- ctx.ReplaceAll(
- [&](const IndexAccessorExpression* expr) -> const IndexAccessorExpression* {
- if (auto* sem = src->Sem().Get(expr)) {
- if (auto* access = sem->UnwrapMaterialize()->As<sem::IndexAccessorExpression>()) {
- if (access->Object()->UnwrapMaterialize()->Type()->HoldsAbstract() &&
- access->Index()->Stage() == sem::EvaluationStage::kOverride) {
- auto* obj = b.Call(builtin::str(builtin::Function::kTintMaterialize),
- ctx.Clone(expr->object));
- return b.IndexAccessor(obj, ctx.Clone(expr->index));
- }
+ ctx.ReplaceAll([&](const IndexAccessorExpression* expr) -> const IndexAccessorExpression* {
+ if (auto* sem = src->Sem().Get(expr)) {
+ if (auto* access = sem->UnwrapMaterialize()->As<sem::IndexAccessorExpression>()) {
+ if (access->Object()->UnwrapMaterialize()->Type()->HoldsAbstract() &&
+ access->Index()->Stage() == sem::EvaluationStage::kOverride) {
+ auto* obj = b.Call(builtin::str(builtin::Function::kTintMaterialize),
+ ctx.Clone(expr->object));
+ return b.IndexAccessor(obj, ctx.Clone(expr->index));
}
}
- return nullptr;
- });
+ }
+ return nullptr;
+ });
ctx.Clone();
return Program(std::move(b));
diff --git a/src/tint/ast/transform/substitute_override_test.cc b/src/tint/ast/transform/substitute_override_test.cc
index 01d9597..9f3cd63 100644
--- a/src/tint/ast/transform/substitute_override_test.cc
+++ b/src/tint/ast/transform/substitute_override_test.cc
@@ -32,7 +32,7 @@
auto* expect = "error: Missing override substitution data";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<SubstituteOverride>(src, data);
EXPECT_EQ(expect, str(got));
@@ -50,7 +50,7 @@
auto* expect = "error: Initializer not provided for override, and override not overridden.";
SubstituteOverride::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<SubstituteOverride::Config>(cfg);
auto got = Run<SubstituteOverride>(src, data);
@@ -75,7 +75,7 @@
SubstituteOverride::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<SubstituteOverride::Config>(cfg);
auto got = Run<SubstituteOverride>(src, data);
@@ -143,7 +143,7 @@
cfg.map.insert({OverrideId{6}, 1.0});
cfg.map.insert({OverrideId{7}, 0.0});
- DataMap data;
+ Transform::DataMap data;
data.Add<SubstituteOverride::Config>(cfg);
auto got = Run<SubstituteOverride>(src, data);
@@ -212,7 +212,7 @@
cfg.map.insert({OverrideId{7}, 0.0});
cfg.map.insert({OverrideId{5}, 13});
- DataMap data;
+ Transform::DataMap data;
data.Add<SubstituteOverride::Config>(cfg);
auto got = Run<SubstituteOverride>(src, data);
@@ -241,7 +241,7 @@
SubstituteOverride::Config cfg;
cfg.map.insert({OverrideId{0}, 11.0});
- DataMap data;
+ Transform::DataMap data;
data.Add<SubstituteOverride::Config>(cfg);
auto got = Run<SubstituteOverride>(src, data);
@@ -282,7 +282,7 @@
SubstituteOverride::Config cfg;
cfg.map.insert({OverrideId{0}, 0.0});
- DataMap data;
+ Transform::DataMap data;
data.Add<SubstituteOverride::Config>(cfg);
auto got = Run<SubstituteOverride>(src, data);
diff --git a/src/tint/ast/transform/test_helper.h b/src/tint/ast/transform/test_helper.h
index 08b8e30..0ec2ec2 100644
--- a/src/tint/ast/transform/test_helper.h
+++ b/src/tint/ast/transform/test_helper.h
@@ -21,6 +21,7 @@
#include <vector>
#include "gtest/gtest.h"
+#include "src/tint/ast/transform/transform.h"
#include "src/tint/reader/wgsl/parser.h"
#include "src/tint/transform/manager.h"
#include "src/tint/writer/wgsl/generator.h"
@@ -66,11 +67,11 @@
/// `transform`.
/// @param transform the transform to apply
/// @param in the input WGSL source
- /// @param data the optional DataMap to pass to Transform::Run()
+ /// @param data the optional Transform::DataMap to pass to Transform::Run()
/// @return the transformed output
Output Run(std::string in,
std::unique_ptr<transform::Transform> transform,
- const DataMap& data = {}) {
+ const tint::transform::DataMap& data = {}) {
std::vector<std::unique_ptr<transform::Transform>> transforms;
transforms.emplace_back(std::move(transform));
return Run(std::move(in), std::move(transforms), data);
@@ -79,10 +80,10 @@
/// Transforms and returns the WGSL source `in`, transformed using
/// a transform of type `TRANSFORM`.
/// @param in the input WGSL source
- /// @param data the optional DataMap to pass to Transform::Run()
+ /// @param data the optional Transform::DataMap to pass to Transform::Run()
/// @return the transformed output
template <typename... TRANSFORMS>
- Output Run(std::string in, const DataMap& data = {}) {
+ Output Run(std::string in, const tint::transform::DataMap& data = {}) {
auto file = std::make_unique<Source::File>("test", in);
auto program = reader::wgsl::Parse(file.get());
@@ -95,26 +96,28 @@
/// Transforms and returns program `program`, transformed using a transform of
/// type `TRANSFORM`.
/// @param program the input Program
- /// @param data the optional DataMap to pass to Transform::Run()
+ /// @param data the optional Transform::DataMap to pass to Transform::Run()
/// @return the transformed output
template <typename... TRANSFORMS>
- Output Run(Program&& program, const DataMap& data = {}) {
+ Output Run(Program&& program, const tint::transform::DataMap& data = {}) {
if (!program.IsValid()) {
return Output(std::move(program));
}
tint::transform::Manager manager;
+ tint::transform::DataMap outputs;
for (auto* transform_ptr : std::initializer_list<Transform*>{new TRANSFORMS()...}) {
manager.append(std::unique_ptr<Transform>(transform_ptr));
}
- return manager.Run(&program, data);
+ auto result = manager.Run(&program, data, outputs);
+ return {std::move(result), std::move(outputs)};
}
/// @param program the input program
- /// @param data the optional DataMap to pass to Transform::Run()
+ /// @param data the optional Transform::DataMap to pass to Transform::Run()
/// @return true if the transform should be run for the given input.
template <typename TRANSFORM>
- bool ShouldRun(Program&& program, const DataMap& data = {}) {
+ bool ShouldRun(Program&& program, const tint::transform::DataMap& data = {}) {
if (!program.IsValid()) {
ADD_FAILURE() << "ShouldRun() called with invalid program: "
<< program.Diagnostics().str();
@@ -123,7 +126,7 @@
const Transform& t = TRANSFORM();
- DataMap outputs;
+ tint::transform::DataMap outputs;
auto result = t.Apply(&program, data, outputs);
if (!result) {
return false;
@@ -137,10 +140,10 @@
}
/// @param in the input WGSL source
- /// @param data the optional DataMap to pass to Transform::Run()
+ /// @param data the optional Transform::DataMap to pass to Transform::Run()
/// @return true if the transform should be run for the given input.
template <typename TRANSFORM>
- bool ShouldRun(std::string in, const DataMap& data = {}) {
+ bool ShouldRun(std::string in, const tint::transform::DataMap& data = {}) {
auto file = std::make_unique<Source::File>("test", in);
auto program = reader::wgsl::Parse(file.get());
return ShouldRun<TRANSFORM>(std::move(program), data);
diff --git a/src/tint/ast/transform/texture_1d_to_2d_test.cc b/src/tint/ast/transform/texture_1d_to_2d_test.cc
index 75da6fc..4189385 100644
--- a/src/tint/ast/transform/texture_1d_to_2d_test.cc
+++ b/src/tint/ast/transform/texture_1d_to_2d_test.cc
@@ -23,7 +23,7 @@
TEST_F(Texture1DTo2DTest, EmptyModule) {
auto* src = "";
- DataMap data;
+ Transform::DataMap data;
EXPECT_FALSE(ShouldRun<Texture1DTo2D>(src, data));
}
@@ -39,7 +39,7 @@
@group(0) @binding(1) var s : sampler;
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -65,7 +65,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -87,7 +87,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -109,7 +109,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -131,7 +131,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -153,7 +153,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -167,7 +167,7 @@
@group(0) @binding(0) var t : texture_storage_2d<r32float, write>;
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -184,7 +184,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
EXPECT_FALSE(ShouldRun<Texture1DTo2D>(src, data));
}
@@ -193,7 +193,7 @@
var<private> i : i32;
)";
- DataMap data;
+ Transform::DataMap data;
EXPECT_FALSE(ShouldRun<Texture1DTo2D>(src, data));
}
@@ -202,7 +202,7 @@
@group(0) @binding(0) var<uniform> m : mat2x2<f32>;
)";
- DataMap data;
+ Transform::DataMap data;
EXPECT_FALSE(ShouldRun<Texture1DTo2D>(src, data));
}
@@ -234,7 +234,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -265,7 +265,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
@@ -290,7 +290,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<Texture1DTo2D>(src, data);
EXPECT_EQ(expect, str(got));
diff --git a/src/tint/ast/transform/transform.cc b/src/tint/ast/transform/transform.cc
index 2270aff..bee1f39 100644
--- a/src/tint/ast/transform/transform.cc
+++ b/src/tint/ast/transform/transform.cc
@@ -28,20 +28,9 @@
#include "src/tint/type/sampler.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::Transform);
-TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::Data);
namespace tint::ast::transform {
-Data::Data() = default;
-Data::Data(const Data&) = default;
-Data::~Data() = default;
-Data& Data::operator=(const Data&) = default;
-
-DataMap::DataMap() = default;
-DataMap::DataMap(DataMap&&) = default;
-DataMap::~DataMap() = default;
-DataMap& DataMap::operator=(DataMap&&) = default;
-
Output::Output() = default;
Output::Output(Program&& p) : program(std::move(p)) {}
Transform::Transform() = default;
diff --git a/src/tint/ast/transform/transform.h b/src/tint/ast/transform/transform.h
index 82cadce..2ad3701 100644
--- a/src/tint/ast/transform/transform.h
+++ b/src/tint/ast/transform/transform.h
@@ -15,8 +15,8 @@
#ifndef SRC_TINT_AST_TRANSFORM_TRANSFORM_H_
#define SRC_TINT_AST_TRANSFORM_TRANSFORM_H_
-#include <memory>
-#include <unordered_map>
+#include "src/tint/transform/transform.h"
+
#include <utility>
#include "src/tint/program.h"
@@ -24,107 +24,6 @@
namespace tint::ast::transform {
-/// Data is the base class for transforms that accept extra input or emit extra
-/// output information along with a Program.
-class Data : public utils::Castable<Data> {
- public:
- /// Constructor
- Data();
-
- /// Copy constructor
- Data(const Data&);
-
- /// Destructor
- ~Data() override;
-
- /// Assignment operator
- /// @returns this Data
- Data& operator=(const Data&);
-};
-
-/// DataMap is a map of Data unique pointers keyed by the Data's ClassID.
-class DataMap {
- public:
- /// Constructor
- DataMap();
-
- /// Move constructor
- DataMap(DataMap&&);
-
- /// Constructor
- /// @param data_unique_ptrs a variadic list of additional data unique_ptrs
- /// produced by the transform
- template <typename... DATA>
- explicit DataMap(DATA... data_unique_ptrs) {
- PutAll(std::forward<DATA>(data_unique_ptrs)...);
- }
-
- /// Destructor
- ~DataMap();
-
- /// Move assignment operator
- /// @param rhs the DataMap to move into this DataMap
- /// @return this DataMap
- DataMap& operator=(DataMap&& rhs);
-
- /// Adds the data into DataMap keyed by the ClassID of type T.
- /// @param data the data to add to the DataMap
- template <typename T>
- void Put(std::unique_ptr<T>&& data) {
- static_assert(std::is_base_of<Data, T>::value, "T does not derive from Data");
- map_[&utils::TypeInfo::Of<T>()] = std::move(data);
- }
-
- /// Creates the data of type `T` with the provided arguments and adds it into
- /// DataMap keyed by the ClassID of type T.
- /// @param args the arguments forwarded to the initializer for type T
- template <typename T, typename... ARGS>
- void Add(ARGS&&... args) {
- Put(std::make_unique<T>(std::forward<ARGS>(args)...));
- }
-
- /// @returns a pointer to the Data placed into the DataMap with a call to
- /// Put()
- template <typename T>
- T const* Get() const {
- return const_cast<DataMap*>(this)->Get<T>();
- }
-
- /// @returns a pointer to the Data placed into the DataMap with a call to
- /// Put()
- template <typename T>
- T* Get() {
- auto it = map_.find(&utils::TypeInfo::Of<T>());
- if (it == map_.end()) {
- return nullptr;
- }
- return static_cast<T*>(it->second.get());
- }
-
- /// Add moves all the data from other into this DataMap
- /// @param other the DataMap to move into this DataMap
- void Add(DataMap&& other) {
- for (auto& it : other.map_) {
- map_.emplace(it.first, std::move(it.second));
- }
- other.map_.clear();
- }
-
- private:
- template <typename T0>
- void PutAll(T0&& first) {
- Put(std::forward<T0>(first));
- }
-
- template <typename T0, typename... Tn>
- void PutAll(T0&& first, Tn&&... remainder) {
- Put(std::forward<T0>(first));
- PutAll(std::forward<Tn>(remainder)...);
- }
-
- std::unordered_map<const utils::TypeInfo*, std::unique_ptr<Data>> map_;
-};
-
/// The return type of Run()
class Output {
public:
@@ -147,11 +46,11 @@
Program program;
/// Extra output generated by the transforms.
- DataMap data;
+ tint::transform::DataMap data;
};
/// Interface for Program transforms
-class Transform : public utils::Castable<Transform> {
+class Transform : public utils::Castable<Transform, tint::transform::Transform> {
public:
/// Constructor
Transform();
diff --git a/src/tint/ast/transform/truncate_interstage_variables.cc b/src/tint/ast/transform/truncate_interstage_variables.cc
index 157c544..1e5bf71 100644
--- a/src/tint/ast/transform/truncate_interstage_variables.cc
+++ b/src/tint/ast/transform/truncate_interstage_variables.cc
@@ -154,16 +154,15 @@
}
// Replace return statements with new truncated shader IO struct
- ctx.ReplaceAll(
- [&](const ReturnStatement* return_statement) -> const ReturnStatement* {
- auto* return_sem = sem.Get(return_statement);
- if (auto mapping_fn_sym =
- entry_point_functions_to_truncate_functions.Find(return_sem->Function())) {
- return b.Return(return_statement->source,
- b.Call(*mapping_fn_sym, ctx.Clone(return_statement->value)));
- }
- return nullptr;
- });
+ ctx.ReplaceAll([&](const ReturnStatement* return_statement) -> const ReturnStatement* {
+ auto* return_sem = sem.Get(return_statement);
+ if (auto mapping_fn_sym =
+ entry_point_functions_to_truncate_functions.Find(return_sem->Function())) {
+ return b.Return(return_statement->source,
+ b.Call(*mapping_fn_sym, ctx.Clone(return_statement->value)));
+ }
+ return nullptr;
+ });
// Remove IO attributes from old shader IO struct which is not used as entry point output
// anymore.
diff --git a/src/tint/ast/transform/truncate_interstage_variables_test.cc b/src/tint/ast/transform/truncate_interstage_variables_test.cc
index 14e546c..ecd691e 100644
--- a/src/tint/ast/transform/truncate_interstage_variables_test.cc
+++ b/src/tint/ast/transform/truncate_interstage_variables_test.cc
@@ -51,7 +51,7 @@
{
// Empty interstage_locations: truncate all interstage variables, should run
TruncateInterstageVariables::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
EXPECT_TRUE(ShouldRun<TruncateInterstageVariables>(src, data));
}
@@ -61,7 +61,7 @@
TruncateInterstageVariables::Config cfg;
cfg.interstage_locations[0] = true;
cfg.interstage_locations[2] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
EXPECT_FALSE(ShouldRun<TruncateInterstageVariables>(src, data));
}
@@ -70,7 +70,7 @@
// Partial interstage_locations are marked: should run
TruncateInterstageVariables::Config cfg;
cfg.interstage_locations[2] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
EXPECT_TRUE(ShouldRun<TruncateInterstageVariables>(src, data));
}
@@ -91,7 +91,7 @@
TruncateInterstageVariables::Config cfg;
cfg.interstage_locations[2] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
EXPECT_FALSE(ShouldRun<TruncateInterstageVariables>(src, data));
@@ -109,7 +109,7 @@
TruncateInterstageVariables::Config cfg;
cfg.interstage_locations[0] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
data.Add<CanonicalizeEntryPointIO::Config>(CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
@@ -169,7 +169,7 @@
// fragment has input at @location(1)
cfg.interstage_locations[1] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
@@ -226,7 +226,7 @@
// fragment has input at @location(3)
cfg.interstage_locations[3] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
@@ -279,7 +279,7 @@
)";
TruncateInterstageVariables::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
@@ -349,7 +349,7 @@
cfg.interstage_locations[3] = true;
cfg.interstage_locations[5] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
@@ -426,7 +426,7 @@
// fragment has input at @location(3)
cfg.interstage_locations[3] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
@@ -521,7 +521,7 @@
// fragment has input at @location(3)
cfg.interstage_locations[3] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
@@ -586,7 +586,7 @@
// fragment has input at @location(3)
cfg.interstage_locations[3] = true;
- DataMap data;
+ Transform::DataMap data;
data.Add<TruncateInterstageVariables::Config>(cfg);
auto got = Run<TruncateInterstageVariables>(src, data);
diff --git a/src/tint/ast/transform/var_for_dynamic_index_test.cc b/src/tint/ast/transform/var_for_dynamic_index_test.cc
index 4cfb15e..34d781f 100644
--- a/src/tint/ast/transform/var_for_dynamic_index_test.cc
+++ b/src/tint/ast/transform/var_for_dynamic_index_test.cc
@@ -49,7 +49,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -73,7 +73,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -105,7 +105,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -138,7 +138,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -171,7 +171,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -204,7 +204,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -237,7 +237,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -277,7 +277,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -311,7 +311,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -364,7 +364,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -398,7 +398,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -451,7 +451,7 @@
}
)";
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -467,7 +467,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -483,7 +483,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -501,7 +501,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -519,7 +519,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -537,7 +537,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
@@ -553,7 +553,7 @@
auto* expect = src;
- DataMap data;
+ Transform::DataMap data;
auto got = Run<VarForDynamicIndex>(src, data);
EXPECT_EQ(expect, str(got));
diff --git a/src/tint/ast/transform/vertex_pulling_test.cc b/src/tint/ast/transform/vertex_pulling_test.cc
index eb46dd5..a0640e8 100644
--- a/src/tint/ast/transform/vertex_pulling_test.cc
+++ b/src/tint/ast/transform/vertex_pulling_test.cc
@@ -28,7 +28,7 @@
auto* expect = "error: Vertex stage entry point not found";
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>();
auto got = Run<VertexPulling>(src, data);
@@ -51,7 +51,7 @@
VertexPulling::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -68,7 +68,7 @@
VertexPulling::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -90,7 +90,7 @@
VertexPulling::Config cfg;
cfg.vertex_state = {{{15, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -118,7 +118,7 @@
VertexPulling::Config cfg;
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -154,7 +154,7 @@
VertexPulling::Config cfg;
cfg.vertex_state = {{{4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -190,7 +190,7 @@
VertexPulling::Config cfg;
cfg.vertex_state = {{{4, VertexStepMode::kInstance, {{VertexFormat::kFloat32, 0, 0}}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -227,7 +227,7 @@
cfg.vertex_state = {{{4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}};
cfg.pulling_group = 5;
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -272,7 +272,7 @@
VertexPulling::Config cfg;
cfg.vertex_state = {{{4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -329,7 +329,7 @@
},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -407,7 +407,7 @@
},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -485,7 +485,7 @@
},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -560,7 +560,7 @@
},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -635,7 +635,7 @@
},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -676,7 +676,7 @@
VertexStepMode::kVertex,
{{VertexFormat::kFloat32, 0, 0}, {VertexFormat::kFloat32x4, 0, 1}}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -729,7 +729,7 @@
{16, VertexStepMode::kVertex, {{VertexFormat::kFloat32x4, 0, 2}}},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -786,7 +786,7 @@
{16, VertexStepMode::kVertex, {{VertexFormat::kFloat16x4, 0, 2}}},
}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -835,7 +835,7 @@
VertexStepMode::kVertex,
{{VertexFormat::kFloat32, 0, 0}, {VertexFormat::kFloat32x4, 0, 1}}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, std::move(data));
@@ -905,7 +905,7 @@
{VertexFormat::kSint32x4, 64, 7},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -975,7 +975,7 @@
{VertexFormat::kUint32x4, 64, 7},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1069,7 +1069,7 @@
{VertexFormat::kFloat32x4, 64, 13},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1167,7 +1167,7 @@
{VertexFormat::kFloat32x4, 64, 13},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1237,7 +1237,7 @@
{VertexFormat::kSint32x4, 63, 7},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1307,7 +1307,7 @@
{VertexFormat::kUint32x4, 63, 7},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1401,7 +1401,7 @@
{VertexFormat::kFloat32x4, 63, 13},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1499,7 +1499,7 @@
{VertexFormat::kFloat32x4, 63, 13},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1577,7 +1577,7 @@
{VertexFormat::kSint32x3, 64, 9},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1655,7 +1655,7 @@
{VertexFormat::kUint32x3, 64, 9},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1757,7 +1757,7 @@
{VertexFormat::kFloat32x3, 64, 15},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1863,7 +1863,7 @@
{VertexFormat::kFloat32x3, 64, 15},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -1957,7 +1957,7 @@
{VertexFormat::kSint32x4, 64, 13},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -2051,7 +2051,7 @@
{VertexFormat::kUint32x4, 64, 13},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -2181,7 +2181,7 @@
{VertexFormat::kFloat32x4, 64, 24}, {VertexFormat::kFloat32x4, 64, 25},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
@@ -2315,7 +2315,7 @@
{VertexFormat::kFloat32x4, 64, 24}, {VertexFormat::kFloat32x4, 64, 25},
}}}};
- DataMap data;
+ Transform::DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index 9f7fa36..bfdc41f 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -947,32 +947,30 @@
/// Returns true on success, false on error (program will immediately exit)
std::function<bool(tint::inspector::Inspector& inspector,
tint::transform::Manager& manager,
- tint::ast::transform::DataMap& inputs)>
+ tint::transform::DataMap& inputs)>
make;
};
std::vector<TransformFactory> transforms = {
{"first_index_offset",
- [](tint::inspector::Inspector&, tint::transform::Manager& m,
- tint::ast::transform::DataMap& i) {
+ [](tint::inspector::Inspector&, tint::transform::Manager& m, tint::transform::DataMap& i) {
i.Add<tint::ast::transform::FirstIndexOffset::BindingPoint>(0, 0);
m.Add<tint::ast::transform::FirstIndexOffset>();
return true;
}},
{"renamer",
- [](tint::inspector::Inspector&, tint::transform::Manager& m,
- tint::ast::transform::DataMap&) {
+ [](tint::inspector::Inspector&, tint::transform::Manager& m, tint::transform::DataMap&) {
m.Add<tint::ast::transform::Renamer>();
return true;
}},
{"robustness",
[&](tint::inspector::Inspector&, tint::transform::Manager&,
- tint::ast::transform::DataMap&) { // enabled via writer option
+ tint::transform::DataMap&) { // enabled via writer option
options.enable_robustness = true;
return true;
}},
{"substitute_override",
[&](tint::inspector::Inspector& inspector, tint::transform::Manager& m,
- tint::ast::transform::DataMap& i) {
+ tint::transform::DataMap& i) {
tint::ast::transform::SubstituteOverride::Config cfg;
std::unordered_map<tint::OverrideId, double> values;
@@ -1098,7 +1096,7 @@
}
tint::transform::Manager transform_manager;
- tint::ast::transform::DataMap transform_inputs;
+ tint::transform::DataMap transform_inputs;
// Renaming must always come first
switch (options.format) {
@@ -1173,14 +1171,15 @@
transform_inputs.Add<tint::ast::transform::SingleEntryPoint::Config>(options.ep_name);
}
- auto out = transform_manager.Run(program.get(), std::move(transform_inputs));
- if (!out.program.IsValid()) {
- tint::cmd::PrintWGSL(std::cerr, out.program);
- diag_formatter.format(out.program.Diagnostics(), diag_printer.get());
+ tint::transform::DataMap outputs;
+ auto out = transform_manager.Run(program.get(), std::move(transform_inputs), outputs);
+ if (!out.IsValid()) {
+ tint::cmd::PrintWGSL(std::cerr, out);
+ diag_formatter.format(out.Diagnostics(), diag_printer.get());
return 1;
}
- *program = std::move(out.program);
+ *program = std::move(out);
bool success = false;
switch (options.format) {
diff --git a/src/tint/fuzzers/shuffle_transform.cc b/src/tint/fuzzers/shuffle_transform.cc
index 9a075c2..6d0dfd7 100644
--- a/src/tint/fuzzers/shuffle_transform.cc
+++ b/src/tint/fuzzers/shuffle_transform.cc
@@ -24,8 +24,8 @@
ShuffleTransform::ShuffleTransform(size_t seed) : seed_(seed) {}
ast::transform::Transform::ApplyResult ShuffleTransform::Apply(const Program* src,
- const ast::transform::DataMap&,
- ast::transform::DataMap&) const {
+ const transform::DataMap&,
+ transform::DataMap&) const {
ProgramBuilder b;
CloneContext ctx{&b, src, /* auto_clone_symbols */ true};
diff --git a/src/tint/fuzzers/shuffle_transform.h b/src/tint/fuzzers/shuffle_transform.h
index 6edbfd7..8a5ceeb 100644
--- a/src/tint/fuzzers/shuffle_transform.h
+++ b/src/tint/fuzzers/shuffle_transform.h
@@ -28,8 +28,8 @@
/// @copydoc ast::transform::Transform::Apply
ApplyResult Apply(const Program* program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
+ const transform::DataMap& inputs,
+ transform::DataMap& outputs) const override;
private:
size_t seed_;
diff --git a/src/tint/fuzzers/tint_common_fuzzer.cc b/src/tint/fuzzers/tint_common_fuzzer.cc
index 122ab87..5595d10 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.cc
+++ b/src/tint/fuzzers/tint_common_fuzzer.cc
@@ -205,10 +205,10 @@
diagnostics_ = program.Diagnostics();
auto validate_program = [&](auto& out) {
- if (!out.program.IsValid()) {
+ if (!out.IsValid()) {
// Transforms can produce error messages for bad input.
// Catch ICEs and errors from non transform systems.
- for (const auto& diag : out.program.Diagnostics()) {
+ for (const auto& diag : out.Diagnostics()) {
if (diag.severity > diag::Severity::Error ||
diag.system != diag::System::Transform) {
VALIDITY_ERROR(program.Diagnostics(),
@@ -219,13 +219,14 @@
return 0;
}
- program = std::move(out.program);
+ program = std::move(out);
RunInspector(&program);
return 1;
};
if (transform_manager_) {
- auto out = transform_manager_->Run(&program, *transform_inputs_);
+ transform::DataMap outputs;
+ auto out = transform_manager_->Run(&program, *transform_inputs_, outputs);
if (!validate_program(out)) {
return 0;
}
@@ -248,13 +249,14 @@
}
if (!cfg.map.empty()) {
- ast::transform::DataMap override_data;
+ transform::DataMap override_data;
override_data.Add<ast::transform::SubstituteOverride::Config>(cfg);
transform::Manager mgr;
mgr.append(std::make_unique<ast::transform::SubstituteOverride>());
- auto out = mgr.Run(&program, override_data);
+ transform::DataMap outputs;
+ auto out = mgr.Run(&program, override_data, outputs);
if (!validate_program(out)) {
return 0;
}
diff --git a/src/tint/fuzzers/tint_common_fuzzer.h b/src/tint/fuzzers/tint_common_fuzzer.h
index fdf50d5..c1cb656 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.h
+++ b/src/tint/fuzzers/tint_common_fuzzer.h
@@ -63,7 +63,7 @@
/// @param tm manager for transforms to run
/// @param inputs data for transforms to run
- void SetTransformManager(transform::Manager* tm, ast::transform::DataMap* inputs) {
+ void SetTransformManager(transform::Manager* tm, transform::DataMap* inputs) {
assert((!tm || inputs) && "DataMap must be !nullptr if Manager !nullptr");
transform_manager_ = tm;
transform_inputs_ = inputs;
@@ -121,7 +121,7 @@
InputFormat input_;
OutputFormat output_;
transform::Manager* transform_manager_ = nullptr;
- ast::transform::DataMap* transform_inputs_ = nullptr;
+ transform::DataMap* transform_inputs_ = nullptr;
bool dump_input_ = false;
tint::diag::List diagnostics_;
bool enforce_validity = false;
diff --git a/src/tint/fuzzers/tint_reader_writer_fuzzer.h b/src/tint/fuzzers/tint_reader_writer_fuzzer.h
index 94c4fc4..b5d0a95 100644
--- a/src/tint/fuzzers/tint_reader_writer_fuzzer.h
+++ b/src/tint/fuzzers/tint_reader_writer_fuzzer.h
@@ -38,7 +38,7 @@
/// invoked.
/// @param tm manager for transforms to run
/// @param inputs data for transforms to run
- void SetTransformManager(transform::Manager* tm, ast::transform::DataMap* inputs) {
+ void SetTransformManager(transform::Manager* tm, transform::DataMap* inputs) {
tm_set_ = true;
CommonFuzzer::SetTransformManager(tm, inputs);
}
diff --git a/src/tint/fuzzers/transform_builder.h b/src/tint/fuzzers/transform_builder.h
index 037568f..a8bcb6d 100644
--- a/src/tint/fuzzers/transform_builder.h
+++ b/src/tint/fuzzers/transform_builder.h
@@ -48,7 +48,7 @@
transform::Manager* manager() { return &manager_; }
/// @returns data for transforms
- ast::transform::DataMap* data_map() { return &data_map_; }
+ transform::DataMap* data_map() { return &data_map_; }
/// Adds a transform and needed data to |manager_| and |data_map_|.
/// @tparam T - A class that inherits from ast::transform::Transform and has an
@@ -73,7 +73,7 @@
private:
DataBuilder builder_;
transform::Manager manager_;
- ast::transform::DataMap data_map_;
+ transform::DataMap data_map_;
DataBuilder* builder() { return &builder_; }
diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc
index 7baf0cd..2968d28 100644
--- a/src/tint/ir/binary_test.cc
+++ b/src/tint/ir/binary_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ir/builder.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
@@ -23,10 +24,10 @@
using IR_InstructionTest = TestHelper;
TEST_F(IR_InstructionTest, CreateAnd) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.And(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
- b.builder.Constant(2_i));
+ const auto* inst = b.And(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
@@ -45,10 +46,10 @@
}
TEST_F(IR_InstructionTest, CreateOr) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Or(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
- b.builder.Constant(2_i));
+ const auto* inst = b.Or(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kOr);
@@ -65,10 +66,10 @@
}
TEST_F(IR_InstructionTest, CreateXor) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Xor(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
- b.builder.Constant(2_i));
+ const auto* inst = b.Xor(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kXor);
@@ -85,10 +86,10 @@
}
TEST_F(IR_InstructionTest, CreateEqual) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Equal(b.builder.ir.types.Get<type::Bool>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.Equal(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kEqual);
@@ -105,10 +106,10 @@
}
TEST_F(IR_InstructionTest, CreateNotEqual) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.NotEqual(b.builder.ir.types.Get<type::Bool>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.NotEqual(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kNotEqual);
@@ -125,10 +126,10 @@
}
TEST_F(IR_InstructionTest, CreateLessThan) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.LessThan(b.builder.ir.types.Get<type::Bool>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.LessThan(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kLessThan);
@@ -145,10 +146,11 @@
}
TEST_F(IR_InstructionTest, CreateGreaterThan) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.GreaterThan(b.builder.ir.types.Get<type::Bool>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst =
+ b.GreaterThan(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kGreaterThan);
@@ -165,10 +167,11 @@
}
TEST_F(IR_InstructionTest, CreateLessThanEqual) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.LessThanEqual(b.builder.ir.types.Get<type::Bool>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst =
+ b.LessThanEqual(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kLessThanEqual);
@@ -185,10 +188,11 @@
}
TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.GreaterThanEqual(b.builder.ir.types.Get<type::Bool>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst =
+ b.GreaterThanEqual(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kGreaterThanEqual);
@@ -205,9 +209,9 @@
}
TEST_F(IR_InstructionTest, CreateNot) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Not(b.builder.ir.types.Get<type::Bool>(), b.builder.Constant(true));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.Not(b.ir.types.Get<type::Bool>(), b.Constant(true));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kEqual);
@@ -224,10 +228,10 @@
}
TEST_F(IR_InstructionTest, CreateShiftLeft) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.ShiftLeft(b.builder.ir.types.Get<type::I32>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.ShiftLeft(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kShiftLeft);
@@ -244,10 +248,10 @@
}
TEST_F(IR_InstructionTest, CreateShiftRight) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.ShiftRight(b.builder.ir.types.Get<type::I32>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.ShiftRight(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kShiftRight);
@@ -264,10 +268,10 @@
}
TEST_F(IR_InstructionTest, CreateAdd) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Add(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
- b.builder.Constant(2_i));
+ const auto* inst = b.Add(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kAdd);
@@ -284,10 +288,10 @@
}
TEST_F(IR_InstructionTest, CreateSubtract) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Subtract(b.builder.ir.types.Get<type::I32>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.Subtract(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kSubtract);
@@ -304,10 +308,10 @@
}
TEST_F(IR_InstructionTest, CreateMultiply) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Multiply(b.builder.ir.types.Get<type::I32>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.Multiply(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kMultiply);
@@ -324,10 +328,10 @@
}
TEST_F(IR_InstructionTest, CreateDivide) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Divide(b.builder.ir.types.Get<type::I32>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.Divide(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kDivide);
@@ -344,10 +348,10 @@
}
TEST_F(IR_InstructionTest, CreateModulo) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Modulo(b.builder.ir.types.Get<type::I32>(),
- b.builder.Constant(4_i), b.builder.Constant(2_i));
+ const auto* inst = b.Modulo(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->kind, Binary::Kind::kModulo);
@@ -364,9 +368,9 @@
}
TEST_F(IR_InstructionTest, Binary_Usage) {
- auto& b = CreateEmptyBuilder();
- const auto* inst = b.builder.And(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
- b.builder.Constant(2_i));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.And(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
@@ -380,9 +384,10 @@
}
TEST_F(IR_InstructionTest, Binary_Usage_DuplicateValue) {
- auto& b = CreateEmptyBuilder();
- auto val = b.builder.Constant(4_i);
- const auto* inst = b.builder.And(b.builder.ir.types.Get<type::I32>(), val, val);
+ Module mod;
+ Builder b{mod};
+ auto val = b.Constant(4_i);
+ const auto* inst = b.And(b.ir.types.Get<type::I32>(), val, val);
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
ASSERT_EQ(inst->LHS(), inst->RHS());
diff --git a/src/tint/ir/bitcast_test.cc b/src/tint/ir/bitcast_test.cc
index dfe7461..e78b734 100644
--- a/src/tint/ir/bitcast_test.cc
+++ b/src/tint/ir/bitcast_test.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ir/builder.h"
+#include "src/tint/ir/constant.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
@@ -23,9 +25,9 @@
using IR_InstructionTest = TestHelper;
TEST_F(IR_InstructionTest, Bitcast) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Bitcast(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.Bitcast(b.ir.types.Get<type::I32>(), b.Constant(4_i));
ASSERT_TRUE(inst->Is<ir::Bitcast>());
ASSERT_NE(inst->Type(), nullptr);
@@ -38,9 +40,9 @@
}
TEST_F(IR_InstructionTest, Bitcast_Usage) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Bitcast(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.Bitcast(b.ir.types.Get<type::I32>(), b.Constant(4_i));
ASSERT_EQ(inst->args.Length(), 1u);
ASSERT_NE(inst->args[0], nullptr);
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index fe350cd..d62bb43 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -20,9 +20,7 @@
namespace tint::ir {
-Builder::Builder() {}
-
-Builder::Builder(Module&& mod) : ir(std::move(mod)) {}
+Builder::Builder(Module& mod) : ir(mod) {}
Builder::~Builder() = default;
@@ -49,8 +47,13 @@
return ir.flow_nodes.Create<FunctionTerminator>();
}
-Function* Builder::CreateFunction() {
- auto* ir_func = ir.flow_nodes.Create<Function>();
+Function* Builder::CreateFunction(Symbol name,
+ type::Type* return_type,
+ Function::PipelineStage stage,
+ std::optional<std::array<uint32_t, 3>> wg_size) {
+ TINT_ASSERT(IR, return_type);
+
+ auto* ir_func = ir.flow_nodes.Create<Function>(name, return_type, stage, wg_size);
ir_func->start_target = CreateBlock();
ir_func->end_target = CreateFunctionTerminator();
@@ -60,8 +63,10 @@
return ir_func;
}
-If* Builder::CreateIf() {
- auto* ir_if = ir.flow_nodes.Create<If>();
+If* Builder::CreateIf(Value* condition) {
+ TINT_ASSERT(IR, condition);
+
+ auto* ir_if = ir.flow_nodes.Create<If>(condition);
ir_if->true_.target = CreateBlock();
ir_if->false_.target = CreateBlock();
ir_if->merge.target = CreateBlock();
@@ -85,8 +90,8 @@
return ir_loop;
}
-Switch* Builder::CreateSwitch() {
- auto* ir_switch = ir.flow_nodes.Create<Switch>();
+Switch* Builder::CreateSwitch(Value* condition) {
+ auto* ir_switch = ir.flow_nodes.Create<Switch>(condition);
ir_switch->merge.target = CreateBlock();
return ir_switch;
}
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index 87a256b..b4a2a81 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -50,10 +50,8 @@
class Builder {
public:
/// Constructor
- Builder();
- /// Constructor
/// @param mod the ir::Module to wrap with this builder
- explicit Builder(Module&& mod);
+ explicit Builder(Module& mod);
/// Destructor
~Builder();
@@ -67,20 +65,29 @@
FunctionTerminator* CreateFunctionTerminator();
/// Creates a function flow node
+ /// @param name the function name
+ /// @param return_type the function return type
+ /// @param stage the function stage
+ /// @param wg_size the workgroup_size
/// @returns the flow node
- Function* CreateFunction();
+ Function* CreateFunction(Symbol name,
+ type::Type* return_type,
+ Function::PipelineStage stage = Function::PipelineStage::kUndefined,
+ std::optional<std::array<uint32_t, 3>> wg_size = {});
/// Creates an if flow node
+ /// @param condition the if condition
/// @returns the flow node
- If* CreateIf();
+ If* CreateIf(Value* condition);
/// Creates a loop flow node
/// @returns the flow node
Loop* CreateLoop();
/// Creates a switch flow node
+ /// @param condition the switch condition
/// @returns the flow node
- Switch* CreateSwitch();
+ Switch* CreateSwitch(Value* condition);
/// Creates a case flow node for the given case branch.
/// @param s the switch to create the case into
@@ -92,7 +99,7 @@
/// @param from the block to branch from
/// @param to the node to branch too
/// @param args arguments to the branch
- void Branch(Block* from, FlowNode* to, utils::VectorRef<Value*> args);
+ void Branch(Block* from, FlowNode* to, utils::VectorRef<Value*> args = {});
/// Creates a constant::Value
/// @param args the arguments
@@ -363,7 +370,7 @@
ir::Block* CreateRootBlockIfNeeded();
/// The IR module.
- Module ir;
+ Module& ir;
};
} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc
deleted file mode 100644
index bf6a0e7..0000000
--- a/src/tint/ir/builder_impl.cc
+++ /dev/null
@@ -1,1145 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/ir/builder_impl.h"
-
-#include <iostream>
-
-#include "src/tint/ast/alias.h"
-#include "src/tint/ast/assignment_statement.h"
-#include "src/tint/ast/binary_expression.h"
-#include "src/tint/ast/bitcast_expression.h"
-#include "src/tint/ast/block_statement.h"
-#include "src/tint/ast/bool_literal_expression.h"
-#include "src/tint/ast/break_if_statement.h"
-#include "src/tint/ast/break_statement.h"
-#include "src/tint/ast/call_expression.h"
-#include "src/tint/ast/call_statement.h"
-#include "src/tint/ast/compound_assignment_statement.h"
-#include "src/tint/ast/const.h"
-#include "src/tint/ast/const_assert.h"
-#include "src/tint/ast/continue_statement.h"
-#include "src/tint/ast/discard_statement.h"
-#include "src/tint/ast/float_literal_expression.h"
-#include "src/tint/ast/for_loop_statement.h"
-#include "src/tint/ast/function.h"
-#include "src/tint/ast/id_attribute.h"
-#include "src/tint/ast/identifier.h"
-#include "src/tint/ast/identifier_expression.h"
-#include "src/tint/ast/if_statement.h"
-#include "src/tint/ast/int_literal_expression.h"
-#include "src/tint/ast/invariant_attribute.h"
-#include "src/tint/ast/let.h"
-#include "src/tint/ast/literal_expression.h"
-#include "src/tint/ast/loop_statement.h"
-#include "src/tint/ast/override.h"
-#include "src/tint/ast/return_statement.h"
-#include "src/tint/ast/statement.h"
-#include "src/tint/ast/struct.h"
-#include "src/tint/ast/struct_member_align_attribute.h"
-#include "src/tint/ast/struct_member_size_attribute.h"
-#include "src/tint/ast/switch_statement.h"
-#include "src/tint/ast/templated_identifier.h"
-#include "src/tint/ast/unary_op_expression.h"
-#include "src/tint/ast/var.h"
-#include "src/tint/ast/variable_decl_statement.h"
-#include "src/tint/ast/while_statement.h"
-#include "src/tint/ir/function.h"
-#include "src/tint/ir/if.h"
-#include "src/tint/ir/loop.h"
-#include "src/tint/ir/module.h"
-#include "src/tint/ir/store.h"
-#include "src/tint/ir/switch.h"
-#include "src/tint/ir/value.h"
-#include "src/tint/program.h"
-#include "src/tint/sem/builtin.h"
-#include "src/tint/sem/call.h"
-#include "src/tint/sem/function.h"
-#include "src/tint/sem/materialize.h"
-#include "src/tint/sem/module.h"
-#include "src/tint/sem/switch_statement.h"
-#include "src/tint/sem/value_constructor.h"
-#include "src/tint/sem/value_conversion.h"
-#include "src/tint/sem/value_expression.h"
-#include "src/tint/sem/variable.h"
-#include "src/tint/switch.h"
-#include "src/tint/type/void.h"
-#include "src/tint/utils/defer.h"
-#include "src/tint/utils/scoped_assignment.h"
-
-namespace tint::ir {
-namespace {
-
-using ResultType = utils::Result<Module>;
-
-class FlowStackScope {
- public:
- FlowStackScope(BuilderImpl* impl, FlowNode* node) : impl_(impl) {
- impl_->flow_stack.Push(node);
- }
-
- ~FlowStackScope() { impl_->flow_stack.Pop(); }
-
- private:
- BuilderImpl* impl_;
-};
-
-bool IsBranched(const Block* b) {
- return b->branch.target != nullptr;
-}
-
-bool IsConnected(const FlowNode* b) {
- // Function is always connected as it's the start.
- if (b->Is<ir::Function>()) {
- return true;
- }
-
- for (auto* parent : b->inbound_branches) {
- if (IsConnected(parent)) {
- return true;
- }
- }
- // Getting here means all the incoming branches are disconnected.
- return false;
-}
-
-} // namespace
-
-BuilderImpl::BuilderImpl(const Program* program)
- : program_(program),
- clone_ctx_{
- type::CloneContext{{&program->Symbols()}, {&builder.ir.symbols, &builder.ir.types}},
- {&builder.ir.constants}} {}
-
-BuilderImpl::~BuilderImpl() = default;
-
-void BuilderImpl::add_error(const Source& s, const std::string& err) {
- diagnostics_.add_error(tint::diag::System::IR, err, s);
-}
-
-void BuilderImpl::BranchTo(FlowNode* node, utils::VectorRef<Value*> args) {
- TINT_ASSERT(IR, current_flow_block);
- TINT_ASSERT(IR, !IsBranched(current_flow_block));
-
- builder.Branch(current_flow_block, node, args);
- current_flow_block = nullptr;
-}
-
-void BuilderImpl::BranchToIfNeeded(FlowNode* node) {
- if (!current_flow_block || IsBranched(current_flow_block)) {
- return;
- }
- BranchTo(node);
-}
-
-FlowNode* BuilderImpl::FindEnclosingControl(ControlFlags flags) {
- for (auto it = flow_stack.rbegin(); it != flow_stack.rend(); ++it) {
- if ((*it)->Is<Loop>()) {
- return *it;
- }
- if (flags == ControlFlags::kExcludeSwitch) {
- continue;
- }
- if ((*it)->Is<Switch>()) {
- return *it;
- }
- }
- return nullptr;
-}
-
-Symbol BuilderImpl::CloneSymbol(Symbol sym) const {
- return clone_ctx_.type_ctx.dst.st->Register(sym.Name());
-}
-
-ResultType BuilderImpl::Build() {
- auto* sem = program_->Sem().Module();
-
- for (auto* decl : sem->DependencyOrderedDeclarations()) {
- tint::Switch(
- decl, //
- [&](const ast::Struct*) {
- // Will be encoded into the `type::Struct` when used. We will then hoist all
- // used structs up to module scope when converting IR.
- },
- [&](const ast::Alias*) {
- // Folded away and doesn't appear in the IR.
- },
- [&](const ast::Variable* var) {
- // Setup the current flow node to be the root block for the module. The builder will
- // handle creating it if it doesn't exist already.
- TINT_SCOPED_ASSIGNMENT(current_flow_block, builder.CreateRootBlockIfNeeded());
- EmitVariable(var);
- },
- [&](const ast::Function* func) { EmitFunction(func); },
- // [&](const ast::Enable*) {
- // TODO(dsinclair): Implement? I think these need to be passed along so further stages
- // know what is enabled.
- // },
- [&](const ast::ConstAssert*) {
- // Evaluated by the resolver, drop from the IR.
- },
- [&](Default) {
- add_error(decl->source, "unknown type: " + std::string(decl->TypeInfo().name));
- });
- }
- if (!diagnostics_.empty()) {
- return utils::Failure;
- }
-
- return ResultType{std::move(builder.ir)};
-}
-
-void BuilderImpl::EmitFunction(const ast::Function* ast_func) {
- // The flow stack should have been emptied when the previous function finished building.
- TINT_ASSERT(IR, flow_stack.IsEmpty());
-
- auto* ir_func = builder.CreateFunction();
- ir_func->name = CloneSymbol(ast_func->name->symbol);
- current_function_ = ir_func;
- builder.ir.functions.Push(ir_func);
-
- ast_to_flow_[ast_func] = ir_func;
-
- const auto* sem = program_->Sem().Get(ast_func);
- if (ast_func->IsEntryPoint()) {
- builder.ir.entry_points.Push(ir_func);
-
- switch (ast_func->PipelineStage()) {
- case ast::PipelineStage::kVertex:
- ir_func->pipeline_stage = Function::PipelineStage::kVertex;
- break;
- case ast::PipelineStage::kFragment:
- ir_func->pipeline_stage = Function::PipelineStage::kFragment;
- break;
- case ast::PipelineStage::kCompute: {
- ir_func->pipeline_stage = Function::PipelineStage::kCompute;
-
- auto wg_size = sem->WorkgroupSize();
- ir_func->workgroup_size = {
- wg_size[0].value(),
- wg_size[1].value_or(1),
- wg_size[2].value_or(1),
- };
- break;
- }
- default: {
- TINT_ICE(IR, diagnostics_) << "Invalid pipeline stage";
- return;
- }
- }
-
- for (auto* attr : ast_func->return_type_attributes) {
- tint::Switch(
- attr, //
- [&](const ast::LocationAttribute*) {
- ir_func->return_attributes.Push(Function::ReturnAttribute::kLocation);
- },
- [&](const ast::InvariantAttribute*) {
- ir_func->return_attributes.Push(Function::ReturnAttribute::kInvariant);
- },
- [&](const ast::BuiltinAttribute* b) {
- if (auto* ident_sem =
- program_->Sem()
- .Get(b)
- ->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>()) {
- switch (ident_sem->Value()) {
- case builtin::BuiltinValue::kPosition:
- ir_func->return_attributes.Push(
- Function::ReturnAttribute::kPosition);
- break;
- case builtin::BuiltinValue::kFragDepth:
- ir_func->return_attributes.Push(
- Function::ReturnAttribute::kFragDepth);
- break;
- case builtin::BuiltinValue::kSampleMask:
- ir_func->return_attributes.Push(
- Function::ReturnAttribute::kSampleMask);
- break;
- default:
- TINT_ICE(IR, diagnostics_)
- << "Unknown builtin value in return attributes "
- << ident_sem->Value();
- return;
- }
- } else {
- TINT_ICE(IR, diagnostics_) << "Builtin attribute sem invalid";
- return;
- }
- });
- }
- }
- ir_func->return_type = sem->ReturnType()->Clone(clone_ctx_.type_ctx);
- ir_func->return_location = sem->ReturnLocation();
-
- {
- FlowStackScope scope(this, ir_func);
-
- current_flow_block = ir_func->start_target;
- EmitBlock(ast_func->body);
-
- // TODO(dsinclair): Store return type and attributes
- // TODO(dsinclair): Store parameters
-
- // If the branch target has already been set then a `return` was called. Only set in the
- // case where `return` wasn't called.
- BranchToIfNeeded(current_function_->end_target);
- }
-
- TINT_ASSERT(IR, flow_stack.IsEmpty());
- current_flow_block = nullptr;
- current_function_ = nullptr;
-}
-
-void BuilderImpl::EmitStatements(utils::VectorRef<const ast::Statement*> stmts) {
- for (auto* s : stmts) {
- EmitStatement(s);
-
- // If the current flow block has a branch target then the rest of the statements in this
- // block are dead code. Skip them.
- if (!current_flow_block || IsBranched(current_flow_block)) {
- break;
- }
- }
-}
-
-void BuilderImpl::EmitStatement(const ast::Statement* stmt) {
- tint::Switch(
- stmt, //
- [&](const ast::AssignmentStatement* a) { EmitAssignment(a); },
- [&](const ast::BlockStatement* b) { EmitBlock(b); },
- [&](const ast::BreakStatement* b) { EmitBreak(b); },
- [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); },
- [&](const ast::CallStatement* c) { EmitCall(c); },
- [&](const ast::CompoundAssignmentStatement* c) { EmitCompoundAssignment(c); },
- [&](const ast::ContinueStatement* c) { EmitContinue(c); },
- [&](const ast::DiscardStatement* d) { EmitDiscard(d); },
- [&](const ast::IfStatement* i) { EmitIf(i); },
- [&](const ast::LoopStatement* l) { EmitLoop(l); },
- [&](const ast::ForLoopStatement* l) { EmitForLoop(l); },
- [&](const ast::WhileStatement* l) { EmitWhile(l); },
- [&](const ast::ReturnStatement* r) { EmitReturn(r); },
- [&](const ast::SwitchStatement* s) { EmitSwitch(s); },
- [&](const ast::VariableDeclStatement* v) { EmitVariable(v->variable); },
- [&](const ast::ConstAssert*) {
- // Not emitted
- },
- [&](Default) {
- add_error(stmt->source,
- "unknown statement type: " + std::string(stmt->TypeInfo().name));
- });
-}
-
-void BuilderImpl::EmitAssignment(const ast::AssignmentStatement* stmt) {
- auto lhs = EmitExpression(stmt->lhs);
- if (!lhs) {
- return;
- }
-
- auto rhs = EmitExpression(stmt->rhs);
- if (!rhs) {
- return;
- }
- auto store = builder.Store(lhs.Get(), rhs.Get());
- current_flow_block->instructions.Push(store);
-}
-
-void BuilderImpl::EmitCompoundAssignment(const ast::CompoundAssignmentStatement* stmt) {
- auto lhs = EmitExpression(stmt->lhs);
- if (!lhs) {
- return;
- }
-
- auto rhs = EmitExpression(stmt->rhs);
- if (!rhs) {
- return;
- }
-
- auto* ty = lhs.Get()->Type();
- Binary* inst = nullptr;
- switch (stmt->op) {
- case ast::BinaryOp::kAnd:
- inst = builder.And(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kOr:
- inst = builder.Or(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kXor:
- inst = builder.Xor(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kShiftLeft:
- inst = builder.ShiftLeft(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kShiftRight:
- inst = builder.ShiftRight(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kAdd:
- inst = builder.Add(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kSubtract:
- inst = builder.Subtract(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kMultiply:
- inst = builder.Multiply(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kDivide:
- inst = builder.Divide(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kModulo:
- inst = builder.Modulo(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kLessThanEqual:
- case ast::BinaryOp::kGreaterThanEqual:
- case ast::BinaryOp::kGreaterThan:
- case ast::BinaryOp::kLessThan:
- case ast::BinaryOp::kNotEqual:
- case ast::BinaryOp::kEqual:
- case ast::BinaryOp::kLogicalAnd:
- case ast::BinaryOp::kLogicalOr:
- TINT_ICE(IR, diagnostics_) << "invalid compound assignment";
- return;
- case ast::BinaryOp::kNone:
- TINT_ICE(IR, diagnostics_) << "missing binary operand type";
- return;
- }
- current_flow_block->instructions.Push(inst);
-
- auto store = builder.Store(lhs.Get(), inst);
- current_flow_block->instructions.Push(store);
-}
-
-void BuilderImpl::EmitBlock(const ast::BlockStatement* block) {
- scopes_.Push();
- TINT_DEFER(scopes_.Pop());
-
- // Note, this doesn't need to emit a Block as the current block flow node should be sufficient
- // as the blocks all get flattened. Each flow control node will inject the basic blocks it
- // requires.
- EmitStatements(block->statements);
-}
-
-void BuilderImpl::EmitIf(const ast::IfStatement* stmt) {
- auto* if_node = builder.CreateIf();
-
- // Emit the if condition into the end of the preceding block
- auto reg = EmitExpression(stmt->condition);
- if (!reg) {
- return;
- }
- if_node->condition = reg.Get();
-
- BranchTo(if_node);
-
- ast_to_flow_[stmt] = if_node;
-
- {
- FlowStackScope scope(this, if_node);
-
- current_flow_block = if_node->true_.target->As<Block>();
- EmitBlock(stmt->body);
-
- // If the true branch did not execute control flow, then go to the merge target
- BranchToIfNeeded(if_node->merge.target);
-
- current_flow_block = if_node->false_.target->As<Block>();
- if (stmt->else_statement) {
- EmitStatement(stmt->else_statement);
- }
-
- // If the false branch did not execute control flow, then go to the merge target
- BranchToIfNeeded(if_node->merge.target);
- }
- current_flow_block = nullptr;
-
- // If both branches went somewhere, then they both returned, continued or broke. So, there is no
- // need for the if merge-block and there is nothing to branch to the merge block anyway.
- if (IsConnected(if_node->merge.target)) {
- current_flow_block = if_node->merge.target->As<Block>();
- }
-}
-
-void BuilderImpl::EmitLoop(const ast::LoopStatement* stmt) {
- auto* loop_node = builder.CreateLoop();
-
- BranchTo(loop_node);
-
- ast_to_flow_[stmt] = loop_node;
-
- {
- FlowStackScope scope(this, loop_node);
-
- current_flow_block = loop_node->start.target->As<Block>();
- EmitBlock(stmt->body);
-
- // The current block didn't `break`, `return` or `continue`, go to the continuing block.
- BranchToIfNeeded(loop_node->continuing.target);
-
- current_flow_block = loop_node->continuing.target->As<Block>();
- if (stmt->continuing) {
- EmitBlock(stmt->continuing);
- }
-
- // Branch back to the start node if the continue target didn't branch out already
- BranchToIfNeeded(loop_node->start.target);
- }
-
- // The loop merge can get disconnected if the loop returns directly, or the continuing target
- // branches, eventually, to the merge, but nothing branched to the continuing target.
- current_flow_block = loop_node->merge.target->As<Block>();
- if (!IsConnected(loop_node->merge.target)) {
- current_flow_block = nullptr;
- }
-}
-
-void BuilderImpl::EmitWhile(const ast::WhileStatement* stmt) {
- auto* loop_node = builder.CreateLoop();
- // Continue is always empty, just go back to the start
- TINT_ASSERT(IR, loop_node->continuing.target->Is<Block>());
- builder.Branch(loop_node->continuing.target->As<Block>(), loop_node->start.target,
- utils::Empty);
-
- BranchTo(loop_node);
-
- ast_to_flow_[stmt] = loop_node;
-
- {
- FlowStackScope scope(this, loop_node);
-
- current_flow_block = loop_node->start.target->As<Block>();
-
- // Emit the while condition into the start target of the loop
- auto reg = EmitExpression(stmt->condition);
- if (!reg) {
- return;
- }
-
- // Create an `if (cond) {} else {break;}` control flow
- auto* if_node = builder.CreateIf();
- TINT_ASSERT(IR, if_node->true_.target->Is<Block>());
- builder.Branch(if_node->true_.target->As<Block>(), if_node->merge.target, utils::Empty);
-
- TINT_ASSERT(IR, if_node->false_.target->Is<Block>());
- builder.Branch(if_node->false_.target->As<Block>(), loop_node->merge.target, utils::Empty);
- if_node->condition = reg.Get();
-
- BranchTo(if_node);
-
- current_flow_block = if_node->merge.target->As<Block>();
- EmitBlock(stmt->body);
-
- BranchToIfNeeded(loop_node->continuing.target);
- }
- // The while loop always has a path to the merge target as the break statement comes before
- // anything inside the loop.
- current_flow_block = loop_node->merge.target->As<Block>();
-}
-
-void BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
- auto* loop_node = builder.CreateLoop();
- TINT_ASSERT(IR, loop_node->continuing.target->Is<Block>());
- builder.Branch(loop_node->continuing.target->As<Block>(), loop_node->start.target,
- utils::Empty);
-
- // Make sure the initializer ends up in a contained scope
- scopes_.Push();
- TINT_DEFER(scopes_.Pop());
-
- if (stmt->initializer) {
- // Emit the for initializer before branching to the loop
- EmitStatement(stmt->initializer);
- }
-
- BranchTo(loop_node);
-
- ast_to_flow_[stmt] = loop_node;
-
- {
- FlowStackScope scope(this, loop_node);
-
- current_flow_block = loop_node->start.target->As<Block>();
-
- if (stmt->condition) {
- // Emit the condition into the target target of the loop
- auto reg = EmitExpression(stmt->condition);
- if (!reg) {
- return;
- }
-
- // Create an `if (cond) {} else {break;}` control flow
- auto* if_node = builder.CreateIf();
- TINT_ASSERT(IR, if_node->true_.target->Is<Block>());
- builder.Branch(if_node->true_.target->As<Block>(), if_node->merge.target, utils::Empty);
-
- TINT_ASSERT(IR, if_node->false_.target->Is<Block>());
- builder.Branch(if_node->false_.target->As<Block>(), loop_node->merge.target,
- utils::Empty);
- if_node->condition = reg.Get();
-
- BranchTo(if_node);
- current_flow_block = if_node->merge.target->As<Block>();
- }
-
- EmitBlock(stmt->body);
- BranchToIfNeeded(loop_node->continuing.target);
-
- if (stmt->continuing) {
- current_flow_block = loop_node->continuing.target->As<Block>();
- EmitStatement(stmt->continuing);
- }
- }
-
- // The while loop always has a path to the merge target as the break statement comes before
- // anything inside the loop.
- current_flow_block = loop_node->merge.target->As<Block>();
-}
-
-void BuilderImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
- auto* switch_node = builder.CreateSwitch();
-
- // Emit the condition into the preceding block
- auto reg = EmitExpression(stmt->condition);
- if (!reg) {
- return;
- }
- switch_node->condition = reg.Get();
-
- BranchTo(switch_node);
-
- ast_to_flow_[stmt] = switch_node;
-
- {
- FlowStackScope scope(this, switch_node);
-
- const auto* sem = program_->Sem().Get(stmt);
- for (const auto* c : sem->Cases()) {
- utils::Vector<Switch::CaseSelector, 4> selectors;
- for (const auto* selector : c->Selectors()) {
- if (selector->IsDefault()) {
- selectors.Push({nullptr});
- } else {
- selectors.Push({builder.Constant(selector->Value()->Clone(clone_ctx_))});
- }
- }
-
- current_flow_block = builder.CreateCase(switch_node, selectors);
- EmitBlock(c->Body()->Declaration());
-
- BranchToIfNeeded(switch_node->merge.target);
- }
- }
- current_flow_block = nullptr;
-
- if (IsConnected(switch_node->merge.target)) {
- current_flow_block = switch_node->merge.target->As<Block>();
- }
-}
-
-void BuilderImpl::EmitReturn(const ast::ReturnStatement* stmt) {
- utils::Vector<Value*, 1> ret_value;
- if (stmt->value) {
- auto ret = EmitExpression(stmt->value);
- if (!ret) {
- return;
- }
- ret_value.Push(ret.Get());
- }
-
- BranchTo(current_function_->end_target, std::move(ret_value));
-}
-
-void BuilderImpl::EmitBreak(const ast::BreakStatement*) {
- auto* current_control = FindEnclosingControl(ControlFlags::kNone);
- TINT_ASSERT(IR, current_control);
-
- if (auto* c = current_control->As<Loop>()) {
- BranchTo(c->merge.target);
- } else if (auto* s = current_control->As<Switch>()) {
- BranchTo(s->merge.target);
- } else {
- TINT_UNREACHABLE(IR, diagnostics_);
- }
-}
-
-void BuilderImpl::EmitContinue(const ast::ContinueStatement*) {
- auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
- TINT_ASSERT(IR, current_control);
-
- if (auto* c = current_control->As<Loop>()) {
- BranchTo(c->continuing.target);
- } else {
- TINT_UNREACHABLE(IR, diagnostics_);
- }
-}
-
-// Discard is being treated as an instruction. The semantics in WGSL is demote_to_helper, so the
-// code has to continue as before it just predicates writes. If WGSL grows some kind of terminating
-// discard that would probably make sense as a FlowNode but would then require figuring out the
-// multi-level exit that is triggered.
-void BuilderImpl::EmitDiscard(const ast::DiscardStatement*) {
- auto* inst = builder.Discard();
- current_flow_block->instructions.Push(inst);
-}
-
-void BuilderImpl::EmitBreakIf(const ast::BreakIfStatement* stmt) {
- auto* if_node = builder.CreateIf();
-
- // Emit the break-if condition into the end of the preceding block
- auto reg = EmitExpression(stmt->condition);
- if (!reg) {
- return;
- }
- if_node->condition = reg.Get();
-
- BranchTo(if_node);
-
- ast_to_flow_[stmt] = if_node;
-
- auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
- TINT_ASSERT(IR, current_control);
- TINT_ASSERT(IR, current_control->Is<Loop>());
-
- auto* loop = current_control->As<Loop>();
-
- current_flow_block = if_node->true_.target->As<Block>();
- BranchTo(loop->merge.target);
-
- current_flow_block = if_node->false_.target->As<Block>();
- BranchTo(if_node->merge.target);
-
- current_flow_block = if_node->merge.target->As<Block>();
-
- // The `break-if` has to be the last item in the continuing block. The false branch of the
- // `break-if` will always take us back to the start of the loop.
- BranchTo(loop->start.target);
-}
-
-utils::Result<Value*> BuilderImpl::EmitExpression(const ast::Expression* expr) {
- // If this is a value that has been const-eval'd return the result.
- if (auto* sem = program_->Sem().Get(expr)->As<sem::ValueExpression>()) {
- if (auto* v = sem->ConstantValue()) {
- if (auto* cv = v->Clone(clone_ctx_)) {
- return builder.Constant(cv);
- }
- }
- }
-
- return tint::Switch(
- expr,
- // [&](const ast::IndexAccessorExpression* a) {
- // TODO(dsinclair): Implement
- // },
- [&](const ast::BinaryExpression* b) { return EmitBinary(b); },
- [&](const ast::BitcastExpression* b) { return EmitBitcast(b); },
- [&](const ast::CallExpression* c) { return EmitCall(c); },
- [&](const ast::IdentifierExpression* i) {
- auto* v = scopes_.Get(i->identifier->symbol);
- return utils::Result<Value*>{v};
- },
- [&](const ast::LiteralExpression* l) { return EmitLiteral(l); },
- // [&](const ast::MemberAccessorExpression* m) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::PhonyExpression*) {
- // TODO(dsinclair): Implement. The call may have side effects so has to be made.
- // },
- [&](const ast::UnaryOpExpression* u) { return EmitUnary(u); },
- [&](Default) {
- add_error(expr->source,
- "unknown expression type: " + std::string(expr->TypeInfo().name));
- return utils::Failure;
- });
-}
-
-void BuilderImpl::EmitVariable(const ast::Variable* var) {
- auto* sem = program_->Sem().Get(var);
-
- return tint::Switch( //
- var,
- [&](const ast::Var* v) {
- auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
- auto* val = builder.Declare(ty, sem->AddressSpace(), sem->Access());
- current_flow_block->instructions.Push(val);
-
- if (v->initializer) {
- auto init = EmitExpression(v->initializer);
- if (!init) {
- return;
- }
- val->initializer = init.Get();
- }
- // Store the declaration so we can get the instruction to store too
- scopes_.Set(v->name->symbol, val);
-
- // Record the original name of the var
- builder.ir.SetName(val, v->name->symbol.Name());
- },
- [&](const ast::Let* l) {
- // A `let` doesn't exist as a standalone item in the IR, it's just the result of the
- // initializer.
- auto init = EmitExpression(l->initializer);
- if (!init) {
- return;
- }
-
- // Store the results of the initialization
- scopes_.Set(l->name->symbol, init.Get());
-
- // Record the original name of the let
- builder.ir.SetName(init.Get(), l->name->symbol.Name());
- },
- [&](const ast::Override*) {
- add_error(var->source,
- "found an `Override` variable. The SubstituteOverrides "
- "transform must be run before converting to IR");
- },
- [&](const ast::Const*) {
- // Skip. This should be handled by const-eval already, so the const will be a
- // `constant::` value at the usage sites. Can just ignore the `const` variable as it
- // should never be used.
- //
- // TODO(dsinclair): Probably want to store the const variable somewhere and then in
- // identifier expression log an error if we ever see a const identifier. Add this when
- // identifiers and variables are supported.
- },
- [&](Default) {
- add_error(var->source, "unknown variable: " + std::string(var->TypeInfo().name));
- });
-}
-
-utils::Result<Value*> BuilderImpl::EmitUnary(const ast::UnaryOpExpression* expr) {
- auto val = EmitExpression(expr->expr);
- if (!val) {
- return utils::Failure;
- }
-
- auto* sem = program_->Sem().Get(expr);
- auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
-
- Instruction* inst = nullptr;
- switch (expr->op) {
- case ast::UnaryOp::kAddressOf:
- inst = builder.AddressOf(ty, val.Get());
- break;
- case ast::UnaryOp::kComplement:
- inst = builder.Complement(ty, val.Get());
- break;
- case ast::UnaryOp::kIndirection:
- inst = builder.Indirection(ty, val.Get());
- break;
- case ast::UnaryOp::kNegation:
- inst = builder.Negation(ty, val.Get());
- break;
- case ast::UnaryOp::kNot:
- inst = builder.Not(ty, val.Get());
- break;
- }
-
- current_flow_block->instructions.Push(inst);
- return inst;
-}
-
-// A short-circut needs special treatment. The short-circuit is decomposed into the relevant if
-// statements and declarations.
-utils::Result<Value*> BuilderImpl::EmitShortCircuit(const ast::BinaryExpression* expr) {
- switch (expr->op) {
- case ast::BinaryOp::kLogicalAnd:
- case ast::BinaryOp::kLogicalOr:
- break;
- default:
- TINT_ICE(IR, diagnostics_) << "invalid operation type for short-circut decomposition";
- return utils::Failure;
- }
-
- // Evaluate the LHS of the short-circuit
- auto lhs = EmitExpression(expr->lhs);
- if (!lhs) {
- return utils::Failure;
- }
-
- // Generate a variable to store the short-circut into
- auto* ty = builder.ir.types.Get<type::Bool>();
- auto* result_var =
- builder.Declare(ty, builtin::AddressSpace::kFunction, builtin::Access::kReadWrite);
- current_flow_block->instructions.Push(result_var);
-
- auto* lhs_store = builder.Store(result_var, lhs.Get());
- current_flow_block->instructions.Push(lhs_store);
-
- auto* if_node = builder.CreateIf();
- if_node->condition = lhs.Get();
- BranchTo(if_node);
-
- utils::Result<Value*> rhs;
- {
- FlowStackScope scope(this, if_node);
-
- // If this is an `&&` then we only evaluate the RHS expression in the true block.
- // If this is an `||` then we only evaluate the RHS expression in the false block.
- if (expr->op == ast::BinaryOp::kLogicalAnd) {
- current_flow_block = if_node->true_.target->As<Block>();
- } else {
- current_flow_block = if_node->false_.target->As<Block>();
- }
-
- rhs = EmitExpression(expr->rhs);
- if (!rhs) {
- return utils::Failure;
- }
- auto* rhs_store = builder.Store(result_var, rhs.Get());
- current_flow_block->instructions.Push(rhs_store);
-
- BranchTo(if_node->merge.target);
- }
- current_flow_block = if_node->merge.target->As<Block>();
-
- return result_var;
-}
-
-utils::Result<Value*> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr) {
- if (expr->op == ast::BinaryOp::kLogicalAnd || expr->op == ast::BinaryOp::kLogicalOr) {
- return EmitShortCircuit(expr);
- }
-
- auto lhs = EmitExpression(expr->lhs);
- if (!lhs) {
- return utils::Failure;
- }
-
- auto rhs = EmitExpression(expr->rhs);
- if (!rhs) {
- return utils::Failure;
- }
-
- auto* sem = program_->Sem().Get(expr);
- auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
-
- Binary* inst = nullptr;
- switch (expr->op) {
- case ast::BinaryOp::kAnd:
- inst = builder.And(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kOr:
- inst = builder.Or(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kXor:
- inst = builder.Xor(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kEqual:
- inst = builder.Equal(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kNotEqual:
- inst = builder.NotEqual(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kLessThan:
- inst = builder.LessThan(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kGreaterThan:
- inst = builder.GreaterThan(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kLessThanEqual:
- inst = builder.LessThanEqual(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kGreaterThanEqual:
- inst = builder.GreaterThanEqual(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kShiftLeft:
- inst = builder.ShiftLeft(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kShiftRight:
- inst = builder.ShiftRight(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kAdd:
- inst = builder.Add(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kSubtract:
- inst = builder.Subtract(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kMultiply:
- inst = builder.Multiply(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kDivide:
- inst = builder.Divide(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kModulo:
- inst = builder.Modulo(ty, lhs.Get(), rhs.Get());
- break;
- case ast::BinaryOp::kLogicalAnd:
- case ast::BinaryOp::kLogicalOr:
- TINT_ICE(IR, diagnostics_) << "short circuit op should have already been handled";
- return utils::Failure;
- case ast::BinaryOp::kNone:
- TINT_ICE(IR, diagnostics_) << "missing binary operand type";
- return utils::Failure;
- }
-
- current_flow_block->instructions.Push(inst);
- return inst;
-}
-
-utils::Result<Value*> BuilderImpl::EmitBitcast(const ast::BitcastExpression* expr) {
- auto val = EmitExpression(expr->expr);
- if (!val) {
- return utils::Failure;
- }
-
- auto* sem = program_->Sem().Get(expr);
- auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
- auto* inst = builder.Bitcast(ty, val.Get());
-
- current_flow_block->instructions.Push(inst);
- return inst;
-}
-
-void BuilderImpl::EmitCall(const ast::CallStatement* stmt) {
- (void)EmitCall(stmt->expr);
-}
-
-utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
- // If this is a materialized semantic node, just use the constant value.
- if (auto* mat = program_->Sem().Get(expr)) {
- if (mat->ConstantValue()) {
- auto* cv = mat->ConstantValue()->Clone(clone_ctx_);
- if (!cv) {
- add_error(expr->source, "failed to get constant value for call " +
- std::string(expr->TypeInfo().name));
- return utils::Failure;
- }
- return builder.Constant(cv);
- }
- }
-
- utils::Vector<Value*, 8> args;
- args.Reserve(expr->args.Length());
-
- // Emit the arguments
- for (const auto* arg : expr->args) {
- auto value = EmitExpression(arg);
- if (!value) {
- add_error(arg->source, "failed to convert arguments");
- return utils::Failure;
- }
- args.Push(value.Get());
- }
-
- auto* sem = program_->Sem().Get<sem::Call>(expr);
- if (!sem) {
- add_error(expr->source, "failed to get semantic information for call " +
- std::string(expr->TypeInfo().name));
- return utils::Failure;
- }
-
- auto* ty = sem->Target()->ReturnType()->Clone(clone_ctx_.type_ctx);
-
- Instruction* inst = nullptr;
-
- // If this is a builtin function, emit the specific builtin value
- if (auto* b = sem->Target()->As<sem::Builtin>()) {
- inst = builder.Builtin(ty, b->Type(), args);
- } else if (sem->Target()->As<sem::ValueConstructor>()) {
- inst = builder.Construct(ty, std::move(args));
- } else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
- auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
- inst = builder.Convert(ty, from, std::move(args));
- } else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
- TINT_UNIMPLEMENTED(IR, diagnostics_) << "missing templated ident support";
- return utils::Failure;
- } else {
- // Not a builtin and not a templated call, so this is a user function.
- auto name = CloneSymbol(expr->target->identifier->symbol);
- inst = builder.UserCall(ty, name, std::move(args));
- }
- if (inst == nullptr) {
- return utils::Failure;
- }
- current_flow_block->instructions.Push(inst);
- return inst;
-}
-
-utils::Result<Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
- auto* sem = program_->Sem().Get(lit);
- if (!sem) {
- add_error(lit->source, "failed to get semantic information for node " +
- std::string(lit->TypeInfo().name));
- return utils::Failure;
- }
-
- auto* cv = sem->ConstantValue()->Clone(clone_ctx_);
- if (!cv) {
- add_error(lit->source,
- "failed to get constant value for node " + std::string(lit->TypeInfo().name));
- return utils::Failure;
- }
- return builder.Constant(cv);
-}
-
-void BuilderImpl::EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs) {
- for (auto* attr : attrs) {
- EmitAttribute(attr);
- }
-}
-
-void BuilderImpl::EmitAttribute(const ast::Attribute* attr) {
- tint::Switch( //
- attr,
- // [&](const ast::WorkgroupAttribute* wg) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::StageAttribute* s) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::BindingAttribute* b) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::GroupAttribute* g) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::LocationAttribute* l) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::BuiltinAttribute* b) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::InterpolateAttribute* i) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::InvariantAttribute* i) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::MustUseAttribute* i) {
- // TODO(dsinclair): Implement
- // },
- [&](const ast::IdAttribute*) {
- add_error(attr->source,
- "found an `Id` attribute. The SubstituteOverrides transform "
- "must be run before converting to IR");
- },
- [&](const ast::StructMemberSizeAttribute*) {
- TINT_ICE(IR, diagnostics_)
- << "StructMemberSizeAttribute encountered during IR conversion";
- },
- [&](const ast::StructMemberAlignAttribute*) {
- TINT_ICE(IR, diagnostics_)
- << "StructMemberAlignAttribute encountered during IR conversion";
- },
- // [&](const ast::StrideAttribute* s) {
- // TODO(dsinclair): Implement
- // },
- // [&](const ast::InternalAttribute *i) {
- // TODO(dsinclair): Implement
- // },
- [&](Default) {
- add_error(attr->source, "unknown attribute: " + std::string(attr->TypeInfo().name));
- });
-}
-
-} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl.h b/src/tint/ir/builder_impl.h
deleted file mode 100644
index f6bed12..0000000
--- a/src/tint/ir/builder_impl.h
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_TINT_IR_BUILDER_IMPL_H_
-#define SRC_TINT_IR_BUILDER_IMPL_H_
-
-#include <string>
-#include <unordered_map>
-#include <utility>
-
-#include "src/tint/ast/type.h"
-#include "src/tint/constant/clone_context.h"
-#include "src/tint/diagnostic/diagnostic.h"
-#include "src/tint/ir/builder.h"
-#include "src/tint/ir/flow_node.h"
-#include "src/tint/ir/module.h"
-#include "src/tint/ir/value.h"
-#include "src/tint/scope_stack.h"
-#include "src/tint/utils/result.h"
-
-// Forward Declarations
-namespace tint {
-class Program;
-} // namespace tint
-namespace tint::ast {
-class Attribute;
-class AssignmentStatement;
-class BinaryExpression;
-class BitcastExpression;
-class BlockStatement;
-class BreakIfStatement;
-class BreakStatement;
-class CallExpression;
-class CallStatement;
-class CompoundAssignmentStatement;
-class ContinueStatement;
-class DiscardStatement;
-class Expression;
-class ForLoopStatement;
-class Function;
-class IfStatement;
-class LoopStatement;
-class LiteralExpression;
-class Node;
-class ReturnStatement;
-class Statement;
-class SwitchStatement;
-class UnaryOpExpression;
-class WhileStatement;
-class Variable;
-} // namespace tint::ast
-namespace tint::sem {
-class Builtin;
-} // namespace tint::sem
-
-namespace tint::ir {
-
-/// Builds an ir::Module from a given ast::Program
-class BuilderImpl {
- public:
- /// Constructor
- /// @param program the program to create from
- explicit BuilderImpl(const Program* program);
- /// Destructor
- ~BuilderImpl();
-
- /// Builds an ir::Module from the given Program
- /// @returns true on success, false otherwise
- utils::Result<Module> Build();
-
- /// @returns the diagnostics
- diag::List Diagnostics() const { return diagnostics_; }
-
- /// Emits a function to the IR.
- /// @param func the function to emit
- void EmitFunction(const ast::Function* func);
-
- /// Emits a set of statements to the IR.
- /// @param stmts the statements to emit
- void EmitStatements(utils::VectorRef<const ast::Statement*> stmts);
-
- /// Emits a statement to the IR
- /// @param stmt the statment to emit
- void EmitStatement(const ast::Statement* stmt);
-
- /// Emits a block statement to the IR.
- /// @param block the block to emit
- void EmitBlock(const ast::BlockStatement* block);
-
- /// Emits an if control node to the IR.
- /// @param stmt the if statement
- void EmitIf(const ast::IfStatement* stmt);
-
- /// Emits a return node to the IR.
- /// @param stmt the return AST statement
- void EmitReturn(const ast::ReturnStatement* stmt);
-
- /// Emits a loop control node to the IR.
- /// @param stmt the loop statement
- void EmitLoop(const ast::LoopStatement* stmt);
-
- /// Emits a loop control node to the IR.
- /// @param stmt the while statement
- void EmitWhile(const ast::WhileStatement* stmt);
-
- /// Emits a loop control node to the IR.
- /// @param stmt the for loop statement
- void EmitForLoop(const ast::ForLoopStatement* stmt);
-
- /// Emits a switch statement
- /// @param stmt the switch statement
- void EmitSwitch(const ast::SwitchStatement* stmt);
-
- /// Emits a break statement
- /// @param stmt the break statement
- void EmitBreak(const ast::BreakStatement* stmt);
-
- /// Emits a continue statement
- /// @param stmt the continue statement
- void EmitContinue(const ast::ContinueStatement* stmt);
-
- /// Emits a discard statement
- void EmitDiscard(const ast::DiscardStatement*);
-
- /// Emits a break-if statement
- /// @param stmt the break-if statement
- void EmitBreakIf(const ast::BreakIfStatement* stmt);
-
- /// Emits an assignment statement
- /// @param stmt the statement
- void EmitAssignment(const ast::AssignmentStatement* stmt);
-
- /// Emits a compound assignment statement
- /// @param stmt the statement
- void EmitCompoundAssignment(const ast::CompoundAssignmentStatement* stmt);
-
- /// Emits an expression
- /// @param expr the expression to emit
- /// @returns true if successful, false otherwise
- utils::Result<Value*> EmitExpression(const ast::Expression* expr);
-
- /// Emits a variable
- /// @param var the variable to emit
- void EmitVariable(const ast::Variable* var);
-
- /// Emits a Unary expression
- /// @param expr the unary expression
- /// @returns the value storing the result if successful, utils::Failure otherwise
- utils::Result<Value*> EmitUnary(const ast::UnaryOpExpression* expr);
-
- /// Emits a short-circult binary expression
- /// @param expr the binary expression
- /// @returns the value storing the result if successful, utils::Failure otherwise
- utils::Result<Value*> EmitShortCircuit(const ast::BinaryExpression* expr);
-
- /// Emits a binary expression
- /// @param expr the binary expression
- /// @returns the value storing the result if successful, utils::Failure otherwise
- utils::Result<Value*> EmitBinary(const ast::BinaryExpression* expr);
-
- /// Emits a bitcast expression
- /// @param expr the bitcast expression
- /// @returns the value storing the result if successful, utils::Failure otherwise
- utils::Result<Value*> EmitBitcast(const ast::BitcastExpression* expr);
-
- /// Emits a call expression
- /// @param stmt the call statement
- void EmitCall(const ast::CallStatement* stmt);
-
- /// Emits a call expression
- /// @param expr the call expression
- /// @returns the value storing the result if successful, utils::Failure otherwise
- utils::Result<Value*> EmitCall(const ast::CallExpression* expr);
-
- /// Emits a literal expression
- /// @param lit the literal to emit
- /// @returns true if successful, false otherwise
- utils::Result<Value*> EmitLiteral(const ast::LiteralExpression* lit);
-
- /// Emits a set of attributes
- /// @param attrs the attributes to emit
- void EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs);
-
- /// Emits an attribute
- /// @param attr the attribute to emit
- void EmitAttribute(const ast::Attribute* attr);
-
- /// Retrieve the IR Flow node for a given AST node.
- /// @param n the node to lookup
- /// @returns the FlowNode for the given ast::Node or nullptr if it doesn't exist.
- const ir::FlowNode* FlowNodeForAstNode(const ast::Node* n) const {
- if (ast_to_flow_.count(n) == 0) {
- return nullptr;
- }
- return ast_to_flow_.at(n);
- }
-
- /// The stack of flow control blocks.
- utils::Vector<FlowNode*, 8> flow_stack;
-
- /// The IR builder being used by the impl.
- Builder builder;
-
- /// The current flow block for expressions
- Block* current_flow_block = nullptr;
-
- private:
- enum class ControlFlags { kNone, kExcludeSwitch };
-
- void BranchTo(ir::FlowNode* node, utils::VectorRef<Value*> args = {});
- void BranchToIfNeeded(ir::FlowNode* node);
-
- FlowNode* FindEnclosingControl(ControlFlags flags);
-
- void add_error(const Source& s, const std::string& err);
-
- Symbol CloneSymbol(Symbol sym) const;
-
- const Program* program_ = nullptr;
- Function* current_function_ = nullptr;
- ScopeStack<Symbol, Value*> scopes_;
- constant::CloneContext clone_ctx_;
- diag::List diagnostics_;
-
- /// Map from ast nodes to flow nodes, used to retrieve the flow node for a given AST node.
- /// Used for testing purposes.
- std::unordered_map<const ast::Node*, const FlowNode*> ast_to_flow_;
-};
-
-} // namespace tint::ir
-
-#endif // SRC_TINT_IR_BUILDER_IMPL_H_
diff --git a/src/tint/ir/builder_impl_binary_test.cc b/src/tint/ir/builder_impl_binary_test.cc
deleted file mode 100644
index 3be8405..0000000
--- a/src/tint/ir/builder_impl_binary_test.cc
+++ /dev/null
@@ -1,696 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/ir/test_helper.h"
-
-#include "gmock/gmock.h"
-#include "src/tint/ast/case_selector.h"
-#include "src/tint/ast/int_literal_expression.h"
-#include "src/tint/constant/scalar.h"
-
-namespace tint::ir {
-namespace {
-
-using namespace tint::number_suffixes; // NOLINT
-
-using IR_BuilderImplTest = TestHelper;
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Add(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = add %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundAdd) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kAdd);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = add %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Sub(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = sub %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundSubtract) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kSubtract);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = sub %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Mul(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = mul %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundMultiply) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kMultiply);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = mul %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Div(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = div %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundDiv) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kDivide);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = div %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Mod(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = mod %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundModulo) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kModulo);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = mod %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = And(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = and %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundAnd) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.bool_());
- auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kAnd);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, bool, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, bool, read_write> = and %v1:ref<private, bool, read_write>, false
- store %v1:ref<private, bool, read_write>, %2:ref<private, bool, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Or(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = or %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundOr) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.bool_());
- auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kOr);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, bool, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, bool, read_write> = or %v1:ref<private, bool, read_write>, false
- store %v1:ref<private, bool, read_write>, %2:ref<private, bool, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Xor(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = xor %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundXor) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kXor);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = xor %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) {
- Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
- auto* expr = LogicalAnd(Call("my_func"), false);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():bool
- %fn2 = block
- ret true
-func_end
-
-%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn4 = block
- %1:bool = call my_func
- %tint_symbol:bool = var function, read_write
- store %tint_symbol:bool, %1:bool
- branch %fn5
-
- %fn5 = if %1:bool [t: %fn6, f: %fn7, m: %fn8]
- # true branch
- %fn6 = block
- store %tint_symbol:bool, false
- branch %fn8
-
- # if merge
- %fn8 = block
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) {
- Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
- auto* expr = LogicalOr(Call("my_func"), true);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():bool
- %fn2 = block
- ret true
-func_end
-
-%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn4 = block
- %1:bool = call my_func
- %tint_symbol:bool = var function, read_write
- store %tint_symbol:bool, %1:bool
- branch %fn5
-
- %fn5 = if %1:bool [t: %fn6, f: %fn7, m: %fn8]
- # true branch
- # false branch
- %fn7 = block
- store %tint_symbol:bool, true
- branch %fn8
-
- # if merge
- %fn8 = block
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Equal(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:bool = eq %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = NotEqual(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:bool = neq %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = LessThan(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:bool = lt %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = GreaterThan(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:bool = gt %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = LessThanEqual(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:bool = lte %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = GreaterThanEqual(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:bool = gte %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Shl(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = shiftl %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundShiftLeft) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftLeft);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = shiftl %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
- auto* expr = Shr(Call("my_func"), 4_u);
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = shiftr %1:u32, 4u
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundShiftRight) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
- auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftRight);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, u32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %2:ref<private, u32, read_write> = shiftr %v1:ref<private, u32, read_write>, 1u
- store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
- Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
-
- auto* expr = LogicalAnd(LessThan(Call("my_func"), 2_f),
- GreaterThan(2.5_f, Div(Call("my_func"), Mul(2.3_f, Call("my_func")))));
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():f32
- %fn2 = block
- ret 0.0f
-func_end
-
-%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn4 = block
- %1:f32 = call my_func
- %2:bool = lt %1:f32, 2.0f
- %tint_symbol:bool = var function, read_write
- store %tint_symbol:bool, %2:bool
- branch %fn5
-
- %fn5 = if %2:bool [t: %fn6, f: %fn7, m: %fn8]
- # true branch
- %fn6 = block
- %4:f32 = call my_func
- %5:f32 = call my_func
- %6:f32 = mul 2.29999995231628417969f, %5:f32
- %7:f32 = div %4:f32, %6:f32
- %8:bool = gt 2.5f, %7:f32
- store %tint_symbol:bool, %8:bool
- branch %fn8
-
- # if merge
- %fn8 = block
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound_WithConstEval) {
- Func("my_func", utils::Vector{Param("p", ty.bool_())}, ty.bool_(), utils::Vector{Return(true)});
- auto* expr = Call("my_func", LogicalAnd(LessThan(2.4_f, 2_f),
- GreaterThan(2.5_f, Div(10_f, Mul(2.3_f, 9.4_f)))));
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():bool
- %fn2 = block
- ret true
-func_end
-
-%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn4 = block
- %tint_symbol:bool = call my_func, false
- ret
-func_end
-
-)");
-}
-
-} // namespace
-} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl_call_test.cc b/src/tint/ir/builder_impl_call_test.cc
deleted file mode 100644
index 0fb070e..0000000
--- a/src/tint/ir/builder_impl_call_test.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/ir/test_helper.h"
-
-#include "gmock/gmock.h"
-#include "src/tint/ast/case_selector.h"
-#include "src/tint/ast/int_literal_expression.h"
-#include "src/tint/constant/scalar.h"
-
-namespace tint::ir {
-namespace {
-
-using namespace tint::number_suffixes; // NOLINT
-
-using IR_BuilderImplTest = TestHelper;
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) {
- Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
-
- auto* expr = Bitcast<f32>(Call("my_func"));
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:f32 = call my_func
-%2:f32 = bitcast %1:f32
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitStatement_Discard) {
- auto* expr = Discard();
- Func("test_function", {}, ty.void_(), expr,
- utils::Vector{
- create<ast::StageAttribute>(ast::PipelineStage::kFragment),
- });
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- b.EmitStatement(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(discard
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) {
- Func("my_func", utils::Vector{Param("p", ty.f32())}, ty.void_(), utils::Empty);
-
- auto* stmt = CallStmt(Call("my_func", Mul(2_a, 3_a)));
- WrapInFunction(stmt);
-
- auto& b = CreateBuilder();
-
- InjectFlowBlock();
- b.EmitStatement(stmt);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:void = call my_func, 6.0f
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Convert) {
- auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i));
- auto* expr = Call(ty.f32(), i);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
- ASSERT_TRUE(r);
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%i:ref<private, i32, read_write> = var private, read_write, 1i
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %tint_symbol:f32 = convert i32, %i:ref<private, i32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_ConstructEmpty) {
- auto* expr = vec3(ty.f32());
- GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
- ASSERT_TRUE(r);
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%i:ref<private, vec3<f32>, read_write> = var private, read_write, vec3<f32> 0.0f
-
-
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Construct) {
- auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
- auto* expr = vec3(ty.f32(), 2_f, 3_f, i);
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
- ASSERT_TRUE(r);
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%i:ref<private, f32, read_write> = var private, read_write, 1.0f
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %tint_symbol:vec3<f32> = construct 2.0f, 3.0f, %i:ref<private, f32, read_write>
- ret
-func_end
-
-)");
-}
-
-} // namespace
-} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl_unary_test.cc b/src/tint/ir/builder_impl_unary_test.cc
deleted file mode 100644
index 2323acb..0000000
--- a/src/tint/ir/builder_impl_unary_test.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/ir/test_helper.h"
-
-#include "gmock/gmock.h"
-#include "src/tint/ast/case_selector.h"
-#include "src/tint/ast/int_literal_expression.h"
-#include "src/tint/constant/scalar.h"
-
-namespace tint::ir {
-namespace {
-
-using namespace tint::number_suffixes; // NOLINT
-
-using IR_BuilderImplTest = TestHelper;
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Not) {
- Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(false)});
- auto* expr = Not(Call("my_func"));
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:bool = call my_func
-%2:bool = eq %1:bool, false
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Complement) {
- Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(1_u)});
- auto* expr = Complement(Call("my_func"));
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
-%2:u32 = complement %1:u32
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Negation) {
- Func("my_func", utils::Empty, ty.i32(), utils::Vector{Return(1_i)});
- auto* expr = Negation(Call("my_func"));
- WrapInFunction(expr);
-
- auto& b = CreateBuilder();
- InjectFlowBlock();
- auto r = b.EmitExpression(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
- ASSERT_TRUE(r);
-
- Disassembler d(b.builder.ir);
- d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1:i32 = call my_func
-%2:i32 = negation %1:i32
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Unary_AddressOf) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
-
- auto* expr = Decl(Let("v2", AddressOf("v1")));
- WrapInFunction(expr);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, i32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %v2:ptr<private, i32, read_write> = addr_of %v1:ref<private, i32, read_write>
- ret
-func_end
-
-)");
-}
-
-TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Indirection) {
- GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
- utils::Vector stmts = {
- Decl(Let("v3", AddressOf("v1"))),
- Decl(Let("v2", Deref("v3"))),
- };
- WrapInFunction(stmts);
-
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
-
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%v1:ref<private, i32, read_write> = var private, read_write
-
-
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- %v3:ptr<private, i32, read_write> = addr_of %v1:ref<private, i32, read_write>
- %v2:i32 = indirection %v3:ptr<private, i32, read_write>
- ret
-func_end
-
-)");
-}
-
-} // namespace
-} // namespace tint::ir
diff --git a/src/tint/ir/constant_test.cc b/src/tint/ir/constant_test.cc
index c550763..7005751 100644
--- a/src/tint/ir/constant_test.cc
+++ b/src/tint/ir/constant_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ir/builder.h"
#include "src/tint/ir/test_helper.h"
#include "src/tint/ir/value.h"
@@ -23,11 +24,12 @@
using IR_ConstantTest = TestHelper;
TEST_F(IR_ConstantTest, f32) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
utils::StringStream str;
- auto* c = b.builder.Constant(1.2_f);
+ auto* c = b.Constant(1.2_f);
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
EXPECT_TRUE(c->value->Is<constant::Scalar<f32>>());
@@ -38,11 +40,12 @@
}
TEST_F(IR_ConstantTest, f16) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
utils::StringStream str;
- auto* c = b.builder.Constant(1.1_h);
+ auto* c = b.Constant(1.1_h);
EXPECT_EQ(1.1_h, c->value->As<constant::Scalar<f16>>()->ValueAs<f16>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
@@ -53,11 +56,12 @@
}
TEST_F(IR_ConstantTest, i32) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
utils::StringStream str;
- auto* c = b.builder.Constant(1_i);
+ auto* c = b.Constant(1_i);
EXPECT_EQ(1_i, c->value->As<constant::Scalar<i32>>()->ValueAs<i32>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
@@ -68,11 +72,12 @@
}
TEST_F(IR_ConstantTest, u32) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
utils::StringStream str;
- auto* c = b.builder.Constant(2_u);
+ auto* c = b.Constant(2_u);
EXPECT_EQ(2_u, c->value->As<constant::Scalar<u32>>()->ValueAs<u32>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
@@ -83,18 +88,19 @@
}
TEST_F(IR_ConstantTest, bool) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
{
utils::StringStream str;
- auto* c = b.builder.Constant(false);
+ auto* c = b.Constant(false);
EXPECT_FALSE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
{
utils::StringStream str;
- auto c = b.builder.Constant(true);
+ auto c = b.Constant(true);
EXPECT_TRUE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index 688fc41..d4ee3a7 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -138,13 +138,14 @@
out_ << "]";
}
- out_ << std::endl;
+ out_ << " {" << std::endl;
{
ScopedIndent func_indent(indent_size_);
ScopedStopNode scope(stop_nodes_, f->end_target);
Walk(f->start_target);
}
+ out_ << "} ";
Walk(f->end_target);
},
[&](const ir::Block* b) {
@@ -153,16 +154,23 @@
return;
}
- Indent() << "%fn" << IdOf(b) << " = block" << std::endl;
- EmitBlockInstructions(b);
+ Indent() << "%fn" << IdOf(b) << " = block {" << std::endl;
+ {
+ ScopedIndent si(indent_size_);
+ EmitBlockInstructions(b);
+ }
+ Indent() << "}";
+ std::string suffix = "";
if (b->branch.target->Is<FunctionTerminator>()) {
- Indent() << "ret";
+ out_ << " -> %func_end";
+ suffix = "return";
} else if (b->branch.target->Is<RootTerminator>()) {
// Nothing to do
} else {
- Indent() << "branch "
- << "%fn" << IdOf(b->branch.target);
+ out_ << " -> "
+ << "%fn" << IdOf(b->branch.target);
+ suffix = "branch";
}
if (!b->branch.args.IsEmpty()) {
out_ << " ";
@@ -173,6 +181,9 @@
EmitValue(v);
}
}
+ if (!suffix.empty()) {
+ out_ << " # " << suffix;
+ }
out_ << std::endl;
if (!b->branch.target->Is<FunctionTerminator>()) {
@@ -294,7 +305,7 @@
},
[&](const ir::FunctionTerminator*) {
TINT_ASSERT(IR, in_function_);
- Indent() << "func_end" << std::endl << std::endl;
+ Indent() << "%func_end" << std::endl << std::endl;
},
[&](const ir::RootTerminator*) {
TINT_ASSERT(IR, !in_function_);
diff --git a/src/tint/ir/discard_test.cc b/src/tint/ir/discard_test.cc
index b1bf8c2..054727f 100644
--- a/src/tint/ir/discard_test.cc
+++ b/src/tint/ir/discard_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ir/builder.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
@@ -21,9 +22,10 @@
using IR_InstructionTest = TestHelper;
TEST_F(IR_InstructionTest, Discard) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- const auto* inst = b.builder.Discard();
+ const auto* inst = b.Discard();
ASSERT_TRUE(inst->Is<ir::Discard>());
}
diff --git a/src/tint/ir/from_program.cc b/src/tint/ir/from_program.cc
index d093103..f7729f3 100644
--- a/src/tint/ir/from_program.cc
+++ b/src/tint/ir/from_program.cc
@@ -14,20 +14,1221 @@
#include "src/tint/ir/from_program.h"
-#include "src/tint/ir/builder_impl.h"
+#include <iostream>
+#include <unordered_map>
+#include <utility>
+
+#include "src/tint/ast/alias.h"
+#include "src/tint/ast/assignment_statement.h"
+#include "src/tint/ast/binary_expression.h"
+#include "src/tint/ast/bitcast_expression.h"
+#include "src/tint/ast/block_statement.h"
+#include "src/tint/ast/bool_literal_expression.h"
+#include "src/tint/ast/break_if_statement.h"
+#include "src/tint/ast/break_statement.h"
+#include "src/tint/ast/call_expression.h"
+#include "src/tint/ast/call_statement.h"
+#include "src/tint/ast/compound_assignment_statement.h"
+#include "src/tint/ast/const.h"
+#include "src/tint/ast/const_assert.h"
+#include "src/tint/ast/continue_statement.h"
+#include "src/tint/ast/discard_statement.h"
+#include "src/tint/ast/enable.h"
+#include "src/tint/ast/float_literal_expression.h"
+#include "src/tint/ast/for_loop_statement.h"
+#include "src/tint/ast/function.h"
+#include "src/tint/ast/id_attribute.h"
+#include "src/tint/ast/identifier.h"
+#include "src/tint/ast/identifier_expression.h"
+#include "src/tint/ast/if_statement.h"
+#include "src/tint/ast/increment_decrement_statement.h"
+#include "src/tint/ast/int_literal_expression.h"
+#include "src/tint/ast/invariant_attribute.h"
+#include "src/tint/ast/let.h"
+#include "src/tint/ast/literal_expression.h"
+#include "src/tint/ast/loop_statement.h"
+#include "src/tint/ast/override.h"
+#include "src/tint/ast/return_statement.h"
+#include "src/tint/ast/statement.h"
+#include "src/tint/ast/struct.h"
+#include "src/tint/ast/struct_member_align_attribute.h"
+#include "src/tint/ast/struct_member_size_attribute.h"
+#include "src/tint/ast/switch_statement.h"
+#include "src/tint/ast/templated_identifier.h"
+#include "src/tint/ast/unary_op_expression.h"
+#include "src/tint/ast/var.h"
+#include "src/tint/ast/variable_decl_statement.h"
+#include "src/tint/ast/while_statement.h"
+#include "src/tint/ir/builder.h"
+#include "src/tint/ir/function.h"
+#include "src/tint/ir/if.h"
+#include "src/tint/ir/loop.h"
+#include "src/tint/ir/module.h"
+#include "src/tint/ir/store.h"
+#include "src/tint/ir/switch.h"
+#include "src/tint/ir/value.h"
#include "src/tint/program.h"
+#include "src/tint/scope_stack.h"
+#include "src/tint/sem/builtin.h"
+#include "src/tint/sem/call.h"
+#include "src/tint/sem/function.h"
+#include "src/tint/sem/materialize.h"
+#include "src/tint/sem/module.h"
+#include "src/tint/sem/switch_statement.h"
+#include "src/tint/sem/value_constructor.h"
+#include "src/tint/sem/value_conversion.h"
+#include "src/tint/sem/value_expression.h"
+#include "src/tint/sem/variable.h"
+#include "src/tint/switch.h"
+#include "src/tint/type/void.h"
+#include "src/tint/utils/defer.h"
+#include "src/tint/utils/result.h"
+#include "src/tint/utils/scoped_assignment.h"
+
+using namespace tint::number_suffixes; // NOLINT
namespace tint::ir {
+namespace {
+
+using ResultType = utils::Result<Module, diag::List>;
+
+bool IsBranched(const Block* b) {
+ return b->branch.target != nullptr;
+}
+
+bool IsConnected(const FlowNode* b) {
+ // Function is always connected as it's the start.
+ if (b->Is<ir::Function>()) {
+ return true;
+ }
+
+ for (auto* parent : b->inbound_branches) {
+ if (IsConnected(parent)) {
+ return true;
+ }
+ }
+ // Getting here means all the incoming branches are disconnected.
+ return false;
+}
+
+/// Impl is the private-implementation of FromProgram().
+class Impl {
+ public:
+ /// Constructor
+ /// @param program the program to convert to IR
+ explicit Impl(const Program* program) : program_(program) {}
+
+ /// Builds an IR module from the program passed to the constructor.
+ /// @return the IR module or an error.
+ ResultType Build() { return EmitModule(); }
+
+ private:
+ enum class ControlFlags { kNone, kExcludeSwitch };
+
+ // The input Program
+ const Program* program_ = nullptr;
+
+ /// The IR module being built
+ Module mod;
+
+ /// The IR builder being used by the impl.
+ Builder builder_{mod};
+
+ // The clone context used to clone data from #program_
+ constant::CloneContext clone_ctx_{
+ /* type_ctx */ type::CloneContext{
+ /* src */ {&program_->Symbols()},
+ /* dst */ {&builder_.ir.symbols, &builder_.ir.types},
+ },
+ /* dst */ {&builder_.ir.constants},
+ };
+
+ /// The stack of flow control blocks.
+ utils::Vector<FlowNode*, 8> flow_stack_;
+
+ /// The current flow block for expressions.
+ Block* current_flow_block_ = nullptr;
+
+ /// The current function being processed.
+ Function* current_function_ = nullptr;
+
+ /// The current stack of scopes being processed.
+ ScopeStack<Symbol, Value*> scopes_;
+
+ /// The diagnostic that have been raised.
+ diag::List diagnostics_;
+
+ /// Map from ast nodes to flow nodes, used to retrieve the flow node for a given AST node.
+ /// Used for testing purposes.
+ std::unordered_map<const ast::Node*, const FlowNode*> ast_to_flow_;
+
+ class FlowStackScope {
+ public:
+ FlowStackScope(Impl* impl, FlowNode* node) : impl_(impl) { impl_->flow_stack_.Push(node); }
+
+ ~FlowStackScope() { impl_->flow_stack_.Pop(); }
+
+ private:
+ Impl* impl_;
+ };
+
+ void add_error(const Source& s, const std::string& err) {
+ diagnostics_.add_error(tint::diag::System::IR, err, s);
+ }
+
+ void BranchTo(FlowNode* node, utils::VectorRef<Value*> args = {}) {
+ TINT_ASSERT(IR, current_flow_block_);
+ TINT_ASSERT(IR, !IsBranched(current_flow_block_));
+
+ builder_.Branch(current_flow_block_, node, args);
+ current_flow_block_ = nullptr;
+ }
+
+ void BranchToIfNeeded(FlowNode* node) {
+ if (!current_flow_block_ || IsBranched(current_flow_block_)) {
+ return;
+ }
+ BranchTo(node);
+ }
+
+ FlowNode* FindEnclosingControl(ControlFlags flags) {
+ for (auto it = flow_stack_.rbegin(); it != flow_stack_.rend(); ++it) {
+ if ((*it)->Is<Loop>()) {
+ return *it;
+ }
+ if (flags == ControlFlags::kExcludeSwitch) {
+ continue;
+ }
+ if ((*it)->Is<Switch>()) {
+ return *it;
+ }
+ }
+ return nullptr;
+ }
+
+ Symbol CloneSymbol(Symbol sym) const {
+ return clone_ctx_.type_ctx.dst.st->Register(sym.Name());
+ }
+
+ ResultType EmitModule() {
+ auto* sem = program_->Sem().Module();
+
+ for (auto* decl : sem->DependencyOrderedDeclarations()) {
+ tint::Switch(
+ decl, //
+ [&](const ast::Struct*) {
+ // Will be encoded into the `type::Struct` when used. We will then hoist all
+ // used structs up to module scope when converting IR.
+ },
+ [&](const ast::Alias*) {
+ // Folded away and doesn't appear in the IR.
+ },
+ [&](const ast::Variable* var) {
+ // Setup the current flow node to be the root block for the module. The builder
+ // will handle creating it if it doesn't exist already.
+ TINT_SCOPED_ASSIGNMENT(current_flow_block_, builder_.CreateRootBlockIfNeeded());
+ EmitVariable(var);
+ },
+ [&](const ast::Function* func) { EmitFunction(func); },
+ [&](const ast::Enable*) {
+ // TODO(dsinclair): Implement? I think these need to be passed along so further
+ // stages know what is enabled.
+ },
+ [&](const ast::ConstAssert*) {
+ // Evaluated by the resolver, drop from the IR.
+ },
+ [&](Default) {
+ add_error(decl->source, "unknown type: " + std::string(decl->TypeInfo().name));
+ });
+ }
+
+ if (diagnostics_.contains_errors()) {
+ return ResultType(std::move(diagnostics_));
+ }
+
+ return ResultType{std::move(mod)};
+ }
+
+ void EmitFunction(const ast::Function* ast_func) {
+ // The flow stack should have been emptied when the previous function finished building.
+ TINT_ASSERT(IR, flow_stack_.IsEmpty());
+
+ const auto* sem = program_->Sem().Get(ast_func);
+
+ auto* ir_func = builder_.CreateFunction(CloneSymbol(ast_func->name->symbol),
+ sem->ReturnType()->Clone(clone_ctx_.type_ctx));
+ current_function_ = ir_func;
+ builder_.ir.functions.Push(ir_func);
+
+ ast_to_flow_[ast_func] = ir_func;
+
+ if (ast_func->IsEntryPoint()) {
+ switch (ast_func->PipelineStage()) {
+ case ast::PipelineStage::kVertex:
+ ir_func->pipeline_stage = Function::PipelineStage::kVertex;
+ break;
+ case ast::PipelineStage::kFragment:
+ ir_func->pipeline_stage = Function::PipelineStage::kFragment;
+ break;
+ case ast::PipelineStage::kCompute: {
+ ir_func->pipeline_stage = Function::PipelineStage::kCompute;
+
+ auto wg_size = sem->WorkgroupSize();
+ ir_func->workgroup_size = {
+ wg_size[0].value(),
+ wg_size[1].value_or(1),
+ wg_size[2].value_or(1),
+ };
+ break;
+ }
+ default: {
+ TINT_ICE(IR, diagnostics_) << "Invalid pipeline stage";
+ return;
+ }
+ }
+
+ for (auto* attr : ast_func->return_type_attributes) {
+ tint::Switch(
+ attr, //
+ [&](const ast::LocationAttribute*) {
+ ir_func->return_attributes.Push(Function::ReturnAttribute::kLocation);
+ },
+ [&](const ast::InvariantAttribute*) {
+ ir_func->return_attributes.Push(Function::ReturnAttribute::kInvariant);
+ },
+ [&](const ast::BuiltinAttribute* b) {
+ if (auto* ident_sem =
+ program_->Sem()
+ .Get(b)
+ ->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>()) {
+ switch (ident_sem->Value()) {
+ case builtin::BuiltinValue::kPosition:
+ ir_func->return_attributes.Push(
+ Function::ReturnAttribute::kPosition);
+ break;
+ case builtin::BuiltinValue::kFragDepth:
+ ir_func->return_attributes.Push(
+ Function::ReturnAttribute::kFragDepth);
+ break;
+ case builtin::BuiltinValue::kSampleMask:
+ ir_func->return_attributes.Push(
+ Function::ReturnAttribute::kSampleMask);
+ break;
+ default:
+ TINT_ICE(IR, diagnostics_)
+ << "Unknown builtin value in return attributes "
+ << ident_sem->Value();
+ return;
+ }
+ } else {
+ TINT_ICE(IR, diagnostics_) << "Builtin attribute sem invalid";
+ return;
+ }
+ });
+ }
+ }
+ ir_func->return_location = sem->ReturnLocation();
+
+ {
+ FlowStackScope scope(this, ir_func);
+
+ current_flow_block_ = ir_func->start_target;
+ EmitBlock(ast_func->body);
+
+ // TODO(dsinclair): Store return type and attributes
+ // TODO(dsinclair): Store parameters
+
+ // If the branch target has already been set then a `return` was called. Only set in the
+ // case where `return` wasn't called.
+ BranchToIfNeeded(current_function_->end_target);
+ }
+
+ TINT_ASSERT(IR, flow_stack_.IsEmpty());
+ current_flow_block_ = nullptr;
+ current_function_ = nullptr;
+ }
+
+ void EmitStatements(utils::VectorRef<const ast::Statement*> stmts) {
+ for (auto* s : stmts) {
+ EmitStatement(s);
+
+ // If the current flow block has a branch target then the rest of the statements in this
+ // block are dead code. Skip them.
+ if (!current_flow_block_ || IsBranched(current_flow_block_)) {
+ break;
+ }
+ }
+ }
+
+ void EmitStatement(const ast::Statement* stmt) {
+ tint::Switch(
+ stmt, //
+ [&](const ast::AssignmentStatement* a) { EmitAssignment(a); },
+ [&](const ast::BlockStatement* b) { EmitBlock(b); },
+ [&](const ast::BreakStatement* b) { EmitBreak(b); },
+ [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); },
+ [&](const ast::CallStatement* c) { EmitCall(c); },
+ [&](const ast::CompoundAssignmentStatement* c) { EmitCompoundAssignment(c); },
+ [&](const ast::ContinueStatement* c) { EmitContinue(c); },
+ [&](const ast::DiscardStatement* d) { EmitDiscard(d); },
+ [&](const ast::IfStatement* i) { EmitIf(i); },
+ [&](const ast::LoopStatement* l) { EmitLoop(l); },
+ [&](const ast::ForLoopStatement* l) { EmitForLoop(l); },
+ [&](const ast::WhileStatement* l) { EmitWhile(l); },
+ [&](const ast::ReturnStatement* r) { EmitReturn(r); },
+ [&](const ast::SwitchStatement* s) { EmitSwitch(s); },
+ [&](const ast::VariableDeclStatement* v) { EmitVariable(v->variable); },
+ [&](const ast::IncrementDecrementStatement* i) { EmitIncrementDecrement(i); },
+ [&](const ast::ConstAssert*) {
+ // Not emitted
+ },
+ [&](Default) {
+ add_error(stmt->source,
+ "unknown statement type: " + std::string(stmt->TypeInfo().name));
+ });
+ }
+
+ void EmitAssignment(const ast::AssignmentStatement* stmt) {
+ auto lhs = EmitExpression(stmt->lhs);
+ if (!lhs) {
+ return;
+ }
+
+ auto rhs = EmitExpression(stmt->rhs);
+ if (!rhs) {
+ return;
+ }
+ auto store = builder_.Store(lhs.Get(), rhs.Get());
+ current_flow_block_->instructions.Push(store);
+ }
+
+ void EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) {
+ auto lhs = EmitExpression(stmt->lhs);
+ if (!lhs) {
+ return;
+ }
+
+ auto* ty = lhs.Get()->Type();
+ auto* rhs = ty->UnwrapRef()->is_signed_integer_scalar() ? builder_.Constant(1_i)
+ : builder_.Constant(1_u);
+
+ Binary* inst = nullptr;
+ if (stmt->increment) {
+ inst = builder_.Add(ty, lhs.Get(), rhs);
+ } else {
+ inst = builder_.Subtract(ty, lhs.Get(), rhs);
+ }
+ current_flow_block_->instructions.Push(inst);
+
+ auto store = builder_.Store(lhs.Get(), inst);
+ current_flow_block_->instructions.Push(store);
+ }
+
+ void EmitCompoundAssignment(const ast::CompoundAssignmentStatement* stmt) {
+ auto lhs = EmitExpression(stmt->lhs);
+ if (!lhs) {
+ return;
+ }
+
+ auto rhs = EmitExpression(stmt->rhs);
+ if (!rhs) {
+ return;
+ }
+ auto* ty = lhs.Get()->Type();
+ Binary* inst = nullptr;
+ switch (stmt->op) {
+ case ast::BinaryOp::kAnd:
+ inst = builder_.And(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kOr:
+ inst = builder_.Or(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kXor:
+ inst = builder_.Xor(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kShiftLeft:
+ inst = builder_.ShiftLeft(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kShiftRight:
+ inst = builder_.ShiftRight(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kAdd:
+ inst = builder_.Add(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kSubtract:
+ inst = builder_.Subtract(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kMultiply:
+ inst = builder_.Multiply(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kDivide:
+ inst = builder_.Divide(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kModulo:
+ inst = builder_.Modulo(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kLessThanEqual:
+ case ast::BinaryOp::kGreaterThanEqual:
+ case ast::BinaryOp::kGreaterThan:
+ case ast::BinaryOp::kLessThan:
+ case ast::BinaryOp::kNotEqual:
+ case ast::BinaryOp::kEqual:
+ case ast::BinaryOp::kLogicalAnd:
+ case ast::BinaryOp::kLogicalOr:
+ TINT_ICE(IR, diagnostics_) << "invalid compound assignment";
+ return;
+ case ast::BinaryOp::kNone:
+ TINT_ICE(IR, diagnostics_) << "missing binary operand type";
+ return;
+ }
+ current_flow_block_->instructions.Push(inst);
+
+ auto store = builder_.Store(lhs.Get(), inst);
+ current_flow_block_->instructions.Push(store);
+ }
+
+ void EmitBlock(const ast::BlockStatement* block) {
+ scopes_.Push();
+ TINT_DEFER(scopes_.Pop());
+
+ // Note, this doesn't need to emit a Block as the current block flow node should be
+ // sufficient as the blocks all get flattened. Each flow control node will inject the basic
+ // blocks it requires.
+ EmitStatements(block->statements);
+ }
+
+ void EmitIf(const ast::IfStatement* stmt) {
+ // Emit the if condition into the end of the preceding block
+ auto reg = EmitExpression(stmt->condition);
+ if (!reg) {
+ return;
+ }
+ auto* if_node = builder_.CreateIf(reg.Get());
+
+ BranchTo(if_node);
+
+ ast_to_flow_[stmt] = if_node;
+
+ {
+ FlowStackScope scope(this, if_node);
+
+ current_flow_block_ = if_node->true_.target->As<Block>();
+ EmitBlock(stmt->body);
+
+ // If the true branch did not execute control flow, then go to the merge target
+ BranchToIfNeeded(if_node->merge.target);
+
+ current_flow_block_ = if_node->false_.target->As<Block>();
+ if (stmt->else_statement) {
+ EmitStatement(stmt->else_statement);
+ }
+
+ // If the false branch did not execute control flow, then go to the merge target
+ BranchToIfNeeded(if_node->merge.target);
+ }
+ current_flow_block_ = nullptr;
+
+ // If both branches went somewhere, then they both returned, continued or broke. So, there
+ // is no need for the if merge-block and there is nothing to branch to the merge block
+ // anyway.
+ if (IsConnected(if_node->merge.target)) {
+ current_flow_block_ = if_node->merge.target->As<Block>();
+ }
+ }
+
+ void EmitLoop(const ast::LoopStatement* stmt) {
+ auto* loop_node = builder_.CreateLoop();
+
+ BranchTo(loop_node);
+
+ ast_to_flow_[stmt] = loop_node;
+
+ {
+ FlowStackScope scope(this, loop_node);
+
+ current_flow_block_ = loop_node->start.target->As<Block>();
+
+ // The loop doesn't use EmitBlock because it needs the scope stack to not get popped
+ // until after the continuing block.
+ scopes_.Push();
+ TINT_DEFER(scopes_.Pop());
+ EmitStatements(stmt->body->statements);
+
+ // The current block didn't `break`, `return` or `continue`, go to the continuing block.
+ BranchToIfNeeded(loop_node->continuing.target);
+
+ current_flow_block_ = loop_node->continuing.target->As<Block>();
+ if (stmt->continuing) {
+ EmitBlock(stmt->continuing);
+ }
+
+ // Branch back to the start node if the continue target didn't branch out already
+ BranchToIfNeeded(loop_node->start.target);
+ }
+
+ // The loop merge can get disconnected if the loop returns directly, or the continuing
+ // target branches, eventually, to the merge, but nothing branched to the continuing target.
+ current_flow_block_ = loop_node->merge.target->As<Block>();
+ if (!IsConnected(loop_node->merge.target)) {
+ current_flow_block_ = nullptr;
+ }
+ }
+
+ void EmitWhile(const ast::WhileStatement* stmt) {
+ auto* loop_node = builder_.CreateLoop();
+ // Continue is always empty, just go back to the start
+ TINT_ASSERT(IR, loop_node->continuing.target->Is<Block>());
+ builder_.Branch(loop_node->continuing.target->As<Block>(), loop_node->start.target,
+ utils::Empty);
+
+ BranchTo(loop_node);
+
+ ast_to_flow_[stmt] = loop_node;
+
+ {
+ FlowStackScope scope(this, loop_node);
+
+ current_flow_block_ = loop_node->start.target->As<Block>();
+
+ // Emit the while condition into the start target of the loop
+ auto reg = EmitExpression(stmt->condition);
+ if (!reg) {
+ return;
+ }
+
+ // Create an `if (cond) {} else {break;}` control flow
+ auto* if_node = builder_.CreateIf(reg.Get());
+ TINT_ASSERT(IR, if_node->true_.target->Is<Block>());
+ builder_.Branch(if_node->true_.target->As<Block>(), if_node->merge.target,
+ utils::Empty);
+
+ TINT_ASSERT(IR, if_node->false_.target->Is<Block>());
+ builder_.Branch(if_node->false_.target->As<Block>(), loop_node->merge.target,
+ utils::Empty);
+
+ BranchTo(if_node);
+
+ current_flow_block_ = if_node->merge.target->As<Block>();
+ EmitBlock(stmt->body);
+
+ BranchToIfNeeded(loop_node->continuing.target);
+ }
+ // The while loop always has a path to the merge target as the break statement comes before
+ // anything inside the loop.
+ current_flow_block_ = loop_node->merge.target->As<Block>();
+ }
+
+ void EmitForLoop(const ast::ForLoopStatement* stmt) {
+ auto* loop_node = builder_.CreateLoop();
+ TINT_ASSERT(IR, loop_node->continuing.target->Is<Block>());
+ builder_.Branch(loop_node->continuing.target->As<Block>(), loop_node->start.target,
+ utils::Empty);
+
+ // Make sure the initializer ends up in a contained scope
+ scopes_.Push();
+ TINT_DEFER(scopes_.Pop());
+
+ if (stmt->initializer) {
+ // Emit the for initializer before branching to the loop
+ EmitStatement(stmt->initializer);
+ }
+
+ BranchTo(loop_node);
+
+ ast_to_flow_[stmt] = loop_node;
+
+ {
+ FlowStackScope scope(this, loop_node);
+
+ current_flow_block_ = loop_node->start.target->As<Block>();
+
+ if (stmt->condition) {
+ // Emit the condition into the target target of the loop
+ auto reg = EmitExpression(stmt->condition);
+ if (!reg) {
+ return;
+ }
+
+ // Create an `if (cond) {} else {break;}` control flow
+ auto* if_node = builder_.CreateIf(reg.Get());
+ TINT_ASSERT(IR, if_node->true_.target->Is<Block>());
+ builder_.Branch(if_node->true_.target->As<Block>(), if_node->merge.target,
+ utils::Empty);
+
+ TINT_ASSERT(IR, if_node->false_.target->Is<Block>());
+ builder_.Branch(if_node->false_.target->As<Block>(), loop_node->merge.target,
+ utils::Empty);
+
+ BranchTo(if_node);
+ current_flow_block_ = if_node->merge.target->As<Block>();
+ }
+
+ EmitBlock(stmt->body);
+ BranchToIfNeeded(loop_node->continuing.target);
+
+ if (stmt->continuing) {
+ current_flow_block_ = loop_node->continuing.target->As<Block>();
+ EmitStatement(stmt->continuing);
+ }
+ }
+
+ // The while loop always has a path to the merge target as the break statement comes before
+ // anything inside the loop.
+ current_flow_block_ = loop_node->merge.target->As<Block>();
+ }
+
+ void EmitSwitch(const ast::SwitchStatement* stmt) {
+ // Emit the condition into the preceding block
+ auto reg = EmitExpression(stmt->condition);
+ if (!reg) {
+ return;
+ }
+ auto* switch_node = builder_.CreateSwitch(reg.Get());
+
+ BranchTo(switch_node);
+
+ ast_to_flow_[stmt] = switch_node;
+
+ {
+ FlowStackScope scope(this, switch_node);
+
+ const auto* sem = program_->Sem().Get(stmt);
+ for (const auto* c : sem->Cases()) {
+ utils::Vector<Switch::CaseSelector, 4> selectors;
+ for (const auto* selector : c->Selectors()) {
+ if (selector->IsDefault()) {
+ selectors.Push({nullptr});
+ } else {
+ selectors.Push({builder_.Constant(selector->Value()->Clone(clone_ctx_))});
+ }
+ }
+
+ current_flow_block_ = builder_.CreateCase(switch_node, selectors);
+ EmitBlock(c->Body()->Declaration());
+
+ BranchToIfNeeded(switch_node->merge.target);
+ }
+ }
+ current_flow_block_ = nullptr;
+
+ if (IsConnected(switch_node->merge.target)) {
+ current_flow_block_ = switch_node->merge.target->As<Block>();
+ }
+ }
+
+ void EmitReturn(const ast::ReturnStatement* stmt) {
+ utils::Vector<Value*, 1> ret_value;
+ if (stmt->value) {
+ auto ret = EmitExpression(stmt->value);
+ if (!ret) {
+ return;
+ }
+ ret_value.Push(ret.Get());
+ }
+
+ BranchTo(current_function_->end_target, std::move(ret_value));
+ }
+
+ void EmitBreak(const ast::BreakStatement*) {
+ auto* current_control = FindEnclosingControl(ControlFlags::kNone);
+ TINT_ASSERT(IR, current_control);
+
+ if (auto* c = current_control->As<Loop>()) {
+ BranchTo(c->merge.target);
+ } else if (auto* s = current_control->As<Switch>()) {
+ BranchTo(s->merge.target);
+ } else {
+ TINT_UNREACHABLE(IR, diagnostics_);
+ }
+ }
+
+ void EmitContinue(const ast::ContinueStatement*) {
+ auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
+ TINT_ASSERT(IR, current_control);
+
+ if (auto* c = current_control->As<Loop>()) {
+ BranchTo(c->continuing.target);
+ } else {
+ TINT_UNREACHABLE(IR, diagnostics_);
+ }
+ }
+
+ // Discard is being treated as an instruction. The semantics in WGSL is demote_to_helper, so the
+ // code has to continue as before it just predicates writes. If WGSL grows some kind of
+ // terminating discard that would probably make sense as a FlowNode but would then require
+ // figuring out the multi-level exit that is triggered.
+ void EmitDiscard(const ast::DiscardStatement*) {
+ auto* inst = builder_.Discard();
+ current_flow_block_->instructions.Push(inst);
+ }
+
+ void EmitBreakIf(const ast::BreakIfStatement* stmt) {
+ // Emit the break-if condition into the end of the preceding block
+ auto reg = EmitExpression(stmt->condition);
+ if (!reg) {
+ return;
+ }
+ auto* if_node = builder_.CreateIf(reg.Get());
+
+ BranchTo(if_node);
+
+ ast_to_flow_[stmt] = if_node;
+
+ auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
+ TINT_ASSERT(IR, current_control);
+ TINT_ASSERT(IR, current_control->Is<Loop>());
+
+ auto* loop = current_control->As<Loop>();
+
+ current_flow_block_ = if_node->true_.target->As<Block>();
+ BranchTo(loop->merge.target);
+
+ current_flow_block_ = if_node->false_.target->As<Block>();
+ BranchTo(if_node->merge.target);
+
+ current_flow_block_ = if_node->merge.target->As<Block>();
+
+ // The `break-if` has to be the last item in the continuing block. The false branch of the
+ // `break-if` will always take us back to the start of the loop.
+ BranchTo(loop->start.target);
+ }
+
+ utils::Result<Value*> EmitExpression(const ast::Expression* expr) {
+ // If this is a value that has been const-eval'd return the result.
+ if (auto* sem = program_->Sem().Get(expr)->As<sem::ValueExpression>()) {
+ if (auto* v = sem->ConstantValue()) {
+ if (auto* cv = v->Clone(clone_ctx_)) {
+ return builder_.Constant(cv);
+ }
+ }
+ }
+
+ return tint::Switch(
+ expr,
+ // [&](const ast::IndexAccessorExpression* a) {
+ // TODO(dsinclair): Implement
+ // },
+ [&](const ast::BinaryExpression* b) { return EmitBinary(b); },
+ [&](const ast::BitcastExpression* b) { return EmitBitcast(b); },
+ [&](const ast::CallExpression* c) { return EmitCall(c); },
+ [&](const ast::IdentifierExpression* i) -> utils::Result<Value*> {
+ auto* v = scopes_.Get(i->identifier->symbol);
+ if (TINT_UNLIKELY(!v)) {
+ add_error(expr->source,
+ "unable to find identifier " + i->identifier->symbol.Name());
+ return utils::Failure;
+ }
+ return {v};
+ },
+ [&](const ast::LiteralExpression* l) { return EmitLiteral(l); },
+ // [&](const ast::MemberAccessorExpression* m) {
+ // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::PhonyExpression*) {
+ // TODO(dsinclair): Implement. The call may have side effects so has to be made.
+ // },
+ [&](const ast::UnaryOpExpression* u) { return EmitUnary(u); },
+ [&](Default) {
+ add_error(expr->source,
+ "unknown expression type: " + std::string(expr->TypeInfo().name));
+ return utils::Failure;
+ });
+ }
+
+ void EmitVariable(const ast::Variable* var) {
+ auto* sem = program_->Sem().Get(var);
+
+ return tint::Switch( //
+ var,
+ [&](const ast::Var* v) {
+ auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
+ auto* val = builder_.Declare(ty, sem->AddressSpace(), sem->Access());
+ current_flow_block_->instructions.Push(val);
+
+ if (v->initializer) {
+ auto init = EmitExpression(v->initializer);
+ if (!init) {
+ return;
+ }
+ val->initializer = init.Get();
+ }
+ // Store the declaration so we can get the instruction to store too
+ scopes_.Set(v->name->symbol, val);
+
+ // Record the original name of the var
+ builder_.ir.SetName(val, v->name->symbol.Name());
+ },
+ [&](const ast::Let* l) {
+ // A `let` doesn't exist as a standalone item in the IR, it's just the result of the
+ // initializer.
+ auto init = EmitExpression(l->initializer);
+ if (!init) {
+ return;
+ }
+
+ // Store the results of the initialization
+ scopes_.Set(l->name->symbol, init.Get());
+
+ // Record the original name of the let
+ builder_.ir.SetName(init.Get(), l->name->symbol.Name());
+ },
+ [&](const ast::Override*) {
+ add_error(var->source,
+ "found an `Override` variable. The SubstituteOverrides "
+ "transform must be run before converting to IR");
+ },
+ [&](const ast::Const*) {
+ // Skip. This should be handled by const-eval already, so the const will be a
+ // `constant::` value at the usage sites. Can just ignore the `const` variable as it
+ // should never be used.
+ //
+ // TODO(dsinclair): Probably want to store the const variable somewhere and then in
+ // identifier expression log an error if we ever see a const identifier. Add this
+ // when identifiers and variables are supported.
+ },
+ [&](Default) {
+ add_error(var->source, "unknown variable: " + std::string(var->TypeInfo().name));
+ });
+ }
+
+ utils::Result<Value*> EmitUnary(const ast::UnaryOpExpression* expr) {
+ auto val = EmitExpression(expr->expr);
+ if (!val) {
+ return utils::Failure;
+ }
+
+ auto* sem = program_->Sem().Get(expr);
+ auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
+
+ Instruction* inst = nullptr;
+ switch (expr->op) {
+ case ast::UnaryOp::kAddressOf:
+ inst = builder_.AddressOf(ty, val.Get());
+ break;
+ case ast::UnaryOp::kComplement:
+ inst = builder_.Complement(ty, val.Get());
+ break;
+ case ast::UnaryOp::kIndirection:
+ inst = builder_.Indirection(ty, val.Get());
+ break;
+ case ast::UnaryOp::kNegation:
+ inst = builder_.Negation(ty, val.Get());
+ break;
+ case ast::UnaryOp::kNot:
+ inst = builder_.Not(ty, val.Get());
+ break;
+ }
+
+ current_flow_block_->instructions.Push(inst);
+ return inst;
+ }
+
+ // A short-circut needs special treatment. The short-circuit is decomposed into the relevant if
+ // statements and declarations.
+ utils::Result<Value*> EmitShortCircuit(const ast::BinaryExpression* expr) {
+ switch (expr->op) {
+ case ast::BinaryOp::kLogicalAnd:
+ case ast::BinaryOp::kLogicalOr:
+ break;
+ default:
+ TINT_ICE(IR, diagnostics_)
+ << "invalid operation type for short-circut decomposition";
+ return utils::Failure;
+ }
+
+ // Evaluate the LHS of the short-circuit
+ auto lhs = EmitExpression(expr->lhs);
+ if (!lhs) {
+ return utils::Failure;
+ }
+
+ // Generate a variable to store the short-circut into
+ auto* ty = builder_.ir.types.Get<type::Bool>();
+ auto* result_var =
+ builder_.Declare(ty, builtin::AddressSpace::kFunction, builtin::Access::kReadWrite);
+ current_flow_block_->instructions.Push(result_var);
+
+ auto* lhs_store = builder_.Store(result_var, lhs.Get());
+ current_flow_block_->instructions.Push(lhs_store);
+
+ auto* if_node = builder_.CreateIf(lhs.Get());
+ BranchTo(if_node);
+
+ utils::Result<Value*> rhs;
+ {
+ FlowStackScope scope(this, if_node);
+
+ // If this is an `&&` then we only evaluate the RHS expression in the true block.
+ // If this is an `||` then we only evaluate the RHS expression in the false block.
+ if (expr->op == ast::BinaryOp::kLogicalAnd) {
+ current_flow_block_ = if_node->true_.target->As<Block>();
+ } else {
+ current_flow_block_ = if_node->false_.target->As<Block>();
+ }
+
+ rhs = EmitExpression(expr->rhs);
+ if (!rhs) {
+ return utils::Failure;
+ }
+ auto* rhs_store = builder_.Store(result_var, rhs.Get());
+ current_flow_block_->instructions.Push(rhs_store);
+
+ BranchTo(if_node->merge.target);
+ }
+ current_flow_block_ = if_node->merge.target->As<Block>();
+
+ return result_var;
+ }
+
+ utils::Result<Value*> EmitBinary(const ast::BinaryExpression* expr) {
+ if (expr->op == ast::BinaryOp::kLogicalAnd || expr->op == ast::BinaryOp::kLogicalOr) {
+ return EmitShortCircuit(expr);
+ }
+
+ auto lhs = EmitExpression(expr->lhs);
+ if (!lhs) {
+ return utils::Failure;
+ }
+
+ auto rhs = EmitExpression(expr->rhs);
+ if (!rhs) {
+ return utils::Failure;
+ }
+
+ auto* sem = program_->Sem().Get(expr);
+ auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
+
+ Binary* inst = nullptr;
+ switch (expr->op) {
+ case ast::BinaryOp::kAnd:
+ inst = builder_.And(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kOr:
+ inst = builder_.Or(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kXor:
+ inst = builder_.Xor(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kEqual:
+ inst = builder_.Equal(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kNotEqual:
+ inst = builder_.NotEqual(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kLessThan:
+ inst = builder_.LessThan(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kGreaterThan:
+ inst = builder_.GreaterThan(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kLessThanEqual:
+ inst = builder_.LessThanEqual(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kGreaterThanEqual:
+ inst = builder_.GreaterThanEqual(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kShiftLeft:
+ inst = builder_.ShiftLeft(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kShiftRight:
+ inst = builder_.ShiftRight(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kAdd:
+ inst = builder_.Add(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kSubtract:
+ inst = builder_.Subtract(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kMultiply:
+ inst = builder_.Multiply(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kDivide:
+ inst = builder_.Divide(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kModulo:
+ inst = builder_.Modulo(ty, lhs.Get(), rhs.Get());
+ break;
+ case ast::BinaryOp::kLogicalAnd:
+ case ast::BinaryOp::kLogicalOr:
+ TINT_ICE(IR, diagnostics_) << "short circuit op should have already been handled";
+ return utils::Failure;
+ case ast::BinaryOp::kNone:
+ TINT_ICE(IR, diagnostics_) << "missing binary operand type";
+ return utils::Failure;
+ }
+
+ current_flow_block_->instructions.Push(inst);
+ return inst;
+ }
+
+ utils::Result<Value*> EmitBitcast(const ast::BitcastExpression* expr) {
+ auto val = EmitExpression(expr->expr);
+ if (!val) {
+ return utils::Failure;
+ }
+
+ auto* sem = program_->Sem().Get(expr);
+ auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
+ auto* inst = builder_.Bitcast(ty, val.Get());
+
+ current_flow_block_->instructions.Push(inst);
+ return inst;
+ }
+
+ void EmitCall(const ast::CallStatement* stmt) { (void)EmitCall(stmt->expr); }
+
+ utils::Result<Value*> EmitCall(const ast::CallExpression* expr) {
+ // If this is a materialized semantic node, just use the constant value.
+ if (auto* mat = program_->Sem().Get(expr)) {
+ if (mat->ConstantValue()) {
+ auto* cv = mat->ConstantValue()->Clone(clone_ctx_);
+ if (!cv) {
+ add_error(expr->source, "failed to get constant value for call " +
+ std::string(expr->TypeInfo().name));
+ return utils::Failure;
+ }
+ return builder_.Constant(cv);
+ }
+ }
+
+ utils::Vector<Value*, 8> args;
+ args.Reserve(expr->args.Length());
+
+ // Emit the arguments
+ for (const auto* arg : expr->args) {
+ auto value = EmitExpression(arg);
+ if (!value) {
+ add_error(arg->source, "failed to convert arguments");
+ return utils::Failure;
+ }
+ args.Push(value.Get());
+ }
+
+ auto* sem = program_->Sem().Get<sem::Call>(expr);
+ if (!sem) {
+ add_error(expr->source, "failed to get semantic information for call " +
+ std::string(expr->TypeInfo().name));
+ return utils::Failure;
+ }
+
+ auto* ty = sem->Target()->ReturnType()->Clone(clone_ctx_.type_ctx);
+
+ Instruction* inst = nullptr;
+
+ // If this is a builtin function, emit the specific builtin value
+ if (auto* b = sem->Target()->As<sem::Builtin>()) {
+ inst = builder_.Builtin(ty, b->Type(), args);
+ } else if (sem->Target()->As<sem::ValueConstructor>()) {
+ inst = builder_.Construct(ty, std::move(args));
+ } else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
+ auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
+ inst = builder_.Convert(ty, from, std::move(args));
+ } else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
+ TINT_UNIMPLEMENTED(IR, diagnostics_) << "missing templated ident support";
+ return utils::Failure;
+ } else {
+ // Not a builtin and not a templated call, so this is a user function.
+ auto name = CloneSymbol(expr->target->identifier->symbol);
+ inst = builder_.UserCall(ty, name, std::move(args));
+ }
+ if (inst == nullptr) {
+ return utils::Failure;
+ }
+ current_flow_block_->instructions.Push(inst);
+ return inst;
+ }
+
+ utils::Result<Value*> EmitLiteral(const ast::LiteralExpression* lit) {
+ auto* sem = program_->Sem().Get(lit);
+ if (!sem) {
+ add_error(lit->source, "failed to get semantic information for node " +
+ std::string(lit->TypeInfo().name));
+ return utils::Failure;
+ }
+
+ auto* cv = sem->ConstantValue()->Clone(clone_ctx_);
+ if (!cv) {
+ add_error(lit->source,
+ "failed to get constant value for node " + std::string(lit->TypeInfo().name));
+ return utils::Failure;
+ }
+ return builder_.Constant(cv);
+ }
+
+ // void EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs) {
+ // for (auto* attr : attrs) {
+ // EmitAttribute(attr);
+ // }
+ // }
+ //
+ // void EmitAttribute(const ast::Attribute* attr) {
+ // tint::Switch( //
+ // attr,
+ // [&](const ast::WorkgroupAttribute* wg) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::StageAttribute* s) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::BindingAttribute* b) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::GroupAttribute* g) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::LocationAttribute* l) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::BuiltinAttribute* b) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::InterpolateAttribute* i) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::InvariantAttribute* i) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::MustUseAttribute* i) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::IdAttribute*) {
+ // add_error(attr->source,
+ // "found an `Id` attribute. The SubstituteOverrides transform "
+ // "must be run before converting to IR");
+ // },
+ // [&](const ast::StructMemberSizeAttribute*) {
+ // TINT_ICE(IR, diagnostics_)
+ // << "StructMemberSizeAttribute encountered during IR conversion";
+ // },
+ // [&](const ast::StructMemberAlignAttribute*) {
+ // TINT_ICE(IR, diagnostics_)
+ // << "StructMemberAlignAttribute encountered during IR conversion";
+ // },
+ // [&](const ast::StrideAttribute* s) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](const ast::InternalAttribute *i) {
+ // // TODO(dsinclair): Implement
+ // },
+ // [&](Default) {
+ // add_error(attr->source, "unknown attribute: " +
+ // std::string(attr->TypeInfo().name));
+ // });
+ // }
+};
+
+} // namespace
+
utils::Result<Module, std::string> FromProgram(const Program* program) {
if (!program->IsValid()) {
return std::string("input program is not valid");
}
- BuilderImpl b(program);
+ Impl b(program);
auto r = b.Build();
if (!r) {
- return b.Diagnostics().str();
+ return r.Failure().str();
}
return r.Move();
diff --git a/src/tint/ir/from_program_binary_test.cc b/src/tint/ir/from_program_binary_test.cc
new file mode 100644
index 0000000..33266cb
--- /dev/null
+++ b/src/tint/ir/from_program_binary_test.cc
@@ -0,0 +1,808 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/test_helper.h"
+
+#include "gmock/gmock.h"
+#include "src/tint/ast/case_selector.h"
+#include "src/tint/ast/int_literal_expression.h"
+#include "src/tint/constant/scalar.h"
+
+namespace tint::ir {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+
+using IR_BuilderImplTest = TestHelper;
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Add(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = add %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Increment) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = Increment("v1");
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = add %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundAdd) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kAdd);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = add %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Sub(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = sub %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Decrement) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
+ auto* expr = Decrement("v1");
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, i32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, i32, read_write> = sub %v1:ref<private, i32, read_write>, 1i
+ store %v1:ref<private, i32, read_write>, %2:ref<private, i32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundSubtract) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kSubtract);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = sub %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Mul(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = mul %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundMultiply) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kMultiply);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = mul %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Div(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = div %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundDiv) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kDivide);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = div %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Mod(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = mod %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundModulo) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kModulo);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = mod %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = And(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = and %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundAnd) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.bool_());
+ auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kAnd);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, bool, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, bool, read_write> = and %v1:ref<private, bool, read_write>, false
+ store %v1:ref<private, bool, read_write>, %2:ref<private, bool, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Or(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = or %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundOr) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.bool_());
+ auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kOr);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, bool, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, bool, read_write> = or %v1:ref<private, bool, read_write>, false
+ store %v1:ref<private, bool, read_write>, %2:ref<private, bool, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Xor(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = xor %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundXor) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kXor);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = xor %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) {
+ Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
+ auto* expr = LogicalAnd(Call("my_func"), false);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool {
+ %fn2 = block {
+ } -> %func_end true # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:bool = call my_func
+ %tint_symbol:bool = var function, read_write
+ store %tint_symbol:bool, %1:bool
+ } -> %fn5 # branch
+
+ %fn5 = if %1:bool [t: %fn6, f: %fn7, m: %fn8]
+ # true branch
+ %fn6 = block {
+ store %tint_symbol:bool, false
+ } -> %fn8 # branch
+
+ # if merge
+ %fn8 = block {
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) {
+ Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
+ auto* expr = LogicalOr(Call("my_func"), true);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool {
+ %fn2 = block {
+ } -> %func_end true # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:bool = call my_func
+ %tint_symbol:bool = var function, read_write
+ store %tint_symbol:bool, %1:bool
+ } -> %fn5 # branch
+
+ %fn5 = if %1:bool [t: %fn6, f: %fn7, m: %fn8]
+ # true branch
+ # false branch
+ %fn7 = block {
+ store %tint_symbol:bool, true
+ } -> %fn8 # branch
+
+ # if merge
+ %fn8 = block {
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Equal(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:bool = eq %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = NotEqual(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:bool = neq %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = LessThan(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:bool = lt %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = GreaterThan(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:bool = gt %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = LessThanEqual(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:bool = lte %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = GreaterThanEqual(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:bool = gte %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Shl(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = shiftl %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundShiftLeft) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftLeft);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = shiftl %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Shr(Call("my_func"), 4_u);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 0u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = shiftr %1:u32, 4u
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundShiftRight) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
+ auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftRight);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, u32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %2:ref<private, u32, read_write> = shiftr %v1:ref<private, u32, read_write>, 1u
+ store %v1:ref<private, u32, read_write>, %2:ref<private, u32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
+ Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
+
+ auto* expr = LogicalAnd(LessThan(Call("my_func"), 2_f),
+ GreaterThan(2.5_f, Div(Call("my_func"), Mul(2.3_f, Call("my_func")))));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():f32 {
+ %fn2 = block {
+ } -> %func_end 0.0f # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:f32 = call my_func
+ %2:bool = lt %1:f32, 2.0f
+ %tint_symbol:bool = var function, read_write
+ store %tint_symbol:bool, %2:bool
+ } -> %fn5 # branch
+
+ %fn5 = if %2:bool [t: %fn6, f: %fn7, m: %fn8]
+ # true branch
+ %fn6 = block {
+ %4:f32 = call my_func
+ %5:f32 = call my_func
+ %6:f32 = mul 2.29999995231628417969f, %5:f32
+ %7:f32 = div %4:f32, %6:f32
+ %8:bool = gt 2.5f, %7:f32
+ store %tint_symbol:bool, %8:bool
+ } -> %fn8 # branch
+
+ # if merge
+ %fn8 = block {
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound_WithConstEval) {
+ Func("my_func", utils::Vector{Param("p", ty.bool_())}, ty.bool_(), utils::Vector{Return(true)});
+ auto* expr = Call("my_func", LogicalAnd(LessThan(2.4_f, 2_f),
+ GreaterThan(2.5_f, Div(10_f, Mul(2.3_f, 9.4_f)))));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool {
+ %fn2 = block {
+ } -> %func_end true # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %tint_symbol:bool = call my_func, false
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/from_program_call_test.cc b/src/tint/ir/from_program_call_test.cc
new file mode 100644
index 0000000..ae217d1
--- /dev/null
+++ b/src/tint/ir/from_program_call_test.cc
@@ -0,0 +1,154 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/test_helper.h"
+
+#include "gmock/gmock.h"
+#include "src/tint/ast/case_selector.h"
+#include "src/tint/ast/int_literal_expression.h"
+#include "src/tint/constant/scalar.h"
+
+namespace tint::ir {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+
+using IR_BuilderImplTest = TestHelper;
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) {
+ Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
+
+ auto* expr = Bitcast<f32>(Call("my_func"));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():f32 {
+ %fn2 = block {
+ } -> %func_end 0.0f # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:f32 = call my_func
+ %tint_symbol:f32 = bitcast %1:f32
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitStatement_Discard) {
+ auto* expr = Discard();
+ Func("test_function", {}, ty.void_(), expr,
+ utils::Vector{
+ create<ast::StageAttribute>(ast::PipelineStage::kFragment),
+ });
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func test_function():void [@fragment] {
+ %fn2 = block {
+ discard
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) {
+ Func("my_func", utils::Vector{Param("p", ty.f32())}, ty.void_(), utils::Empty);
+
+ auto* stmt = CallStmt(Call("my_func", Mul(2_a, 3_a)));
+ WrapInFunction(stmt);
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():void {
+ %fn2 = block {
+ } -> %func_end # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:void = call my_func, 6.0f
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Convert) {
+ auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i));
+ auto* expr = Call(ty.f32(), i);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %i:ref<private, i32, read_write> = var private, read_write, 1i
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %tint_symbol:f32 = convert i32, %i:ref<private, i32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_ConstructEmpty) {
+ auto* expr = vec3(ty.f32());
+ GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %i:ref<private, vec3<f32>, read_write> = var private, read_write, vec3<f32> 0.0f
+}
+
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Construct) {
+ auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
+ auto* expr = vec3(ty.f32(), 2_f, 3_f, i);
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %i:ref<private, f32, read_write> = var private, read_write, 1.0f
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %tint_symbol:vec3<f32> = construct 2.0f, 3.0f, %i:ref<private, f32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl_literal_test.cc b/src/tint/ir/from_program_literal_test.cc
similarity index 61%
rename from src/tint/ir/builder_impl_literal_test.cc
rename to src/tint/ir/from_program_literal_test.cc
index 090f3f8..de5e81e 100644
--- a/src/tint/ir/builder_impl_literal_test.cc
+++ b/src/tint/ir/from_program_literal_test.cc
@@ -18,10 +18,26 @@
#include "src/tint/ast/case_selector.h"
#include "src/tint/ast/int_literal_expression.h"
#include "src/tint/constant/scalar.h"
+#include "src/tint/ir/block.h"
+#include "src/tint/ir/constant.h"
+#include "src/tint/ir/var.h"
namespace tint::ir {
namespace {
+Value* GlobalVarInitializer(const Module& m) {
+ if (m.root_block->instructions.Length() == 0u) {
+ ADD_FAILURE() << "m.root_block has no instruction";
+ return nullptr;
+ }
+ auto* var = m.root_block->instructions[0]->As<ir::Var>();
+ if (!var) {
+ ADD_FAILURE() << "m.root_block.instructions[0] was not a var";
+ return nullptr;
+ }
+ return var->initializer;
+}
+
using namespace tint::number_suffixes; // NOLINT
using IR_BuilderImplTest = TestHelper;
@@ -30,12 +46,12 @@
auto* expr = Expr(true);
GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
- auto& b = CreateBuilder();
- auto r = b.EmitLiteral(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_TRUE(r.Get()->Is<Constant>());
- auto* val = r.Get()->As<Constant>()->value;
+ auto* init = GlobalVarInitializer(m.Get());
+ ASSERT_TRUE(Is<Constant>(init));
+ auto* val = init->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
EXPECT_TRUE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
@@ -44,12 +60,12 @@
auto* expr = Expr(false);
GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
- auto& b = CreateBuilder();
- auto r = b.EmitLiteral(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_TRUE(r.Get()->Is<Constant>());
- auto* val = r.Get()->As<Constant>()->value;
+ auto* init = GlobalVarInitializer(m.Get());
+ ASSERT_TRUE(Is<Constant>(init));
+ auto* val = init->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
EXPECT_FALSE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
@@ -58,12 +74,12 @@
auto* expr = Expr(1.2_f);
GlobalVar("a", ty.f32(), builtin::AddressSpace::kPrivate, expr);
- auto& b = CreateBuilder();
- auto r = b.EmitLiteral(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_TRUE(r.Get()->Is<Constant>());
- auto* val = r.Get()->As<Constant>()->value;
+ auto* init = GlobalVarInitializer(m.Get());
+ ASSERT_TRUE(Is<Constant>(init));
+ auto* val = init->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<f32>>());
EXPECT_EQ(1.2_f, val->As<constant::Scalar<f32>>()->ValueAs<f32>());
}
@@ -73,12 +89,12 @@
auto* expr = Expr(1.2_h);
GlobalVar("a", ty.f16(), builtin::AddressSpace::kPrivate, expr);
- auto& b = CreateBuilder();
- auto r = b.EmitLiteral(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_TRUE(r.Get()->Is<Constant>());
- auto* val = r.Get()->As<Constant>()->value;
+ auto* init = GlobalVarInitializer(m.Get());
+ ASSERT_TRUE(Is<Constant>(init));
+ auto* val = init->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<f16>>());
EXPECT_EQ(1.2_h, val->As<constant::Scalar<f16>>()->ValueAs<f32>());
}
@@ -87,12 +103,12 @@
auto* expr = Expr(-2_i);
GlobalVar("a", ty.i32(), builtin::AddressSpace::kPrivate, expr);
- auto& b = CreateBuilder();
- auto r = b.EmitLiteral(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_TRUE(r.Get()->Is<Constant>());
- auto* val = r.Get()->As<Constant>()->value;
+ auto* init = GlobalVarInitializer(m.Get());
+ ASSERT_TRUE(Is<Constant>(init));
+ auto* val = init->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<i32>>());
EXPECT_EQ(-2_i, val->As<constant::Scalar<i32>>()->ValueAs<f32>());
}
@@ -101,12 +117,12 @@
auto* expr = Expr(2_u);
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
- auto& b = CreateBuilder();
- auto r = b.EmitLiteral(expr);
- ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_TRUE(r.Get()->Is<Constant>());
- auto* val = r.Get()->As<Constant>()->value;
+ auto* init = GlobalVarInitializer(m.Get());
+ ASSERT_TRUE(Is<Constant>(init));
+ auto* val = init->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<u32>>());
EXPECT_EQ(2_u, val->As<constant::Scalar<u32>>()->ValueAs<f32>());
}
diff --git a/src/tint/ir/builder_impl_materialize_test.cc b/src/tint/ir/from_program_materialize_test.cc
similarity index 84%
rename from src/tint/ir/builder_impl_materialize_test.cc
rename to src/tint/ir/from_program_materialize_test.cc
index 6b4ae84..ba293a7 100644
--- a/src/tint/ir/builder_impl_materialize_test.cc
+++ b/src/tint/ir/from_program_materialize_test.cc
@@ -31,14 +31,13 @@
Func("test_function", {}, ty.f32(), expr, utils::Empty);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m), R"(%fn1 = func test_function():f32
- %fn2 = block
- ret 2.0f
-func_end
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func test_function():f32 {
+ %fn2 = block {
+ } -> %func_end 2.0f # return
+} %func_end
)");
}
diff --git a/src/tint/ir/builder_impl_store_test.cc b/src/tint/ir/from_program_store_test.cc
similarity index 80%
rename from src/tint/ir/builder_impl_store_test.cc
rename to src/tint/ir/from_program_store_test.cc
index 82fbc0a..4e89dbe 100644
--- a/src/tint/ir/builder_impl_store_test.cc
+++ b/src/tint/ir/from_program_store_test.cc
@@ -32,20 +32,19 @@
auto* expr = Assign("a", 4_u);
WrapInFunction(expr);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%a:ref<private, u32, read_write> = var private, read_write
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %a:ref<private, u32, read_write> = var private, read_write
+}
-
-%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn3 = block
- store %a:ref<private, u32, read_write>, 4u
- ret
-func_end
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ store %a:ref<private, u32, read_write>, 4u
+ } -> %func_end # return
+} %func_end
)");
}
diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/from_program_test.cc
similarity index 67%
rename from src/tint/ir/builder_impl_test.cc
rename to src/tint/ir/from_program_test.cc
index 36eb3b6..234b6cc 100644
--- a/src/tint/ir/builder_impl_test.cc
+++ b/src/tint/ir/from_program_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2022 The Tint Authors.
+// Copyright 2023 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,34 +18,63 @@
#include "src/tint/ast/case_selector.h"
#include "src/tint/ast/int_literal_expression.h"
#include "src/tint/constant/scalar.h"
+#include "src/tint/ir/block.h"
+#include "src/tint/ir/function_terminator.h"
+#include "src/tint/ir/if.h"
+#include "src/tint/ir/loop.h"
+#include "src/tint/ir/switch.h"
namespace tint::ir {
namespace {
+/// Looks for the flow node with the given type T.
+/// If no flow node is found, then nullptr is returned.
+/// If multiple flow nodes are found with the type T, then an error is raised and the first is
+/// returned.
+template <typename T>
+const T* FindSingleFlowNode(const Module& mod) {
+ const T* found = nullptr;
+ size_t count = 0;
+ for (auto* node : mod.flow_nodes.Objects()) {
+ if (auto* as = node->As<T>()) {
+ count++;
+ if (!found) {
+ found = as;
+ }
+ }
+ }
+ if (count > 1) {
+ ADD_FAILURE() << "FindSingleFlowNode() found " << count << " nodes of type "
+ << utils::TypeInfo::Of<T>().name;
+ }
+ return found;
+}
+
using namespace tint::number_suffixes; // NOLINT
using IR_BuilderImplTest = TestHelper;
TEST_F(IR_BuilderImplTest, Func) {
Func("f", utils::Empty, ty.void_(), utils::Empty);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
- ASSERT_EQ(0u, m.entry_points.Length());
- ASSERT_EQ(1u, m.functions.Length());
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* f = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+
+ auto* f = m->functions[0];
ASSERT_NE(f->start_target, nullptr);
ASSERT_NE(f->end_target, nullptr);
EXPECT_EQ(1u, f->start_target->inbound_branches.Length());
EXPECT_EQ(1u, f->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m), R"(%fn1 = func f():void
- %fn2 = block
- ret
-func_end
+ EXPECT_EQ(m->functions[0]->pipeline_stage, Function::PipelineStage::kUndefined);
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func f():void {
+ %fn2 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -53,33 +82,27 @@
TEST_F(IR_BuilderImplTest, EntryPoint) {
Func("f", utils::Empty, ty.void_(), utils::Empty,
utils::Vector{Stage(ast::PipelineStage::kFragment)});
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
- ASSERT_EQ(1u, m.entry_points.Length());
- EXPECT_EQ(m.functions[0], m.entry_points[0]);
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(m->functions[0]->pipeline_stage, Function::PipelineStage::kFragment);
}
TEST_F(IR_BuilderImplTest, IfStatement) {
auto* ast_if = If(true, Block(), Else(Block()));
WrapInFunction(ast_if);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- EXPECT_TRUE(ir_if->Is<ir::If>());
-
- auto* flow = ir_if->As<ir::If>();
+ auto* flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(flow->true_.target, nullptr);
ASSERT_NE(flow->false_.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, flow->inbound_branches.Length());
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
@@ -88,24 +111,24 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = if true [t: %fn4, f: %fn5, m: %fn6]
# true branch
- %fn4 = block
- branch %fn6
+ %fn4 = block {
+ } -> %fn6 # branch
# false branch
- %fn5 = block
- branch %fn6
+ %fn5 = block {
+ } -> %fn6 # branch
# if merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -114,21 +137,16 @@
auto* ast_if = If(true, Block(Return()));
WrapInFunction(ast_if);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- EXPECT_TRUE(ir_if->Is<ir::If>());
-
- auto* flow = ir_if->As<ir::If>();
+ auto* flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(flow->true_.target, nullptr);
ASSERT_NE(flow->false_.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, flow->inbound_branches.Length());
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
@@ -137,23 +155,23 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = if true [t: %fn4, f: %fn5, m: %fn6]
# true branch
- %fn4 = block
- ret
+ %fn4 = block {
+ } -> %func_end # return
# false branch
- %fn5 = block
- branch %fn6
+ %fn5 = block {
+ } -> %fn6 # branch
# if merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -162,21 +180,16 @@
auto* ast_if = If(true, Block(), Else(Block(Return())));
WrapInFunction(ast_if);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- EXPECT_TRUE(ir_if->Is<ir::If>());
-
- auto* flow = ir_if->As<ir::If>();
+ auto* flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(flow->true_.target, nullptr);
ASSERT_NE(flow->false_.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, flow->inbound_branches.Length());
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
@@ -185,23 +198,23 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = if true [t: %fn4, f: %fn5, m: %fn6]
# true branch
- %fn4 = block
- branch %fn6
+ %fn4 = block {
+ } -> %fn6 # branch
# false branch
- %fn5 = block
- ret
+ %fn5 = block {
+ } -> %func_end # return
# if merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -210,21 +223,16 @@
auto* ast_if = If(true, Block(Return()), Else(Block(Return())));
WrapInFunction(ast_if);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- EXPECT_TRUE(ir_if->Is<ir::If>());
-
- auto* flow = ir_if->As<ir::If>();
+ auto* flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(flow->true_.target, nullptr);
ASSERT_NE(flow->false_.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, flow->inbound_branches.Length());
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
@@ -233,19 +241,19 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = if true [t: %fn4, f: %fn5]
# true branch
- %fn4 = block
- ret
+ %fn4 = block {
+ } -> %func_end # return
# false branch
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -255,55 +263,47 @@
auto* ast_if = If(true, Block(ast_loop));
WrapInFunction(ast_if);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- EXPECT_TRUE(ir_if->Is<ir::If>());
-
- auto* if_flow = ir_if->As<ir::If>();
+ auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(if_flow->true_.target, nullptr);
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
+ ASSERT_NE(loop_flow, nullptr);
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = if true [t: %fn4, f: %fn5, m: %fn6]
# true branch
- %fn4 = block
- branch %fn7
+ %fn4 = block {
+ } -> %fn7 # branch
%fn7 = loop [s: %fn8, m: %fn9]
# loop start
- %fn8 = block
- branch %fn9
+ %fn8 = block {
+ } -> %fn9 # branch
# loop merge
- %fn9 = block
- branch %fn6
+ %fn9 = block {
+ } -> %fn6 # branch
# false branch
- %fn5 = block
- branch %fn6
+ %fn5 = block {
+ } -> %fn6 # branch
# if merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -312,21 +312,16 @@
auto* ast_loop = Loop(Block(Break()));
WrapInFunction(ast_loop);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* flow = ir_loop->As<ir::Loop>();
+ auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(flow->start.target, nullptr);
ASSERT_NE(flow->continuing.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, flow->inbound_branches.Length());
EXPECT_EQ(2u, flow->start.target->inbound_branches.Length());
@@ -335,20 +330,20 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, m: %fn5]
# loop start
- %fn4 = block
- branch %fn5
+ %fn4 = block {
+ } -> %fn5 # branch
# loop merge
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -358,30 +353,21 @@
auto* ast_loop = Loop(Block(ast_if, Continue()));
WrapInFunction(ast_loop);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- ASSERT_TRUE(ir_if->Is<ir::If>());
-
- auto* if_flow = ir_if->As<ir::If>();
+ auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(if_flow->true_.target, nullptr);
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
@@ -394,37 +380,37 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, c: %fn5, m: %fn6]
# loop start
- %fn4 = block
- branch %fn7
+ %fn4 = block {
+ } -> %fn7 # branch
%fn7 = if true [t: %fn8, f: %fn9, m: %fn10]
# true branch
- %fn8 = block
- branch %fn6
+ %fn8 = block {
+ } -> %fn6 # branch
# false branch
- %fn9 = block
- branch %fn10
+ %fn9 = block {
+ } -> %fn10 # branch
# if merge
- %fn10 = block
- branch %fn5
+ %fn10 = block {
+ } -> %fn5 # branch
# loop continuing
- %fn5 = block
- branch %fn4
+ %fn5 = block {
+ } -> %fn4 # branch
# loop merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -434,30 +420,21 @@
auto* ast_loop = Loop(Block(), Block(ast_break_if));
WrapInFunction(ast_loop);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- auto* ir_break_if = FlowNodeForAstNode(ast_break_if);
- ASSERT_NE(ir_break_if, nullptr);
- ASSERT_TRUE(ir_break_if->Is<ir::If>());
-
- auto* break_if_flow = ir_break_if->As<ir::If>();
+ auto* break_if_flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(break_if_flow->true_.target, nullptr);
ASSERT_NE(break_if_flow->false_.target, nullptr);
ASSERT_NE(break_if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
@@ -470,37 +447,81 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, c: %fn5, m: %fn6]
# loop start
- %fn4 = block
- branch %fn5
+ %fn4 = block {
+ } -> %fn5 # branch
# loop continuing
- %fn5 = block
- branch %fn7
+ %fn5 = block {
+ } -> %fn7 # branch
%fn7 = if true [t: %fn8, f: %fn9, m: %fn10]
# true branch
- %fn8 = block
- branch %fn6
+ %fn8 = block {
+ } -> %fn6 # branch
# false branch
- %fn9 = block
- branch %fn10
+ %fn9 = block {
+ } -> %fn10 # branch
# if merge
- %fn10 = block
- branch %fn4
+ %fn10 = block {
+ } -> %fn4 # branch
# loop merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, Loop_Continuing_Body_Scope) {
+ auto* a = Decl(Let("a", Expr(true)));
+ auto* ast_break_if = BreakIf("a");
+ auto* ast_loop = Loop(Block(a), Block(ast_break_if));
+ WrapInFunction(ast_loop);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
+
+ %fn3 = loop [s: %fn4, c: %fn5, m: %fn6]
+ # loop start
+ %fn4 = block {
+ } -> %fn5 # branch
+
+ # loop continuing
+ %fn5 = block {
+ } -> %fn7 # branch
+
+ %fn7 = if true [t: %fn8, f: %fn9, m: %fn10]
+ # true branch
+ %fn8 = block {
+ } -> %fn6 # branch
+
+ # false branch
+ %fn9 = block {
+ } -> %fn10 # branch
+
+ # if merge
+ %fn10 = block {
+ } -> %fn4 # branch
+
+ # loop merge
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -510,30 +531,21 @@
auto* ast_loop = Loop(Block(ast_if, Continue()));
WrapInFunction(ast_loop);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- ASSERT_TRUE(ir_if->Is<ir::If>());
-
- auto* if_flow = ir_if->As<ir::If>();
+ auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(if_flow->true_.target, nullptr);
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
@@ -546,33 +558,33 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, c: %fn5]
# loop start
- %fn4 = block
- branch %fn6
+ %fn4 = block {
+ } -> %fn6 # branch
%fn6 = if true [t: %fn7, f: %fn8, m: %fn9]
# true branch
- %fn7 = block
- ret
+ %fn7 = block {
+ } -> %func_end # return
# false branch
- %fn8 = block
- branch %fn9
+ %fn8 = block {
+ } -> %fn9 # branch
# if merge
- %fn9 = block
- branch %fn5
+ %fn9 = block {
+ } -> %fn5 # branch
# loop continuing
- %fn5 = block
- branch %fn4
+ %fn5 = block {
+ } -> %fn4 # branch
-func_end
+} %func_end
)");
}
@@ -581,21 +593,16 @@
auto* ast_loop = Loop(Block(Return(), Continue()));
WrapInFunction(ast_loop, If(true, Block(Return())));
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
@@ -604,16 +611,16 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4]
# loop start
- %fn4 = block
- ret
-func_end
+ %fn4 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -631,33 +638,21 @@
auto* ast_if = If(true, Block(Return()));
WrapInFunction(Block(ast_loop, ast_if));
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- auto* ir_if = FlowNodeForAstNode(ast_if);
- EXPECT_EQ(ir_if, nullptr);
-
- auto* ir_break_if = FlowNodeForAstNode(ast_break_if);
- ASSERT_NE(ir_break_if, nullptr);
- EXPECT_TRUE(ir_break_if->Is<ir::If>());
-
- auto* break_if_flow = ir_break_if->As<ir::If>();
+ auto* break_if_flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(break_if_flow->true_.target, nullptr);
ASSERT_NE(break_if_flow->false_.target, nullptr);
ASSERT_NE(break_if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
@@ -667,16 +662,16 @@
// This is 1 because only the loop branch happens. The subsequent if return is dead code.
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4]
# loop start
- %fn4 = block
- ret
-func_end
+ %fn4 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -686,30 +681,21 @@
auto* ast_loop = Loop(Block(ast_if, Continue()));
WrapInFunction(ast_loop);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop = FlowNodeForAstNode(ast_loop);
- ASSERT_NE(ir_loop, nullptr);
- EXPECT_TRUE(ir_loop->Is<ir::Loop>());
-
- auto* loop_flow = ir_loop->As<ir::Loop>();
+ auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(loop_flow->start.target, nullptr);
ASSERT_NE(loop_flow->continuing.target, nullptr);
ASSERT_NE(loop_flow->merge.target, nullptr);
- auto* ir_if = FlowNodeForAstNode(ast_if);
- ASSERT_NE(ir_if, nullptr);
- ASSERT_TRUE(ir_if->Is<ir::If>());
-
- auto* if_flow = ir_if->As<ir::If>();
+ auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
ASSERT_NE(if_flow->true_.target, nullptr);
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
@@ -722,29 +708,29 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, m: %fn5]
# loop start
- %fn4 = block
- branch %fn6
+ %fn4 = block {
+ } -> %fn6 # branch
%fn6 = if true [t: %fn7, f: %fn8]
# true branch
- %fn7 = block
- branch %fn5
+ %fn7 = block {
+ } -> %fn5 # branch
# false branch
- %fn8 = block
- branch %fn5
+ %fn8 = block {
+ } -> %fn5 # branch
# loop merge
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -763,76 +749,68 @@
WrapInFunction(ast_loop_a);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_loop_a = FlowNodeForAstNode(ast_loop_a);
- ASSERT_NE(ir_loop_a, nullptr);
- EXPECT_TRUE(ir_loop_a->Is<ir::Loop>());
- auto* loop_flow_a = ir_loop_a->As<ir::Loop>();
+ ASSERT_EQ(1u, m->functions.Length());
+
+ auto block_exit = [&](const ir::FlowNode* node) -> const ir::FlowNode* {
+ if (auto* block = As<ir::Block>(node)) {
+ return block->branch.target;
+ }
+ return nullptr;
+ };
+
+ auto* loop_flow_a = As<ir::Loop>(m->functions[0]->start_target->branch.target);
+ ASSERT_NE(loop_flow_a, nullptr);
ASSERT_NE(loop_flow_a->start.target, nullptr);
ASSERT_NE(loop_flow_a->continuing.target, nullptr);
ASSERT_NE(loop_flow_a->merge.target, nullptr);
- auto* ir_loop_b = FlowNodeForAstNode(ast_loop_b);
- ASSERT_NE(ir_loop_b, nullptr);
- EXPECT_TRUE(ir_loop_b->Is<ir::Loop>());
- auto* loop_flow_b = ir_loop_b->As<ir::Loop>();
+ auto* loop_flow_b = As<ir::Loop>(block_exit(loop_flow_a->start.target));
+ ASSERT_NE(loop_flow_b, nullptr);
ASSERT_NE(loop_flow_b->start.target, nullptr);
ASSERT_NE(loop_flow_b->continuing.target, nullptr);
ASSERT_NE(loop_flow_b->merge.target, nullptr);
- auto* ir_loop_c = FlowNodeForAstNode(ast_loop_c);
- ASSERT_NE(ir_loop_c, nullptr);
- EXPECT_TRUE(ir_loop_c->Is<ir::Loop>());
- auto* loop_flow_c = ir_loop_c->As<ir::Loop>();
- ASSERT_NE(loop_flow_c->start.target, nullptr);
- ASSERT_NE(loop_flow_c->continuing.target, nullptr);
- ASSERT_NE(loop_flow_c->merge.target, nullptr);
-
- auto* ir_loop_d = FlowNodeForAstNode(ast_loop_d);
- ASSERT_NE(ir_loop_d, nullptr);
- EXPECT_TRUE(ir_loop_d->Is<ir::Loop>());
- auto* loop_flow_d = ir_loop_d->As<ir::Loop>();
- ASSERT_NE(loop_flow_d->start.target, nullptr);
- ASSERT_NE(loop_flow_d->continuing.target, nullptr);
- ASSERT_NE(loop_flow_d->merge.target, nullptr);
-
- auto* ir_if_a = FlowNodeForAstNode(ast_if_a);
- ASSERT_NE(ir_if_a, nullptr);
- EXPECT_TRUE(ir_if_a->Is<ir::If>());
- auto* if_flow_a = ir_if_a->As<ir::If>();
+ auto* if_flow_a = As<ir::If>(block_exit(loop_flow_b->start.target));
+ ASSERT_NE(if_flow_a, nullptr);
ASSERT_NE(if_flow_a->true_.target, nullptr);
ASSERT_NE(if_flow_a->false_.target, nullptr);
ASSERT_NE(if_flow_a->merge.target, nullptr);
- auto* ir_if_b = FlowNodeForAstNode(ast_if_b);
- ASSERT_NE(ir_if_b, nullptr);
- EXPECT_TRUE(ir_if_b->Is<ir::If>());
- auto* if_flow_b = ir_if_b->As<ir::If>();
+ auto* if_flow_b = As<ir::If>(block_exit(if_flow_a->merge.target));
+ ASSERT_NE(if_flow_b, nullptr);
ASSERT_NE(if_flow_b->true_.target, nullptr);
ASSERT_NE(if_flow_b->false_.target, nullptr);
ASSERT_NE(if_flow_b->merge.target, nullptr);
- auto* ir_if_c = FlowNodeForAstNode(ast_if_c);
- ASSERT_NE(ir_if_c, nullptr);
- EXPECT_TRUE(ir_if_c->Is<ir::If>());
- auto* if_flow_c = ir_if_c->As<ir::If>();
+ auto* loop_flow_c = As<ir::Loop>(block_exit(loop_flow_b->continuing.target));
+ ASSERT_NE(loop_flow_c, nullptr);
+ ASSERT_NE(loop_flow_c->start.target, nullptr);
+ ASSERT_NE(loop_flow_c->continuing.target, nullptr);
+ ASSERT_NE(loop_flow_c->merge.target, nullptr);
+
+ auto* loop_flow_d = As<ir::Loop>(block_exit(loop_flow_c->merge.target));
+ ASSERT_NE(loop_flow_d, nullptr);
+ ASSERT_NE(loop_flow_d->start.target, nullptr);
+ ASSERT_NE(loop_flow_d->continuing.target, nullptr);
+ ASSERT_NE(loop_flow_d->merge.target, nullptr);
+
+ auto* if_flow_c = As<ir::If>(block_exit(loop_flow_d->continuing.target));
+ ASSERT_NE(if_flow_c, nullptr);
ASSERT_NE(if_flow_c->true_.target, nullptr);
ASSERT_NE(if_flow_c->false_.target, nullptr);
ASSERT_NE(if_flow_c->merge.target, nullptr);
- auto* ir_if_d = FlowNodeForAstNode(ast_if_d);
- ASSERT_NE(ir_if_d, nullptr);
- EXPECT_TRUE(ir_if_d->Is<ir::If>());
- auto* if_flow_d = ir_if_d->As<ir::If>();
+ auto* if_flow_d = As<ir::If>(block_exit(loop_flow_b->merge.target));
+ ASSERT_NE(if_flow_d, nullptr);
ASSERT_NE(if_flow_d->true_.target, nullptr);
ASSERT_NE(if_flow_d->false_.target, nullptr);
ASSERT_NE(if_flow_d->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, loop_flow_a->inbound_branches.Length());
EXPECT_EQ(2u, loop_flow_a->start.target->inbound_branches.Length());
@@ -869,111 +847,111 @@
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, c: %fn5, m: %fn6]
# loop start
- %fn4 = block
- branch %fn7
+ %fn4 = block {
+ } -> %fn7 # branch
%fn7 = loop [s: %fn8, c: %fn9, m: %fn10]
# loop start
- %fn8 = block
- branch %fn11
+ %fn8 = block {
+ } -> %fn11 # branch
%fn11 = if true [t: %fn12, f: %fn13, m: %fn14]
# true branch
- %fn12 = block
- branch %fn10
+ %fn12 = block {
+ } -> %fn10 # branch
# false branch
- %fn13 = block
- branch %fn14
+ %fn13 = block {
+ } -> %fn14 # branch
# if merge
- %fn14 = block
- branch %fn15
+ %fn14 = block {
+ } -> %fn15 # branch
%fn15 = if true [t: %fn16, f: %fn17, m: %fn18]
# true branch
- %fn16 = block
- branch %fn9
+ %fn16 = block {
+ } -> %fn9 # branch
# false branch
- %fn17 = block
- branch %fn18
+ %fn17 = block {
+ } -> %fn18 # branch
# if merge
- %fn18 = block
- branch %fn9
+ %fn18 = block {
+ } -> %fn9 # branch
# loop continuing
- %fn9 = block
- branch %fn19
+ %fn9 = block {
+ } -> %fn19 # branch
%fn19 = loop [s: %fn20, m: %fn21]
# loop start
- %fn20 = block
- branch %fn21
+ %fn20 = block {
+ } -> %fn21 # branch
# loop merge
- %fn21 = block
- branch %fn22
+ %fn21 = block {
+ } -> %fn22 # branch
%fn22 = loop [s: %fn23, c: %fn24, m: %fn25]
# loop start
- %fn23 = block
- branch %fn24
+ %fn23 = block {
+ } -> %fn24 # branch
# loop continuing
- %fn24 = block
- branch %fn26
+ %fn24 = block {
+ } -> %fn26 # branch
%fn26 = if true [t: %fn27, f: %fn28, m: %fn29]
# true branch
- %fn27 = block
- branch %fn25
+ %fn27 = block {
+ } -> %fn25 # branch
# false branch
- %fn28 = block
- branch %fn29
+ %fn28 = block {
+ } -> %fn29 # branch
# if merge
- %fn29 = block
- branch %fn23
+ %fn29 = block {
+ } -> %fn23 # branch
# loop merge
- %fn25 = block
- branch %fn8
+ %fn25 = block {
+ } -> %fn8 # branch
# loop merge
- %fn10 = block
- branch %fn30
+ %fn10 = block {
+ } -> %fn30 # branch
%fn30 = if true [t: %fn31, f: %fn32, m: %fn33]
# true branch
- %fn31 = block
- branch %fn6
+ %fn31 = block {
+ } -> %fn6 # branch
# false branch
- %fn32 = block
- branch %fn33
+ %fn32 = block {
+ } -> %fn33 # branch
# if merge
- %fn33 = block
- branch %fn5
+ %fn33 = block {
+ } -> %fn5 # branch
# loop continuing
- %fn5 = block
- branch %fn4
+ %fn5 = block {
+ } -> %fn4 # branch
# loop merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -982,15 +960,10 @@
auto* ast_while = While(false, Block());
WrapInFunction(ast_while);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_while = FlowNodeForAstNode(ast_while);
- ASSERT_NE(ir_while, nullptr);
- ASSERT_TRUE(ir_while->Is<ir::Loop>());
-
- auto* flow = ir_while->As<ir::Loop>();
+ auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(flow->start.target, nullptr);
ASSERT_NE(flow->continuing.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
@@ -1002,8 +975,8 @@
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
EXPECT_EQ(1u, flow->inbound_branches.Length());
@@ -1014,37 +987,37 @@
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, c: %fn5, m: %fn6]
# loop start
- %fn4 = block
- branch %fn7
+ %fn4 = block {
+ } -> %fn7 # branch
%fn7 = if false [t: %fn8, f: %fn9, m: %fn10]
# true branch
- %fn8 = block
- branch %fn10
+ %fn8 = block {
+ } -> %fn10 # branch
# false branch
- %fn9 = block
- branch %fn6
+ %fn9 = block {
+ } -> %fn6 # branch
# if merge
- %fn10 = block
- branch %fn5
+ %fn10 = block {
+ } -> %fn5 # branch
# loop continuing
- %fn5 = block
- branch %fn4
+ %fn5 = block {
+ } -> %fn4 # branch
# loop merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1053,15 +1026,10 @@
auto* ast_while = While(true, Block(Return()));
WrapInFunction(ast_while);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_while = FlowNodeForAstNode(ast_while);
- ASSERT_NE(ir_while, nullptr);
- ASSERT_TRUE(ir_while->Is<ir::Loop>());
-
- auto* flow = ir_while->As<ir::Loop>();
+ auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(flow->start.target, nullptr);
ASSERT_NE(flow->continuing.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
@@ -1073,8 +1041,8 @@
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
EXPECT_EQ(1u, flow->inbound_branches.Length());
@@ -1085,32 +1053,32 @@
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, m: %fn5]
# loop start
- %fn4 = block
- branch %fn6
+ %fn4 = block {
+ } -> %fn6 # branch
%fn6 = if true [t: %fn7, f: %fn8, m: %fn9]
# true branch
- %fn7 = block
- branch %fn9
+ %fn7 = block {
+ } -> %fn9 # branch
# false branch
- %fn8 = block
- branch %fn5
+ %fn8 = block {
+ } -> %fn5 # branch
# if merge
- %fn9 = block
- ret
+ %fn9 = block {
+ } -> %func_end # return
# loop merge
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1132,15 +1100,10 @@
auto* ast_for = For(Decl(Var("i", ty.i32())), LessThan("i", 10_a), Increment("i"), Block());
WrapInFunction(ast_for);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_for = FlowNodeForAstNode(ast_for);
- ASSERT_NE(ir_for, nullptr);
- ASSERT_TRUE(ir_for->Is<ir::Loop>());
-
- auto* flow = ir_for->As<ir::Loop>();
+ auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(flow->start.target, nullptr);
ASSERT_NE(flow->continuing.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
@@ -1152,8 +1115,8 @@
ASSERT_NE(if_flow->false_.target, nullptr);
ASSERT_NE(if_flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
EXPECT_EQ(1u, flow->inbound_branches.Length());
@@ -1164,28 +1127,23 @@
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m), R"()");
+ EXPECT_EQ(Disassemble(m.Get()), R"()");
}
TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
auto* ast_for = For(nullptr, nullptr, nullptr, Block(Break()));
WrapInFunction(ast_for);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_for = FlowNodeForAstNode(ast_for);
- ASSERT_NE(ir_for, nullptr);
- ASSERT_TRUE(ir_for->Is<ir::Loop>());
-
- auto* flow = ir_for->As<ir::Loop>();
+ auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
ASSERT_NE(flow->start.target, nullptr);
ASSERT_NE(flow->continuing.target, nullptr);
ASSERT_NE(flow->merge.target, nullptr);
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
EXPECT_EQ(1u, flow->inbound_branches.Length());
EXPECT_EQ(2u, flow->start.target->inbound_branches.Length());
@@ -1193,20 +1151,20 @@
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = loop [s: %fn4, m: %fn5]
# loop start
- %fn4 = block
- branch %fn5
+ %fn4 = block {
+ } -> %fn5 # branch
# loop merge
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1218,20 +1176,15 @@
WrapInFunction(ast_switch);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_switch = FlowNodeForAstNode(ast_switch);
- ASSERT_NE(ir_switch, nullptr);
- ASSERT_TRUE(ir_switch->Is<ir::Switch>());
-
- auto* flow = ir_switch->As<ir::Switch>();
+ auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
ASSERT_NE(flow->merge.target, nullptr);
ASSERT_EQ(3u, flow->cases.Length());
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
@@ -1253,28 +1206,28 @@
EXPECT_EQ(3u, flow->merge.target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = switch 1i [c: (0i, %fn4), c: (1i, %fn5), c: (default, %fn6), m: %fn7]
# case 0i
- %fn4 = block
- branch %fn7
+ %fn4 = block {
+ } -> %fn7 # branch
# case 1i
- %fn5 = block
- branch %fn7
+ %fn5 = block {
+ } -> %fn7 # branch
# case default
- %fn6 = block
- branch %fn7
+ %fn6 = block {
+ } -> %fn7 # branch
# switch merge
- %fn7 = block
- ret
-func_end
+ %fn7 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1287,20 +1240,15 @@
WrapInFunction(ast_switch);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_switch = FlowNodeForAstNode(ast_switch);
- ASSERT_NE(ir_switch, nullptr);
- ASSERT_TRUE(ir_switch->Is<ir::Switch>());
-
- auto* flow = ir_switch->As<ir::Switch>();
+ auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
ASSERT_NE(flow->merge.target, nullptr);
ASSERT_EQ(1u, flow->cases.Length());
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
ASSERT_EQ(3u, flow->cases[0].selectors.Length());
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
@@ -1318,20 +1266,20 @@
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = switch 1i [c: (0i 1i default, %fn4), m: %fn5]
# case 0i 1i default
- %fn4 = block
- branch %fn5
+ %fn4 = block {
+ } -> %fn5 # branch
# switch merge
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1340,20 +1288,15 @@
auto* ast_switch = Switch(1_i, utils::Vector{DefaultCase(Block())});
WrapInFunction(ast_switch);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_switch = FlowNodeForAstNode(ast_switch);
- ASSERT_NE(ir_switch, nullptr);
- ASSERT_TRUE(ir_switch->Is<ir::Switch>());
-
- auto* flow = ir_switch->As<ir::Switch>();
+ auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
ASSERT_NE(flow->merge.target, nullptr);
ASSERT_EQ(1u, flow->cases.Length());
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
EXPECT_TRUE(flow->cases[0].selectors[0].IsDefault());
@@ -1363,20 +1306,20 @@
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = switch 1i [c: (default, %fn4), m: %fn5]
# case default
- %fn4 = block
- branch %fn5
+ %fn4 = block {
+ } -> %fn5 # branch
# switch merge
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1387,20 +1330,15 @@
DefaultCase(Block())});
WrapInFunction(ast_switch);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- auto* ir_switch = FlowNodeForAstNode(ast_switch);
- ASSERT_NE(ir_switch, nullptr);
- ASSERT_TRUE(ir_switch->Is<ir::Switch>());
-
- auto* flow = ir_switch->As<ir::Switch>();
+ auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
ASSERT_NE(flow->merge.target, nullptr);
ASSERT_EQ(2u, flow->cases.Length());
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
@@ -1417,24 +1355,24 @@
// This is 1 because the if is dead-code eliminated and the return doesn't happen.
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = switch 1i [c: (0i, %fn4), c: (default, %fn5), m: %fn6]
# case 0i
- %fn4 = block
- branch %fn6
+ %fn4 = block {
+ } -> %fn6 # branch
# case default
- %fn5 = block
- branch %fn6
+ %fn5 = block {
+ } -> %fn6 # branch
# switch merge
- %fn6 = block
- ret
-func_end
+ %fn6 = block {
+ } -> %func_end # return
+} %func_end
)");
}
@@ -1446,22 +1384,17 @@
auto* ast_if = If(true, Block(Return()));
WrapInFunction(ast_switch, ast_if);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- ASSERT_EQ(FlowNodeForAstNode(ast_if), nullptr);
+ ASSERT_EQ(FindSingleFlowNode<ir::If>(m.Get()), nullptr);
- auto* ir_switch = FlowNodeForAstNode(ast_switch);
- ASSERT_NE(ir_switch, nullptr);
- ASSERT_TRUE(ir_switch->Is<ir::Switch>());
-
- auto* flow = ir_switch->As<ir::Switch>();
+ auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
ASSERT_NE(flow->merge.target, nullptr);
ASSERT_EQ(2u, flow->cases.Length());
- ASSERT_EQ(1u, m.functions.Length());
- auto* func = m.functions[0];
+ ASSERT_EQ(1u, m->functions.Length());
+ auto* func = m->functions[0];
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
@@ -1477,19 +1410,19 @@
EXPECT_EQ(0u, flow->merge.target->inbound_branches.Length());
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- branch %fn3
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ } -> %fn3 # branch
%fn3 = switch 1i [c: (0i, %fn4), c: (default, %fn5)]
# case 0i
- %fn4 = block
- ret
+ %fn4 = block {
+ } -> %func_end # return
# case default
- %fn5 = block
- ret
-func_end
+ %fn5 = block {
+ } -> %func_end # return
+} %func_end
)");
}
diff --git a/src/tint/ir/from_program_unary_test.cc b/src/tint/ir/from_program_unary_test.cc
new file mode 100644
index 0000000..b2ba2d7
--- /dev/null
+++ b/src/tint/ir/from_program_unary_test.cc
@@ -0,0 +1,148 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/test_helper.h"
+
+#include "gmock/gmock.h"
+#include "src/tint/ast/case_selector.h"
+#include "src/tint/ast/int_literal_expression.h"
+#include "src/tint/constant/scalar.h"
+
+namespace tint::ir {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+
+using IR_BuilderImplTest = TestHelper;
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Not) {
+ Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(false)});
+ auto* expr = Not(Call("my_func"));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool {
+ %fn2 = block {
+ } -> %func_end false # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:bool = call my_func
+ %tint_symbol:bool = eq %1:bool, false
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Complement) {
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(1_u)});
+ auto* expr = Complement(Call("my_func"));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32 {
+ %fn2 = block {
+ } -> %func_end 1u # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:u32 = call my_func
+ %tint_symbol:u32 = complement %1:u32
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Negation) {
+ Func("my_func", utils::Empty, ty.i32(), utils::Vector{Return(1_i)});
+ auto* expr = Negation(Call("my_func"));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():i32 {
+ %fn2 = block {
+ } -> %func_end 1i # return
+} %func_end
+
+%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn4 = block {
+ %1:i32 = call my_func
+ %tint_symbol:i32 = negation %1:i32
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Unary_AddressOf) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
+
+ auto* expr = Decl(Let("v2", AddressOf("v1")));
+ WrapInFunction(expr);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, i32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %v2:ptr<private, i32, read_write> = addr_of %v1:ref<private, i32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Indirection) {
+ GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
+ utils::Vector stmts = {
+ Decl(Let("v3", AddressOf("v1"))),
+ Decl(Let("v2", Deref("v3"))),
+ };
+ WrapInFunction(stmts);
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %v1:ref<private, i32, read_write> = var private, read_write
+}
+
+
+%fn2 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn3 = block {
+ %v3:ptr<private, i32, read_write> = addr_of %v1:ref<private, i32, read_write>
+ %v2:i32 = indirection %v3:ptr<private, i32, read_write>
+ } -> %func_end # return
+} %func_end
+
+)");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl_var_test.cc b/src/tint/ir/from_program_var_test.cc
similarity index 66%
rename from src/tint/ir/builder_impl_var_test.cc
rename to src/tint/ir/from_program_var_test.cc
index a3f4d27..b5379ac 100644
--- a/src/tint/ir/builder_impl_var_test.cc
+++ b/src/tint/ir/from_program_var_test.cc
@@ -29,13 +29,12 @@
TEST_F(IR_BuilderImplTest, Emit_GlobalVar_NoInit) {
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%a:ref<private, u32, read_write> = var private, read_write
-
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %a:ref<private, u32, read_write> = var private, read_write
+}
)");
@@ -45,13 +44,12 @@
auto* expr = Expr(2_u);
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m), R"(%fn1 = block
-%a:ref<private, u32, read_write> = var private, read_write, 2u
-
+ EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block {
+ %a:ref<private, u32, read_write> = var private, read_write, 2u
+}
)");
@@ -61,16 +59,15 @@
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction);
WrapInFunction(a);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- %a:ref<function, u32, read_write> = var function, read_write
- ret
-func_end
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ %a:ref<function, u32, read_write> = var function, read_write
+ } -> %func_end # return
+} %func_end
)");
}
@@ -80,16 +77,15 @@
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction, expr);
WrapInFunction(a);
- auto r = Build();
- ASSERT_TRUE(r) << Error();
- auto m = r.Move();
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m),
- R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
- %fn2 = block
- %a:ref<function, u32, read_write> = var function, read_write, 2u
- ret
-func_end
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)] {
+ %fn2 = block {
+ %a:ref<function, u32, read_write> = var function, read_write, 2u
+ } -> %func_end # return
+} %func_end
)");
}
diff --git a/src/tint/ir/function.cc b/src/tint/ir/function.cc
index a03812e..2a5f8c3 100644
--- a/src/tint/ir/function.cc
+++ b/src/tint/ir/function.cc
@@ -18,7 +18,11 @@
namespace tint::ir {
-Function::Function() : Base() {}
+Function::Function(Symbol n,
+ type::Type* rt,
+ PipelineStage stage,
+ std::optional<std::array<uint32_t, 3>> wg_size)
+ : Base(), name(n), pipeline_stage(stage), workgroup_size(wg_size), return_type(rt) {}
Function::~Function() = default;
diff --git a/src/tint/ir/function.h b/src/tint/ir/function.h
index e3d5529..95487b9 100644
--- a/src/tint/ir/function.h
+++ b/src/tint/ir/function.h
@@ -62,7 +62,14 @@
};
/// Constructor
- Function();
+ /// @param n the function name
+ /// @param rt the function return type
+ /// @param stage the function stage
+ /// @param wg_size the workgroup_size
+ Function(Symbol n,
+ type::Type* rt,
+ PipelineStage stage = PipelineStage::kUndefined,
+ std::optional<std::array<uint32_t, 3>> wg_size = {});
~Function() override;
/// The function name
diff --git a/src/tint/ir/if.cc b/src/tint/ir/if.cc
index 22a9078..b59d87f 100644
--- a/src/tint/ir/if.cc
+++ b/src/tint/ir/if.cc
@@ -18,7 +18,7 @@
namespace tint::ir {
-If::If() : Base() {}
+If::If(Value* cond) : Base(), condition(cond) {}
If::~If() = default;
diff --git a/src/tint/ir/if.h b/src/tint/ir/if.h
index 255b165..aadc5c9 100644
--- a/src/tint/ir/if.h
+++ b/src/tint/ir/if.h
@@ -30,7 +30,8 @@
class If : public utils::Castable<If, FlowNode> {
public:
/// Constructor
- If();
+ /// @param cond the if condition
+ explicit If(Value* cond);
~If() override;
/// The true branch block
diff --git a/src/tint/ir/module.h b/src/tint/ir/module.h
index 0f89d86..a7929d2 100644
--- a/src/tint/ir/module.h
+++ b/src/tint/ir/module.h
@@ -75,8 +75,6 @@
/// List of functions in the program
utils::Vector<Function*, 8> functions;
- /// List of indexes into the functions list for the entry points
- utils::Vector<Function*, 8> entry_points;
/// The block containing module level declarations, if any exist.
Block* root_block = nullptr;
diff --git a/src/tint/ir/module_test.cc b/src/tint/ir/module_test.cc
index 15d5cb1..c9b1150 100644
--- a/src/tint/ir/module_test.cc
+++ b/src/tint/ir/module_test.cc
@@ -14,6 +14,7 @@
#include "src/tint/ir/module.h"
#include "src/tint/ir/test_helper.h"
+#include "src/tint/ir/var.h"
namespace tint::ir {
namespace {
diff --git a/src/tint/ir/store_test.cc b/src/tint/ir/store_test.cc
index 0005c80..902ca95 100644
--- a/src/tint/ir/store_test.cc
+++ b/src/tint/ir/store_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ir/builder.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
@@ -23,12 +24,13 @@
using IR_InstructionTest = TestHelper;
TEST_F(IR_InstructionTest, CreateStore) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
// TODO(dsinclair): This is wrong, but we don't have anything correct to store too at the
// moment.
- auto* to = b.builder.Discard();
- const auto* inst = b.builder.Store(to, b.builder.Constant(4_i));
+ auto* to = b.Discard();
+ const auto* inst = b.Store(to, b.Constant(4_i));
ASSERT_TRUE(inst->Is<Store>());
ASSERT_EQ(inst->to, to);
@@ -40,10 +42,11 @@
}
TEST_F(IR_InstructionTest, Store_Usage) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
- auto* to = b.builder.Discard();
- const auto* inst = b.builder.Store(to, b.builder.Constant(4_i));
+ auto* to = b.Discard();
+ const auto* inst = b.Store(to, b.Constant(4_i));
ASSERT_NE(inst->to, nullptr);
ASSERT_EQ(inst->to->Usage().Length(), 1u);
diff --git a/src/tint/ir/switch.cc b/src/tint/ir/switch.cc
index 9ad6d30..ad6a145 100644
--- a/src/tint/ir/switch.cc
+++ b/src/tint/ir/switch.cc
@@ -18,7 +18,7 @@
namespace tint::ir {
-Switch::Switch() : Base() {}
+Switch::Switch(Value* cond) : Base(), condition(cond) {}
Switch::~Switch() = default;
diff --git a/src/tint/ir/switch.h b/src/tint/ir/switch.h
index 2ff927e..6be7b62 100644
--- a/src/tint/ir/switch.h
+++ b/src/tint/ir/switch.h
@@ -44,7 +44,8 @@
};
/// Constructor
- Switch();
+ /// @param cond the condition
+ explicit Switch(Value* cond);
~Switch() override;
/// The switch merge target
diff --git a/src/tint/ir/test_helper.h b/src/tint/ir/test_helper.h
index d8568c2..d9055ce 100644
--- a/src/tint/ir/test_helper.h
+++ b/src/tint/ir/test_helper.h
@@ -20,8 +20,8 @@
#include <utility>
#include "gtest/gtest.h"
-#include "src/tint/ir/builder_impl.h"
#include "src/tint/ir/disassembler.h"
+#include "src/tint/ir/from_program.h"
#include "src/tint/number.h"
#include "src/tint/program_builder.h"
#include "src/tint/utils/string_stream.h"
@@ -36,84 +36,28 @@
~TestHelperBase() override = default;
- /// Builds and returns a BuilderImpl from the program.
- /// @note The builder is only created once. Multiple calls to Build() will
- /// return the same builder without rebuilding.
- /// @return the builder
- BuilderImpl& CreateBuilder() {
- SetResolveOnBuild(true);
-
- if (gen_) {
- return *gen_;
- }
- diag::Formatter formatter;
-
- program_ = std::make_unique<Program>(std::move(*this));
- [&]() { ASSERT_TRUE(program_->IsValid()) << formatter.format(program_->Diagnostics()); }();
- gen_ = std::make_unique<BuilderImpl>(program_.get());
- return *gen_;
- }
-
- /// Injects a flow block into the builder
- /// @returns the injected block
- ir::Block* InjectFlowBlock() {
- auto* block = gen_->builder.CreateBlock();
- gen_->current_flow_block = block;
- return block;
- }
-
- /// Creates a BuilderImpl without an originating program. This is used for testing the
- /// expressions which don't require the full builder implementation. The current flow block
- /// is initialized with an empty block.
- /// @returns the BuilderImpl for testing.
- BuilderImpl& CreateEmptyBuilder() {
- program_ = std::make_unique<Program>();
- gen_ = std::make_unique<BuilderImpl>(program_.get());
- gen_->current_flow_block = gen_->builder.CreateBlock();
- return *gen_;
- }
-
/// Build the module, cleaning up the program before returning.
/// @returns the generated module
- utils::Result<Module> Build() {
- auto& b = CreateBuilder();
- auto m = b.Build();
+ utils::Result<Module, std::string> Build() {
+ SetResolveOnBuild(true);
- // Store the error away in case we need it
- error_ = b.Diagnostics().str();
+ auto program = std::make_unique<Program>(std::move(*this));
+ [&]() {
+ diag::Formatter formatter;
+ ASSERT_TRUE(program->IsValid()) << formatter.format(program->Diagnostics());
+ }();
- // Explicitly remove program to guard against pointers back to ast. Note, this does mean the
- // BuilderImpl is pointing to an invalid program. We keep the BuilderImpl around because we
- // need to be able to map from ast pointers to flow nodes in tests.
- program_ = nullptr;
- return m;
- }
-
- /// @param node the ast node to lookup
- /// @returns the IR flow node for the given ast node.
- const ir::FlowNode* FlowNodeForAstNode(const ast::Node* node) const {
- return gen_->FlowNodeForAstNode(node);
+ return FromProgram(program.get());
}
/// @param mod the module
/// @returns the disassembly string of the module
- std::string Disassemble(Module& mod) const {
+ std::string Disassemble(const Module& mod) const {
Disassembler d(mod);
return d.Disassemble();
}
-
- /// @returns the error generated during build, if any
- std::string Error() const { return error_; }
-
- private:
- std::unique_ptr<BuilderImpl> gen_;
-
- /// The program built with a call to Build()
- std::unique_ptr<Program> program_;
-
- /// Error generated when calling `Build`
- std::string error_;
};
+
using TestHelper = TestHelperBase<testing::Test>;
template <typename T>
diff --git a/src/tint/ir/to_program.cc b/src/tint/ir/to_program.cc
new file mode 100644
index 0000000..8a2dca9
--- /dev/null
+++ b/src/tint/ir/to_program.cc
@@ -0,0 +1,300 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/to_program.h"
+
+#include <utility>
+
+#include "src/tint/ir/block.h"
+#include "src/tint/ir/call.h"
+#include "src/tint/ir/constant.h"
+#include "src/tint/ir/if.h"
+#include "src/tint/ir/instruction.h"
+#include "src/tint/ir/module.h"
+#include "src/tint/ir/store.h"
+#include "src/tint/ir/user_call.h"
+#include "src/tint/ir/var.h"
+#include "src/tint/program_builder.h"
+#include "src/tint/switch.h"
+#include "src/tint/type/atomic.h"
+#include "src/tint/type/depth_multisampled_texture.h"
+#include "src/tint/type/depth_texture.h"
+#include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/pointer.h"
+#include "src/tint/type/reference.h"
+#include "src/tint/type/sampler.h"
+#include "src/tint/type/texture.h"
+#include "src/tint/utils/hashmap.h"
+#include "src/tint/utils/predicates.h"
+#include "src/tint/utils/transform.h"
+#include "src/tint/utils/vector.h"
+
+namespace tint::ir {
+
+namespace {
+
+class State {
+ public:
+ explicit State(const Module& m) : mod(m) {}
+
+ Program Run() {
+ // TODO(crbug.com/tint/1902): Emit root block
+ // TODO(crbug.com/tint/1902): Emit user-declared types
+ for (auto* fn : mod.functions) {
+ Fn(fn);
+ }
+ return Program{std::move(b)};
+ }
+
+ private:
+ const Module& mod;
+ ProgramBuilder b;
+ utils::Hashmap<const Value*, Symbol, 32> value_names_;
+
+ void Fn(const Function* fn) {
+ auto name = Sym(fn->name);
+ // TODO(crbug.com/tint/1915): Properly implement this when we've fleshed out Function
+ utils::Vector<const ast::Parameter*, 1> params{};
+ ast::Type ret_ty;
+ auto* body = Block(fn->start_target);
+ utils::Vector<const ast::Attribute*, 1> attrs{};
+ utils::Vector<const ast::Attribute*, 1> ret_attrs{};
+ b.Func(name, std::move(params), ret_ty, body, std::move(attrs), std::move(ret_attrs));
+ }
+
+ const ast::BlockStatement* Block(const ir::Block* block) {
+ // TODO(crbug.com/tint/1902): Check if the block is dead
+ utils::Vector<const ast::Statement*, decltype(ir::Block::instructions)::static_length>
+ stmts;
+ for (auto* inst : block->instructions) {
+ auto* stmt = Stmt(inst);
+ if (!stmt) {
+ return nullptr;
+ }
+ stmts.Push(stmt);
+ }
+ return b.Block(std::move(stmts));
+ }
+
+ const ast::Statement* FlowNode(const ir::FlowNode* node) {
+ // TODO(crbug.com/tint/1902): Check the node is connected
+ return Switch(
+ node, //
+ [&](const ir::If* i) {
+ auto* cond = Expr(i->condition);
+ auto* t = Branch(i->true_);
+ if (auto* f = Branch(i->false_)) {
+ return b.If(cond, t, b.Else(f));
+ }
+ // TODO(crbug.com/tint/1902): Emit merge block
+ return b.If(cond, t);
+ },
+ [&](Default) {
+ TINT_UNIMPLEMENTED(IR, b.Diagnostics())
+ << "unhandled case in Switch(): " << node->TypeInfo().name;
+ return nullptr;
+ });
+ }
+
+ const ast::BlockStatement* Branch(const ir::Branch& branch) {
+ auto* stmt = FlowNode(branch.target);
+ if (!stmt) {
+ return nullptr;
+ }
+ if (auto* block = stmt->As<ast::BlockStatement>()) {
+ return block;
+ }
+ return b.Block(stmt);
+ }
+
+ const ast::Statement* Stmt(const ir::Instruction* inst) {
+ return Switch(
+ inst, //
+ [&](const ir::Call* i) { return CallStmt(i); }, //
+ [&](const ir::Var* i) { return Var(i); }, //
+ [&](const ir::Store* i) { return Store(i); },
+ [&](Default) {
+ TINT_UNIMPLEMENTED(IR, b.Diagnostics())
+ << "unhandled case in Switch(): " << inst->TypeInfo().name;
+ return nullptr;
+ });
+ }
+
+ const ast::CallStatement* CallStmt(const ir::Call* call) {
+ auto* expr = Call(call);
+ if (!expr) {
+ return nullptr;
+ }
+ return b.CallStmt(expr);
+ }
+
+ const ast::VariableDeclStatement* Var(const ir::Var* var) {
+ Symbol name = NameOf(var);
+ auto ty = Type(var->Type());
+ const ast::Expression* init = nullptr;
+ if (var->initializer) {
+ init = Expr(var->initializer);
+ if (!init) {
+ return nullptr;
+ }
+ }
+ switch (var->address_space) {
+ case builtin::AddressSpace::kFunction:
+ return b.Decl(b.Var(name, ty, init));
+ case builtin::AddressSpace::kStorage:
+ return b.Decl(b.Var(name, ty, init, var->access, var->address_space));
+ default:
+ return b.Decl(b.Var(name, ty, init, var->address_space));
+ }
+ }
+
+ const ast::AssignmentStatement* Store(const ir::Store* store) {
+ auto* expr = Expr(store->from);
+ return b.Assign(NameOf(store->to), expr);
+ }
+
+ const ast::CallExpression* Call(const ir::Call* call) {
+ auto args = utils::Transform(call->args, [&](const ir::Value* arg) { return Expr(arg); });
+ if (args.Any(utils::IsNull)) {
+ return nullptr;
+ }
+ return Switch(
+ call, //
+ [&](const ir::UserCall* c) { return b.Call(Sym(c->name), std::move(args)); },
+ [&](Default) {
+ TINT_UNIMPLEMENTED(IR, b.Diagnostics())
+ << "unhandled case in Switch(): " << call->TypeInfo().name;
+ return nullptr;
+ });
+ }
+
+ const ast::Expression* Expr(const ir::Value* val) {
+ return Switch(
+ val, //
+ [&](const ir::Constant* c) { return ConstExpr(c); },
+ [&](Default) {
+ TINT_UNIMPLEMENTED(IR, b.Diagnostics())
+ << "unhandled case in Switch(): " << val->TypeInfo().name;
+ return nullptr;
+ });
+ }
+
+ const ast::Expression* ConstExpr(const ir::Constant* c) {
+ return Switch(
+ c->Type(), //
+ [&](const type::I32*) { return b.Expr(c->value->ValueAs<i32>()); },
+ [&](const type::U32*) { return b.Expr(c->value->ValueAs<u32>()); },
+ [&](const type::F32*) { return b.Expr(c->value->ValueAs<f32>()); },
+ [&](const type::F16*) { return b.Expr(c->value->ValueAs<f16>()); },
+ [&](const type::Bool*) { return b.Expr(c->value->ValueAs<bool>()); },
+ [&](Default) {
+ TINT_UNIMPLEMENTED(IR, b.Diagnostics())
+ << "unhandled case in Switch(): " << c->TypeInfo().name;
+ return nullptr;
+ });
+ }
+
+ const ast::Type Type(const type::Type* ty) {
+ return Switch(
+ ty, //
+ [&](const type::Void*) { return ast::Type{}; }, //
+ [&](const type::I32*) { return b.ty.i32(); }, //
+ [&](const type::U32*) { return b.ty.u32(); }, //
+ [&](const type::F16*) { return b.ty.f16(); }, //
+ [&](const type::F32*) { return b.ty.f32(); }, //
+ [&](const type::Bool*) { return b.ty.bool_(); },
+ [&](const type::Matrix* m) {
+ auto el = Type(m->type());
+ return b.ty.mat(el, m->columns(), m->rows());
+ },
+ [&](const type::Vector* v) {
+ auto el = Type(v->type());
+ if (v->Packed()) {
+ TINT_ASSERT(IR, v->Width() == 3u);
+ return b.ty(builtin::Builtin::kPackedVec3, el);
+ } else {
+ return b.ty.vec(el, v->Width());
+ }
+ },
+ [&](const type::Array* a) {
+ auto el = Type(a->ElemType());
+ utils::Vector<const ast::Attribute*, 1> attrs;
+ if (!a->IsStrideImplicit()) {
+ attrs.Push(b.Stride(a->Stride()));
+ }
+ if (a->Count()->Is<type::RuntimeArrayCount>()) {
+ return b.ty.array(el, std::move(attrs));
+ }
+ auto count = a->ConstantCount();
+ if (TINT_UNLIKELY(!count)) {
+ TINT_ICE(IR, b.Diagnostics()) << type::Array::kErrExpectedConstantCount;
+ return b.ty.array(el, u32(1), std::move(attrs));
+ }
+ return b.ty.array(el, u32(count.value()), std::move(attrs));
+ },
+ [&](const type::Struct* s) { return b.ty(s->Name().NameView()); },
+ [&](const type::Atomic* a) { return b.ty.atomic(Type(a->Type())); },
+ [&](const type::DepthTexture* t) { return b.ty.depth_texture(t->dim()); },
+ [&](const type::DepthMultisampledTexture* t) {
+ return b.ty.depth_multisampled_texture(t->dim());
+ },
+ [&](const type::ExternalTexture*) { return b.ty.external_texture(); },
+ [&](const type::MultisampledTexture* t) {
+ return b.ty.multisampled_texture(t->dim(), Type(t->type()));
+ },
+ [&](const type::SampledTexture* t) {
+ return b.ty.sampled_texture(t->dim(), Type(t->type()));
+ },
+ [&](const type::StorageTexture* t) {
+ return b.ty.storage_texture(t->dim(), t->texel_format(), t->access());
+ },
+ [&](const type::Sampler* s) { return b.ty.sampler(s->kind()); },
+ [&](const type::Pointer* p) {
+ // Note: type::Pointer always has an inferred access, but WGSL only allows an
+ // explicit access in the 'storage' address space.
+ auto address_space = p->AddressSpace();
+ auto access = address_space == builtin::AddressSpace::kStorage
+ ? p->Access()
+ : builtin::Access::kUndefined;
+ return b.ty.pointer(Type(p->StoreType()), address_space, access);
+ },
+ [&](const type::Reference* r) { return Type(r->StoreType()); },
+ [&](Default) {
+ TINT_UNREACHABLE(IR, b.Diagnostics()) << "unhandled type: " << ty->TypeInfo().name;
+ return ast::Type{};
+ });
+ }
+
+ Symbol NameOf(const Value* value) {
+ TINT_ASSERT(IR, value);
+ return value_names_.GetOrCreate(value, [&] {
+ if (auto sym = mod.NameOf(value)) {
+ return b.Symbols().New(sym.Name());
+ }
+ return b.Symbols().New("v" + std::to_string(value_names_.Count()));
+ });
+ }
+
+ Symbol Sym(const Symbol& s) { return b.Symbols().Register(s.NameView()); }
+
+ // void Err(std::string str) { b.Diagnostics().add_error(diag::System::IR, std::move(str)); }
+};
+
+} // namespace
+
+Program ToProgram(const Module& i) {
+ return State{i}.Run();
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/to_program.h b/src/tint/ir/to_program.h
new file mode 100644
index 0000000..d4cf2c6
--- /dev/null
+++ b/src/tint/ir/to_program.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_IR_TO_PROGRAM_H_
+#define SRC_TINT_IR_TO_PROGRAM_H_
+
+#include "src/tint/program.h"
+
+namespace tint::ir {
+class Module;
+}
+
+namespace tint::ir {
+
+/// Builds a tint::Program from an ir::Module
+/// @param module the IR module
+/// @return the tint::Program.
+/// @note Check the returned Program::Diagnostics() for any errors.
+Program ToProgram(const Module& module);
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_TO_PROGRAM_H_
diff --git a/src/tint/ir/to_program_roundtrip_test.cc b/src/tint/ir/to_program_roundtrip_test.cc
new file mode 100644
index 0000000..11aff46
--- /dev/null
+++ b/src/tint/ir/to_program_roundtrip_test.cc
@@ -0,0 +1,79 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/from_program.h"
+#include "src/tint/ir/test_helper.h"
+#include "src/tint/ir/to_program.h"
+#include "src/tint/reader/wgsl/parser.h"
+#include "src/tint/utils/string.h"
+#include "src/tint/writer/wgsl/generator.h"
+
+#if !TINT_BUILD_WGSL_READER || !TINT_BUILD_WGSL_WRITER
+#error "to_program_roundtrip_test.cc requires both the WGSL reader and writer to be enabled"
+#endif
+
+namespace tint::ir {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+
+class IRToProgramRoundtripTest : public TestHelper {
+ public:
+ void Test(std::string_view input_wgsl, std::string_view expected_wgsl) {
+ auto input = utils::TrimSpace(input_wgsl);
+ Source::File file("test.wgsl", std::string(input));
+ auto input_program = reader::wgsl::Parse(&file);
+ ASSERT_TRUE(input_program.IsValid()) << input_program.Diagnostics().str();
+
+ auto ir_module = FromProgram(&input_program);
+ ASSERT_TRUE(ir_module);
+
+ auto output_program = ToProgram(ir_module.Get());
+ ASSERT_TRUE(output_program.IsValid()) << output_program.Diagnostics().str();
+
+ auto output = writer::wgsl::Generate(&output_program, {});
+ ASSERT_TRUE(output.success) << output.error;
+
+ auto expected = expected_wgsl.empty() ? input : utils::TrimSpace(expected_wgsl);
+ auto got = utils::TrimSpace(output.wgsl);
+ if (expected != got) {
+ tint::ir::Disassembler d{ir_module.Get()};
+ EXPECT_EQ(expected, got) << "IR:" << std::endl << d.Disassemble();
+ }
+ }
+
+ void Test(std::string_view wgsl) { Test(wgsl, wgsl); }
+};
+
+TEST_F(IRToProgramRoundtripTest, EmptyModule) {
+ Test("");
+}
+
+TEST_F(IRToProgramRoundtripTest, EmptySingleFunction) {
+ Test(R"(
+fn f() {
+}
+)");
+}
+
+TEST_F(IRToProgramRoundtripTest, FunctionScopeVar_i32_InitLiteral) {
+ Test(R"(
+fn f() {
+ var i : i32 = 42i;
+}
+)");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/unary_test.cc b/src/tint/ir/unary_test.cc
index 86a3993..392a75e 100644
--- a/src/tint/ir/unary_test.cc
+++ b/src/tint/ir/unary_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ir/builder.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
@@ -23,14 +24,14 @@
using IR_InstructionTest = TestHelper;
TEST_F(IR_InstructionTest, CreateAddressOf) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
// TODO(dsinclair): This would be better as an identifier, but works for now.
- const auto* inst =
- b.builder.AddressOf(b.builder.ir.types.Get<type::Pointer>(
- b.builder.ir.types.Get<type::I32>(),
- builtin::AddressSpace::kPrivate, builtin::Access::kReadWrite),
- b.builder.Constant(4_i));
+ const auto* inst = b.AddressOf(
+ b.ir.types.Get<type::Pointer>(b.ir.types.Get<type::I32>(), builtin::AddressSpace::kPrivate,
+ builtin::Access::kReadWrite),
+ b.Constant(4_i));
ASSERT_TRUE(inst->Is<Unary>());
EXPECT_EQ(inst->kind, Unary::Kind::kAddressOf);
@@ -44,9 +45,9 @@
}
TEST_F(IR_InstructionTest, CreateComplement) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Complement(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.Complement(b.ir.types.Get<type::I32>(), b.Constant(4_i));
ASSERT_TRUE(inst->Is<Unary>());
EXPECT_EQ(inst->kind, Unary::Kind::kComplement);
@@ -58,11 +59,11 @@
}
TEST_F(IR_InstructionTest, CreateIndirection) {
- auto& b = CreateEmptyBuilder();
+ Module mod;
+ Builder b{mod};
// TODO(dsinclair): This would be better as an identifier, but works for now.
- const auto* inst =
- b.builder.Indirection(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
+ const auto* inst = b.Indirection(b.ir.types.Get<type::I32>(), b.Constant(4_i));
ASSERT_TRUE(inst->Is<Unary>());
EXPECT_EQ(inst->kind, Unary::Kind::kIndirection);
@@ -74,9 +75,9 @@
}
TEST_F(IR_InstructionTest, CreateNegation) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Negation(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.Negation(b.ir.types.Get<type::I32>(), b.Constant(4_i));
ASSERT_TRUE(inst->Is<Unary>());
EXPECT_EQ(inst->kind, Unary::Kind::kNegation);
@@ -88,9 +89,9 @@
}
TEST_F(IR_InstructionTest, Unary_Usage) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Negation(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
+ Module mod;
+ Builder b{mod};
+ const auto* inst = b.Negation(b.ir.types.Get<type::I32>(), b.Constant(4_i));
EXPECT_EQ(inst->kind, Unary::Kind::kNegation);
diff --git a/src/tint/reader/spirv/parser.cc b/src/tint/reader/spirv/parser.cc
index bc0f258..1699d2c 100644
--- a/src/tint/reader/spirv/parser.cc
+++ b/src/tint/reader/spirv/parser.cc
@@ -57,13 +57,14 @@
}
transform::Manager manager;
+ transform::DataMap outputs;
manager.Add<ast::transform::Unshadow>();
manager.Add<ast::transform::SimplifyPointers>();
manager.Add<ast::transform::DecomposeStridedMatrix>();
manager.Add<ast::transform::DecomposeStridedArray>();
manager.Add<ast::transform::RemoveUnreachableStatements>();
manager.Add<ast::transform::SpirvAtomic>();
- return manager.Run(&program).program;
+ return manager.Run(&program, {}, outputs);
}
} // namespace tint::reader::spirv
diff --git a/src/tint/transform/manager.cc b/src/tint/transform/manager.cc
index b2e6c80..eff3a0c 100644
--- a/src/tint/transform/manager.cc
+++ b/src/tint/transform/manager.cc
@@ -14,6 +14,9 @@
#include "src/tint/transform/manager.h"
+#include "src/tint/ast/transform/transform.h"
+#include "src/tint/program_builder.h"
+
/// If set to 1 then the transform::Manager will dump the WGSL of the program
/// before and after each transform. Helpful for debugging bad output.
#define TINT_PRINT_PROGRAM_FOR_EACH_TRANSFORM 0
@@ -25,16 +28,14 @@
#define TINT_IF_PRINT_PROGRAM(x)
#endif // TINT_PRINT_PROGRAM_FOR_EACH_TRANSFORM
-TINT_INSTANTIATE_TYPEINFO(tint::transform::Manager);
-
namespace tint::transform {
Manager::Manager() = default;
Manager::~Manager() = default;
-ast::transform::Transform::ApplyResult Manager::Apply(const Program* program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const {
+Program Manager::Run(const Program* program,
+ const transform::DataMap& inputs,
+ transform::DataMap& outputs) const {
#if TINT_PRINT_PROGRAM_FOR_EACH_TRANSFORM
auto print_program = [&](const char* msg, const Transform* transform) {
auto wgsl = Program::printer(program);
@@ -56,25 +57,38 @@
TINT_IF_PRINT_PROGRAM(print_program("Input of", this));
for (const auto& transform : transforms_) {
- if (auto result = transform->Apply(program, inputs, outputs)) {
- output.emplace(std::move(result.value()));
- program = &output.value();
+ if (auto* ast_transform = transform->As<ast::transform::Transform>()) {
+ if (auto result = ast_transform->Apply(program, inputs, outputs)) {
+ output.emplace(std::move(result.value()));
+ program = &output.value();
- if (!program->IsValid()) {
- TINT_IF_PRINT_PROGRAM(print_program("Invalid output of", transform.get()));
- break;
+ if (!program->IsValid()) {
+ TINT_IF_PRINT_PROGRAM(print_program("Invalid output of", transform.get()));
+ break;
+ }
+
+ TINT_IF_PRINT_PROGRAM(print_program("Output of", transform.get()));
+ } else {
+ TINT_IF_PRINT_PROGRAM(std::cout << "Skipped " << transform->TypeInfo().name
+ << std::endl);
}
-
- TINT_IF_PRINT_PROGRAM(print_program("Output of", transform.get()));
} else {
- TINT_IF_PRINT_PROGRAM(std::cout << "Skipped " << transform->TypeInfo().name
- << std::endl);
+ ProgramBuilder b;
+ TINT_ICE(Transform, b.Diagnostics()) << "unhandled transform type";
+ return Program(std::move(b));
}
}
TINT_IF_PRINT_PROGRAM(print_program("Final output of", this));
- return output;
+ if (!output) {
+ ProgramBuilder b;
+ CloneContext ctx{&b, program, /* auto_clone_symbols */ true};
+ ctx.Clone();
+ output = Program(std::move(b));
+ }
+
+ return std::move(output.value());
}
} // namespace tint::transform
diff --git a/src/tint/transform/manager.h b/src/tint/transform/manager.h
index c7b9286..2df5785 100644
--- a/src/tint/transform/manager.h
+++ b/src/tint/transform/manager.h
@@ -19,7 +19,7 @@
#include <utility>
#include <vector>
-#include "src/tint/ast/transform/transform.h"
+#include "src/tint/transform/transform.h"
namespace tint::transform {
@@ -27,11 +27,11 @@
/// The inner transforms will execute in the appended order.
/// If any inner transform fails the manager will return immediately and
/// the error can be retrieved with the Output's diagnostics.
-class Manager final : public tint::utils::Castable<Manager, ast::transform::Transform> {
+class Manager {
public:
/// Constructor
Manager();
- ~Manager() override;
+ ~Manager();
/// Add pass to the manager
/// @param transform the transform to append
@@ -47,10 +47,12 @@
transforms_.emplace_back(std::make_unique<T>(std::forward<ARGS>(args)...));
}
- /// @copydoc ast::transform::Transform::Apply
- ApplyResult Apply(const Program* program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
+ /// Runs the transforms on @p program, returning the transformed clone of @p program.
+ /// @param program the source program to transform
+ /// @param inputs optional extra transform-specific input data
+ /// @param outputs optional extra transform-specific output data
+ /// @returns the transformed program
+ Program Run(const Program* program, const DataMap& inputs, DataMap& outputs) const;
private:
std::vector<std::unique_ptr<Transform>> transforms_;
diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc
new file mode 100644
index 0000000..657f9be
--- /dev/null
+++ b/src/tint/transform/transform.cc
@@ -0,0 +1,37 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/transform.h"
+
+#include "src/tint/program_builder.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::transform::Transform);
+TINT_INSTANTIATE_TYPEINFO(tint::transform::Data);
+
+namespace tint::transform {
+
+Data::Data() = default;
+Data::Data(const Data&) = default;
+Data::~Data() = default;
+Data& Data::operator=(const Data&) = default;
+
+DataMap::DataMap() = default;
+DataMap::DataMap(DataMap&&) = default;
+DataMap::~DataMap() = default;
+DataMap& DataMap::operator=(DataMap&&) = default;
+
+Transform::Transform() = default;
+Transform::~Transform() = default;
+
+} // namespace tint::transform
diff --git a/src/tint/transform/transform.h b/src/tint/transform/transform.h
new file mode 100644
index 0000000..1f8a3f5
--- /dev/null
+++ b/src/tint/transform/transform.h
@@ -0,0 +1,141 @@
+// 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_TRANSFORM_TRANSFORM_H_
+#define SRC_TINT_TRANSFORM_TRANSFORM_H_
+
+#include <memory>
+#include <unordered_map>
+#include <utility>
+
+#include "src/tint/program.h"
+#include "src/tint/utils/castable.h"
+
+namespace tint::transform {
+
+/// Data is the base class for transforms that accept extra input or emit extra output information.
+class Data : public utils::Castable<Data> {
+ public:
+ /// Constructor
+ Data();
+
+ /// Copy constructor
+ Data(const Data&);
+
+ /// Destructor
+ ~Data() override;
+
+ /// Assignment operator
+ /// @returns this Data
+ Data& operator=(const Data&);
+};
+
+/// DataMap is a map of Data unique pointers keyed by the Data's ClassID.
+class DataMap {
+ public:
+ /// Constructor
+ DataMap();
+
+ /// Move constructor
+ DataMap(DataMap&&);
+
+ /// Constructor
+ /// @param data_unique_ptrs a variadic list of additional data unique_ptrs produced by the
+ /// transform
+ template <typename... DATA>
+ explicit DataMap(DATA... data_unique_ptrs) {
+ PutAll(std::forward<DATA>(data_unique_ptrs)...);
+ }
+
+ /// Destructor
+ ~DataMap();
+
+ /// Move assignment operator
+ /// @param rhs the DataMap to move into this DataMap
+ /// @return this DataMap
+ DataMap& operator=(DataMap&& rhs);
+
+ /// Adds the data into DataMap keyed by the ClassID of type T.
+ /// @param data the data to add to the DataMap
+ template <typename T>
+ void Put(std::unique_ptr<T>&& data) {
+ static_assert(std::is_base_of<Data, T>::value, "T does not derive from Data");
+ map_[&utils::TypeInfo::Of<T>()] = std::move(data);
+ }
+
+ /// Creates the data of type `T` with the provided arguments and adds it into DataMap keyed by
+ /// the ClassID of type T.
+ /// @param args the arguments forwarded to the initializer for type T
+ template <typename T, typename... ARGS>
+ void Add(ARGS&&... args) {
+ Put(std::make_unique<T>(std::forward<ARGS>(args)...));
+ }
+
+ /// @returns a pointer to the Data placed into the DataMap with a call to Put()
+ template <typename T>
+ T const* Get() const {
+ return const_cast<DataMap*>(this)->Get<T>();
+ }
+
+ /// @returns a pointer to the Data placed into the DataMap with a call to Put()
+ template <typename T>
+ T* Get() {
+ auto it = map_.find(&utils::TypeInfo::Of<T>());
+ if (it == map_.end()) {
+ return nullptr;
+ }
+ return static_cast<T*>(it->second.get());
+ }
+
+ /// Add moves all the data from other into this DataMap
+ /// @param other the DataMap to move into this DataMap
+ void Add(DataMap&& other) {
+ for (auto& it : other.map_) {
+ map_.emplace(it.first, std::move(it.second));
+ }
+ other.map_.clear();
+ }
+
+ private:
+ template <typename T0>
+ void PutAll(T0&& first) {
+ Put(std::forward<T0>(first));
+ }
+
+ template <typename T0, typename... Tn>
+ void PutAll(T0&& first, Tn&&... remainder) {
+ Put(std::forward<T0>(first));
+ PutAll(std::forward<Tn>(remainder)...);
+ }
+
+ std::unordered_map<const utils::TypeInfo*, std::unique_ptr<Data>> map_;
+};
+
+/// Interface for transforms.
+class Transform : public utils::Castable<Transform> {
+ public:
+ /// @copydoc tint::transform::Data
+ using Data = tint::transform::Data;
+ /// @copydoc tint::transform::DataMap
+ using DataMap = tint::transform::DataMap;
+
+ /// Constructor
+ Transform();
+ /// Destructor
+ ~Transform() override;
+};
+
+} // namespace tint::transform
+
+#endif // SRC_TINT_TRANSFORM_TRANSFORM_H_
diff --git a/src/tint/writer/flatten_bindings.cc b/src/tint/writer/flatten_bindings.cc
index 3aa659d..fe262d6 100644
--- a/src/tint/writer/flatten_bindings.cc
+++ b/src/tint/writer/flatten_bindings.cc
@@ -63,16 +63,15 @@
}
// Run the binding remapper transform.
- tint::ast::transform::Output transform_output;
if (!binding_points.empty()) {
tint::transform::Manager manager;
- tint::ast::transform::DataMap inputs;
+ tint::transform::DataMap inputs;
+ tint::transform::DataMap outputs;
inputs.Add<tint::ast::transform::BindingRemapper::Remappings>(
std::move(binding_points), tint::ast::transform::BindingRemapper::AccessControls{},
/* mayCollide */ true);
manager.Add<tint::ast::transform::BindingRemapper>();
- transform_output = manager.Run(program, inputs);
- return std::move(transform_output.program);
+ return manager.Run(program, inputs, outputs);
}
return {};
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index d3d8130..a15f6a9 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -152,7 +152,7 @@
const Options& options,
const std::string& entry_point) {
transform::Manager manager;
- ast::transform::DataMap data;
+ transform::DataMap data;
manager.Add<ast::transform::DisableUniformityAnalysis>();
@@ -246,10 +246,9 @@
data.Add<ast::transform::CanonicalizeEntryPointIO::Config>(
ast::transform::CanonicalizeEntryPointIO::ShaderStyle::kGlsl);
- auto out = manager.Run(in, data);
-
SanitizedResult result;
- result.program = std::move(out.program);
+ transform::DataMap outputs;
+ result.program = manager.Run(in, data, outputs);
return result;
}
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index c9ebddd..95d2022 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -167,7 +167,7 @@
SanitizedResult Sanitize(const Program* in, const Options& options) {
transform::Manager manager;
- ast::transform::DataMap data;
+ transform::DataMap data;
manager.Add<ast::transform::DisableUniformityAnalysis>();
@@ -305,11 +305,10 @@
ast::transform::CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
data.Add<ast::transform::NumWorkgroupsFromUniform::Config>(options.root_constant_binding_point);
- auto out = manager.Run(in, data);
-
SanitizedResult result;
- result.program = std::move(out.program);
- if (auto* res = out.data.Get<ast::transform::ArrayLengthFromUniform::Result>()) {
+ transform::DataMap outputs;
+ result.program = manager.Run(in, data, outputs);
+ if (auto* res = outputs.Get<ast::transform::ArrayLengthFromUniform::Result>()) {
result.used_array_length_from_uniform_indices = std::move(res->used_size_indices);
}
return result;
diff --git a/src/tint/writer/hlsl/test_helper.h b/src/tint/writer/hlsl/test_helper.h
index e645346..2f8e886 100644
--- a/src/tint/writer/hlsl/test_helper.h
+++ b/src/tint/writer/hlsl/test_helper.h
@@ -87,16 +87,15 @@
}();
transform::Manager transform_manager;
- ast::transform::DataMap transform_data;
+ transform::DataMap transform_data;
+ transform::DataMap outputs;
transform_data.Add<ast::transform::Renamer::Config>(
ast::transform::Renamer::Target::kHlslKeywords,
/* preserve_unicode */ true);
transform_manager.Add<tint::ast::transform::Renamer>();
- auto result = transform_manager.Run(&sanitized_result.program, transform_data);
- [&]() {
- ASSERT_TRUE(result.program.IsValid()) << formatter.format(result.program.Diagnostics());
- }();
- *program = std::move(result.program);
+ auto result = transform_manager.Run(&sanitized_result.program, transform_data, outputs);
+ [&]() { ASSERT_TRUE(result.IsValid()) << formatter.format(result.Diagnostics()); }();
+ *program = std::move(result);
gen_ = std::make_unique<GeneratorImpl>(program.get());
return *gen_;
}
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 23c39f3..55b9f8d 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -167,7 +167,7 @@
SanitizedResult Sanitize(const Program* in, const Options& options) {
transform::Manager manager;
- ast::transform::DataMap data;
+ transform::DataMap data;
manager.Add<ast::transform::DisableUniformityAnalysis>();
@@ -257,14 +257,13 @@
manager.Add<ast::transform::PackedVec3>();
manager.Add<ast::transform::ModuleScopeVarToEntryPointParam>();
- auto out = manager.Run(in, data);
-
SanitizedResult result;
- result.program = std::move(out.program);
+ transform::DataMap outputs;
+ result.program = manager.Run(in, data, outputs);
if (!result.program.IsValid()) {
return result;
}
- if (auto* res = out.data.Get<ast::transform::ArrayLengthFromUniform::Result>()) {
+ if (auto* res = outputs.Get<ast::transform::ArrayLengthFromUniform::Result>()) {
result.used_array_length_from_uniform_indices = std::move(res->used_size_indices);
}
result.needs_storage_buffer_sizes = !result.used_array_length_from_uniform_indices.empty();
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index 9df66ef..1b22710 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -49,7 +49,7 @@
SanitizedResult Sanitize(const Program* in, const Options& options) {
transform::Manager manager;
- ast::transform::DataMap data;
+ transform::DataMap data;
if (options.clamp_frag_depth) {
manager.Add<tint::ast::transform::ClampFragDepth>();
@@ -166,7 +166,8 @@
options.emit_vertex_point_size));
SanitizedResult result;
- result.program = std::move(manager.Run(in, data).program);
+ transform::DataMap outputs;
+ result.program = manager.Run(in, data, outputs);
return result;
}
diff --git a/src/tint/writer/spirv/generator_impl_binary_test.cc b/src/tint/writer/spirv/generator_impl_binary_test.cc
index d5cd2bb..4bf6b81 100644
--- a/src/tint/writer/spirv/generator_impl_binary_test.cc
+++ b/src/tint/writer/spirv/generator_impl_binary_test.cc
@@ -20,13 +20,11 @@
namespace {
TEST_F(SpvGeneratorImplTest, Binary_Add_I32) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("foo");
- func->return_type = ir.types.Get<type::Void>();
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
- func->start_target->instructions.Push(CreateBinary(
- ir::Binary::Kind::kAdd, ir.types.Get<type::I32>(), Constant(1_i), Constant(2_i)));
+ func->start_target->instructions.Push(
+ b.Add(mod.types.Get<type::I32>(), b.Constant(1_i), b.Constant(2_i)));
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -44,13 +42,11 @@
}
TEST_F(SpvGeneratorImplTest, Binary_Add_U32) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("foo");
- func->return_type = ir.types.Get<type::Void>();
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
- func->start_target->instructions.Push(CreateBinary(
- ir::Binary::Kind::kAdd, ir.types.Get<type::U32>(), Constant(1_u), Constant(2_u)));
+ func->start_target->instructions.Push(
+ b.Add(mod.types.Get<type::U32>(), b.Constant(1_u), b.Constant(2_u)));
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -68,13 +64,11 @@
}
TEST_F(SpvGeneratorImplTest, Binary_Add_F32) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("foo");
- func->return_type = ir.types.Get<type::Void>();
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
- func->start_target->instructions.Push(CreateBinary(
- ir::Binary::Kind::kAdd, ir.types.Get<type::F32>(), Constant(1_f), Constant(2_f)));
+ func->start_target->instructions.Push(
+ b.Add(mod.types.Get<type::F32>(), b.Constant(1_f), b.Constant(2_f)));
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -91,17 +85,12 @@
)");
}
-TEST_F(SpvGeneratorImplTest, Binary_Add_Chain) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("foo");
- func->return_type = ir.types.Get<type::Void>();
- func->start_target->branch.target = func->end_target;
+TEST_F(SpvGeneratorImplTest, Binary_Sub_I32) {
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
- auto* a = CreateBinary(ir::Binary::Kind::kAdd, ir.types.Get<type::I32>(), Constant(1_i),
- Constant(2_i));
- func->start_target->instructions.Push(a);
func->start_target->instructions.Push(
- CreateBinary(ir::Binary::Kind::kAdd, ir.types.Get<type::I32>(), a, a));
+ b.Subtract(mod.types.Get<type::I32>(), b.Constant(1_i), b.Constant(2_i)));
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -112,7 +101,148 @@
%8 = OpConstant %6 2
%1 = OpFunction %2 None %3
%4 = OpLabel
-%5 = OpIAdd %6 %7 %8
+%5 = OpISub %6 %7 %8
+OpReturn
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Binary_Sub_U32) {
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
+
+ func->start_target->instructions.Push(
+ b.Subtract(mod.types.Get<type::U32>(), b.Constant(1_u), b.Constant(2_u)));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 0
+%7 = OpConstant %6 1
+%8 = OpConstant %6 2
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+%5 = OpISub %6 %7 %8
+OpReturn
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Binary_Sub_F32) {
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
+
+ func->start_target->instructions.Push(
+ b.Subtract(mod.types.Get<type::F32>(), b.Constant(1_f), b.Constant(2_f)));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeFloat 32
+%7 = OpConstant %6 1
+%8 = OpConstant %6 2
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+%5 = OpFSub %6 %7 %8
+OpReturn
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Binary_Sub_Vec2i) {
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
+
+ auto* lhs = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(mod.types.Get<type::I32>(), 2u),
+ utils::Vector{b.Constant(42_i)->value, b.Constant(-1_i)->value}, false, false);
+ auto* rhs = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(mod.types.Get<type::I32>(), 2u),
+ utils::Vector{b.Constant(0_i)->value, b.Constant(-43_i)->value}, false, false);
+ func->start_target->instructions.Push(
+ b.Subtract(mod.types.Get<type::Vector>(mod.types.Get<type::I32>(), 2u), b.Constant(lhs),
+ b.Constant(rhs)));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%7 = OpTypeInt 32 1
+%6 = OpTypeVector %7 2
+%9 = OpConstant %7 42
+%10 = OpConstant %7 -1
+%8 = OpConstantComposite %6 %9 %10
+%12 = OpConstant %7 0
+%13 = OpConstant %7 -43
+%11 = OpConstantComposite %6 %12 %13
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+%5 = OpISub %6 %8 %11
+OpReturn
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Binary_Sub_Vec4f) {
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
+
+ auto* lhs = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(mod.types.Get<type::F32>(), 4u),
+ utils::Vector{b.Constant(42_f)->value, b.Constant(-1_f)->value, b.Constant(0_f)->value,
+ b.Constant(1.25_f)->value},
+ false, false);
+ auto* rhs = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(mod.types.Get<type::F32>(), 4u),
+ utils::Vector{b.Constant(0_f)->value, b.Constant(1.25_f)->value, b.Constant(-42_f)->value,
+ b.Constant(1_f)->value},
+ false, false);
+ func->start_target->instructions.Push(
+ b.Subtract(mod.types.Get<type::Vector>(mod.types.Get<type::F32>(), 4u), b.Constant(lhs),
+ b.Constant(rhs)));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%7 = OpTypeFloat 32
+%6 = OpTypeVector %7 4
+%9 = OpConstant %7 42
+%10 = OpConstant %7 -1
+%11 = OpConstant %7 0
+%12 = OpConstant %7 1.25
+%8 = OpConstantComposite %6 %9 %10 %11 %12
+%14 = OpConstant %7 -42
+%15 = OpConstant %7 1
+%13 = OpConstantComposite %6 %11 %12 %14 %15
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+%5 = OpFSub %6 %8 %13
+OpReturn
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Binary_Chain) {
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
+
+ auto* a = b.Subtract(mod.types.Get<type::I32>(), b.Constant(1_i), b.Constant(2_i));
+ func->start_target->instructions.Push(a);
+ func->start_target->instructions.Push(b.Add(mod.types.Get<type::I32>(), a, a));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpConstant %6 1
+%8 = OpConstant %6 2
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+%5 = OpISub %6 %7 %8
%9 = OpIAdd %6 %5 %5
OpReturn
OpFunctionEnd
diff --git a/src/tint/writer/spirv/generator_impl_constant_test.cc b/src/tint/writer/spirv/generator_impl_constant_test.cc
index c8d7a10..1e27e89 100644
--- a/src/tint/writer/spirv/generator_impl_constant_test.cc
+++ b/src/tint/writer/spirv/generator_impl_constant_test.cc
@@ -17,9 +17,9 @@
namespace tint::writer::spirv {
namespace {
-TEST_F(SpvGeneratorImplTest, Type_Bool) {
- generator_.Constant(Constant(true));
- generator_.Constant(Constant(false));
+TEST_F(SpvGeneratorImplTest, Constant_Bool) {
+ generator_.Constant(b.Constant(true));
+ generator_.Constant(b.Constant(false));
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeBool
%1 = OpConstantTrue %2
%3 = OpConstantFalse %2
@@ -27,8 +27,8 @@
}
TEST_F(SpvGeneratorImplTest, Constant_I32) {
- generator_.Constant(Constant(i32(42)));
- generator_.Constant(Constant(i32(-1)));
+ generator_.Constant(b.Constant(i32(42)));
+ generator_.Constant(b.Constant(i32(-1)));
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeInt 32 1
%1 = OpConstant %2 42
%3 = OpConstant %2 -1
@@ -36,8 +36,8 @@
}
TEST_F(SpvGeneratorImplTest, Constant_U32) {
- generator_.Constant(Constant(u32(42)));
- generator_.Constant(Constant(u32(4000000000)));
+ generator_.Constant(b.Constant(u32(42)));
+ generator_.Constant(b.Constant(u32(4000000000)));
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeInt 32 0
%1 = OpConstant %2 42
%3 = OpConstant %2 4000000000
@@ -45,8 +45,8 @@
}
TEST_F(SpvGeneratorImplTest, Constant_F32) {
- generator_.Constant(Constant(f32(42)));
- generator_.Constant(Constant(f32(-1)));
+ generator_.Constant(b.Constant(f32(42)));
+ generator_.Constant(b.Constant(f32(-1)));
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeFloat 32
%1 = OpConstant %2 42
%3 = OpConstant %2 -1
@@ -54,19 +54,102 @@
}
TEST_F(SpvGeneratorImplTest, Constant_F16) {
- generator_.Constant(Constant(f16(42)));
- generator_.Constant(Constant(f16(-1)));
+ generator_.Constant(b.Constant(f16(42)));
+ generator_.Constant(b.Constant(f16(-1)));
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeFloat 16
%1 = OpConstant %2 0x1.5p+5
%3 = OpConstant %2 -0x1p+0
)");
}
+TEST_F(SpvGeneratorImplTest, Constant_Vec4Bool) {
+ auto* t = b.Constant(true);
+ auto* f = b.Constant(false);
+ auto* v = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(mod.types.Get<type::Bool>(), 4u),
+ utils::Vector{t->value, f->value, f->value, t->value}, false, true);
+ generator_.Constant(b.Constant(v));
+ EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeBool
+%2 = OpTypeVector %3 4
+%4 = OpConstantTrue %3
+%5 = OpConstantFalse %3
+%1 = OpConstantComposite %2 %4 %5 %5 %4
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Constant_Vec2i) {
+ auto* i = mod.types.Get<type::I32>();
+ auto* i_42 = b.Constant(i32(42));
+ auto* i_n1 = b.Constant(i32(-1));
+ auto* v = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(i, 2u), utils::Vector{i_42->value, i_n1->value}, false, false);
+ generator_.Constant(b.Constant(v));
+ EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 1
+%2 = OpTypeVector %3 2
+%4 = OpConstant %3 42
+%5 = OpConstant %3 -1
+%1 = OpConstantComposite %2 %4 %5
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Constant_Vec3u) {
+ auto* u = mod.types.Get<type::U32>();
+ auto* u_42 = b.Constant(u32(42));
+ auto* u_0 = b.Constant(u32(0));
+ auto* u_4b = b.Constant(u32(4000000000));
+ auto* v = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(u, 3u), utils::Vector{u_42->value, u_0->value, u_4b->value},
+ false, true);
+ generator_.Constant(b.Constant(v));
+ EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 0
+%2 = OpTypeVector %3 3
+%4 = OpConstant %3 42
+%5 = OpConstant %3 0
+%6 = OpConstant %3 4000000000
+%1 = OpConstantComposite %2 %4 %5 %6
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Constant_Vec4f) {
+ auto* f = mod.types.Get<type::F32>();
+ auto* f_42 = b.Constant(f32(42));
+ auto* f_0 = b.Constant(f32(0));
+ auto* f_q = b.Constant(f32(0.25));
+ auto* f_n1 = b.Constant(f32(-1));
+ auto* v = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(f, 4u),
+ utils::Vector{f_42->value, f_0->value, f_q->value, f_n1->value}, false, true);
+ generator_.Constant(b.Constant(v));
+ EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeFloat 32
+%2 = OpTypeVector %3 4
+%4 = OpConstant %3 42
+%5 = OpConstant %3 0
+%6 = OpConstant %3 0.25
+%7 = OpConstant %3 -1
+%1 = OpConstantComposite %2 %4 %5 %6 %7
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Constant_Vec2h) {
+ auto* h = mod.types.Get<type::F16>();
+ auto* h_42 = b.Constant(f16(42));
+ auto* h_q = b.Constant(f16(0.25));
+ auto* v = mod.constants.Create<constant::Composite>(
+ mod.types.Get<type::Vector>(h, 2u), utils::Vector{h_42->value, h_q->value}, false, false);
+ generator_.Constant(b.Constant(v));
+ EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeFloat 16
+%2 = OpTypeVector %3 2
+%4 = OpConstant %3 0x1.5p+5
+%5 = OpConstant %3 0x1p-2
+%1 = OpConstantComposite %2 %4 %5
+)");
+}
+
// Test that we do not emit the same constant more than once.
TEST_F(SpvGeneratorImplTest, Constant_Deduplicate) {
- generator_.Constant(Constant(i32(42)));
- generator_.Constant(Constant(i32(42)));
- generator_.Constant(Constant(i32(42)));
+ generator_.Constant(b.Constant(i32(42)));
+ generator_.Constant(b.Constant(i32(42)));
+ generator_.Constant(b.Constant(i32(42)));
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeInt 32 1
%1 = OpConstant %2 42
)");
diff --git a/src/tint/writer/spirv/generator_impl_function_test.cc b/src/tint/writer/spirv/generator_impl_function_test.cc
index a1ce3cc..b8faebb 100644
--- a/src/tint/writer/spirv/generator_impl_function_test.cc
+++ b/src/tint/writer/spirv/generator_impl_function_test.cc
@@ -18,10 +18,8 @@
namespace {
TEST_F(SpvGeneratorImplTest, Function_Empty) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("foo");
- func->return_type = ir.types.Get<type::Void>();
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -36,9 +34,8 @@
// Test that we do not emit the same function type more than once.
TEST_F(SpvGeneratorImplTest, Function_DeduplicateType) {
- auto* func = CreateFunction();
- func->return_type = ir.types.Get<type::Void>();
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("foo"), mod.types.Get<type::Void>());
+ b.Branch(func->start_target, func->end_target);
generator_.EmitFunction(func);
generator_.EmitFunction(func);
@@ -49,12 +46,9 @@
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Compute) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("main");
- func->return_type = ir.types.Get<type::Void>();
- func->pipeline_stage = ir::Function::PipelineStage::kCompute;
- func->workgroup_size = {32, 4, 1};
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("main"), mod.types.Get<type::Void>(),
+ ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
+ b.Branch(func->start_target, func->end_target);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint GLCompute %1 "main"
@@ -70,11 +64,9 @@
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Fragment) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("main");
- func->return_type = ir.types.Get<type::Void>();
- func->pipeline_stage = ir::Function::PipelineStage::kFragment;
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("main"), mod.types.Get<type::Void>(),
+ ir::Function::PipelineStage::kFragment);
+ b.Branch(func->start_target, func->end_target);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint Fragment %1 "main"
@@ -90,11 +82,9 @@
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Vertex) {
- auto* func = CreateFunction();
- func->name = ir.symbols.Register("main");
- func->return_type = ir.types.Get<type::Void>();
- func->pipeline_stage = ir::Function::PipelineStage::kVertex;
- func->start_target->branch.target = func->end_target;
+ auto* func = b.CreateFunction(mod.symbols.Register("main"), mod.types.Get<type::Void>(),
+ ir::Function::PipelineStage::kVertex);
+ b.Branch(func->start_target, func->end_target);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint Vertex %1 "main"
@@ -109,25 +99,17 @@
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Multiple) {
- auto* f1 = CreateFunction();
- f1->name = ir.symbols.Register("main1");
- f1->return_type = ir.types.Get<type::Void>();
- f1->pipeline_stage = ir::Function::PipelineStage::kCompute;
- f1->workgroup_size = {32, 4, 1};
- f1->start_target->branch.target = f1->end_target;
+ auto* f1 = b.CreateFunction(mod.symbols.Register("main1"), mod.types.Get<type::Void>(),
+ ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
+ b.Branch(f1->start_target, f1->end_target);
- auto* f2 = CreateFunction();
- f2->name = ir.symbols.Register("main2");
- f2->return_type = ir.types.Get<type::Void>();
- f2->pipeline_stage = ir::Function::PipelineStage::kCompute;
- f2->workgroup_size = {8, 2, 16};
- f2->start_target->branch.target = f2->end_target;
+ auto* f2 = b.CreateFunction(mod.symbols.Register("main2"), mod.types.Get<type::Void>(),
+ ir::Function::PipelineStage::kCompute, {{8, 2, 16}});
+ b.Branch(f2->start_target, f2->end_target);
- auto* f3 = CreateFunction();
- f3->name = ir.symbols.Register("main3");
- f3->return_type = ir.types.Get<type::Void>();
- f3->pipeline_stage = ir::Function::PipelineStage::kFragment;
- f3->start_target->branch.target = f3->end_target;
+ auto* f3 = b.CreateFunction(mod.symbols.Register("main3"), mod.types.Get<type::Void>(),
+ ir::Function::PipelineStage::kFragment);
+ b.Branch(f3->start_target, f3->end_target);
generator_.EmitFunction(f1);
generator_.EmitFunction(f2);
diff --git a/src/tint/writer/spirv/generator_impl_ir.cc b/src/tint/writer/spirv/generator_impl_ir.cc
index 202ccbe..5d8c2f0 100644
--- a/src/tint/writer/spirv/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/generator_impl_ir.cc
@@ -26,6 +26,7 @@
#include "src/tint/type/i32.h"
#include "src/tint/type/type.h"
#include "src/tint/type/u32.h"
+#include "src/tint/type/vector.h"
#include "src/tint/type/void.h"
#include "src/tint/writer/spirv/module.h"
@@ -67,31 +68,41 @@
}
uint32_t GeneratorImplIr::Constant(const ir::Constant* constant) {
+ return Constant(constant->value);
+}
+
+uint32_t GeneratorImplIr::Constant(const constant::Value* constant) {
return constants_.GetOrCreate(constant, [&]() {
auto id = module_.NextId();
auto* ty = constant->Type();
- auto* value = constant->value;
Switch(
ty, //
[&](const type::Bool*) {
module_.PushType(
- value->ValueAs<bool>() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
+ constant->ValueAs<bool>() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
{Type(ty), id});
},
[&](const type::I32*) {
- module_.PushType(spv::Op::OpConstant, {Type(ty), id, value->ValueAs<u32>()});
+ module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs<u32>()});
},
[&](const type::U32*) {
module_.PushType(spv::Op::OpConstant,
- {Type(ty), id, U32Operand(value->ValueAs<i32>())});
+ {Type(ty), id, U32Operand(constant->ValueAs<i32>())});
},
[&](const type::F32*) {
- module_.PushType(spv::Op::OpConstant, {Type(ty), id, value->ValueAs<f32>()});
+ module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs<f32>()});
},
[&](const type::F16*) {
module_.PushType(
spv::Op::OpConstant,
- {Type(ty), id, U32Operand(value->ValueAs<f16>().BitsRepresentation())});
+ {Type(ty), id, U32Operand(constant->ValueAs<f16>().BitsRepresentation())});
+ },
+ [&](const type::Vector* vec) {
+ OperandList operands = {Type(ty), id};
+ for (uint32_t i = 0; i < vec->Width(); i++) {
+ operands.push_back(Constant(constant->Index(i)));
+ }
+ module_.PushType(spv::Op::OpConstantComposite, operands);
},
[&](Default) {
TINT_ICE(Writer, diagnostics_) << "unhandled constant type: " << ty->FriendlyName();
@@ -119,6 +130,9 @@
[&](const type::F16*) {
module_.PushType(spv::Op::OpTypeFloat, {id, 16u});
},
+ [&](const type::Vector* vec) {
+ module_.PushType(spv::Op::OpTypeVector, {id, Type(vec->type()), vec->Width()});
+ },
[&](Default) {
TINT_ICE(Writer, diagnostics_) << "unhandled type: " << ty->FriendlyName();
});
@@ -257,6 +271,10 @@
op = binary->Type()->is_integer_scalar_or_vector() ? spv::Op::OpIAdd : spv::Op::OpFAdd;
break;
}
+ case ir::Binary::Kind::kSubtract: {
+ op = binary->Type()->is_integer_scalar_or_vector() ? spv::Op::OpISub : spv::Op::OpFSub;
+ break;
+ }
default: {
TINT_ICE(Writer, diagnostics_)
<< "unimplemented binary instruction: " << static_cast<uint32_t>(binary->kind);
diff --git a/src/tint/writer/spirv/generator_impl_ir.h b/src/tint/writer/spirv/generator_impl_ir.h
index 61870d4..e885edb 100644
--- a/src/tint/writer/spirv/generator_impl_ir.h
+++ b/src/tint/writer/spirv/generator_impl_ir.h
@@ -95,6 +95,11 @@
uint32_t EmitBinary(const ir::Binary* binary);
private:
+ /// Get the result ID of the constant `constant`, emitting its instruction if necessary.
+ /// @param constant the constant to get the ID for
+ /// @returns the result ID of the constant
+ uint32_t Constant(const constant::Value* constant);
+
const ir::Module* ir_;
spirv::Module module_;
BinaryWriter writer_;
@@ -125,22 +130,22 @@
}
};
- /// ConstantHasher provides a hash function for an ir::Constant pointer, hashing the value
+ /// ConstantHasher provides a hash function for a constant::Value pointer, hashing the value
/// instead of the pointer itself.
struct ConstantHasher {
- /// @param c the ir::Constant pointer to create a hash for
+ /// @param c the constant::Value pointer to create a hash for
/// @return the hash value
- inline std::size_t operator()(const ir::Constant* c) const { return c->value->Hash(); }
+ inline std::size_t operator()(const constant::Value* c) const { return c->Hash(); }
};
- /// ConstantEquals provides an equality function for two ir::Constant pointers, comparing their
- /// values instead of the pointers.
+ /// ConstantEquals provides an equality function for two constant::Value pointers, comparing
+ /// their values instead of the pointers.
struct ConstantEquals {
- /// @param a the first ir::Constant pointer to compare
- /// @param b the second ir::Constant pointer to compare
+ /// @param a the first constant::Value pointer to compare
+ /// @param b the second constant::Value pointer to compare
/// @return the hash value
- inline bool operator()(const ir::Constant* a, const ir::Constant* b) const {
- return a->value->Equal(b->value);
+ inline bool operator()(const constant::Value* a, const constant::Value* b) const {
+ return a->Equal(b);
}
};
@@ -151,7 +156,7 @@
utils::Hashmap<FunctionType, uint32_t, 8, FunctionType::Hasher> function_types_;
/// The map of constants to their result IDs.
- utils::Hashmap<const ir::Constant*, uint32_t, 16, ConstantHasher, ConstantEquals> constants_;
+ utils::Hashmap<const constant::Value*, uint32_t, 16, ConstantHasher, ConstantEquals> constants_;
/// The map of instructions to their result IDs.
utils::Hashmap<const ir::Instruction*, uint32_t, 8> instructions_;
diff --git a/src/tint/writer/spirv/generator_impl_type_test.cc b/src/tint/writer/spirv/generator_impl_type_test.cc
index c8a2e8e..c86d363 100644
--- a/src/tint/writer/spirv/generator_impl_type_test.cc
+++ b/src/tint/writer/spirv/generator_impl_type_test.cc
@@ -25,48 +25,93 @@
namespace {
TEST_F(SpvGeneratorImplTest, Type_Void) {
- auto id = generator_.Type(ir.types.Get<type::Void>());
+ auto id = generator_.Type(mod.types.Get<type::Void>());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeVoid\n");
}
TEST_F(SpvGeneratorImplTest, Type_Bool) {
- auto id = generator_.Type(ir.types.Get<type::Bool>());
+ auto id = generator_.Type(mod.types.Get<type::Bool>());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeBool\n");
}
TEST_F(SpvGeneratorImplTest, Type_I32) {
- auto id = generator_.Type(ir.types.Get<type::I32>());
+ auto id = generator_.Type(mod.types.Get<type::I32>());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeInt 32 1\n");
}
TEST_F(SpvGeneratorImplTest, Type_U32) {
- auto id = generator_.Type(ir.types.Get<type::U32>());
+ auto id = generator_.Type(mod.types.Get<type::U32>());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeInt 32 0\n");
}
TEST_F(SpvGeneratorImplTest, Type_F32) {
- auto id = generator_.Type(ir.types.Get<type::F32>());
+ auto id = generator_.Type(mod.types.Get<type::F32>());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeFloat 32\n");
}
TEST_F(SpvGeneratorImplTest, Type_F16) {
- auto id = generator_.Type(ir.types.Get<type::F16>());
+ auto id = generator_.Type(mod.types.Get<type::F16>());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeFloat 16\n");
}
-// Test that we do can emit multiple types.
+TEST_F(SpvGeneratorImplTest, Type_Vec2i) {
+ auto* vec = b.ir.types.Get<type::Vector>(b.ir.types.Get<type::I32>(), 2u);
+ auto id = generator_.Type(vec);
+ EXPECT_EQ(id, 1u);
+ EXPECT_EQ(DumpTypes(),
+ "%2 = OpTypeInt 32 1\n"
+ "%1 = OpTypeVector %2 2\n");
+}
+
+TEST_F(SpvGeneratorImplTest, Type_Vec3u) {
+ auto* vec = b.ir.types.Get<type::Vector>(b.ir.types.Get<type::U32>(), 3u);
+ auto id = generator_.Type(vec);
+ EXPECT_EQ(id, 1u);
+ EXPECT_EQ(DumpTypes(),
+ "%2 = OpTypeInt 32 0\n"
+ "%1 = OpTypeVector %2 3\n");
+}
+
+TEST_F(SpvGeneratorImplTest, Type_Vec4f) {
+ auto* vec = b.ir.types.Get<type::Vector>(b.ir.types.Get<type::F32>(), 4u);
+ auto id = generator_.Type(vec);
+ EXPECT_EQ(id, 1u);
+ EXPECT_EQ(DumpTypes(),
+ "%2 = OpTypeFloat 32\n"
+ "%1 = OpTypeVector %2 4\n");
+}
+
+TEST_F(SpvGeneratorImplTest, Type_Vec4h) {
+ auto* vec = b.ir.types.Get<type::Vector>(b.ir.types.Get<type::F16>(), 2u);
+ auto id = generator_.Type(vec);
+ EXPECT_EQ(id, 1u);
+ EXPECT_EQ(DumpTypes(),
+ "%2 = OpTypeFloat 16\n"
+ "%1 = OpTypeVector %2 2\n");
+}
+
+TEST_F(SpvGeneratorImplTest, Type_Vec4Bool) {
+ auto* vec = b.ir.types.Get<type::Vector>(b.ir.types.Get<type::Bool>(), 4u);
+ auto id = generator_.Type(vec);
+ EXPECT_EQ(id, 1u);
+ EXPECT_EQ(DumpTypes(),
+ "%2 = OpTypeBool\n"
+ "%1 = OpTypeVector %2 4\n");
+}
+
+// Test that we can emit multiple types.
// Includes types with the same opcode but different parameters.
TEST_F(SpvGeneratorImplTest, Type_Multiple) {
- EXPECT_EQ(generator_.Type(ir.types.Get<type::I32>()), 1u);
- EXPECT_EQ(generator_.Type(ir.types.Get<type::U32>()), 2u);
- EXPECT_EQ(generator_.Type(ir.types.Get<type::F32>()), 3u);
- EXPECT_EQ(generator_.Type(ir.types.Get<type::F16>()), 4u);
+ EXPECT_EQ(generator_.Type(mod.types.Get<type::I32>()), 1u);
+ EXPECT_EQ(generator_.Type(mod.types.Get<type::U32>()), 2u);
+ EXPECT_EQ(generator_.Type(mod.types.Get<type::F32>()), 3u);
+ EXPECT_EQ(generator_.Type(mod.types.Get<type::F16>()), 4u);
EXPECT_EQ(DumpTypes(), R"(%1 = OpTypeInt 32 1
%2 = OpTypeInt 32 0
%3 = OpTypeFloat 32
@@ -76,7 +121,7 @@
// Test that we do not emit the same type more than once.
TEST_F(SpvGeneratorImplTest, Type_Deduplicate) {
- auto* i32 = ir.types.Get<type::I32>();
+ auto* i32 = mod.types.Get<type::I32>();
EXPECT_EQ(generator_.Type(i32), 1u);
EXPECT_EQ(generator_.Type(i32), 1u);
EXPECT_EQ(generator_.Type(i32), 1u);
diff --git a/src/tint/writer/spirv/test_helper_ir.h b/src/tint/writer/spirv/test_helper_ir.h
index 6de6f48..3574645 100644
--- a/src/tint/writer/spirv/test_helper_ir.h
+++ b/src/tint/writer/spirv/test_helper_ir.h
@@ -26,9 +26,14 @@
/// Base helper class for testing the SPIR-V generator implementation.
template <typename BASE>
-class SpvGeneratorTestHelperBase : public ir::Builder, public BASE {
+class SpvGeneratorTestHelperBase : public BASE {
public:
- SpvGeneratorTestHelperBase() : generator_(&ir, false) {}
+ SpvGeneratorTestHelperBase() : generator_(&mod, false) {}
+
+ /// The test module
+ ir::Module mod;
+ /// The test builder
+ ir::Builder b{mod};
protected:
/// The SPIR-V generator.