Import Tint changes from Dawn
Changes:
- 2e11963cafd801f8749609cd5c00250b664312a5 D3D12: Skip robustness transform on textures by Jiawei Shao <jiawei.shao@intel.com>
- 3ef08efc818b130e5aa46bb0c23fcbcec3b4d2c3 Add Partial Tint Dual Source Blending Extension by Brandon Jones <brandon1.jones@intel.com>
- 4dc97b404b088d3094f04ed08ec002e53d29f220 [ir] Add a helper for creating struct types by James Price <jrprice@google.com>
- 9397714f67830d5745c3bb871e51e5bb3f857470 [tint][ir] Rename Case::start -> Case::block by Ben Clayton <bclayton@google.com>
- c8f07088e47520a6d20efe9a7929c35c2c1c2c52 [tint][ir] Make ControlInstructions regular instructions by Ben Clayton <bclayton@google.com>
- 2649bd008951a70fd0472dede0df517ab5d5eed8 Vulkan: Skip image robustness transform with VK_EXT_robus... by Jiawei Shao <jiawei.shao@intel.com>
- 5702df1d368de93eddebb815b482567bd48f39c1 [spirv-reader] Detect constant vector splats by James Price <jrprice@google.com>
- 4915adcccaf98049d9e03e7306d03eec1c598310 [tint][ir] Add Unreachable instruction by Ben Clayton <bclayton@google.com>
- 1104ad1c9b9108a0e25fee0ad53b0f6b9cbe489a [spirv-reader] Emit zero value constructors by James Price <jrprice@google.com>
- e38419aac1628f5a012fe47dadb3e3d1f70490ea [spirv-reader] Detect vector splats by James Price <jrprice@google.com>
- 80f0a172352efeadfdaaa7e4da303c5101579a76 [spirv-reader] Emit multi-component swizzles by James Price <jrprice@google.com>
- b62d00861d4823e9f072f998239343ae7f31239b [tint][ir] Add Instruction::Destroy() by Ben Clayton <bclayton@google.com>
- ab0cbed26bb0cb086734dcca58db9aace020d5b7 [tint][ir] Add Destroy(), Alive(), ReplaceAllUsesWith() t... by Ben Clayton <bclayton@google.com>
- a059e59780d140490a337377bcd4f00b28923d50 [tint][ir] Add Builder::Exit() helper by Ben Clayton <bclayton@google.com>
- 27c6d9801ab38f1b6ef7b21003ac1cc52641325d Add static assert: const-eval depends on inf and NaN supp... by David Neto <dneto@google.com>
- c801286132eff43707a13fad9867b163beef8cb8 [ir][spirv-writer] Enable capabilities for F16 by James Price <jrprice@google.com>
- 4187a53d41dc8e5d8bd8344a07e70554990e097f [ir] Validate transform test input and output by James Price <jrprice@google.com>
- b13184bb85a1a4b2d5047b6c751b1b0c3ce0aa35 [tint][utils] Add Any(), All() and list ctor to Hashset by Ben Clayton <bclayton@google.com>
- afa5617f6fd288a16b7755aa03dbafe330216ec4 [ir][spirv-writer] Add MergeReturn transform by James Price <jrprice@google.com>
- aabfc4d85bc39c3ff28670d22cfada276b94860a [ir][spirv-writer] Emit construct instructions by James Price <jrprice@google.com>
- 0d80c3d66152a0211cd64c08929335cc520d23cd [ir] Sever instruction and value. by dan sinclair <dsinclair@chromium.org>
- 367fad852a6c48f9b0691d756c2fe7150c056ead [ir] Spit `instruction` and `value` allocators. by dan sinclair <dsinclair@chromium.org>
- 525b6f5f76e2ddad10c4aa6e3b261d58bfa05a4b [ir] Add Result objects into the instructions by dan sinclair <dsinclair@chromium.org>
- 4934dc0544f8d39db30f791337fbcf94b8c9301c [ir] Update `Value` parameters. by dan sinclair <dsinclair@chromium.org>
- 138d5b7b9f6f2e394b95b040ffd7b041cbba7831 [tint] Move 'using namespace' into anonymous namespace by Ben Clayton <bclayton@google.com>
- b839f673ac7a118aac551959d118aa61b0d77fb6 [ir] Make function an operand of return by James Price <jrprice@google.com>
- 66805b0c0e45eaf4ef95d60d26c32b16ff6ae639 [tint] Migrate to 'fluent types' by Ben Clayton <bclayton@google.com>
- a3390da8f5a22a23bf490e3d0fcfc147e73ba905 [ir] Add Return::Value() to get the return value by James Price <jrprice@google.com>
- 19f92f9cdeab4e4f888d78ad7a3fd5819fdc2a7d [ir] Convert tests to block builder. by dan sinclair <dsinclair@chromium.org>
- 2ef231183fbaf6e2315891257eb72b0a2071739e [ir] Allow builder to auto-append instructions. by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: 2e11963cafd801f8749609cd5c00250b664312a5
Change-Id: I51fe8a11246dfafc61a9551dc7f6d23870ace1a0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/137400
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 2b450fb..1d71177 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -201,8 +201,6 @@
libtint_source_set("libtint_symbols_src") {
sources = [
- "number.cc",
- "number.h",
"program_id.cc",
"program_id.h",
"reflection.h",
@@ -523,6 +521,8 @@
"ir/transform/add_empty_entry_point.h",
"ir/transform/block_decorated_structs.cc",
"ir/transform/block_decorated_structs.h",
+ "ir/transform/merge_return.cc",
+ "ir/transform/merge_return.h",
"ir/transform/var_for_dynamic_index.cc",
"ir/transform/var_for_dynamic_index.h",
]
@@ -577,6 +577,7 @@
"ast/if_statement.h",
"ast/increment_decrement_statement.h",
"ast/index_accessor_expression.h",
+ "ast/index_attribute.h",
"ast/int_literal_expression.h",
"ast/internal_attribute.h",
"ast/interpolate_attribute.h",
@@ -666,6 +667,7 @@
"ast/if_statement.cc",
"ast/increment_decrement_statement.cc",
"ast/index_accessor_expression.cc",
+ "ast/index_attribute.cc",
"ast/int_literal_expression.cc",
"ast/internal_attribute.cc",
"ast/interpolate_attribute.cc",
@@ -812,6 +814,7 @@
"builtin/diagnostic_severity.h",
"builtin/extension.cc",
"builtin/extension.h",
+ "builtin/fluent_types.h",
"builtin/function.cc",
"builtin/function.h",
"builtin/interpolation.h",
@@ -819,6 +822,8 @@
"builtin/interpolation_sampling.h",
"builtin/interpolation_type.cc",
"builtin/interpolation_type.h",
+ "builtin/number.cc",
+ "builtin/number.h",
"builtin/texel_format.cc",
"builtin/texel_format.h",
]
@@ -920,6 +925,7 @@
"constant/value.h",
]
deps = [
+ ":libtint_builtins_src",
":libtint_symbols_src",
":libtint_type_src",
":libtint_utils_src",
@@ -1252,6 +1258,8 @@
"ir/disassembler.h",
"ir/discard.cc",
"ir/discard.h",
+ "ir/exit.cc",
+ "ir/exit.h",
"ir/exit_if.cc",
"ir/exit_if.h",
"ir/exit_loop.cc",
@@ -1266,6 +1274,8 @@
"ir/if.h",
"ir/instruction.cc",
"ir/instruction.h",
+ "ir/instruction_result.cc",
+ "ir/instruction_result.h",
"ir/load.cc",
"ir/load.h",
"ir/location.h",
@@ -1291,6 +1301,8 @@
"ir/transform/transform.h",
"ir/unary.cc",
"ir/unary.h",
+ "ir/unreachable.cc",
+ "ir/unreachable.h",
"ir/user_call.cc",
"ir/user_call.h",
"ir/validate.cc",
@@ -1554,6 +1566,7 @@
"ast/if_statement_test.cc",
"ast/increment_decrement_statement_test.cc",
"ast/index_accessor_expression_test.cc",
+ "ast/index_attribute_test.cc",
"ast/int_literal_expression_test.cc",
"ast/interpolate_attribute_test.cc",
"ast/location_attribute_test.cc",
@@ -1604,6 +1617,7 @@
"builtin/extension_test.cc",
"builtin/interpolation_sampling_test.cc",
"builtin/interpolation_type_test.cc",
+ "builtin/number_test.cc",
"builtin/texel_format_test.cc",
]
deps = [ ":libtint_builtins_src" ]
@@ -1662,6 +1676,7 @@
"resolver/control_block_validation_test.cc",
"resolver/dependency_graph_test.cc",
"resolver/diagnostic_control_test.cc",
+ "resolver/dual_source_blending_extension_test.cc",
"resolver/entry_point_validation_test.cc",
"resolver/evaluation_stage_test.cc",
"resolver/expression_kind_test.cc",
@@ -1825,6 +1840,7 @@
sources = [
"ir/transform/add_empty_entry_point_test.cc",
"ir/transform/block_decorated_structs_test.cc",
+ "ir/transform/merge_return_test.cc",
"ir/transform/test_helper.h",
"ir/transform/var_for_dynamic_index_test.cc",
]
@@ -1998,6 +2014,7 @@
"writer/spirv/ir/generator_impl_ir_binary_test.cc",
"writer/spirv/ir/generator_impl_ir_builtin_test.cc",
"writer/spirv/ir/generator_impl_ir_constant_test.cc",
+ "writer/spirv/ir/generator_impl_ir_construct_test.cc",
"writer/spirv/ir/generator_impl_ir_function_test.cc",
"writer/spirv/ir/generator_impl_ir_if_test.cc",
"writer/spirv/ir/generator_impl_ir_loop_test.cc",
@@ -2256,6 +2273,7 @@
deps = [
":libtint_ast_transform_src",
+ ":libtint_builtins_src",
":libtint_glsl_writer_src",
":libtint_symbols_src",
":libtint_transform_manager_src",
@@ -2266,7 +2284,6 @@
tint_unittests_source_set("tint_unittests_symbols_src") {
sources = [
- "number_test.cc",
"reflection_test.cc",
"scope_stack_test.cc",
"symbol_table_test.cc",
@@ -2331,6 +2348,7 @@
"ir/function_param_test.cc",
"ir/function_test.cc",
"ir/if_test.cc",
+ "ir/instruction_result_test.cc",
"ir/instruction_test.cc",
"ir/ir_test_helper.h",
"ir/load_test.cc",
@@ -2338,6 +2356,7 @@
"ir/module_test.cc",
"ir/multi_in_block_test.cc",
"ir/next_iteration_test.cc",
+ "ir/operand_instruction_test.cc",
"ir/program_test_helper.h",
"ir/return_test.cc",
"ir/store_test.cc",
@@ -2347,6 +2366,7 @@
"ir/unary_test.cc",
"ir/user_call_test.cc",
"ir/validate_test.cc",
+ "ir/value_test.cc",
"ir/var_test.cc",
]
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 6e6d760..5c0bf6f 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -58,14 +58,14 @@
add_library(tint_diagnostic_utils
debug.cc
debug.h
- source.h
- source.cc
diagnostic/diagnostic.cc
diagnostic/diagnostic.h
diagnostic/formatter.cc
diagnostic/formatter.h
diagnostic/printer.cc
diagnostic/printer.h
+ source.cc
+ source.h
utils/debugger.cc
utils/debugger.h
utils/unicode.cc
@@ -158,6 +158,8 @@
ast/increment_decrement_statement.h
ast/index_accessor_expression.cc
ast/index_accessor_expression.h
+ ast/index_attribute.cc
+ ast/index_attribute.h
ast/int_literal_expression.cc
ast/int_literal_expression.h
ast/internal_attribute.cc
@@ -232,6 +234,9 @@
ast/while_statement.h
ast/workgroup_attribute.cc
ast/workgroup_attribute.h
+ builtin/fluent_types.h
+ builtin/number.cc
+ builtin/number.h
clone_context.cc
clone_context.h
constant/clone_context.h
@@ -255,8 +260,6 @@
inspector/resource_binding.h
inspector/scalar.cc
inspector/scalar.h
- number.cc
- number.h
program_builder.cc
program_builder.h
program_id.cc
@@ -761,6 +764,8 @@
ir/exit_loop.h
ir/exit_switch.cc
ir/exit_switch.h
+ ir/exit.cc
+ ir/exit.h
ir/from_program.cc
ir/from_program.h
ir/function.cc
@@ -771,6 +776,8 @@
ir/if.h
ir/instruction.cc
ir/instruction.h
+ ir/instruction_result.cc
+ ir/instruction_result.h
ir/load.cc
ir/load.h
ir/location.h
@@ -796,6 +803,8 @@
ir/to_program.h
ir/unary.cc
ir/unary.h
+ ir/unreachable.cc
+ ir/unreachable.h
ir/user_call.cc
ir/user_call.h
ir/validate.cc
@@ -808,6 +817,8 @@
ir/transform/add_empty_entry_point.h
ir/transform/block_decorated_structs.cc
ir/transform/block_decorated_structs.h
+ ir/transform/merge_return.cc
+ ir/transform/merge_return.h
ir/transform/transform.cc
ir/transform/transform.h
ir/transform/var_for_dynamic_index.cc
@@ -930,6 +941,7 @@
ast/if_statement_test.cc
ast/increment_decrement_statement_test.cc
ast/index_accessor_expression_test.cc
+ ast/index_attribute_test.cc
ast/int_literal_expression_test.cc
ast/interpolate_attribute_test.cc
ast/location_attribute_test.cc
@@ -955,6 +967,7 @@
ast/variable_test.cc
ast/while_statement_test.cc
ast/workgroup_attribute_test.cc
+ builtin/number_test.cc
clone_context_test.cc
constant/composite_test.cc
constant/manager_test.cc
@@ -965,7 +978,6 @@
diagnostic/diagnostic_test.cc
diagnostic/formatter_test.cc
diagnostic/printer_test.cc
- number_test.cc
program_builder_test.cc
program_test.cc
reflection_test.cc
@@ -999,6 +1011,7 @@
resolver/control_block_validation_test.cc
resolver/dependency_graph_test.cc
resolver/diagnostic_control_test.cc
+ resolver/dual_source_blending_extension_test.cc
resolver/entry_point_validation_test.cc
resolver/evaluation_stage_test.cc
resolver/expression_kind_test.cc
@@ -1285,6 +1298,7 @@
writer/spirv/ir/generator_impl_ir_binary_test.cc
writer/spirv/ir/generator_impl_ir_builtin_test.cc
writer/spirv/ir/generator_impl_ir_constant_test.cc
+ writer/spirv/ir/generator_impl_ir_construct_test.cc
writer/spirv/ir/generator_impl_ir_function_test.cc
writer/spirv/ir/generator_impl_ir_if_test.cc
writer/spirv/ir/generator_impl_ir_loop_test.cc
@@ -1532,6 +1546,7 @@
ir/function_param_test.cc
ir/function_test.cc
ir/if_test.cc
+ ir/instruction_result_test.cc
ir/instruction_test.cc
ir/ir_test_helper.h
ir/load_test.cc
@@ -1539,6 +1554,7 @@
ir/module_test.cc
ir/multi_in_block_test.cc
ir/next_iteration_test.cc
+ ir/operand_instruction_test.cc
ir/program_test_helper.h
ir/return_test.cc
ir/store_test.cc
@@ -1546,10 +1562,12 @@
ir/swizzle_test.cc
ir/transform/add_empty_entry_point_test.cc
ir/transform/block_decorated_structs_test.cc
+ ir/transform/merge_return_test.cc
ir/transform/var_for_dynamic_index_test.cc
ir/unary_test.cc
ir/user_call_test.cc
ir/validate_test.cc
+ ir/value_test.cc
ir/var_test.cc
)
endif()
diff --git a/src/tint/ast/builtin_texture_helper_test.cc b/src/tint/ast/builtin_texture_helper_test.cc
index 3231081..5c548db 100644
--- a/src/tint/ast/builtin_texture_helper_test.cc
+++ b/src/tint/ast/builtin_texture_helper_test.cc
@@ -20,11 +20,12 @@
#include "src/tint/type/sampled_texture.h"
#include "src/tint/type/texture_dimension.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::test {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
utils::StringStream& operator<<(utils::StringStream& out, const TextureKind& kind) {
switch (kind) {
case TextureKind::kRegular:
@@ -492,10 +493,10 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(0_i, // component
- kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f)); // coords
+ return b->ExprList(0_i, // component
+ kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f)); // coords
},
/* returns value */ true,
},
@@ -512,11 +513,11 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(0_u, // component
- kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- b->vec2<i32>(3_i, 4_i)); // offset
+ return b->ExprList(0_u, // component
+ kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ b->Call<vec2<i32>>(3_i, 4_i)); // offset
},
/* returns value */ true,
},
@@ -533,11 +534,11 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(0_i, // component
- kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i); // array index
+ return b->ExprList(0_i, // component
+ kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i); // array index
},
/* returns value */ true,
},
@@ -555,12 +556,12 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(0_u, // component
- kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u, // array_index
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(0_u, // component
+ kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u, // array_index
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -576,10 +577,10 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(0_i, // component
- kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f)); // coords
+ return b->ExprList(0_i, // component
+ kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f)); // coords
},
/* returns value */ true,
},
@@ -596,11 +597,11 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(0_u, // component
- kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_u); // array_index
+ return b->ExprList(0_u, // component
+ kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_u); // array_index
},
/* returns value */ true,
},
@@ -615,9 +616,9 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f)); // coords
},
/* returns value */ true,
},
@@ -633,10 +634,10 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- b->vec2<i32>(3_i, 4_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ b->Call<vec2<i32>>(3_i, 4_i)); // offset
},
/* returns value */ true,
},
@@ -652,10 +653,10 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u); // array_index
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u); // array_index
},
/* returns value */ true,
},
@@ -672,11 +673,11 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -691,9 +692,9 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f)); // coords
},
/* returns value */ true,
},
@@ -709,10 +710,10 @@
TextureDataType::kF32,
"textureGather",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_u); // array_index
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_u); // array_index
},
/* returns value */ true,
},
@@ -728,10 +729,10 @@
TextureDataType::kF32,
"textureGatherCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f); // depth_ref
},
/* returns value */ true,
},
@@ -748,11 +749,11 @@
TextureDataType::kF32,
"textureGatherCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f, // depth_ref
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f, // depth_ref
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -769,11 +770,11 @@
TextureDataType::kF32,
"textureGatherCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f); // depth_ref
},
/* returns value */ true,
},
@@ -791,12 +792,12 @@
TextureDataType::kF32,
"textureGatherCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f, // depth_ref
- b->vec2<i32>(5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f, // depth_ref
+ b->Call<vec2<i32>>(5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -812,10 +813,10 @@
TextureDataType::kF32,
"textureGatherCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // depth_ref
},
/* returns value */ true,
},
@@ -832,11 +833,11 @@
TextureDataType::kF32,
"textureGatherCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_u, // array_index
- 5_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_u, // array_index
+ 5_f); // depth_ref
},
/* returns value */ true,
},
@@ -1044,9 +1045,9 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f)); // coords
},
/* returns value */ true,
},
@@ -1062,10 +1063,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- b->vec2<i32>(3_i, 4_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ b->Call<vec2<i32>>(3_i, 4_i)); // offset
},
/* returns value */ true,
},
@@ -1081,10 +1082,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i); // array_index
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i); // array_index
},
/* returns value */ true,
},
@@ -1101,11 +1102,11 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u, // array_index
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u, // array_index
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -1120,9 +1121,9 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f)); // coords
},
/* returns value */ true,
},
@@ -1138,10 +1139,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- b->vec3<i32>(4_i, 5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ b->Call<vec3<i32>>(4_i, 5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -1156,9 +1157,9 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f)); // coords
},
/* returns value */ true,
},
@@ -1174,10 +1175,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_i); // array_index
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_i); // array_index
},
/* returns value */ true,
},
@@ -1192,9 +1193,9 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f)); // coords
},
/* returns value */ true,
},
@@ -1210,10 +1211,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- b->vec2<i32>(3_i, 4_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ b->Call<vec2<i32>>(3_i, 4_i)); // offset
},
/* returns value */ true,
},
@@ -1229,10 +1230,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i); // array_index
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i); // array_index
},
/* returns value */ true,
},
@@ -1249,11 +1250,11 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -1268,9 +1269,9 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f)); // coords
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f)); // coords
},
/* returns value */ true,
},
@@ -1286,10 +1287,10 @@
TextureDataType::kF32,
"textureSample",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_u); // array_index
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_u); // array_index
},
/* returns value */ true,
},
@@ -1305,10 +1306,10 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f); // bias
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f); // bias
},
/* returns value */ true,
},
@@ -1325,11 +1326,11 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f, // bias
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f, // bias
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -1346,11 +1347,11 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 4_u, // array_index
- 3_f); // bias
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 4_u, // array_index
+ 3_f); // bias
},
/* returns value */ true,
},
@@ -1368,12 +1369,12 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f, // bias
- b->vec2<i32>(5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f, // bias
+ b->Call<vec2<i32>>(5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -1389,10 +1390,10 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // bias
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // bias
},
/* returns value */ true,
},
@@ -1409,11 +1410,11 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f, // bias
- b->vec3<i32>(5_i, 6_i, 7_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f, // bias
+ b->Call<vec3<i32>>(5_i, 6_i, 7_i)); // offset
},
/* returns value */ true,
},
@@ -1429,10 +1430,10 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // bias
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // bias
},
/* returns value */ true,
},
@@ -1449,11 +1450,11 @@
TextureDataType::kF32,
"textureSampleBias",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 3_i, // array_index
- 4_f); // bias
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 3_i, // array_index
+ 4_f); // bias
},
/* returns value */ true,
},
@@ -1469,10 +1470,10 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f); // level
},
/* returns value */ true,
},
@@ -1489,11 +1490,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f, // level
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f, // level
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -1510,11 +1511,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f); // level
},
/* returns value */ true,
},
@@ -1532,12 +1533,12 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f, // level
- b->vec2<i32>(5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f, // level
+ b->Call<vec2<i32>>(5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -1553,10 +1554,10 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // level
},
/* returns value */ true,
},
@@ -1573,11 +1574,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f, // level
- b->vec3<i32>(5_i, 6_i, 7_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f, // level
+ b->Call<vec3<i32>>(5_i, 6_i, 7_i)); // offset
},
/* returns value */ true,
},
@@ -1593,10 +1594,10 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // level
},
/* returns value */ true,
},
@@ -1613,11 +1614,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_i, // array_index
- 5_f); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_i, // array_index
+ 5_f); // level
},
/* returns value */ true,
},
@@ -1633,10 +1634,10 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u); // level
},
/* returns value */ true,
},
@@ -1653,11 +1654,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // level
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // level
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -1674,11 +1675,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u, // array_index
- 4_u); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u, // array_index
+ 4_u); // level
},
/* returns value */ true,
},
@@ -1696,12 +1697,12 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u, // array_index
- 4_u, // level
- b->vec2<i32>(5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u, // array_index
+ 4_u, // level
+ b->Call<vec2<i32>>(5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -1717,10 +1718,10 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_i); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_i); // level
},
/* returns value */ true,
},
@@ -1737,11 +1738,11 @@
TextureDataType::kF32,
"textureSampleLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_i, // array_index
- 5_i); // level
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_i, // array_index
+ 5_i); // level
},
/* returns value */ true,
},
@@ -1758,11 +1759,11 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- b->vec2<f32>(3_f, 4_f), // ddx
- b->vec2<f32>(5_f, 6_f)); // ddy
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ b->Call<vec2<f32>>(3_f, 4_f), // ddx
+ b->Call<vec2<f32>>(5_f, 6_f)); // ddy
},
/* returns value */ true,
},
@@ -1780,12 +1781,12 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- b->vec2<f32>(3_f, 4_f), // ddx
- b->vec2<f32>(5_f, 6_f), // ddy
- b->vec2<i32>(7_i, 7_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ b->Call<vec2<f32>>(3_f, 4_f), // ddx
+ b->Call<vec2<f32>>(5_f, 6_f), // ddy
+ b->Call<vec2<i32>>(7_i, 7_i)); // offset
},
/* returns value */ true,
},
@@ -1803,12 +1804,12 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- b->vec2<f32>(4_f, 5_f), // ddx
- b->vec2<f32>(6_f, 7_f)); // ddy
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ b->Call<vec2<f32>>(4_f, 5_f), // ddx
+ b->Call<vec2<f32>>(6_f, 7_f)); // ddy
},
/* returns value */ true,
},
@@ -1827,13 +1828,13 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_u, // array_index
- b->vec2<f32>(4_f, 5_f), // ddx
- b->vec2<f32>(6_f, 7_f), // ddy
- b->vec2<i32>(6_i, 7_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_u, // array_index
+ b->Call<vec2<f32>>(4_f, 5_f), // ddx
+ b->Call<vec2<f32>>(6_f, 7_f), // ddy
+ b->Call<vec2<i32>>(6_i, 7_i)); // offset
},
/* returns value */ true,
},
@@ -1850,11 +1851,11 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- b->vec3<f32>(4_f, 5_f, 6_f), // ddx
- b->vec3<f32>(7_f, 8_f, 9_f)); // ddy
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ b->Call<vec3<f32>>(4_f, 5_f, 6_f), // ddx
+ b->Call<vec3<f32>>(7_f, 8_f, 9_f)); // ddy
},
/* returns value */ true,
},
@@ -1872,12 +1873,12 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- b->vec3<f32>(4_f, 5_f, 6_f), // ddx
- b->vec3<f32>(7_f, 8_f, 9_f), // ddy
- b->vec3<i32>(0_i, 1_i, 2_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ b->Call<vec3<f32>>(4_f, 5_f, 6_f), // ddx
+ b->Call<vec3<f32>>(7_f, 8_f, 9_f), // ddy
+ b->Call<vec3<i32>>(0_i, 1_i, 2_i)); // offset
},
/* returns value */ true,
},
@@ -1894,11 +1895,11 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- b->vec3<f32>(4_f, 5_f, 6_f), // ddx
- b->vec3<f32>(7_f, 8_f, 9_f)); // ddy
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ b->Call<vec3<f32>>(4_f, 5_f, 6_f), // ddx
+ b->Call<vec3<f32>>(7_f, 8_f, 9_f)); // ddy
},
/* returns value */ true,
},
@@ -1916,12 +1917,12 @@
TextureDataType::kF32,
"textureSampleGrad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_u, // array_index
- b->vec3<f32>(5_f, 6_f, 7_f), // ddx
- b->vec3<f32>(8_f, 9_f, 10_f)); // ddy
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_u, // array_index
+ b->Call<vec3<f32>>(5_f, 6_f, 7_f), // ddx
+ b->Call<vec3<f32>>(8_f, 9_f, 10_f)); // ddy
},
/* returns value */ true,
},
@@ -1937,10 +1938,10 @@
TextureDataType::kF32,
"textureSampleCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f); // depth_ref
},
/* returns value */ true,
},
@@ -1957,11 +1958,11 @@
TextureDataType::kF32,
"textureSampleCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f, // depth_ref
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f, // depth_ref
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -1978,11 +1979,11 @@
TextureDataType::kF32,
"textureSampleCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 4_i, // array_index
- 3_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 4_i, // array_index
+ 3_f); // depth_ref
},
/* returns value */ true,
},
@@ -2000,12 +2001,12 @@
TextureDataType::kF32,
"textureSampleCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 4_u, // array_index
- 3_f, // depth_ref
- b->vec2<i32>(5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 4_u, // array_index
+ 3_f, // depth_ref
+ b->Call<vec2<i32>>(5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -2021,10 +2022,10 @@
TextureDataType::kF32,
"textureSampleCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // depth_ref
},
/* returns value */ true,
},
@@ -2041,11 +2042,11 @@
TextureDataType::kF32,
"textureSampleCompare",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_i, // array_index
- 5_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_i, // array_index
+ 5_f); // depth_ref
},
/* returns value */ true,
},
@@ -2061,10 +2062,10 @@
TextureDataType::kF32,
"textureSampleCompareLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f); // depth_ref
},
/* returns value */ true,
},
@@ -2081,11 +2082,11 @@
TextureDataType::kF32,
"textureSampleCompareLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_f, // depth_ref
- b->vec2<i32>(4_i, 5_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_f, // depth_ref
+ b->Call<vec2<i32>>(4_i, 5_i)); // offset
},
/* returns value */ true,
},
@@ -2102,11 +2103,11 @@
TextureDataType::kF32,
"textureSampleCompareLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f); // depth_ref
},
/* returns value */ true,
},
@@ -2124,12 +2125,12 @@
TextureDataType::kF32,
"textureSampleCompareLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec2<f32>(1_f, 2_f), // coords
- 3_i, // array_index
- 4_f, // depth_ref
- b->vec2<i32>(5_i, 6_i)); // offset
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec2<f32>>(1_f, 2_f), // coords
+ 3_i, // array_index
+ 4_f, // depth_ref
+ b->Call<vec2<i32>>(5_i, 6_i)); // offset
},
/* returns value */ true,
},
@@ -2145,10 +2146,10 @@
TextureDataType::kF32,
"textureSampleCompareLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_f); // depth_ref
},
/* returns value */ true,
},
@@ -2165,11 +2166,11 @@
TextureDataType::kF32,
"textureSampleCompareLevel",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- kSamplerName, // s
- b->vec3<f32>(1_f, 2_f, 3_f), // coords
- 4_i, // array_index
- 5_f); // depth_ref
+ return b->ExprList(kTextureName, // t
+ kSamplerName, // s
+ b->Call<vec3<f32>>(1_f, 2_f, 3_f), // coords
+ 4_i, // array_index
+ 5_f); // depth_ref
},
/* returns value */ true,
},
@@ -2231,9 +2232,9 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u); // level
},
/* returns value */ true,
},
@@ -2247,9 +2248,9 @@
TextureDataType::kU32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- 3_i); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ 3_i); // level
},
/* returns value */ true,
},
@@ -2263,9 +2264,9 @@
TextureDataType::kI32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u); // level
},
/* returns value */ true,
},
@@ -2280,10 +2281,10 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- 3_i, // array_index
- 4_i); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ 3_i, // array_index
+ 4_i); // level
},
/* returns value */ true,
},
@@ -2298,10 +2299,10 @@
TextureDataType::kU32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- 3_i, // array_index
- 4_i); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ 3_i, // array_index
+ 4_i); // level
},
/* returns value */ true,
},
@@ -2316,10 +2317,10 @@
TextureDataType::kI32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u, // array_index
- 4_u); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u, // array_index
+ 4_u); // level
},
/* returns value */ true,
},
@@ -2333,9 +2334,9 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec3<i32>(1_i, 2_i, 3_i), // coords
- 4_i); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec3<i32>>(1_i, 2_i, 3_i), // coords
+ 4_i); // level
},
/* returns value */ true,
},
@@ -2349,9 +2350,9 @@
TextureDataType::kU32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec3<i32>(1_i, 2_i, 3_i), // coords
- 4_i); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec3<i32>>(1_i, 2_i, 3_i), // coords
+ 4_i); // level
},
/* returns value */ true,
},
@@ -2365,9 +2366,9 @@
TextureDataType::kI32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec3<u32>(1_u, 2_u, 3_u), // coords
- 4_u); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec3<u32>>(1_u, 2_u, 3_u), // coords
+ 4_u); // level
},
/* returns value */ true,
},
@@ -2381,9 +2382,9 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- 3_i); // sample_index
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ 3_i); // sample_index
},
/* returns value */ true,
},
@@ -2397,9 +2398,9 @@
TextureDataType::kU32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- 3_i); // sample_index
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ 3_i); // sample_index
},
/* returns value */ true,
},
@@ -2413,9 +2414,9 @@
TextureDataType::kI32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u); // sample_index
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u); // sample_index
},
/* returns value */ true,
},
@@ -2429,9 +2430,9 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- 3_i); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ 3_i); // level
},
/* returns value */ true,
},
@@ -2446,10 +2447,10 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u, // array_index
- 4_u); // level
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u, // array_index
+ 4_u); // level
},
/* returns value */ true,
},
@@ -2463,9 +2464,9 @@
TextureDataType::kF32,
"textureLoad",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u); // sample_index
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u); // sample_index
},
/* returns value */ true,
},
@@ -2480,9 +2481,9 @@
TextureDataType::kF32,
"textureStore",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- 1_i, // coords
- b->vec4<f32>(2_f, 3_f, 4_f, 5_f)); // value
+ return b->ExprList(kTextureName, // t
+ 1_i, // coords
+ b->Call<vec4<f32>>(2_f, 3_f, 4_f, 5_f)); // value
},
/* returns value */ false,
},
@@ -2497,9 +2498,9 @@
TextureDataType::kF32,
"textureStore",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<i32>(1_i, 2_i), // coords
- b->vec4<f32>(3_f, 4_f, 5_f, 6_f)); // value
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<i32>>(1_i, 2_i), // coords
+ b->Call<vec4<f32>>(3_f, 4_f, 5_f, 6_f)); // value
},
/* returns value */ false,
},
@@ -2515,10 +2516,10 @@
TextureDataType::kF32,
"textureStore",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec2<u32>(1_u, 2_u), // coords
- 3_u, // array_index
- b->vec4<f32>(4_f, 5_f, 6_f, 7_f)); // value
+ return b->ExprList(kTextureName, // t
+ b->Call<vec2<u32>>(1_u, 2_u), // coords
+ 3_u, // array_index
+ b->Call<vec4<f32>>(4_f, 5_f, 6_f, 7_f)); // value
},
/* returns value */ false,
},
@@ -2533,9 +2534,9 @@
TextureDataType::kF32,
"textureStore",
[](ProgramBuilder* b) {
- return b->ExprList(kTextureName, // t
- b->vec3<u32>(1_u, 2_u, 3_u), // coords
- b->vec4<f32>(4_f, 5_f, 6_f, 7_f)); // value
+ return b->ExprList(kTextureName, // t
+ b->Call<vec3<u32>>(1_u, 2_u, 3_u), // coords
+ b->Call<vec4<f32>>(4_f, 5_f, 6_f, 7_f)); // value
},
/* returns value */ false,
},
diff --git a/src/tint/ast/index_attribute.cc b/src/tint/ast/index_attribute.cc
new file mode 100644
index 0000000..7916226
--- /dev/null
+++ b/src/tint/ast/index_attribute.cc
@@ -0,0 +1,41 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ast/index_attribute.h"
+
+#include <string>
+
+#include "src/tint/program_builder.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::IndexAttribute);
+
+namespace tint::ast {
+
+IndexAttribute::IndexAttribute(ProgramID pid, NodeID nid, const Source& src, const Expression* exp)
+ : Base(pid, nid, src), expr(exp) {}
+
+IndexAttribute::~IndexAttribute() = default;
+
+std::string IndexAttribute::Name() const {
+ return "index";
+}
+
+const IndexAttribute* IndexAttribute::Clone(CloneContext* ctx) const {
+ // Clone arguments outside of create() call to have deterministic ordering
+ auto src = ctx->Clone(source);
+ auto* expr_ = ctx->Clone(expr);
+ return ctx->dst->create<IndexAttribute>(src, expr_);
+}
+
+} // namespace tint::ast
diff --git a/src/tint/ast/index_attribute.h b/src/tint/ast/index_attribute.h
new file mode 100644
index 0000000..e241ba6
--- /dev/null
+++ b/src/tint/ast/index_attribute.h
@@ -0,0 +1,51 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_AST_INDEX_ATTRIBUTE_H_
+#define SRC_TINT_AST_INDEX_ATTRIBUTE_H_
+
+#include <string>
+
+#include "src/tint/ast/attribute.h"
+#include "src/tint/ast/expression.h"
+
+namespace tint::ast {
+
+/// An id attribute for pipeline-overridable constants
+class IndexAttribute final : public utils::Castable<IndexAttribute, Attribute> {
+ public:
+ /// Create an index attribute.
+ /// @param pid the identifier of the program that owns this node
+ /// @param nid the unique node identifier
+ /// @param src the source of this node
+ /// @param expr the numeric id expression
+ IndexAttribute(ProgramID pid, NodeID nid, const Source& src, const Expression* expr);
+ ~IndexAttribute() override;
+
+ /// @returns the WGSL name for the attribute
+ std::string Name() const override;
+
+ /// Clones this node and all transitive child nodes using the `CloneContext`
+ /// `ctx`.
+ /// @param ctx the clone context
+ /// @return the newly cloned node
+ const IndexAttribute* Clone(CloneContext* ctx) const override;
+
+ /// The id expression
+ const Expression* const expr;
+};
+
+} // namespace tint::ast
+
+#endif // SRC_TINT_AST_INDEX_ATTRIBUTE_H_
diff --git a/src/tint/ast/index_attribute_test.cc b/src/tint/ast/index_attribute_test.cc
new file mode 100644
index 0000000..bad37c6
--- /dev/null
+++ b/src/tint/ast/index_attribute_test.cc
@@ -0,0 +1,31 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ast/id_attribute.h"
+
+#include "src/tint/ast/test_helper.h"
+
+namespace tint::ast {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+using IndexAttributeTest = TestHelper;
+
+TEST_F(IndexAttributeTest, Creation) {
+ auto* d = Index(1_a);
+ EXPECT_TRUE(d->expr->Is<IntLiteralExpression>());
+}
+
+} // namespace
+} // namespace tint::ast
diff --git a/src/tint/ast/transform/builtin_polyfill.cc b/src/tint/ast/transform/builtin_polyfill.cc
index 05f5da9..75d91b3 100644
--- a/src/tint/ast/transform/builtin_polyfill.cc
+++ b/src/tint/ast/transform/builtin_polyfill.cc
@@ -29,7 +29,8 @@
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/map.h"
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::BuiltinPolyfill);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::BuiltinPolyfill::Config);
@@ -767,7 +768,7 @@
auto name = b.Symbols().New("tint_textureSampleBaseClampToEdge");
auto body = utils::Vector{
b.Decl(b.Let("dims", b.Call(b.ty.vec2<f32>(), b.Call("textureDimensions", "t", 0_a)))),
- b.Decl(b.Let("half_texel", b.Div(b.vec2<f32>(0.5_a), "dims"))),
+ b.Decl(b.Let("half_texel", b.Div(b.Call<vec2<f32>>(0.5_a), "dims"))),
b.Decl(
b.Let("clamped", b.Call("clamp", "coord", "half_texel", b.Sub(1_a, "half_texel")))),
b.Return(b.Call("textureSampleLevel", "t", "s", "clamped", 0_a)),
@@ -814,7 +815,7 @@
auto name = b.Symbols().New("tint_workgroupUniformLoad");
b.Func(name,
utils::Vector{
- b.Param("p", b.ty.ptr(builtin::AddressSpace::kWorkgroup, T(type))),
+ b.Param("p", b.ty.ptr<workgroup>(T(type))),
},
T(type),
utils::Vector{
diff --git a/src/tint/ast/transform/calculate_array_length.cc b/src/tint/ast/transform/calculate_array_length.cc
index 0e11ad4..9ce16da 100644
--- a/src/tint/ast/transform/calculate_array_length.cc
+++ b/src/tint/ast/transform/calculate_array_length.cc
@@ -35,12 +35,12 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::CalculateArrayLength);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::CalculateArrayLength::BufferSizeIntrinsic);
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::transform {
-
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
bool ShouldRun(const Program* program) {
for (auto* fn : program->AST().Functions()) {
if (auto* sem_fn = program->Sem().Get(fn)) {
@@ -112,7 +112,7 @@
b.Param("buffer",
b.ty.ptr(buffer_type->AddressSpace(), type, buffer_type->Access()),
utils::Vector{disable_validation}),
- b.Param("result", b.ty.ptr(builtin::AddressSpace::kFunction, b.ty.u32())),
+ b.Param("result", b.ty.ptr<function, u32>()),
},
b.ty.void_(), nullptr,
utils::Vector{
diff --git a/src/tint/ast/transform/decompose_strided_matrix_test.cc b/src/tint/ast/transform/decompose_strided_matrix_test.cc
index 4fa8017..f1646ff 100644
--- a/src/tint/ast/transform/decompose_strided_matrix_test.cc
+++ b/src/tint/ast/transform/decompose_strided_matrix_test.cc
@@ -24,11 +24,12 @@
#include "src/tint/ast/transform/unshadow.h"
#include "src/tint/program_builder.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::transform {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using DecomposeStridedMatrixTest = TransformTest;
TEST_F(DecomposeStridedMatrixTest, ShouldRunEmptyModule) {
@@ -356,15 +357,16 @@
});
b.GlobalVar("s", b.ty.Of(S), builtin::AddressSpace::kStorage, builtin::Access::kReadWrite,
b.Group(0_a), b.Binding(0_a));
- b.Func("f", utils::Empty, b.ty.void_(),
- utils::Vector{
- b.Assign(b.MemberAccessor("s", "m"),
- b.mat2x2<f32>(b.vec2<f32>(1_f, 2_f), b.vec2<f32>(3_f, 4_f))),
- },
- utils::Vector{
- b.Stage(PipelineStage::kCompute),
- b.WorkgroupSize(1_i),
- });
+ b.Func(
+ "f", utils::Empty, b.ty.void_(),
+ utils::Vector{
+ b.Assign(b.MemberAccessor("s", "m"),
+ b.Call<mat2x2<f32>>(b.Call<vec2<f32>>(1_f, 2_f), b.Call<vec2<f32>>(3_f, 4_f))),
+ },
+ utils::Vector{
+ b.Stage(PipelineStage::kCompute),
+ b.WorkgroupSize(1_i),
+ });
auto* expect = R"(
struct S {
@@ -415,14 +417,15 @@
});
b.GlobalVar("s", b.ty.Of(S), builtin::AddressSpace::kStorage, builtin::Access::kReadWrite,
b.Group(0_a), b.Binding(0_a));
- b.Func("f", utils::Empty, b.ty.void_(),
- utils::Vector{
- b.Assign(b.IndexAccessor(b.MemberAccessor("s", "m"), 1_i), b.vec2<f32>(1_f, 2_f)),
- },
- utils::Vector{
- b.Stage(PipelineStage::kCompute),
- b.WorkgroupSize(1_i),
- });
+ b.Func(
+ "f", utils::Empty, b.ty.void_(),
+ utils::Vector{
+ b.Assign(b.IndexAccessor(b.MemberAccessor("s", "m"), 1_i), b.Call<vec2<f32>>(1_f, 2_f)),
+ },
+ utils::Vector{
+ b.Stage(PipelineStage::kCompute),
+ b.WorkgroupSize(1_i),
+ });
auto* expect = R"(
struct S {
@@ -482,8 +485,9 @@
b.Decl(b.Let("x", b.Deref("b"))),
b.Decl(b.Let("y", b.IndexAccessor(b.Deref("b"), 1_i))),
b.Decl(b.Let("z", b.IndexAccessor("x", 1_i))),
- b.Assign(b.Deref("b"), b.mat2x2<f32>(b.vec2<f32>(1_f, 2_f), b.vec2<f32>(3_f, 4_f))),
- b.Assign(b.IndexAccessor(b.Deref("b"), 1_i), b.vec2<f32>(5_f, 6_f)),
+ b.Assign(b.Deref("b"), b.Call<mat2x2<f32>>(b.Call<vec2<f32>>(1_f, 2_f),
+ b.Call<vec2<f32>>(3_f, 4_f))),
+ b.Assign(b.IndexAccessor(b.Deref("b"), 1_i), b.Call<vec2<f32>>(5_f, 6_f)),
},
utils::Vector{
b.Stage(PipelineStage::kCompute),
@@ -600,15 +604,16 @@
}),
});
b.GlobalVar("s", b.ty.Of(S), builtin::AddressSpace::kPrivate);
- b.Func("f", utils::Empty, b.ty.void_(),
- utils::Vector{
- b.Assign(b.MemberAccessor("s", "m"),
- b.mat2x2<f32>(b.vec2<f32>(1_f, 2_f), b.vec2<f32>(3_f, 4_f))),
- },
- utils::Vector{
- b.Stage(PipelineStage::kCompute),
- b.WorkgroupSize(1_i),
- });
+ b.Func(
+ "f", utils::Empty, b.ty.void_(),
+ utils::Vector{
+ b.Assign(b.MemberAccessor("s", "m"),
+ b.Call<mat2x2<f32>>(b.Call<vec2<f32>>(1_f, 2_f), b.Call<vec2<f32>>(3_f, 4_f))),
+ },
+ utils::Vector{
+ b.Stage(PipelineStage::kCompute),
+ b.WorkgroupSize(1_i),
+ });
auto* expect = R"(
struct S {
diff --git a/src/tint/ast/transform/module_scope_var_to_entry_point_param.cc b/src/tint/ast/transform/module_scope_var_to_entry_point_param.cc
index db06414..14112f0 100644
--- a/src/tint/ast/transform/module_scope_var_to_entry_point_param.cc
+++ b/src/tint/ast/transform/module_scope_var_to_entry_point_param.cc
@@ -30,6 +30,8 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::ModuleScopeVarToEntryPointParam);
+using namespace tint::builtin::fluent_types; // NOLINT
+
namespace tint::ast::transform {
namespace {
@@ -183,9 +185,7 @@
auto* member_ptr = ctx.dst->AddressOf(
ctx.dst->MemberAccessor(ctx.dst->Deref(workgroup_param()), member));
auto* local_var = ctx.dst->Let(
- new_var_symbol,
- ctx.dst->ty.ptr(builtin::AddressSpace::kWorkgroup, store_type()),
- member_ptr);
+ new_var_symbol, ctx.dst->ty.ptr<workgroup>(store_type()), member_ptr);
ctx.InsertFront(func->body->statements, ctx.dst->Decl(local_var));
is_pointer = true;
} else {
@@ -427,8 +427,7 @@
}
} else {
// Create a parameter that is a pointer to the private variable struct.
- auto ptr = ctx.dst->ty.ptr(builtin::AddressSpace::kPrivate,
- ctx.dst->ty(PrivateStructName()));
+ auto ptr = ctx.dst->ty.ptr<private_>(ctx.dst->ty(PrivateStructName()));
auto* param = ctx.dst->Param(PrivateStructVariableName(), ptr);
ctx.InsertBack(func_ast->params, param);
}
@@ -489,8 +488,7 @@
// The parameter is a struct that contains members for each workgroup variable.
auto* str =
ctx.dst->Structure(ctx.dst->Sym(), std::move(workgroup_parameter_members));
- auto param_type =
- ctx.dst->ty.ptr(builtin::AddressSpace::kWorkgroup, ctx.dst->ty.Of(str));
+ auto param_type = ctx.dst->ty.ptr(workgroup, ctx.dst->ty.Of(str));
auto* param =
ctx.dst->Param(workgroup_param(), param_type,
utils::Vector{
diff --git a/src/tint/ast/transform/multiplanar_external_texture.cc b/src/tint/ast/transform/multiplanar_external_texture.cc
index 87844f8..db1ae5a 100644
--- a/src/tint/ast/transform/multiplanar_external_texture.cc
+++ b/src/tint/ast/transform/multiplanar_external_texture.cc
@@ -27,11 +27,12 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::MultiplanarExternalTexture);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::MultiplanarExternalTexture::NewBindingPoints);
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::transform {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
bool ShouldRun(const Program* program) {
auto ext = program->Types().Find<type::ExternalTexture>();
return ext != nullptr;
@@ -270,34 +271,35 @@
void createGammaCorrectionFn() {
gamma_correction_sym = b.Symbols().New("gammaCorrection");
- b.Func(
- gamma_correction_sym,
- utils::Vector{
- b.Param("v", b.ty.vec3<f32>()),
- b.Param("params", b.ty(gamma_transfer_struct_sym)),
- },
- b.ty.vec3<f32>(),
- utils::Vector{
- // let cond = abs(v) < vec3(params.D);
- b.Decl(b.Let("cond", b.LessThan(b.Call("abs", "v"),
- b.vec3<f32>(b.MemberAccessor("params", "D"))))),
- // let t = sign(v) * ((params.C * abs(v)) + params.F);
- b.Decl(b.Let("t",
- b.Mul(b.Call("sign", "v"),
- b.Add(b.Mul(b.MemberAccessor("params", "C"), b.Call("abs", "v")),
- b.MemberAccessor("params", "F"))))),
- // let f = (sign(v) * pow(((params.A * abs(v)) + params.B),
- // vec3(params.G))) + params.E;
- b.Decl(b.Let("f", b.Mul(b.Call("sign", "v"),
- b.Add(b.Call("pow",
- b.Add(b.Mul(b.MemberAccessor("params", "A"),
- b.Call("abs", "v")),
- b.MemberAccessor("params", "B")),
- b.vec3<f32>(b.MemberAccessor("params", "G"))),
- b.MemberAccessor("params", "E"))))),
- // return select(f, t, cond);
- b.Return(b.Call("select", "f", "t", "cond")),
- });
+ b.Func(gamma_correction_sym,
+ utils::Vector{
+ b.Param("v", b.ty.vec3<f32>()),
+ b.Param("params", b.ty(gamma_transfer_struct_sym)),
+ },
+ b.ty.vec3<f32>(),
+ utils::Vector{
+ // let cond = abs(v) < vec3(params.D);
+ b.Decl(b.Let("cond",
+ b.LessThan(b.Call("abs", "v"),
+ b.Call<vec3<f32>>(b.MemberAccessor("params", "D"))))),
+ // let t = sign(v) * ((params.C * abs(v)) + params.F);
+ b.Decl(b.Let(
+ "t", b.Mul(b.Call("sign", "v"),
+ b.Add(b.Mul(b.MemberAccessor("params", "C"), b.Call("abs", "v")),
+ b.MemberAccessor("params", "F"))))),
+ // let f = (sign(v) * pow(((params.A * abs(v)) + params.B),
+ // vec3(params.G))) + params.E;
+ b.Decl(b.Let(
+ "f", b.Mul(b.Call("sign", "v"),
+ b.Add(b.Call("pow",
+ b.Add(b.Mul(b.MemberAccessor("params", "A"),
+ b.Call("abs", "v")),
+ b.MemberAccessor("params", "B")),
+ b.Call<vec3<f32>>(b.MemberAccessor("params", "G"))),
+ b.MemberAccessor("params", "E"))))),
+ // return select(f, t, cond);
+ b.Return(b.Call("select", "f", "t", "cond")),
+ });
}
/// Constructs a StatementList containing all the statements making up the body of the texture
@@ -313,21 +315,21 @@
case builtin::Function::kTextureSampleBaseClampToEdge:
stmts.Push(b.Decl(b.Let(
"modifiedCoords", b.Mul(b.MemberAccessor("params", "coordTransformationMatrix"),
- b.vec3<f32>("coord", 1_a)))));
+ b.Call<vec3<f32>>("coord", 1_a)))));
stmts.Push(b.Decl(
b.Let("plane0_dims",
b.Call(b.ty.vec2<f32>(), b.Call("textureDimensions", "plane0", 0_a)))));
- stmts.Push(
- b.Decl(b.Let("plane0_half_texel", b.Div(b.vec2<f32>(0.5_a), "plane0_dims"))));
+ stmts.Push(b.Decl(
+ b.Let("plane0_half_texel", b.Div(b.Call<vec2<f32>>(0.5_a), "plane0_dims"))));
stmts.Push(b.Decl(
b.Let("plane0_clamped", b.Call("clamp", "modifiedCoords", "plane0_half_texel",
b.Sub(1_a, "plane0_half_texel")))));
stmts.Push(b.Decl(
b.Let("plane1_dims",
b.Call(b.ty.vec2<f32>(), b.Call("textureDimensions", "plane1", 0_a)))));
- stmts.Push(
- b.Decl(b.Let("plane1_half_texel", b.Div(b.vec2<f32>(0.5_a), "plane1_dims"))));
+ stmts.Push(b.Decl(
+ b.Let("plane1_half_texel", b.Div(b.Call<vec2<f32>>(0.5_a), "plane1_dims"))));
stmts.Push(b.Decl(
b.Let("plane1_clamped", b.Call("clamp", "modifiedCoords", "plane1_half_texel",
b.Sub(1_a, "plane1_half_texel")))));
@@ -346,7 +348,7 @@
// textureLoad(plane0, coord, 0);
plane_0_call = b.Call("textureLoad", "plane0", "coord", 0_a);
// let coord1 = coord >> 1;
- stmts.Push(b.Decl(b.Let("coord1", b.Shr("coord", b.vec2<u32>(1_a)))));
+ stmts.Push(b.Decl(b.Let("coord1", b.Shr("coord", b.Call<vec2<u32>>(1_a)))));
// textureLoad(plane1, coord1, 0);
plane_1_call = b.Call("textureLoad", "plane1", "coord1", 0_a);
break;
@@ -367,8 +369,8 @@
// color = vec4<f32>(plane_0_call.r, plane_1_call.rg, 1.0) *
// params.yuvToRgbConversionMatrix;
b.Assign("color",
- b.Mul(b.vec4<f32>(b.MemberAccessor(plane_0_call, "r"),
- b.MemberAccessor(plane_1_call, "rg"), 1_a),
+ b.Mul(b.Call<vec4<f32>>(b.MemberAccessor(plane_0_call, "r"),
+ b.MemberAccessor(plane_1_call, "rg"), 1_a),
b.MemberAccessor("params", "yuvToRgbConversionMatrix")))))));
// if (params.doYuvToRgbConversionOnly == 0u)
@@ -386,7 +388,7 @@
b.MemberAccessor("params", "gammaEncodeParams"))))));
// return vec4<f32>(color, 1.f);
- stmts.Push(b.Return(b.vec4<f32>("color", 1_a)));
+ stmts.Push(b.Return(b.Call<vec4<f32>>("color", 1_a)));
return stmts;
}
diff --git a/src/tint/ast/transform/preserve_padding.cc b/src/tint/ast/transform/preserve_padding.cc
index 7d9143c..3f51fa4 100644
--- a/src/tint/ast/transform/preserve_padding.cc
+++ b/src/tint/ast/transform/preserve_padding.cc
@@ -26,10 +26,11 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::PreservePadding);
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::transform {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
PreservePadding::PreservePadding() = default;
PreservePadding::~PreservePadding() = default;
@@ -122,8 +123,7 @@
auto helper_name = b.Symbols().New("assign_and_preserve_padding");
utils::Vector<const Parameter*, 2> params = {
b.Param(kDestParamName,
- b.ty.ptr(builtin::AddressSpace::kStorage, CreateASTTypeFor(ctx, ty),
- builtin::Access::kReadWrite)),
+ b.ty.ptr<storage, read_write>(CreateASTTypeFor(ctx, ty))),
b.Param(kValueParamName, CreateASTTypeFor(ctx, ty)),
};
b.Func(helper_name, params, b.ty.void_(), body());
diff --git a/src/tint/ast/transform/robustness.cc b/src/tint/ast/transform/robustness.cc
index aa94748..e0cb752 100644
--- a/src/tint/ast/transform/robustness.cc
+++ b/src/tint/ast/transform/robustness.cc
@@ -35,10 +35,11 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::Robustness);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::Robustness::Config);
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::transform {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
/// PIMPL state for the transform
struct Robustness::State {
/// Constructor
diff --git a/src/tint/ast/transform/vertex_pulling.cc b/src/tint/ast/transform/vertex_pulling.cc
index c2a543e..54cb8c0 100644
--- a/src/tint/ast/transform/vertex_pulling.cc
+++ b/src/tint/ast/transform/vertex_pulling.cc
@@ -32,10 +32,11 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::VertexPulling);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::VertexPulling::Config);
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::ast::transform {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
namespace {
/// The base WGSL type of a component.
@@ -576,71 +577,71 @@
case VertexFormat::kUint8x2: {
// yyxx0000, yyxx0000
- auto* u16s = b.vec2<u32>(load_u16_h());
+ auto* u16s = b.Call<vec2<u32>>(load_u16_h());
// xx000000, yyxx0000
- auto* shl = b.Shl(u16s, b.vec2<u32>(8_u, 0_u));
+ auto* shl = b.Shl(u16s, b.Call<vec2<u32>>(8_u, 0_u));
// 000000xx, 000000yy
- return b.Shr(shl, b.vec2<u32>(24_u));
+ return b.Shr(shl, b.Call<vec2<u32>>(24_u));
}
case VertexFormat::kUint8x4: {
// wwzzyyxx, wwzzyyxx, wwzzyyxx, wwzzyyxx
- auto* u32s = b.vec4<u32>(load_u32());
+ auto* u32s = b.Call<vec4<u32>>(load_u32());
// xx000000, yyxx0000, zzyyxx00, wwzzyyxx
- auto* shl = b.Shl(u32s, b.vec4<u32>(24_u, 16_u, 8_u, 0_u));
+ auto* shl = b.Shl(u32s, b.Call<vec4<u32>>(24_u, 16_u, 8_u, 0_u));
// 000000xx, 000000yy, 000000zz, 000000ww
- return b.Shr(shl, b.vec4<u32>(24_u));
+ return b.Shr(shl, b.Call<vec4<u32>>(24_u));
}
case VertexFormat::kUint16x2: {
// yyyyxxxx, yyyyxxxx
- auto* u32s = b.vec2<u32>(load_u32());
+ auto* u32s = b.Call<vec2<u32>>(load_u32());
// xxxx0000, yyyyxxxx
- auto* shl = b.Shl(u32s, b.vec2<u32>(16_u, 0_u));
+ auto* shl = b.Shl(u32s, b.Call<vec2<u32>>(16_u, 0_u));
// 0000xxxx, 0000yyyy
- return b.Shr(shl, b.vec2<u32>(16_u));
+ return b.Shr(shl, b.Call<vec2<u32>>(16_u));
}
case VertexFormat::kUint16x4: {
// yyyyxxxx, wwwwzzzz
- auto* u32s = b.vec2<u32>(load_u32(), load_next_u32());
+ auto* u32s = b.Call<vec2<u32>>(load_u32(), load_next_u32());
// yyyyxxxx, yyyyxxxx, wwwwzzzz, wwwwzzzz
auto* xxyy = b.MemberAccessor(u32s, "xxyy");
// xxxx0000, yyyyxxxx, zzzz0000, wwwwzzzz
- auto* shl = b.Shl(xxyy, b.vec4<u32>(16_u, 0_u, 16_u, 0_u));
+ auto* shl = b.Shl(xxyy, b.Call<vec4<u32>>(16_u, 0_u, 16_u, 0_u));
// 0000xxxx, 0000yyyy, 0000zzzz, 0000wwww
- return b.Shr(shl, b.vec4<u32>(16_u));
+ return b.Shr(shl, b.Call<vec4<u32>>(16_u));
}
case VertexFormat::kSint8x2: {
// yyxx0000, yyxx0000
- auto* i16s = b.vec2<i32>(load_i16_h());
+ auto* i16s = b.Call<vec2<i32>>(load_i16_h());
// xx000000, yyxx0000
- auto* shl = b.Shl(i16s, b.vec2<u32>(8_u, 0_u));
+ auto* shl = b.Shl(i16s, b.Call<vec2<u32>>(8_u, 0_u));
// ssssssxx, ssssssyy
- return b.Shr(shl, b.vec2<u32>(24_u));
+ return b.Shr(shl, b.Call<vec2<u32>>(24_u));
}
case VertexFormat::kSint8x4: {
// wwzzyyxx, wwzzyyxx, wwzzyyxx, wwzzyyxx
- auto* i32s = b.vec4<i32>(load_i32());
+ auto* i32s = b.Call<vec4<i32>>(load_i32());
// xx000000, yyxx0000, zzyyxx00, wwzzyyxx
- auto* shl = b.Shl(i32s, b.vec4<u32>(24_u, 16_u, 8_u, 0_u));
+ auto* shl = b.Shl(i32s, b.Call<vec4<u32>>(24_u, 16_u, 8_u, 0_u));
// ssssssxx, ssssssyy, sssssszz, ssssssww
- return b.Shr(shl, b.vec4<u32>(24_u));
+ return b.Shr(shl, b.Call<vec4<u32>>(24_u));
}
case VertexFormat::kSint16x2: {
// yyyyxxxx, yyyyxxxx
- auto* i32s = b.vec2<i32>(load_i32());
+ auto* i32s = b.Call<vec2<i32>>(load_i32());
// xxxx0000, yyyyxxxx
- auto* shl = b.Shl(i32s, b.vec2<u32>(16_u, 0_u));
+ auto* shl = b.Shl(i32s, b.Call<vec2<u32>>(16_u, 0_u));
// ssssxxxx, ssssyyyy
- return b.Shr(shl, b.vec2<u32>(16_u));
+ return b.Shr(shl, b.Call<vec2<u32>>(16_u));
}
case VertexFormat::kSint16x4: {
// yyyyxxxx, wwwwzzzz
- auto* i32s = b.vec2<i32>(load_i32(), load_next_i32());
+ auto* i32s = b.Call<vec2<i32>>(load_i32(), load_next_i32());
// yyyyxxxx, yyyyxxxx, wwwwzzzz, wwwwzzzz
auto* xxyy = b.MemberAccessor(i32s, "xxyy");
// xxxx0000, yyyyxxxx, zzzz0000, wwwwzzzz
- auto* shl = b.Shl(xxyy, b.vec4<u32>(16_u, 0_u, 16_u, 0_u));
+ auto* shl = b.Shl(xxyy, b.Call<vec4<u32>>(16_u, 0_u, 16_u, 0_u));
// ssssxxxx, ssssyyyy, sssszzzz, sssswwww
- return b.Shr(shl, b.vec4<u32>(16_u));
+ return b.Shr(shl, b.Call<vec4<u32>>(16_u));
}
case VertexFormat::kUnorm8x2:
return b.MemberAccessor(b.Call("unpack4x8unorm", load_u16_l()), "xy");
@@ -657,14 +658,14 @@
case VertexFormat::kFloat16x2:
return b.Call("unpack2x16float", load_u32());
case VertexFormat::kUnorm16x4:
- return b.vec4<f32>(b.Call("unpack2x16unorm", load_u32()),
- b.Call("unpack2x16unorm", load_next_u32()));
+ return b.Call<vec4<f32>>(b.Call("unpack2x16unorm", load_u32()),
+ b.Call("unpack2x16unorm", load_next_u32()));
case VertexFormat::kSnorm16x4:
- return b.vec4<f32>(b.Call("unpack2x16snorm", load_u32()),
- b.Call("unpack2x16snorm", load_next_u32()));
+ return b.Call<vec4<f32>>(b.Call("unpack2x16snorm", load_u32()),
+ b.Call("unpack2x16snorm", load_next_u32()));
case VertexFormat::kFloat16x4:
- return b.vec4<f32>(b.Call("unpack2x16float", load_u32()),
- b.Call("unpack2x16float", load_next_u32()));
+ return b.Call<vec4<f32>>(b.Call("unpack2x16float", load_u32()),
+ b.Call("unpack2x16float", load_next_u32()));
}
TINT_UNREACHABLE(Transform, b.Diagnostics()) << "format " << static_cast<int>(format);
diff --git a/src/tint/builtin/attribute.cc b/src/tint/builtin/attribute.cc
index 33a5171..0647825 100644
--- a/src/tint/builtin/attribute.cc
+++ b/src/tint/builtin/attribute.cc
@@ -52,6 +52,9 @@
if (str == "id") {
return Attribute::kId;
}
+ if (str == "index") {
+ return Attribute::kIndex;
+ }
if (str == "interpolate") {
return Attribute::kInterpolate;
}
@@ -96,6 +99,8 @@
return out << "group";
case Attribute::kId:
return out << "id";
+ case Attribute::kIndex:
+ return out << "index";
case Attribute::kInterpolate:
return out << "interpolate";
case Attribute::kInvariant:
diff --git a/src/tint/builtin/attribute.h b/src/tint/builtin/attribute.h
index c975267..f9a1868 100644
--- a/src/tint/builtin/attribute.h
+++ b/src/tint/builtin/attribute.h
@@ -41,6 +41,7 @@
kFragment,
kGroup,
kId,
+ kIndex,
kInterpolate,
kInvariant,
kLocation,
@@ -61,9 +62,9 @@
Attribute ParseAttribute(std::string_view str);
constexpr const char* kAttributeStrings[] = {
- "align", "binding", "builtin", "compute", "diagnostic",
- "fragment", "group", "id", "interpolate", "invariant",
- "location", "must_use", "size", "vertex", "workgroup_size",
+ "align", "binding", "builtin", "compute", "diagnostic", "fragment",
+ "group", "id", "index", "interpolate", "invariant", "location",
+ "must_use", "size", "vertex", "workgroup_size",
};
} // namespace tint::builtin
diff --git a/src/tint/builtin/attribute_bench.cc b/src/tint/builtin/attribute_bench.cc
index a25fbf1..267a905 100644
--- a/src/tint/builtin/attribute_bench.cc
+++ b/src/tint/builtin/attribute_bench.cc
@@ -87,55 +87,62 @@
"i",
"rrd",
"iG",
- "FFnterpolate",
- "iEtrplat",
- "inerporrate",
+ "inFFex",
+ "iE",
+ "inrrx",
+ "index",
+ "inx",
+ "inJJD",
+ "ie",
+ "inerpklae",
+ "intrpolate",
+ "inJerpolae",
"interpolate",
- "inteplate",
- "XterJJoDate",
- "inepol8t",
- "nvark1n",
- "invriant",
- "Jnvarant",
+ "interpocate",
+ "interpolaOe",
+ "__nttevvpoKKate",
+ "xnvari5n8",
+ "inFq__ant",
+ "iqqariant",
"invariant",
- "invaricnt",
- "invariaOt",
- "invttKK_ianvv",
- "lxxcati8",
- "Focqq__o",
- "locaiqqn",
+ "invar6a33O",
+ "i96arQttanoo",
+ "inari66nt",
+ "lOxati6zz",
+ "locyytion",
+ "lHHtion",
"location",
- "loc33tio6",
- "ltto6at9QQn",
- "loc66tio",
- "mOxt_u6zz",
- "musyy_use",
- "mHH_use",
+ "qWW4caton",
+ "locOOton",
+ "ocatiYn",
+ "m_use",
+ "mutFuse",
+ "wust_us",
"must_use",
- "qWW4st_se",
- "musOO_se",
- "ust_uYe",
- "i",
- "Fie",
- "siw",
+ "Kst_sff",
+ "qusKK_use",
+ "mFsmm_3se",
+ "ize",
+ "sze",
+ "sbbb",
"size",
- "zff",
- "sizqK",
- "s3zmm",
- "ertex",
- "vereq",
- "vbtbbx",
+ "iie",
+ "siqe",
+ "svvTTe",
+ "vertFFx",
+ "vrQ00P",
+ "vePtex",
"vertex",
- "irtex",
- "vOOteq",
- "vertTvvx",
- "woFFkgroup_size",
- "wfr00grPupsiQe",
- "workgrouP_size",
+ "vsste77",
+ "veCtRRbb",
+ "verteXX",
+ "workgqou_siCCOOO",
+ "worsgroupsuzL",
+ "wXrkgroup_size",
"workgroup_size",
- "workgroup77sise",
- "RRobbkgroupCsize",
- "wXXrkgroup_size",
+ "workgroup_sze",
+ "wqqrOgoupize",
+ "workg22oup_size",
};
for (auto _ : state) {
for (auto* str : kStrings) {
diff --git a/src/tint/builtin/attribute_test.cc b/src/tint/builtin/attribute_test.cc
index 9919467..33f557e 100644
--- a/src/tint/builtin/attribute_test.cc
+++ b/src/tint/builtin/attribute_test.cc
@@ -43,21 +43,14 @@
}
static constexpr Case kValidCases[] = {
- {"align", Attribute::kAlign},
- {"binding", Attribute::kBinding},
- {"builtin", Attribute::kBuiltin},
- {"compute", Attribute::kCompute},
- {"diagnostic", Attribute::kDiagnostic},
- {"fragment", Attribute::kFragment},
- {"group", Attribute::kGroup},
- {"id", Attribute::kId},
- {"interpolate", Attribute::kInterpolate},
- {"invariant", Attribute::kInvariant},
- {"location", Attribute::kLocation},
- {"must_use", Attribute::kMustUse},
- {"size", Attribute::kSize},
- {"vertex", Attribute::kVertex},
- {"workgroup_size", Attribute::kWorkgroupSize},
+ {"align", Attribute::kAlign}, {"binding", Attribute::kBinding},
+ {"builtin", Attribute::kBuiltin}, {"compute", Attribute::kCompute},
+ {"diagnostic", Attribute::kDiagnostic}, {"fragment", Attribute::kFragment},
+ {"group", Attribute::kGroup}, {"id", Attribute::kId},
+ {"index", Attribute::kIndex}, {"interpolate", Attribute::kInterpolate},
+ {"invariant", Attribute::kInvariant}, {"location", Attribute::kLocation},
+ {"must_use", Attribute::kMustUse}, {"size", Attribute::kSize},
+ {"vertex", Attribute::kVertex}, {"workgroup_size", Attribute::kWorkgroupSize},
};
static constexpr Case kInvalidCases[] = {
@@ -85,27 +78,30 @@
{"d", Attribute::kUndefined},
{"i", Attribute::kUndefined},
{"OVd", Attribute::kUndefined},
- {"inyerpolae", Attribute::kUndefined},
- {"rrnterpolll77Ge", Attribute::kUndefined},
- {"inte4pol00te", Attribute::kUndefined},
- {"inoornt", Attribute::kUndefined},
- {"inzzriat", Attribute::kUndefined},
- {"n11pariiin", Attribute::kUndefined},
- {"XXocation", Attribute::kUndefined},
- {"lIIc9955nnon", Attribute::kUndefined},
- {"aaoHHatioYSS", Attribute::kUndefined},
- {"mkksue", Attribute::kUndefined},
- {"gjs_RRs", Attribute::kUndefined},
- {"msb_se", Attribute::kUndefined},
- {"jize", Attribute::kUndefined},
- {"sze", Attribute::kUndefined},
- {"qz", Attribute::kUndefined},
- {"vNNtex", Attribute::kUndefined},
- {"vevvx", Attribute::kUndefined},
- {"veQQex", Attribute::kUndefined},
- {"workgrrupffie", Attribute::kUndefined},
- {"workgroup_sije", Attribute::kUndefined},
- {"workgoupNNwsiz8", Attribute::kUndefined},
+ {"ndyx", Attribute::kUndefined},
+ {"n77rrldGx", Attribute::kUndefined},
+ {"inde40", Attribute::kUndefined},
+ {"itooolate", Attribute::kUndefined},
+ {"intezplate", Attribute::kUndefined},
+ {"ppnerii1olat", Attribute::kUndefined},
+ {"invarianXX", Attribute::kUndefined},
+ {"inv55ria99nII", Attribute::kUndefined},
+ {"irrvariaSSaHH", Attribute::kUndefined},
+ {"lkkcin", Attribute::kUndefined},
+ {"gjctRRo", Attribute::kUndefined},
+ {"lcbton", Attribute::kUndefined},
+ {"mustjuse", Attribute::kUndefined},
+ {"must_se", Attribute::kUndefined},
+ {"muquse", Attribute::kUndefined},
+ {"szNN", Attribute::kUndefined},
+ {"zvv", Attribute::kUndefined},
+ {"QQze", Attribute::kUndefined},
+ {"eterf", Attribute::kUndefined},
+ {"vertjx", Attribute::kUndefined},
+ {"v82wNNx", Attribute::kUndefined},
+ {"worgroup_size", Attribute::kUndefined},
+ {"workgrourr_size", Attribute::kUndefined},
+ {"workgroGp_size", Attribute::kUndefined},
};
using AttributeParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/builtin/extension.cc b/src/tint/builtin/extension.cc
index aca6220..a8d4567 100644
--- a/src/tint/builtin/extension.cc
+++ b/src/tint/builtin/extension.cc
@@ -40,6 +40,9 @@
if (str == "chromium_experimental_push_constant") {
return Extension::kChromiumExperimentalPushConstant;
}
+ if (str == "chromium_internal_dual_source_blending") {
+ return Extension::kChromiumInternalDualSourceBlending;
+ }
if (str == "chromium_internal_relaxed_uniform_layout") {
return Extension::kChromiumInternalRelaxedUniformLayout;
}
@@ -61,6 +64,8 @@
return out << "chromium_experimental_full_ptr_parameters";
case Extension::kChromiumExperimentalPushConstant:
return out << "chromium_experimental_push_constant";
+ case Extension::kChromiumInternalDualSourceBlending:
+ return out << "chromium_internal_dual_source_blending";
case Extension::kChromiumInternalRelaxedUniformLayout:
return out << "chromium_internal_relaxed_uniform_layout";
case Extension::kF16:
diff --git a/src/tint/builtin/extension.h b/src/tint/builtin/extension.h
index 6beeda3..6883f4b 100644
--- a/src/tint/builtin/extension.h
+++ b/src/tint/builtin/extension.h
@@ -36,6 +36,7 @@
kChromiumExperimentalDp4A,
kChromiumExperimentalFullPtrParameters,
kChromiumExperimentalPushConstant,
+ kChromiumInternalDualSourceBlending,
kChromiumInternalRelaxedUniformLayout,
kF16,
};
@@ -51,9 +52,13 @@
Extension ParseExtension(std::string_view str);
constexpr const char* kExtensionStrings[] = {
- "chromium_disable_uniformity_analysis", "chromium_experimental_dp4a",
- "chromium_experimental_full_ptr_parameters", "chromium_experimental_push_constant",
- "chromium_internal_relaxed_uniform_layout", "f16",
+ "chromium_disable_uniformity_analysis",
+ "chromium_experimental_dp4a",
+ "chromium_experimental_full_ptr_parameters",
+ "chromium_experimental_push_constant",
+ "chromium_internal_dual_source_blending",
+ "chromium_internal_relaxed_uniform_layout",
+ "f16",
};
// A unique vector of extensions
diff --git a/src/tint/builtin/extension_bench.cc b/src/tint/builtin/extension_bench.cc
index 7a50281..447bf55 100644
--- a/src/tint/builtin/extension_bench.cc
+++ b/src/tint/builtin/extension_bench.cc
@@ -59,20 +59,27 @@
"chromium_exp9rimFntal_ush_constant",
"chrmium_experimental_push_constant",
"cOOromium_experiVeHtal_puh_conRRtant",
- "chromium_internl_relaxyd_uniform_layout",
- "chromnnum_internrr77_Gelaxell_uniform_layout",
- "chromium_intern4l_relaxe00_uniform_layout",
+ "chromium_internay_dual_sorce_blending",
+ "chrnnmium_internal_duGrr_source_bllend77ng",
+ "chromiu4_inter00al_dual_source_blending",
+ "chromium_internal_dual_source_blending",
+ "chromium_intoornal_dua_sorce_bleding",
+ "cromium_nternal_dual_sourcezzblending",
+ "chiiomiu_internal_dppal_source11blendig",
+ "XXhromium_internal_relaxed_uniform_layout",
+ "chromium_99nternal_reIInaxed_un55form_layout",
+ "chromYuaaSSinternrrl_rHHlaxed_uniform_layout",
"chromium_internal_relaxed_uniform_layout",
- "chrmoom_internal_relaxed_uniform_lyout",
- "chroium_internal_rlaxed_uniform_layzzut",
- "chromium_internaii_r11axed_uppifor_layout",
- "f1XX",
- "55199II",
- "frSSHHa",
+ "chroiHm_internal_rkklaxd_uniform_layou",
+ "chromium_internl_relaxedguniRRorm_lajou",
+ "chromium_inernal_relaxedbuniorm_layout",
+ "fj6",
+ "f6",
+ "q",
"f16",
- "U",
- "jV3",
- "",
+ "fNN",
+ "fv",
+ "Q16",
};
for (auto _ : state) {
for (auto* str : kStrings) {
diff --git a/src/tint/builtin/extension_test.cc b/src/tint/builtin/extension_test.cc
index 9ef8683..cc13b13 100644
--- a/src/tint/builtin/extension_test.cc
+++ b/src/tint/builtin/extension_test.cc
@@ -48,6 +48,7 @@
{"chromium_experimental_full_ptr_parameters",
Extension::kChromiumExperimentalFullPtrParameters},
{"chromium_experimental_push_constant", Extension::kChromiumExperimentalPushConstant},
+ {"chromium_internal_dual_source_blending", Extension::kChromiumInternalDualSourceBlending},
{"chromium_internal_relaxed_uniform_layout", Extension::kChromiumInternalRelaxedUniformLayout},
{"f16", Extension::kF16},
};
@@ -65,12 +66,15 @@
{"chvomium_experimental_push_constiint", Extension::kUndefined},
{"chromiu8WWexperimental_push_constant", Extension::kUndefined},
{"chromium_experiMental_push_costanxx", Extension::kUndefined},
- {"chromium_internal_relaxed_unXform_layugg", Extension::kUndefined},
- {"chromiuu_iVterna_relxed_unifXrm_layout", Extension::kUndefined},
- {"chromium_internal_relaxed_uni3orm_layout", Extension::kUndefined},
- {"fE6", Extension::kUndefined},
- {"fPTT", Extension::kUndefined},
- {"dxx6", Extension::kUndefined},
+ {"Xhromium_ggnternal_dual_sourceblending", Extension::kUndefined},
+ {"chromium_internludual_sorce_bVenXing", Extension::kUndefined},
+ {"chromium_internal_dual_source_b3ending", Extension::kUndefined},
+ {"chromium_internal_rElaxed_uniform_layout", Extension::kUndefined},
+ {"chromium_internalPPrTTlaed_uniform_layout", Extension::kUndefined},
+ {"chroddium_internxxl_relaxed_unform_layout", Extension::kUndefined},
+ {"4416", Extension::kUndefined},
+ {"fSVV6", Extension::kUndefined},
+ {"RR2", Extension::kUndefined},
};
using ExtensionParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/builtin/fluent_types.h b/src/tint/builtin/fluent_types.h
new file mode 100644
index 0000000..925b54e
--- /dev/null
+++ b/src/tint/builtin/fluent_types.h
@@ -0,0 +1,237 @@
+// 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_BUILTIN_FLUENT_TYPES_H_
+#define SRC_TINT_BUILTIN_FLUENT_TYPES_H_
+
+#include <stdint.h>
+
+#include "src/tint/builtin/access.h"
+#include "src/tint/builtin/address_space.h"
+#include "src/tint/builtin/number.h"
+
+namespace tint::builtin::fluent_types {
+
+// A sentinel type used by some template arguments to signal that the a type should be inferred.
+struct Infer {};
+
+/// A 'fluent' type helper used to construct an ast::Array or type::Array.
+/// @tparam T the array element type
+/// @tparam N the array length. 0 represents a runtime-sized array.
+/// @see https://www.w3.org/TR/WGSL/#array-types
+template <typename T = Infer, uint32_t N = 0>
+struct array {
+ /// the array element type
+ using type = T;
+ /// the array length. 0 represents a runtime-sized array.
+ static constexpr uint32_t length = N;
+};
+
+/// A 'fluent' type helper used to construct an ast::Atomic or type::Atomic.
+/// @tparam T the atomic element type
+/// @see https://www.w3.org/TR/WGSL/#atomic-types
+template <typename T>
+struct atomic {
+ /// the atomic element type
+ using type = T;
+};
+
+/// A 'fluent' type helper used to construct an ast::Vector or type::Vector.
+/// @tparam N the vector width
+/// @tparam T the vector element type
+template <uint32_t N, typename T = Infer>
+struct vec {
+ /// the vector width
+ static constexpr uint32_t width = N;
+ /// the vector element type
+ using type = T;
+};
+
+/// A 'fluent' type helper used to construct an ast::Matrix or type::Matrix.
+/// @tparam C the number of columns of the matrix
+/// @tparam R the number of rows of the matrix
+/// @tparam T the matrix element type
+/// @see https://www.w3.org/TR/WGSL/#matrix-types
+template <uint32_t C, uint32_t R, typename T = Infer>
+struct mat {
+ /// the number of columns of the matrix
+ static constexpr uint32_t columns = C;
+ /// the number of rows of the matrix
+ static constexpr uint32_t rows = R;
+ /// the matrix element type
+ using type = T;
+ /// the column vector type
+ using column = vec<R, T>;
+};
+
+/// A 'fluent' type helper used to construct an ast::Pointer or type::Pointer.
+/// @tparam ADDRESS the pointer address space
+/// @tparam T the pointer storage type
+/// @tparam ACCESS the pointer access control
+template <builtin::AddressSpace ADDRESS,
+ typename T,
+ builtin::Access ACCESS = builtin::Access::kUndefined>
+struct ptr {
+ /// the pointer address space
+ static constexpr builtin::AddressSpace address = ADDRESS;
+ /// the pointer storage type
+ using type = T;
+ /// the pointer access control
+ static constexpr builtin::Access access = ACCESS;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Aliases
+//
+// Shorthand aliases for the types declared above
+////////////////////////////////////////////////////////////////////////////////
+
+//! @cond Doxygen_Suppress
+template <typename T>
+using mat2x2 = mat<2, 2, T>;
+
+template <typename T>
+using mat2x3 = mat<2, 3, T>;
+
+template <typename T>
+using mat2x4 = mat<2, 4, T>;
+
+template <typename T>
+using mat3x2 = mat<3, 2, T>;
+
+template <typename T>
+using mat3x3 = mat<3, 3, T>;
+
+template <typename T>
+using mat3x4 = mat<3, 4, T>;
+
+template <typename T>
+using mat4x2 = mat<4, 2, T>;
+
+template <typename T>
+using mat4x3 = mat<4, 3, T>;
+
+template <typename T>
+using mat4x4 = mat<4, 4, T>;
+
+template <typename T>
+using vec2 = vec<2, T>;
+
+template <typename T>
+using vec3 = vec<3, T>;
+
+template <typename T>
+using vec4 = vec<4, T>;
+
+//! @endcond
+
+////////////////////////////////////////////////////////////////////////////////
+// Address space aliases
+////////////////////////////////////////////////////////////////////////////////
+static constexpr builtin::AddressSpace function = builtin::AddressSpace::kFunction;
+static constexpr builtin::AddressSpace private_ = builtin::AddressSpace::kPrivate;
+static constexpr builtin::AddressSpace push_constant = builtin::AddressSpace::kPushConstant;
+static constexpr builtin::AddressSpace storage = builtin::AddressSpace::kStorage;
+static constexpr builtin::AddressSpace uniform = builtin::AddressSpace::kUniform;
+static constexpr builtin::AddressSpace workgroup = builtin::AddressSpace::kWorkgroup;
+
+////////////////////////////////////////////////////////////////////////////////
+// Access control aliases
+////////////////////////////////////////////////////////////////////////////////
+static constexpr builtin::Access read = builtin::Access::kRead;
+static constexpr builtin::Access read_write = builtin::Access::kReadWrite;
+static constexpr builtin::Access write = builtin::Access::kWrite;
+
+////////////////////////////////////////////////////////////////////////////////
+// Traits
+////////////////////////////////////////////////////////////////////////////////
+namespace detail {
+
+//! @cond Doxygen_Suppress
+template <typename T>
+struct IsArray {
+ static constexpr bool value = false;
+};
+
+template <typename T, uint32_t N>
+struct IsArray<array<T, N>> {
+ static constexpr bool value = true;
+};
+
+template <typename T>
+struct IsAtomic {
+ static constexpr bool value = false;
+};
+
+template <typename T>
+struct IsAtomic<atomic<T>> {
+ static constexpr bool value = true;
+};
+
+template <typename T>
+struct IsMatrix {
+ static constexpr bool value = false;
+};
+
+template <uint32_t C, uint32_t R, typename T>
+struct IsMatrix<mat<C, R, T>> {
+ static constexpr bool value = true;
+};
+
+template <typename T>
+struct IsVector {
+ static constexpr bool value = false;
+};
+
+template <uint32_t N, typename T>
+struct IsVector<vec<N, T>> {
+ static constexpr bool value = true;
+};
+
+template <typename T>
+struct IsPointer {
+ static constexpr bool value = false;
+};
+
+template <builtin::AddressSpace ADDRESS, typename T, builtin::Access ACCESS>
+struct IsPointer<ptr<ADDRESS, T, ACCESS>> {
+ static constexpr bool value = true;
+};
+//! @endcond
+
+} // namespace detail
+
+/// Evaluates to true if `T` is a array
+template <typename T>
+static constexpr bool IsArray = fluent_types::detail::IsArray<T>::value;
+
+/// Evaluates to true if `T` is a atomic
+template <typename T>
+static constexpr bool IsAtomic = fluent_types::detail::IsAtomic<T>::value;
+
+/// Evaluates to true if `T` is a mat
+template <typename T>
+static constexpr bool IsMatrix = fluent_types::detail::IsMatrix<T>::value;
+
+/// Evaluates to true if `T` is a vec
+template <typename T>
+static constexpr bool IsVector = fluent_types::detail::IsVector<T>::value;
+
+/// Evaluates to true if `T` is a ptr
+template <typename T>
+static constexpr bool IsPointer = fluent_types::detail::IsPointer<T>::value;
+
+} // namespace tint::builtin::fluent_types
+
+#endif // SRC_TINT_BUILTIN_FLUENT_TYPES_H_
diff --git a/src/tint/number.cc b/src/tint/builtin/number.cc
similarity index 99%
rename from src/tint/number.cc
rename to src/tint/builtin/number.cc
index 8b85670..bf15fef 100644
--- a/src/tint/number.cc
+++ b/src/tint/builtin/number.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/tint/number.h"
+#include "src/tint/builtin/number.h"
#include <algorithm>
#include <cmath>
@@ -345,7 +345,7 @@
}
// static
-Number<detail::NumberKindF16> f16::FromBits(uint16_t bits) {
+Number<tint::detail::NumberKindF16> f16::FromBits(uint16_t bits) {
// Assert we use binary32 (i.e. float) as underlying type, which has 4 bytes.
static_assert(std::is_same<f16::type, float>());
diff --git a/src/tint/number.h b/src/tint/builtin/number.h
similarity index 95%
rename from src/tint/number.h
rename to src/tint/builtin/number.h
index 06ab7fd..23b9d0e 100644
--- a/src/tint/number.h
+++ b/src/tint/builtin/number.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef SRC_TINT_NUMBER_H_
-#define SRC_TINT_NUMBER_H_
+#ifndef SRC_TINT_BUILTIN_NUMBER_H_
+#define SRC_TINT_BUILTIN_NUMBER_H_
#include <stdint.h>
#include <cmath>
@@ -66,16 +66,16 @@
/// Evaluates to true iff T is a Number
template <typename T>
-constexpr bool IsNumber = detail::IsNumber<T>::value;
+constexpr bool IsNumber = tint::detail::IsNumber<T>::value;
/// Resolves to the underlying type for a Number.
template <typename T>
-using UnwrapNumber = typename detail::NumberUnwrapper<T>::type;
+using UnwrapNumber = typename tint::detail::NumberUnwrapper<T>::type;
/// Evaluates to true iff T or Number<T> is a floating-point type or is NumberKindF16.
template <typename T>
constexpr bool IsFloatingPoint = std::is_floating_point_v<UnwrapNumber<T>> ||
- std::is_same_v<UnwrapNumber<T>, detail::NumberKindF16>;
+ std::is_same_v<UnwrapNumber<T>, tint::detail::NumberKindF16>;
/// Evaluates to true iff T or Number<T> is an integral type.
template <typename T>
@@ -186,7 +186,7 @@
/// The partial specification of Number for f16 type, storing the f16 value as float,
/// and enforcing proper explicit casting.
template <>
-struct Number<detail::NumberKindF16> : NumberBase<Number<detail::NumberKindF16>> {
+struct Number<tint::detail::NumberKindF16> : NumberBase<Number<tint::detail::NumberKindF16>> {
/// C++ does not have a native float16 type, so we use a 32-bit float instead.
using type = float;
@@ -226,7 +226,7 @@
/// Negation operator
/// @returns the negative value of the number
- Number operator-() const { return Number<detail::NumberKindF16>(-value); }
+ Number operator-() const { return Number<tint::detail::NumberKindF16>(-value); }
/// Assignment operator with parameter as native floating point type
/// @param v the new value
@@ -246,7 +246,7 @@
/// Creates an f16 value from the uint16_t bit representation.
/// @param bits the bits to convert from
/// @returns the binary16 value based off the provided bit pattern.
- static Number<detail::NumberKindF16> FromBits(uint16_t bits);
+ static Number<tint::detail::NumberKindF16> FromBits(uint16_t bits);
/// @param value the input float32 value
/// @returns the float32 value quantized to the smaller float16 value, through truncation of the
@@ -272,7 +272,14 @@
using f32 = Number<float>;
/// `f16` is a type alias to `Number<detail::NumberKindF16>`, which should be IEEE 754 binary16.
/// However since C++ don't have native binary16 type, the value is stored as float.
-using f16 = Number<detail::NumberKindF16>;
+using f16 = Number<tint::detail::NumberKindF16>;
+
+/// The algorithms in this module require support for infinity and quiet NaNs on
+/// floating point types.
+static_assert(std::numeric_limits<float>::has_infinity);
+static_assert(std::numeric_limits<float>::has_quiet_NaN);
+static_assert(std::numeric_limits<double>::has_infinity);
+static_assert(std::numeric_limits<double>::has_quiet_NaN);
template <typename T, utils::traits::EnableIf<IsFloatingPoint<T>>* = nullptr>
inline const auto kPi = T(UnwrapNumber<T>(3.14159265358979323846));
@@ -576,7 +583,7 @@
return {};
}
- return AInt{detail::Mod(a.value, b.value)};
+ return AInt{tint::detail::Mod(a.value, b.value)};
}
/// @returns the remainder of a / b, or an empty optional if the resulting value overflowed the
@@ -587,7 +594,7 @@
if (b == FloatingPointT{0.0} || b == FloatingPointT{-0.0}) {
return {};
}
- auto result = FloatingPointT{detail::Mod(a.value, b.value)};
+ auto result = FloatingPointT{tint::detail::Mod(a.value, b.value)};
if (!std::isfinite(result.value)) {
return {};
}
@@ -681,4 +688,4 @@
} // namespace std
-#endif // SRC_TINT_NUMBER_H_
+#endif // SRC_TINT_BUILTIN_NUMBER_H_
diff --git a/src/tint/number_test.cc b/src/tint/builtin/number_test.cc
similarity index 100%
rename from src/tint/number_test.cc
rename to src/tint/builtin/number_test.cc
diff --git a/src/tint/constant/composite.h b/src/tint/constant/composite.h
index 23367a5..c2f264c 100644
--- a/src/tint/constant/composite.h
+++ b/src/tint/constant/composite.h
@@ -15,8 +15,8 @@
#ifndef SRC_TINT_CONSTANT_COMPOSITE_H_
#define SRC_TINT_CONSTANT_COMPOSITE_H_
+#include "src/tint/builtin/number.h"
#include "src/tint/constant/value.h"
-#include "src/tint/number.h"
#include "src/tint/type/type.h"
#include "src/tint/utils/castable.h"
#include "src/tint/utils/hash.h"
diff --git a/src/tint/constant/manager.h b/src/tint/constant/manager.h
index d356988..43d5049 100644
--- a/src/tint/constant/manager.h
+++ b/src/tint/constant/manager.h
@@ -17,8 +17,8 @@
#include <utility>
+#include "src/tint/builtin/number.h"
#include "src/tint/constant/value.h"
-#include "src/tint/number.h"
#include "src/tint/type/manager.h"
#include "src/tint/utils/hash.h"
#include "src/tint/utils/unique_allocator.h"
diff --git a/src/tint/constant/scalar.h b/src/tint/constant/scalar.h
index 23684ec..442bc59 100644
--- a/src/tint/constant/scalar.h
+++ b/src/tint/constant/scalar.h
@@ -15,9 +15,9 @@
#ifndef SRC_TINT_CONSTANT_SCALAR_H_
#define SRC_TINT_CONSTANT_SCALAR_H_
+#include "src/tint/builtin/number.h"
#include "src/tint/constant/manager.h"
#include "src/tint/constant/value.h"
-#include "src/tint/number.h"
#include "src/tint/type/type.h"
#include "src/tint/utils/castable.h"
#include "src/tint/utils/hash.h"
diff --git a/src/tint/constant/value.h b/src/tint/constant/value.h
index baf1171..34ca335 100644
--- a/src/tint/constant/value.h
+++ b/src/tint/constant/value.h
@@ -17,9 +17,9 @@
#include <variant>
+#include "src/tint/builtin/number.h"
#include "src/tint/constant/clone_context.h"
#include "src/tint/constant/node.h"
-#include "src/tint/number.h"
#include "src/tint/type/type.h"
#include "src/tint/utils/castable.h"
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 0d667ab..4943c1c 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -76,6 +76,8 @@
chromium_experimental_full_ptr_parameters
// A Chromium-specific extension that relaxes memory layout requirements for uniform storage.
chromium_internal_relaxed_uniform_layout
+ // A Chromium-specific extension that enables dual source blending.
+ chromium_internal_dual_source_blending
}
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
@@ -260,6 +262,7 @@
fragment
group
id
+ index
interpolate
invariant
location
diff --git a/src/tint/ir/access.cc b/src/tint/ir/access.cc
index 8f2a793..a040991 100644
--- a/src/tint/ir/access.cc
+++ b/src/tint/ir/access.cc
@@ -23,14 +23,10 @@
namespace tint::ir {
//! @cond Doxygen_Suppress
-Access::Access(const type::Type* ty, Value* object, utils::VectorRef<Value*> indices)
- : result_type_(ty) {
- TINT_ASSERT(IR, object);
- TINT_ASSERT(IR, result_type_);
- TINT_ASSERT(IR, !indices.IsEmpty());
-
- AddOperand(object);
- AddOperands(std::move(indices));
+Access::Access(InstructionResult* result, Value* object, utils::VectorRef<Value*> indices) {
+ AddOperand(Access::kObjectOperandOffset, object);
+ AddOperands(Access::kIndicesOperandOffset, std::move(indices));
+ AddResult(result);
}
Access::~Access() = default;
diff --git a/src/tint/ir/access.h b/src/tint/ir/access.h
index 04467e5..7c0c917 100644
--- a/src/tint/ir/access.h
+++ b/src/tint/ir/access.h
@@ -21,32 +21,26 @@
namespace tint::ir {
/// An access instruction in the IR.
-class Access : public utils::Castable<Access, OperandInstruction<3>> {
+class Access : public utils::Castable<Access, OperandInstruction<3, 1>> {
public:
- /// The base offset in Operands() for the object being accessed
+ /// The offset in Operands() for the object being accessed
static constexpr size_t kObjectOperandOffset = 0;
/// The base offset in Operands() for the access indices
static constexpr size_t kIndicesOperandOffset = 1;
/// Constructor
- /// @param result_type the result type
+ /// @param result the result value
/// @param object the accessor object
/// @param indices the indices to access
- Access(const type::Type* result_type, Value* object, utils::VectorRef<Value*> indices);
+ Access(InstructionResult* result, Value* object, utils::VectorRef<Value*> indices);
~Access() override;
- /// @returns the type of the value
- const type::Type* Type() override { return result_type_; }
-
/// @returns the object used for the access
Value* Object() { return operands_[kObjectOperandOffset]; }
/// @returns the accessor indices
utils::Slice<Value*> Indices() { return operands_.Slice().Offset(kIndicesOperandOffset); }
-
- private:
- const type::Type* result_type_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/access_test.cc b/src/tint/ir/access_test.cc
index 1f0e947..7840cc3 100644
--- a/src/tint/ir/access_test.cc
+++ b/src/tint/ir/access_test.cc
@@ -18,6 +18,8 @@
#include "gtest/gtest-spi.h"
#include "src/tint/ir/ir_test_helper.h"
+using namespace tint::builtin::fluent_types; // NOLINT
+
namespace tint::ir {
namespace {
@@ -29,10 +31,23 @@
auto* idx = b.Constant(u32(1));
auto* a = b.Access(ty.i32(), var, idx);
- EXPECT_THAT(var->Usages(), testing::UnorderedElementsAre(Usage{a, 0u}));
+ EXPECT_THAT(var->Result()->Usages(), testing::UnorderedElementsAre(Usage{a, 0u}));
EXPECT_THAT(idx->Usages(), testing::UnorderedElementsAre(Usage{a, 1u}));
}
+TEST_F(IR_AccessTest, Result) {
+ auto* type = ty.ptr<function, i32>();
+ auto* var = b.Var(type);
+ auto* idx = b.Constant(u32(1));
+ auto* a = b.Access(ty.i32(), var, idx);
+
+ EXPECT_TRUE(a->HasResults());
+ EXPECT_FALSE(a->HasMultiResults());
+
+ EXPECT_TRUE(a->Result()->Is<InstructionResult>());
+ EXPECT_EQ(a, a->Result()->Source());
+}
+
TEST_F(IR_AccessTest, Fail_NullType) {
EXPECT_FATAL_FAILURE(
{
@@ -45,39 +60,5 @@
"");
}
-TEST_F(IR_AccessTest, Fail_NullObject) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Access(mod.Types().i32(), nullptr, u32(1));
- },
- "");
-}
-
-TEST_F(IR_AccessTest, Fail_EmptyIndices) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- auto* ty = (mod.Types().ptr<function, i32>());
- auto* var = b.Var(ty);
- b.Access(mod.Types().i32(), var, utils::Empty);
- },
- "");
-}
-
-TEST_F(IR_AccessTest, Fail_NullIndex) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- auto* ty = (mod.Types().ptr<function, i32>());
- auto* var = b.Var(ty);
- b.Access(mod.Types().i32(), var, nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/binary.cc b/src/tint/ir/binary.cc
index 6287715..f4de0e6 100644
--- a/src/tint/ir/binary.cc
+++ b/src/tint/ir/binary.cc
@@ -19,14 +19,10 @@
namespace tint::ir {
-Binary::Binary(enum Kind kind, const type::Type* res_ty, Value* lhs, Value* rhs)
- : kind_(kind), result_type_(res_ty) {
- TINT_ASSERT(IR, result_type_);
- TINT_ASSERT(IR, lhs);
- TINT_ASSERT(IR, rhs);
-
- AddOperand(lhs);
- AddOperand(rhs);
+Binary::Binary(InstructionResult* result, enum Kind kind, Value* lhs, Value* rhs) : kind_(kind) {
+ AddOperand(Binary::kLhsOperandOffset, lhs);
+ AddOperand(Binary::kRhsOperandOffset, rhs);
+ AddResult(result);
}
Binary::~Binary() = default;
diff --git a/src/tint/ir/binary.h b/src/tint/ir/binary.h
index 6c8e6d4..e70ab0f 100644
--- a/src/tint/ir/binary.h
+++ b/src/tint/ir/binary.h
@@ -21,8 +21,14 @@
namespace tint::ir {
/// A binary instruction in the IR.
-class Binary : public utils::Castable<Binary, OperandInstruction<2>> {
+class Binary : public utils::Castable<Binary, OperandInstruction<2, 1>> {
public:
+ /// The offset in Operands() for the LHS
+ static constexpr size_t kLhsOperandOffset = 0;
+
+ /// The offset in Operands() for the RHS
+ static constexpr size_t kRhsOperandOffset = 1;
+
/// The kind of instruction.
enum class Kind {
kAdd,
@@ -47,28 +53,24 @@
};
/// Constructor
+ /// @param result the result value
/// @param kind the kind of binary instruction
- /// @param type the result type
/// @param lhs the lhs of the instruction
/// @param rhs the rhs of the instruction
- Binary(enum Kind kind, const type::Type* type, Value* lhs, Value* rhs);
+ Binary(InstructionResult* result, enum Kind kind, Value* lhs, Value* rhs);
~Binary() override;
/// @returns the kind of the binary instruction
enum Kind Kind() { return kind_; }
- /// @returns the type of the value
- const type::Type* Type() override { return result_type_; }
-
/// @returns the left-hand-side value for the instruction
- Value* LHS() { return operands_[0]; }
+ Value* LHS() { return operands_[kLhsOperandOffset]; }
/// @returns the right-hand-side value for the instruction
- Value* RHS() { return operands_[1]; }
+ Value* RHS() { return operands_[kRhsOperandOffset]; }
private:
enum Kind kind_;
- const type::Type* result_type_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc
index 8b3a90d..0d3c151 100644
--- a/src/tint/ir/binary_test.cc
+++ b/src/tint/ir/binary_test.cc
@@ -35,24 +35,13 @@
"");
}
-TEST_F(IR_BinaryTest, Fail_NullLHS) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Add(mod.Types().u32(), nullptr, u32(2));
- },
- "");
-}
+TEST_F(IR_BinaryTest, Result) {
+ auto* a = b.Add(mod.Types().i32(), 4_i, 2_i);
-TEST_F(IR_BinaryTest, Fail_NullRHS) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Add(mod.Types().u32(), u32(1), nullptr);
- },
- "");
+ EXPECT_TRUE(a->HasResults());
+ EXPECT_FALSE(a->HasMultiResults());
+ EXPECT_TRUE(a->Result()->Is<InstructionResult>());
+ EXPECT_EQ(a, a->Result()->Source());
}
TEST_F(IR_BinaryTest, CreateAnd) {
@@ -60,7 +49,7 @@
ASSERT_TRUE(inst->Is<Binary>());
EXPECT_EQ(inst->Kind(), Binary::Kind::kAnd);
- ASSERT_NE(inst->Type(), nullptr);
+ ASSERT_NE(inst->Results()[0]->Type(), nullptr);
ASSERT_TRUE(inst->LHS()->Is<Constant>());
auto lhs = inst->LHS()->As<Constant>()->Value();
diff --git a/src/tint/ir/bitcast.cc b/src/tint/ir/bitcast.cc
index a219749..c65e8bc 100644
--- a/src/tint/ir/bitcast.cc
+++ b/src/tint/ir/bitcast.cc
@@ -19,10 +19,9 @@
namespace tint::ir {
-Bitcast::Bitcast(const type::Type* ty, Value* val) : Base(ty) {
- TINT_ASSERT(IR, val);
-
- AddOperand(val);
+Bitcast::Bitcast(InstructionResult* result, Value* val) {
+ AddOperand(Bitcast::kValueOperandOffset, val);
+ AddResult(result);
}
Bitcast::~Bitcast() = default;
diff --git a/src/tint/ir/bitcast.h b/src/tint/ir/bitcast.h
index ddf74b9..4e437ae 100644
--- a/src/tint/ir/bitcast.h
+++ b/src/tint/ir/bitcast.h
@@ -23,10 +23,13 @@
/// A bitcast instruction in the IR.
class Bitcast : public utils::Castable<Bitcast, Call> {
public:
+ /// The offset in Operands() for the value
+ static constexpr size_t kValueOperandOffset = 0;
+
/// Constructor
- /// @param type the result type
+ /// @param result the result value
/// @param val the value being bitcast
- Bitcast(const type::Type* type, Value* val);
+ Bitcast(InstructionResult* result, Value* val);
~Bitcast() override;
};
diff --git a/src/tint/ir/bitcast_test.cc b/src/tint/ir/bitcast_test.cc
index e925349..d9a975e 100644
--- a/src/tint/ir/bitcast_test.cc
+++ b/src/tint/ir/bitcast_test.cc
@@ -30,7 +30,7 @@
auto* inst = b.Bitcast(mod.Types().i32(), 4_i);
ASSERT_TRUE(inst->Is<ir::Bitcast>());
- ASSERT_NE(inst->Type(), nullptr);
+ ASSERT_NE(inst->Result()->Type(), nullptr);
auto args = inst->Args();
ASSERT_EQ(args.Length(), 1u);
@@ -40,6 +40,15 @@
EXPECT_EQ(4_i, val->As<constant::Scalar<i32>>()->ValueAs<i32>());
}
+TEST_F(IR_BitcastTest, Result) {
+ auto* a = b.Bitcast(mod.Types().i32(), 4_i);
+
+ EXPECT_TRUE(a->HasResults());
+ EXPECT_FALSE(a->HasMultiResults());
+ EXPECT_TRUE(a->Result()->Is<InstructionResult>());
+ EXPECT_EQ(a, a->Result()->Source());
+}
+
TEST_F(IR_BitcastTest, Bitcast_Usage) {
auto* inst = b.Bitcast(mod.Types().i32(), 4_i);
@@ -49,16 +58,6 @@
EXPECT_THAT(args[0]->Usages(), testing::UnorderedElementsAre(Usage{inst, 0u}));
}
-TEST_F(IR_BitcastTest, Fail_NullValue) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Bitcast(mod.Types().i32(), nullptr);
- },
- "");
-}
-
TEST_F(IR_BitcastTest, Fail_NullType) {
EXPECT_FATAL_FAILURE(
{
diff --git a/src/tint/ir/block.cc b/src/tint/ir/block.cc
index 4dad6c2..c743065 100644
--- a/src/tint/ir/block.cc
+++ b/src/tint/ir/block.cc
@@ -157,16 +157,4 @@
inst->next = nullptr;
}
-void Block::SetInstructions(utils::VectorRef<Instruction*> instructions) {
- for (auto* i : instructions) {
- Append(i);
- }
-}
-
-void Block::SetInstructions(std::initializer_list<Instruction*> instructions) {
- for (auto* i : instructions) {
- Append(i);
- }
-}
-
} // namespace tint::ir
diff --git a/src/tint/ir/block.h b/src/tint/ir/block.h
index 9b9a4ca..60f6b31 100644
--- a/src/tint/ir/block.h
+++ b/src/tint/ir/block.h
@@ -50,14 +50,6 @@
return instructions_.last->As<ir::Branch>();
}
- /// Sets the instructions in the block
- /// @param instructions the instructions to set
- void SetInstructions(utils::VectorRef<Instruction*> instructions);
-
- /// Sets the instructions in the block
- /// @param instructions the instructions to set
- void SetInstructions(std::initializer_list<Instruction*> instructions);
-
/// @returns the instructions in the block
Instruction* Instructions() { return instructions_.first; }
diff --git a/src/tint/ir/block_test.cc b/src/tint/ir/block_test.cc
index 3549a05..e9523c5 100644
--- a/src/tint/ir/block_test.cc
+++ b/src/tint/ir/block_test.cc
@@ -83,35 +83,6 @@
EXPECT_TRUE(blk->HasBranchTarget());
}
-TEST_F(IR_BlockTest, SetInstructions) {
- auto* inst1 = b.Loop();
- auto* inst2 = b.Loop();
- auto* inst3 = b.Loop();
-
- auto* blk = b.Block();
- blk->SetInstructions({inst1, inst2, inst3});
-
- ASSERT_EQ(inst1->Block(), blk);
- ASSERT_EQ(inst2->Block(), blk);
- ASSERT_EQ(inst3->Block(), blk);
-
- EXPECT_FALSE(blk->IsEmpty());
- EXPECT_EQ(3u, blk->Length());
-
- auto* inst = blk->Instructions();
- ASSERT_EQ(inst, inst1);
- ASSERT_EQ(inst->prev, nullptr);
- inst = inst->next;
-
- ASSERT_EQ(inst, inst2);
- ASSERT_EQ(inst->prev, inst1);
- inst = inst->next;
-
- ASSERT_EQ(inst, inst3);
- ASSERT_EQ(inst->prev, inst2);
- ASSERT_EQ(inst->next, nullptr);
-}
-
TEST_F(IR_BlockTest, Append) {
auto* inst1 = b.Loop();
auto* inst2 = b.Loop();
@@ -285,13 +256,12 @@
}
TEST_F(IR_BlockTest, Replace_Middle) {
- auto* inst1 = b.Loop();
- auto* inst2 = b.Loop();
- auto* inst3 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst1, inst4, inst3});
+ auto* inst1 = blk->Append(b.Loop());
+ auto* inst4 = blk->Append(b.Loop());
+ auto* inst3 = blk->Append(b.Loop());
+
+ auto* inst2 = b.Loop();
blk->Replace(inst4, inst2);
ASSERT_EQ(inst1->Block(), blk);
@@ -317,12 +287,11 @@
}
TEST_F(IR_BlockTest, Replace_Start) {
- auto* inst1 = b.Loop();
- auto* inst2 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst4, inst2});
+ auto* inst4 = blk->Append(b.Loop());
+ auto* inst2 = blk->Append(b.Loop());
+
+ auto* inst1 = b.Loop();
blk->Replace(inst4, inst1);
ASSERT_EQ(inst1->Block(), blk);
@@ -343,12 +312,11 @@
}
TEST_F(IR_BlockTest, Replace_End) {
- auto* inst1 = b.Loop();
- auto* inst2 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst1, inst4});
+ auto* inst1 = blk->Append(b.Loop());
+ auto* inst4 = blk->Append(b.Loop());
+
+ auto* inst2 = b.Loop();
blk->Replace(inst4, inst2);
ASSERT_EQ(inst1->Block(), blk);
@@ -369,11 +337,10 @@
}
TEST_F(IR_BlockTest, Replace_OnlyNode) {
- auto* inst1 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst4});
+ auto* inst4 = blk->Append(b.Loop());
+
+ auto* inst1 = b.Loop();
blk->Replace(inst4, inst1);
ASSERT_EQ(inst1->Block(), blk);
@@ -389,12 +356,10 @@
}
TEST_F(IR_BlockTest, Remove_Middle) {
- auto* inst1 = b.Loop();
- auto* inst2 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst1, inst4, inst2});
+ auto* inst1 = blk->Append(b.Loop());
+ auto* inst4 = blk->Append(b.Loop());
+ auto* inst2 = blk->Append(b.Loop());
blk->Remove(inst4);
ASSERT_EQ(inst4->Block(), nullptr);
@@ -413,11 +378,9 @@
}
TEST_F(IR_BlockTest, Remove_Start) {
- auto* inst1 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst4, inst1});
+ auto* inst4 = blk->Append(b.Loop());
+ auto* inst1 = blk->Append(b.Loop());
blk->Remove(inst4);
ASSERT_EQ(inst4->Block(), nullptr);
@@ -432,11 +395,9 @@
}
TEST_F(IR_BlockTest, Remove_End) {
- auto* inst1 = b.Loop();
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst1, inst4});
+ auto* inst1 = blk->Append(b.Loop());
+ auto* inst4 = blk->Append(b.Loop());
blk->Remove(inst4);
ASSERT_EQ(inst4->Block(), nullptr);
@@ -451,10 +412,8 @@
}
TEST_F(IR_BlockTest, Remove_OnlyNode) {
- auto* inst4 = b.Loop();
-
auto* blk = b.Block();
- blk->SetInstructions({inst4});
+ auto* inst4 = blk->Append(b.Loop());
blk->Remove(inst4);
ASSERT_EQ(inst4->Block(), nullptr);
diff --git a/src/tint/ir/branch.h b/src/tint/ir/branch.h
index 15a7d42..1069529 100644
--- a/src/tint/ir/branch.h
+++ b/src/tint/ir/branch.h
@@ -27,7 +27,7 @@
namespace tint::ir {
/// A branch instruction.
-class Branch : public utils::Castable<Branch, OperandInstruction<1>> {
+class Branch : public utils::Castable<Branch, OperandInstruction<1, 0>> {
public:
~Branch() override;
diff --git a/src/tint/ir/break_if.cc b/src/tint/ir/break_if.cc
index 4a18fb8..3b34c28 100644
--- a/src/tint/ir/break_if.cc
+++ b/src/tint/ir/break_if.cc
@@ -24,19 +24,15 @@
namespace tint::ir {
-BreakIf::BreakIf(Value* condition,
- ir::Loop* loop,
- utils::VectorRef<Value*> args /* = utils::Empty */)
- : loop_(loop) {
- TINT_ASSERT(IR, condition);
+BreakIf::BreakIf(Value* condition, ir::Loop* loop, utils::VectorRef<Value*> args) : loop_(loop) {
TINT_ASSERT(IR, loop_);
- AddOperand(condition);
+ AddOperand(BreakIf::kConditionOperandOffset, condition);
+ AddOperands(BreakIf::kArgsOperandOffset, std::move(args));
+
if (loop_) {
loop_->Body()->AddInboundSiblingBranch(this);
- loop_->Merge()->AddInboundSiblingBranch(this);
}
- AddOperands(std::move(args));
}
BreakIf::~BreakIf() = default;
diff --git a/src/tint/ir/break_if.h b/src/tint/ir/break_if.h
index 1eba580..59046b2 100644
--- a/src/tint/ir/break_if.h
+++ b/src/tint/ir/break_if.h
@@ -29,6 +29,12 @@
/// A break-if iteration instruction.
class BreakIf : public utils::Castable<BreakIf, Branch> {
public:
+ /// The offset in Operands() for the condition
+ static constexpr size_t kConditionOperandOffset = 0;
+
+ /// The base offset in Operands() for the arguments
+ static constexpr size_t kArgsOperandOffset = 1;
+
/// Constructor
/// @param condition the break condition
/// @param loop the loop containing the break-if
@@ -37,10 +43,12 @@
~BreakIf() override;
/// @returns the branch arguments
- utils::Slice<Value* const> Args() override { return operands_.Slice().Offset(1); }
+ utils::Slice<Value* const> Args() override {
+ return operands_.Slice().Offset(kArgsOperandOffset);
+ }
/// @returns the break condition
- Value* Condition() { return operands_[0]; }
+ Value* Condition() { return operands_[kConditionOperandOffset]; }
/// @returns the loop containing the break-if
ir::Loop* Loop() { return loop_; }
diff --git a/src/tint/ir/break_if_test.cc b/src/tint/ir/break_if_test.cc
index 9dd095a..2ce17ae 100644
--- a/src/tint/ir/break_if_test.cc
+++ b/src/tint/ir/break_if_test.cc
@@ -37,14 +37,15 @@
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{brk, 2u}));
}
-TEST_F(IR_BreakIfTest, Fail_NullCondition) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.BreakIf(nullptr, b.Loop());
- },
- "");
+TEST_F(IR_BreakIfTest, Results) {
+ auto* loop = b.Loop();
+ auto* cond = b.Constant(true);
+ auto* arg1 = b.Constant(1_u);
+ auto* arg2 = b.Constant(2_u);
+
+ auto* brk = b.BreakIf(cond, loop, arg1, arg2);
+ EXPECT_FALSE(brk->HasResults());
+ EXPECT_FALSE(brk->HasMultiResults());
}
TEST_F(IR_BreakIfTest, Fail_NullLoop) {
@@ -57,15 +58,5 @@
"");
}
-TEST_F(IR_BreakIfTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.BreakIf(true, b.Loop(), nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index e2d2b83..2bb295b 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -24,6 +24,8 @@
Builder::Builder(Module& mod) : ir(mod) {}
+Builder::Builder(Module& mod, ir::Block* block) : current_block_(block), ir(mod) {}
+
Builder::~Builder() = default;
ir::Block* Builder::RootBlock() {
@@ -52,7 +54,7 @@
}
ir::Loop* Builder::Loop() {
- return ir.values.Create<ir::Loop>(Block(), MultiInBlock(), MultiInBlock(), MultiInBlock());
+ return Append(ir.instructions.Create<ir::Loop>(Block(), MultiInBlock(), MultiInBlock()));
}
Block* Builder::Case(ir::Switch* s, utils::VectorRef<Switch::CaseSelector> selectors) {
@@ -67,11 +69,11 @@
}
ir::Discard* Builder::Discard() {
- return ir.values.Create<ir::Discard>(ir.Types().void_());
+ return Append(ir.instructions.Create<ir::Discard>());
}
ir::Var* Builder::Var(const type::Pointer* type) {
- return ir.values.Create<ir::Var>(type);
+ return Append(ir.instructions.Create<ir::Var>(InstructionResult(type)));
}
ir::BlockParam* Builder::BlockParam(const type::Type* type) {
@@ -82,16 +84,8 @@
return ir.values.Create<ir::FunctionParam>(type);
}
-ir::Swizzle* Builder::Swizzle(const type::Type* type,
- ir::Value* object,
- utils::VectorRef<uint32_t> indices) {
- return ir.values.Create<ir::Swizzle>(type, object, std::move(indices));
-}
-
-ir::Swizzle* Builder::Swizzle(const type::Type* type,
- ir::Value* object,
- std::initializer_list<uint32_t> indices) {
- return ir.values.Create<ir::Swizzle>(type, object, utils::Vector<uint32_t, 4>(indices));
+ir::Unreachable* Builder::Unreachable() {
+ return Append(ir.instructions.Create<ir::Unreachable>());
}
} // namespace tint::ir
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index 1bb2973..9a2c817 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -35,6 +35,7 @@
#include "src/tint/ir/function.h"
#include "src/tint/ir/function_param.h"
#include "src/tint/ir/if.h"
+#include "src/tint/ir/instruction_result.h"
#include "src/tint/ir/load.h"
#include "src/tint/ir/loop.h"
#include "src/tint/ir/module.h"
@@ -45,9 +46,11 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/swizzle.h"
#include "src/tint/ir/unary.h"
+#include "src/tint/ir/unreachable.h"
#include "src/tint/ir/user_call.h"
#include "src/tint/ir/value.h"
#include "src/tint/ir/var.h"
+#include "src/tint/switch.h"
#include "src/tint/type/bool.h"
#include "src/tint/type/f16.h"
#include "src/tint/type/f32.h"
@@ -73,13 +76,33 @@
using DisableIfVectorLike = utils::traits::EnableIf<
!utils::IsVectorLike<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
+ template <typename T>
+ T* Append(T* val) {
+ if (current_block_) {
+ current_block_->Append(val);
+ }
+ return val;
+ }
+
+ /// If set, any created instruction will be auto-appended to the block.
+ ir::Block* current_block_ = nullptr;
+
public:
/// Constructor
/// @param mod the ir::Module to wrap with this builder
explicit Builder(Module& mod);
+ /// Constructor
+ /// @param mod the ir::Module to wrap with this builder
+ /// @param block the block to insert too
+ Builder(Module& mod, ir::Block* block);
/// Destructor
~Builder();
+ /// Creates a new builder wrapping the given block
+ /// @param b the block to set as the current block
+ /// @returns the builder
+ Builder With(Block* b) { return Builder(ir, b); }
+
/// @returns a new block
ir::Block* Block();
@@ -102,8 +125,8 @@
/// @returns the flow node
template <typename T>
ir::If* If(T&& condition) {
- return ir.values.Create<ir::If>(Value(std::forward<T>(condition)), Block(), Block(),
- MultiInBlock());
+ return Append(
+ ir.instructions.Create<ir::If>(Value(std::forward<T>(condition)), Block(), Block()));
}
/// Creates a loop flow node
@@ -115,7 +138,7 @@
/// @returns the flow node
template <typename T>
ir::Switch* Switch(T&& condition) {
- return ir.values.Create<ir::Switch>(Value(std::forward<T>(condition)), MultiInBlock());
+ return Append(ir.instructions.Create<ir::Switch>(Value(std::forward<T>(condition))));
}
/// Creates a case flow node for the given case branch.
@@ -170,15 +193,30 @@
return Constant(std::forward<T>(number));
}
+ /// Pass-through overload for nullptr values
+ /// @returns nullptr
+ ir::Value* Value(std::nullptr_t) { return nullptr; }
+
/// Pass-through overload for Value()
/// @param v the ir::Value pointer
/// @returns @p v
ir::Value* Value(ir::Value* v) { return v; }
- /// Creates a ir::Constant for the given boolean
- /// @param v the boolean value
- /// @returns the new constant
- ir::Constant* Value(bool v) { return Constant(v); }
+ /// Extract the first result from the instruction
+ /// @param inst the instruction
+ /// @returns the result value
+ ir::Value* Value(ir::Instruction* inst) {
+ TINT_ASSERT(IR, inst->HasResults() && !inst->HasMultiResults());
+ return inst->Result();
+ }
+
+ /// Creates a value from the given number
+ /// @param n the number
+ /// @returns the value
+ template <typename T>
+ ir::Value* Value(Number<T> n) {
+ return Constant(n);
+ }
/// Pass-through overload for Values() with vector-like argument
/// @param vec the vector of ir::Value*
@@ -211,8 +249,9 @@
/// @returns the operation
template <typename LHS, typename RHS>
ir::Binary* Binary(enum Binary::Kind kind, const type::Type* type, LHS&& lhs, RHS&& rhs) {
- return ir.values.Create<ir::Binary>(kind, type, Value(std::forward<LHS>(lhs)),
- Value(std::forward<RHS>(rhs)));
+ return Append(ir.instructions.Create<ir::Binary>(InstructionResult(type), kind,
+ Value(std::forward<LHS>(lhs)),
+ Value(std::forward<RHS>(rhs))));
}
/// Creates an And operation
@@ -394,7 +433,8 @@
/// @returns the operation
template <typename VAL>
ir::Unary* Unary(enum Unary::Kind kind, const type::Type* type, VAL&& val) {
- return ir.values.Create<ir::Unary>(kind, type, Value(std::forward<VAL>(val)));
+ return Append(ir.instructions.Create<ir::Unary>(InstructionResult(type), kind,
+ Value(std::forward<VAL>(val))));
}
/// Creates a Complement operation
@@ -430,7 +470,8 @@
/// @returns the instruction
template <typename VAL>
ir::Bitcast* Bitcast(const type::Type* type, VAL&& val) {
- return ir.values.Create<ir::Bitcast>(type, Value(std::forward<VAL>(val)));
+ return Append(ir.instructions.Create<ir::Bitcast>(InstructionResult(type),
+ Value(std::forward<VAL>(val))));
}
/// Creates a discard instruction
@@ -444,7 +485,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::UserCall* Call(const type::Type* type, ir::Function* func, ARGS&&... args) {
- return ir.values.Create<ir::UserCall>(type, func, Values(std::forward<ARGS>(args)...));
+ return Append(ir.instructions.Create<ir::UserCall>(InstructionResult(type), func,
+ Values(std::forward<ARGS>(args)...)));
}
/// Creates a builtin call instruction
@@ -454,7 +496,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::BuiltinCall* Call(const type::Type* type, builtin::Function func, ARGS&&... args) {
- return ir.values.Create<ir::BuiltinCall>(type, func, Values(std::forward<ARGS>(args)...));
+ return Append(ir.instructions.Create<ir::BuiltinCall>(InstructionResult(type), func,
+ Values(std::forward<ARGS>(args)...)));
}
/// Creates a value conversion instruction
@@ -463,7 +506,8 @@
/// @returns the instruction
template <typename VAL>
ir::Convert* Convert(const type::Type* to, VAL&& val) {
- return ir.values.Create<ir::Convert>(to, Value(std::forward<VAL>(val)));
+ return Append(ir.instructions.Create<ir::Convert>(InstructionResult(to),
+ Value(std::forward<VAL>(val))));
}
/// Creates a value constructor instruction
@@ -472,7 +516,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::Construct* Construct(const type::Type* type, ARGS&&... args) {
- return ir.values.Create<ir::Construct>(type, Values(std::forward<ARGS>(args)...));
+ return Append(ir.instructions.Create<ir::Construct>(InstructionResult(type),
+ Values(std::forward<ARGS>(args)...)));
}
/// Creates a load instruction
@@ -480,16 +525,19 @@
/// @returns the instruction
template <typename VAL>
ir::Load* Load(VAL&& from) {
- return ir.values.Create<ir::Load>(Value(std::forward<VAL>(from)));
+ auto* val = Value(std::forward<VAL>(from));
+ return Append(
+ ir.instructions.Create<ir::Load>(InstructionResult(val->Type()->UnwrapPtr()), val));
}
/// Creates a store instruction
/// @param to the expression being stored too
/// @param from the expression being stored
/// @returns the instruction
- template <typename ARG>
- ir::Store* Store(ir::Value* to, ARG&& from) {
- return ir.values.Create<ir::Store>(to, Value(std::forward<ARG>(from)));
+ template <typename TO, typename ARG>
+ ir::Store* Store(TO&& to, ARG&& from) {
+ return Append(ir.instructions.Create<ir::Store>(Value(std::forward<TO>(to)),
+ Value(std::forward<ARG>(from))));
}
/// Creates a new `var` declaration
@@ -500,7 +548,9 @@
/// Creates a return instruction
/// @param func the function being returned
/// @returns the instruction
- ir::Return* Return(ir::Function* func) { return ir.values.Create<ir::Return>(func); }
+ ir::Return* Return(ir::Function* func) {
+ return Append(ir.instructions.Create<ir::Return>(func));
+ }
/// Creates a return instruction
/// @param func the function being returned
@@ -508,7 +558,7 @@
/// @returns the instruction
template <typename ARG>
ir::Return* Return(ir::Function* func, ARG&& value) {
- return ir.values.Create<ir::Return>(func, Value(std::forward<ARG>(value)));
+ return Append(ir.instructions.Create<ir::Return>(func, Value(std::forward<ARG>(value))));
}
/// Creates a loop next iteration instruction
@@ -517,7 +567,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::NextIteration* NextIteration(ir::Loop* loop, ARGS&&... args) {
- return ir.values.Create<ir::NextIteration>(loop, Values(std::forward<ARGS>(args)...));
+ return Append(
+ ir.instructions.Create<ir::NextIteration>(loop, Values(std::forward<ARGS>(args)...)));
}
/// Creates a loop break-if instruction
@@ -527,8 +578,8 @@
/// @returns the instruction
template <typename CONDITION, typename... ARGS>
ir::BreakIf* BreakIf(CONDITION&& condition, ir::Loop* loop, ARGS&&... args) {
- return ir.values.Create<ir::BreakIf>(Value(std::forward<CONDITION>(condition)), loop,
- Values(std::forward<ARGS>(args)...));
+ return Append(ir.instructions.Create<ir::BreakIf>(
+ Value(std::forward<CONDITION>(condition)), loop, Values(std::forward<ARGS>(args)...)));
}
/// Creates a continue instruction
@@ -537,7 +588,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::Continue* Continue(ir::Loop* loop, ARGS&&... args) {
- return ir.values.Create<ir::Continue>(loop, Values(std::forward<ARGS>(args)...));
+ return Append(
+ ir.instructions.Create<ir::Continue>(loop, Values(std::forward<ARGS>(args)...)));
}
/// Creates an exit switch instruction
@@ -546,7 +598,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::ExitSwitch* ExitSwitch(ir::Switch* sw, ARGS&&... args) {
- return ir.values.Create<ir::ExitSwitch>(sw, Values(std::forward<ARGS>(args)...));
+ return Append(
+ ir.instructions.Create<ir::ExitSwitch>(sw, Values(std::forward<ARGS>(args)...)));
}
/// Creates an exit loop instruction
@@ -555,7 +608,8 @@
/// @returns the instruction
template <typename... ARGS>
ir::ExitLoop* ExitLoop(ir::Loop* loop, ARGS&&... args) {
- return ir.values.Create<ir::ExitLoop>(loop, Values(std::forward<ARGS>(args)...));
+ return Append(
+ ir.instructions.Create<ir::ExitLoop>(loop, Values(std::forward<ARGS>(args)...)));
}
/// Creates an exit if instruction
@@ -564,7 +618,20 @@
/// @returns the instruction
template <typename... ARGS>
ir::ExitIf* ExitIf(ir::If* i, ARGS&&... args) {
- return ir.values.Create<ir::ExitIf>(i, Values(std::forward<ARGS>(args)...));
+ return Append(ir.instructions.Create<ir::ExitIf>(i, Values(std::forward<ARGS>(args)...)));
+ }
+
+ /// Creates an exit instruction for the given control instruction
+ /// @param inst the control instruction being exited
+ /// @param args the branch arguments
+ /// @returns the exit instruction, or nullptr if the control instruction is not supported.
+ template <typename... ARGS>
+ ir::Branch* Exit(ir::ControlInstruction* inst, ARGS&&... args) {
+ return tint::Switch(
+ inst, //
+ [&](ir::If* i) { return ExitIf(i, std::forward<ARGS>(args)...); },
+ [&](ir::Loop* i) { return ExitLoop(i, std::forward<ARGS>(args)...); },
+ [&](ir::Switch* i) { return ExitSwitch(i, std::forward<ARGS>(args)...); });
}
/// Creates a new `BlockParam`
@@ -582,9 +649,11 @@
/// @param object the object being accessed
/// @param indices the access indices
/// @returns the instruction
- template <typename... ARGS>
- ir::Access* Access(const type::Type* type, ir::Value* object, ARGS&&... indices) {
- return ir.values.Create<ir::Access>(type, object, Values(std::forward<ARGS>(indices)...));
+ template <typename OBJ, typename... ARGS>
+ ir::Access* Access(const type::Type* type, OBJ&& object, ARGS&&... indices) {
+ return Append(ir.instructions.Create<ir::Access>(InstructionResult(type),
+ Value(std::forward<OBJ>(object)),
+ Values(std::forward<ARGS>(indices)...)));
}
/// Creates a new `Swizzle`
@@ -592,23 +661,41 @@
/// @param object the object being swizzled
/// @param indices the swizzle indices
/// @returns the instruction
- ir::Swizzle* Swizzle(const type::Type* type,
- ir::Value* object,
- utils::VectorRef<uint32_t> indices);
+ template <typename OBJ>
+ ir::Swizzle* Swizzle(const type::Type* type, OBJ&& object, utils::VectorRef<uint32_t> indices) {
+ return Append(ir.instructions.Create<ir::Swizzle>(
+ InstructionResult(type), Value(std::forward<OBJ>(object)), std::move(indices)));
+ }
/// Creates a new `Swizzle`
/// @param type the return type
/// @param object the object being swizzled
/// @param indices the swizzle indices
/// @returns the instruction
+ template <typename OBJ>
ir::Swizzle* Swizzle(const type::Type* type,
- ir::Value* object,
- std::initializer_list<uint32_t> indices);
+ OBJ&& object,
+ std::initializer_list<uint32_t> indices) {
+ return Append(ir.instructions.Create<ir::Swizzle>(InstructionResult(type),
+ Value(std::forward<OBJ>(object)),
+ utils::Vector<uint32_t, 4>(indices)));
+ }
+
+ /// Creates an unreachable instruction
+ /// @returns the instruction
+ ir::Unreachable* Unreachable();
/// Retrieves the root block for the module, creating if necessary
/// @returns the root block
ir::Block* RootBlock();
+ /// Creates a new runtime value
+ /// @param type the return type
+ /// @returns the value
+ ir::InstructionResult* InstructionResult(const type::Type* type) {
+ return ir.values.Create<ir::InstructionResult>(type);
+ }
+
/// The IR module.
Module& ir;
};
diff --git a/src/tint/ir/builtin_call.cc b/src/tint/ir/builtin_call.cc
index a230510..2726191 100644
--- a/src/tint/ir/builtin_call.cc
+++ b/src/tint/ir/builtin_call.cc
@@ -22,13 +22,15 @@
namespace tint::ir {
-BuiltinCall::BuiltinCall(const type::Type* ty,
+BuiltinCall::BuiltinCall(InstructionResult* result,
builtin::Function func,
utils::VectorRef<Value*> arguments)
- : Base(ty), func_(func) {
+ : func_(func) {
TINT_ASSERT(IR, func != builtin::Function::kNone);
TINT_ASSERT(IR, func != builtin::Function::kTintMaterialize);
- AddOperands(std::move(arguments));
+
+ AddOperands(BuiltinCall::kArgsOperandOffset, std::move(arguments));
+ AddResult(result);
}
BuiltinCall::~BuiltinCall() = default;
diff --git a/src/tint/ir/builtin_call.h b/src/tint/ir/builtin_call.h
index 4aef1eb..3a142a5 100644
--- a/src/tint/ir/builtin_call.h
+++ b/src/tint/ir/builtin_call.h
@@ -24,11 +24,14 @@
/// A builtin call instruction in the IR.
class BuiltinCall : public utils::Castable<BuiltinCall, Call> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
- /// @param res_type the result type
+ /// @param result the result value
/// @param func the builtin function
/// @param args the conversion arguments
- BuiltinCall(const type::Type* res_type,
+ BuiltinCall(InstructionResult* result,
builtin::Function func,
utils::VectorRef<Value*> args = utils::Empty);
~BuiltinCall() override;
diff --git a/src/tint/ir/builtin_call_test.cc b/src/tint/ir/builtin_call_test.cc
index fb6580e..f0928a0 100644
--- a/src/tint/ir/builtin_call_test.cc
+++ b/src/tint/ir/builtin_call_test.cc
@@ -32,6 +32,17 @@
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{builtin, 1u}));
}
+TEST_F(IR_BuiltinCallTest, Result) {
+ auto* arg1 = b.Constant(1_u);
+ auto* arg2 = b.Constant(2_u);
+ auto* builtin = b.Call(mod.Types().f32(), builtin::Function::kAbs, arg1, arg2);
+
+ EXPECT_TRUE(builtin->HasResults());
+ EXPECT_FALSE(builtin->HasMultiResults());
+ EXPECT_TRUE(builtin->Result()->Is<InstructionResult>());
+ EXPECT_EQ(builtin->Result()->Source(), builtin);
+}
+
TEST_F(IR_BuiltinCallTest, Fail_NullType) {
EXPECT_FATAL_FAILURE(
{
@@ -62,15 +73,5 @@
"");
}
-TEST_F(IR_BuiltinCallTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Call(mod.Types().f32(), builtin::Function::kAbs, nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/call.cc b/src/tint/ir/call.cc
index 30174d4..ead6124 100644
--- a/src/tint/ir/call.cc
+++ b/src/tint/ir/call.cc
@@ -20,9 +20,7 @@
namespace tint::ir {
-Call::Call(const type::Type* res_ty) : result_type_(res_ty) {
- TINT_ASSERT(IR, result_type_);
-}
+Call::Call() = default;
Call::~Call() = default;
diff --git a/src/tint/ir/call.h b/src/tint/ir/call.h
index c26aa5d..041c012 100644
--- a/src/tint/ir/call.h
+++ b/src/tint/ir/call.h
@@ -21,25 +21,16 @@
namespace tint::ir {
/// A Call instruction in the IR.
-class Call : public utils::Castable<Call, OperandInstruction<4>> {
+class Call : public utils::Castable<Call, OperandInstruction<4, 1>> {
public:
~Call() override;
- /// @returns the type of the value
- const type::Type* Type() override { return result_type_; }
-
/// @returns the call arguments
virtual utils::Slice<Value* const> Args() { return operands_.Slice(); }
protected:
/// Constructor
- Call() = delete;
- /// Constructor
- /// @param result_type the result type
- explicit Call(const type::Type* result_type);
-
- private:
- const type::Type* result_type_ = nullptr;
+ Call();
};
} // namespace tint::ir
diff --git a/src/tint/ir/construct.cc b/src/tint/ir/construct.cc
index c4a330e..6dbbd45 100644
--- a/src/tint/ir/construct.cc
+++ b/src/tint/ir/construct.cc
@@ -22,8 +22,9 @@
namespace tint::ir {
-Construct::Construct(const type::Type* ty, utils::VectorRef<Value*> arguments) : Base(ty) {
- AddOperands(std::move(arguments));
+Construct::Construct(InstructionResult* result, utils::VectorRef<Value*> arguments) {
+ AddOperands(Construct::kArgsOperandOffset, std::move(arguments));
+ AddResult(result);
}
Construct::~Construct() = default;
diff --git a/src/tint/ir/construct.h b/src/tint/ir/construct.h
index 4a15849..a2fe9b3 100644
--- a/src/tint/ir/construct.h
+++ b/src/tint/ir/construct.h
@@ -23,10 +23,13 @@
/// A constructor instruction in the IR.
class Construct : public utils::Castable<Construct, Call> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
- /// @param type the result type
+ /// @param result the result value
/// @param args the constructor arguments
- explicit Construct(const type::Type* type, utils::VectorRef<Value*> args = utils::Empty);
+ explicit Construct(InstructionResult* result, utils::VectorRef<Value*> args = utils::Empty);
~Construct() override;
};
diff --git a/src/tint/ir/construct_test.cc b/src/tint/ir/construct_test.cc
index fa31ff9..956aefd 100644
--- a/src/tint/ir/construct_test.cc
+++ b/src/tint/ir/construct_test.cc
@@ -33,6 +33,17 @@
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{c, 1u}));
}
+TEST_F(IR_ConstructTest, Result) {
+ auto* arg1 = b.Constant(true);
+ auto* arg2 = b.Constant(false);
+ auto* c = b.Construct(mod.Types().f32(), arg1, arg2);
+
+ EXPECT_TRUE(c->HasResults());
+ EXPECT_FALSE(c->HasMultiResults());
+ EXPECT_TRUE(c->Result()->Is<InstructionResult>());
+ EXPECT_EQ(c, c->Result()->Source());
+}
+
TEST_F(IR_ConstructTest, Fail_NullType) {
EXPECT_FATAL_FAILURE(
{
@@ -43,15 +54,5 @@
"");
}
-TEST_F(IR_ConstructTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Construct(mod.Types().f32(), nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/continue.cc b/src/tint/ir/continue.cc
index e1e8d84..5bb29ff 100644
--- a/src/tint/ir/continue.cc
+++ b/src/tint/ir/continue.cc
@@ -24,14 +24,14 @@
namespace tint::ir {
-Continue::Continue(ir::Loop* loop, utils::VectorRef<Value*> args /* = utils::Empty */)
- : loop_(loop) {
+Continue::Continue(ir::Loop* loop, utils::VectorRef<Value*> args) : loop_(loop) {
TINT_ASSERT(IR, loop_);
+ AddOperands(Continue::kArgsOperandOffset, std::move(args));
+
if (loop_) {
loop_->Continuing()->AddInboundSiblingBranch(this);
}
- AddOperands(std::move(args));
}
Continue::~Continue() = default;
diff --git a/src/tint/ir/continue.h b/src/tint/ir/continue.h
index f9c5455..6beda97 100644
--- a/src/tint/ir/continue.h
+++ b/src/tint/ir/continue.h
@@ -28,6 +28,9 @@
/// A continue instruction.
class Continue : public utils::Castable<Continue, Branch> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
/// @param loop the loop owning the continue block
/// @param args the branch arguments
diff --git a/src/tint/ir/continue_test.cc b/src/tint/ir/continue_test.cc
index 29ea605..d16defb 100644
--- a/src/tint/ir/continue_test.cc
+++ b/src/tint/ir/continue_test.cc
@@ -35,6 +35,17 @@
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{brk, 1u}));
}
+TEST_F(IR_ContinueTest, Results) {
+ auto* loop = b.Loop();
+ auto* arg1 = b.Constant(1_u);
+ auto* arg2 = b.Constant(2_u);
+
+ auto* brk = b.Continue(loop, arg1, arg2);
+
+ EXPECT_FALSE(brk->HasResults());
+ EXPECT_FALSE(brk->HasMultiResults());
+}
+
TEST_F(IR_ContinueTest, Fail_NullLoop) {
EXPECT_FATAL_FAILURE(
{
@@ -45,15 +56,5 @@
"");
}
-TEST_F(IR_ContinueTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Continue(b.Loop(), nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/control_instruction.cc b/src/tint/ir/control_instruction.cc
index efcac64..6451622 100644
--- a/src/tint/ir/control_instruction.cc
+++ b/src/tint/ir/control_instruction.cc
@@ -20,4 +20,12 @@
ControlInstruction::~ControlInstruction() = default;
+void ControlInstruction::AddExit(Exit* exit) {
+ exits_.Add(exit);
+}
+
+void ControlInstruction::RemoveExit(Exit* exit) {
+ exits_.Remove(exit);
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/control_instruction.h b/src/tint/ir/control_instruction.h
index cd0e7d3..ebe5825 100644
--- a/src/tint/ir/control_instruction.h
+++ b/src/tint/ir/control_instruction.h
@@ -15,16 +15,65 @@
#ifndef SRC_TINT_IR_CONTROL_INSTRUCTION_H_
#define SRC_TINT_IR_CONTROL_INSTRUCTION_H_
+#include <utility>
+
#include "src/tint/ir/branch.h"
+#include "src/tint/ir/operand_instruction.h"
+
+// Forward declarations
+namespace tint::ir {
+class Block;
+class Exit;
+} // namespace tint::ir
namespace tint::ir {
/// Base class of instructions that perform branches to two or more blocks, owned by the
/// ControlInstruction.
-class ControlInstruction : public utils::Castable<ControlInstruction, Branch> {
+class ControlInstruction : public utils::Castable<ControlInstruction, OperandInstruction<1, 1>> {
public:
/// Destructor
~ControlInstruction() override;
+
+ /// Calls @p cb for each block owned by this control instruction
+ /// @param cb the function to call once for each block
+ virtual void ForeachBlock(const std::function<void(ir::Block*)>& cb) = 0;
+
+ /// Sets the results of the control instruction
+ /// @param values the new result values
+ void SetResults(utils::VectorRef<InstructionResult*> values) {
+ for (auto* value : results_) {
+ value->SetSource(nullptr);
+ }
+ results_ = std::move(values);
+ for (auto* value : results_) {
+ value->SetSource(this);
+ }
+ }
+
+ /// Sets the results of the control instruction
+ /// @param values the new result values
+ template <typename... ARGS,
+ typename = std::enable_if_t<!utils::IsVectorLike<
+ utils::traits::Decay<utils::traits::NthTypeOf<0, ARGS..., void>>>>>
+ void SetResults(ARGS&&... values) {
+ SetResults(utils::Vector{std::forward<ARGS>(values)...});
+ }
+
+ /// @return All the exit branches for the flow control instruction
+ const utils::Hashset<Exit*, 2>& Exits() const { return exits_; }
+
+ /// Adds the exit to the flow control instruction
+ /// @param exit the exit instruction
+ void AddExit(Exit* exit);
+
+ /// Removes the exit to the flow control instruction
+ /// @param exit the exit instruction
+ void RemoveExit(Exit* exit);
+
+ protected:
+ /// The flow control exits
+ utils::Hashset<Exit*, 2> exits_;
};
} // namespace tint::ir
diff --git a/src/tint/ir/convert.cc b/src/tint/ir/convert.cc
index ed5961b..51e99f3 100644
--- a/src/tint/ir/convert.cc
+++ b/src/tint/ir/convert.cc
@@ -22,10 +22,9 @@
namespace tint::ir {
-Convert::Convert(const type::Type* to_type, Value* value) : Base(to_type) {
- TINT_ASSERT_OR_RETURN(IR, value);
-
- AddOperand(value);
+Convert::Convert(InstructionResult* result, Value* value) {
+ AddOperand(Convert::kValueOperandOffset, value);
+ AddResult(result);
}
Convert::~Convert() = default;
diff --git a/src/tint/ir/convert.h b/src/tint/ir/convert.h
index 0bb07cf..59d02d7 100644
--- a/src/tint/ir/convert.h
+++ b/src/tint/ir/convert.h
@@ -24,10 +24,13 @@
/// A value conversion instruction in the IR.
class Convert : public utils::Castable<Convert, Call> {
public:
+ /// The offset in Operands() for the value
+ static constexpr size_t kValueOperandOffset = 0;
+
/// Constructor
- /// @param to_type the target conversion type
+ /// @param result the result value
/// @param value the value to convert
- Convert(const type::Type* to_type, Value* value);
+ Convert(InstructionResult* result, Value* value);
~Convert() override;
};
diff --git a/src/tint/ir/convert_test.cc b/src/tint/ir/convert_test.cc
index d1affd4..5851d80 100644
--- a/src/tint/ir/convert_test.cc
+++ b/src/tint/ir/convert_test.cc
@@ -32,14 +32,13 @@
"");
}
-TEST_F(IR_ConvertTest, Fail_NoArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Convert(mod.Types().f32(), nullptr);
- },
- "");
+TEST_F(IR_ConvertTest, Results) {
+ auto* c = b.Convert(mod.Types().i32(), 1_u);
+
+ EXPECT_TRUE(c->HasResults());
+ EXPECT_FALSE(c->HasMultiResults());
+ EXPECT_TRUE(c->Result()->Is<InstructionResult>());
+ EXPECT_EQ(c->Result()->Source(), c);
}
} // namespace
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index 6d17316..27598f0 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -33,6 +33,7 @@
#include "src/tint/ir/exit_loop.h"
#include "src/tint/ir/exit_switch.h"
#include "src/tint/ir/if.h"
+#include "src/tint/ir/instruction_result.h"
#include "src/tint/ir/load.h"
#include "src/tint/ir/loop.h"
#include "src/tint/ir/multi_in_block.h"
@@ -42,6 +43,7 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/swizzle.h"
#include "src/tint/ir/transform/block_decorated_structs.h"
+#include "src/tint/ir/unreachable.h"
#include "src/tint/ir/user_call.h"
#include "src/tint/ir/var.h"
#include "src/tint/switch.h"
@@ -82,13 +84,6 @@
current_output_start_pos_ = out_.tellp();
}
-void Disassembler::EmitBlockInstructions(Block* b) {
- for (auto* inst : *b) {
- Indent();
- EmitInstruction(inst);
- }
-}
-
size_t Disassembler::IdOf(Block* node) {
TINT_ASSERT(IR, node);
return block_ids_.GetOrCreate(node, [&] { return block_ids_.Count(); });
@@ -118,7 +113,7 @@
if (mod_.root_block) {
Indent() << "# Root block";
EmitLine();
- WalkInternal(mod_.root_block);
+ EmitBlock(mod_.root_block);
EmitLine();
}
@@ -128,15 +123,7 @@
return out_.str();
}
-void Disassembler::Walk(Block* blk) {
- if (visited_.Contains(blk)) {
- return;
- }
- visited_.Add(blk);
- WalkInternal(blk);
-}
-
-void Disassembler::WalkInternal(Block* blk) {
+void Disassembler::EmitBlock(Block* blk) {
Indent();
SourceMarker sm(this);
@@ -154,7 +141,10 @@
EmitLine();
{
ScopedIndent si(indent_size_);
- EmitBlockInstructions(blk);
+ for (auto* inst : *blk) {
+ Indent();
+ EmitInstruction(inst);
+ }
}
Indent() << "}";
@@ -279,17 +269,19 @@
{
ScopedIndent si(indent_size_);
- Walk(func->StartTarget());
+ EmitBlock(func->StartTarget());
}
Indent() << "}";
EmitLine();
}
+void Disassembler::EmitValueWithType(Instruction* val) {
+ EmitValueWithType(val->Result());
+}
+
void Disassembler::EmitValueWithType(Value* val) {
EmitValue(val);
- if (auto* i = val->As<ir::Instruction>(); i->Type() != nullptr) {
- out_ << ":" << i->Type()->FriendlyName();
- }
+ out_ << ":" << val->Type()->FriendlyName();
}
void Disassembler::EmitValue(Value* val) {
@@ -338,10 +330,16 @@
};
emit(constant->Value());
},
- [&](ir::Instruction* i) { out_ << "%" << IdOf(i); },
+ [&](ir::InstructionResult* rv) { out_ << "%" << IdOf(rv); },
[&](ir::BlockParam* p) { out_ << "%" << IdOf(p) << ":" << p->Type()->FriendlyName(); },
[&](ir::FunctionParam* p) { out_ << "%" << IdOf(p); },
- [&](Default) { out_ << "Unknown value: " << val->TypeInfo().name; });
+ [&](Default) {
+ if (val == nullptr) {
+ out_ << "undef";
+ } else {
+ out_ << "Unknown value: " << val->TypeInfo().name;
+ }
+ });
}
void Disassembler::EmitInstructionName(std::string_view name, Instruction* inst) {
@@ -494,11 +492,15 @@
void Disassembler::EmitIf(If* i) {
SourceMarker sm(this);
+ if (i->Result()) {
+ EmitValueWithType(i->Result());
+ out_ << " = ";
+ }
out_ << "if ";
EmitOperand(i, i->Condition(), If::kConditionOperandOffset);
- bool has_true = i->True()->HasBranchTarget();
- bool has_false = i->False()->HasBranchTarget();
+ bool has_true = !i->True()->IsEmpty();
+ bool has_false = !i->False()->IsEmpty();
out_ << " [";
if (has_true) {
@@ -510,9 +512,6 @@
}
out_ << "f: %b" << IdOf(i->False());
}
- if (i->Merge()->HasBranchTarget()) {
- out_ << ", m: %b" << IdOf(i->Merge());
- }
out_ << "]";
sm.Store(i);
@@ -523,7 +522,7 @@
Indent() << "# True block";
EmitLine();
- Walk(i->True());
+ EmitBlock(i->True());
EmitLine();
}
if (has_false) {
@@ -531,65 +530,50 @@
Indent() << "# False block";
EmitLine();
- Walk(i->False());
- EmitLine();
- }
- if (i->Merge()->HasBranchTarget()) {
- Indent() << "# Merge block";
- EmitLine();
- Walk(i->Merge());
+ EmitBlock(i->False());
EmitLine();
}
}
void Disassembler::EmitLoop(Loop* l) {
- utils::Vector<std::string, 4> parts;
- if (l->Initializer()->HasBranchTarget()) {
+ utils::Vector<std::string, 3> parts;
+ if (!l->Initializer()->IsEmpty()) {
parts.Push("i: %b" + std::to_string(IdOf(l->Initializer())));
}
- if (l->Body()->HasBranchTarget()) {
+ if (!l->Body()->IsEmpty()) {
parts.Push("b: %b" + std::to_string(IdOf(l->Body())));
}
- if (l->Continuing()->HasBranchTarget()) {
+ if (!l->Continuing()->IsEmpty()) {
parts.Push("c: %b" + std::to_string(IdOf(l->Continuing())));
}
- if (l->Merge()->HasBranchTarget()) {
- parts.Push("m: %b" + std::to_string(IdOf(l->Merge())));
- }
SourceMarker sm(this);
out_ << "loop [" << utils::Join(parts, ", ") << "]";
sm.Store(l);
+
EmitLine();
- if (l->Initializer()->HasBranchTarget()) {
+ if (!l->Initializer()->IsEmpty()) {
ScopedIndent si(indent_size_);
Indent() << "# Initializer block";
EmitLine();
- Walk(l->Initializer());
+ EmitBlock(l->Initializer());
EmitLine();
}
- if (l->Body()->HasBranchTarget()) {
+ if (!l->Body()->IsEmpty()) {
ScopedIndent si(indent_size_);
Indent() << "# Body block";
EmitLine();
- Walk(l->Body());
+ EmitBlock(l->Body());
EmitLine();
}
- if (l->Continuing()->HasBranchTarget()) {
+ if (!l->Continuing()->IsEmpty()) {
ScopedIndent si(indent_size_);
Indent() << "# Continuing block";
EmitLine();
- Walk(l->Continuing());
- EmitLine();
- }
- if (l->Merge()->HasBranchTarget()) {
- Indent() << "# Merge block";
- EmitLine();
-
- Walk(l->Merge());
+ EmitBlock(l->Continuing());
EmitLine();
}
}
@@ -614,10 +598,7 @@
EmitValue(selector.val);
}
}
- out_ << ", %b" << IdOf(c.Start()) << ")";
- }
- if (s->Merge()->HasBranchTarget()) {
- out_ << ", m: %b" << IdOf(s->Merge());
+ out_ << ", %b" << IdOf(c.Block()) << ")";
}
out_ << "]";
EmitLine();
@@ -627,14 +608,7 @@
Indent() << "# Case block";
EmitLine();
- Walk(c.Start());
- EmitLine();
- }
- if (s->Merge()->HasBranchTarget()) {
- Indent() << "# Merge block";
- EmitLine();
-
- Walk(s->Merge());
+ EmitBlock(c.Block());
EmitLine();
}
}
@@ -642,18 +616,20 @@
void Disassembler::EmitBranch(Branch* b) {
SourceMarker sm(this);
tint::Switch(
- b, //
- [&](Return*) { out_ << "ret"; },
- [&](Continue* cont) { out_ << "continue %b" << IdOf(cont->Loop()->Continuing()); },
- [&](ExitIf* ei) { out_ << "exit_if %b" << IdOf(ei->If()->Merge()); },
- [&](ExitSwitch* es) { out_ << "exit_switch %b" << IdOf(es->Switch()->Merge()); },
- [&](ExitLoop* el) { out_ << "exit_loop %b" << IdOf(el->Loop()->Merge()); },
- [&](NextIteration* ni) { out_ << "next_iteration %b" << IdOf(ni->Loop()->Body()); },
- [&](BreakIf* bi) {
+ b, //
+ [&](ir::Return*) { out_ << "ret"; }, //
+ [&](ir::Continue* cont) { out_ << "continue %b" << IdOf(cont->Loop()->Continuing()); }, //
+ [&](ir::ExitIf*) { out_ << "exit_if"; }, //
+ [&](ir::ExitSwitch*) { out_ << "exit_switch"; }, //
+ [&](ir::ExitLoop*) { out_ << "exit_loop"; }, //
+ [&](ir::NextIteration* ni) { out_ << "next_iteration %b" << IdOf(ni->Loop()->Body()); }, //
+ [&](ir::Unreachable*) { out_ << "unreachable"; }, //
+ [&](ir::BreakIf* bi) {
out_ << "break_if ";
EmitValue(bi->Condition());
out_ << " %b" << IdOf(bi->Loop()->Body());
},
+ [&](Unreachable*) { out_ << "unreachable"; },
[&](Default) { out_ << "Unknown branch " << b->TypeInfo().name; });
if (!b->Args().IsEmpty()) {
diff --git a/src/tint/ir/disassembler.h b/src/tint/ir/disassembler.h
index 6d7248c..71773f1 100644
--- a/src/tint/ir/disassembler.h
+++ b/src/tint/ir/disassembler.h
@@ -48,10 +48,6 @@
/// @returns the string representation of the module
std::string Disassemble();
- /// Writes the block instructions to the stream
- /// @param b the block containing the instructions
- void EmitBlockInstructions(Block* b);
-
/// @returns the string representation
std::string AsString() const { return out_.str(); }
@@ -113,14 +109,14 @@
size_t IdOf(Block* blk);
std::string_view IdOf(Value* node);
- void Walk(Block* blk);
- void WalkInternal(Block* blk);
+ void EmitBlock(Block* blk);
void EmitFunction(Function* func);
void EmitParamAttributes(FunctionParam* p);
void EmitReturnAttributes(Function* func);
void EmitBindingPoint(BindingPoint p);
void EmitLocation(Location loc);
void EmitInstruction(Instruction* inst);
+ void EmitValueWithType(Instruction* val);
void EmitValueWithType(Value* val);
void EmitValue(Value* val);
void EmitValueList(utils::Slice<ir::Value* const> values);
@@ -141,7 +137,6 @@
Module& mod_;
utils::StringStream out_;
- utils::Hashset<Block*, 32> visited_;
utils::Hashmap<Block*, size_t, 32> block_ids_;
utils::Hashmap<Value*, std::string, 32> value_ids_;
uint32_t indent_size_ = 0;
diff --git a/src/tint/ir/discard.cc b/src/tint/ir/discard.cc
index ab9a511..f5c53a3 100644
--- a/src/tint/ir/discard.cc
+++ b/src/tint/ir/discard.cc
@@ -20,11 +20,7 @@
namespace tint::ir {
-Discard::Discard(const type::Type* ty) : Base(ty) {
- if (ty) {
- TINT_ASSERT(IR, ty->Is<type::Void>());
- }
-}
+Discard::Discard() = default;
Discard::~Discard() = default;
diff --git a/src/tint/ir/discard.h b/src/tint/ir/discard.h
index 24b9c59..e87474c 100644
--- a/src/tint/ir/discard.h
+++ b/src/tint/ir/discard.h
@@ -25,8 +25,7 @@
class Discard : public utils::Castable<Discard, Call> {
public:
/// Constructor
- /// @param ty the type of the discard, must be Void type.
- explicit Discard(const type::Type* ty);
+ Discard();
~Discard() override;
};
diff --git a/src/tint/ir/discard_test.cc b/src/tint/ir/discard_test.cc
index 91e1ef1..d6954de 100644
--- a/src/tint/ir/discard_test.cc
+++ b/src/tint/ir/discard_test.cc
@@ -27,17 +27,11 @@
ASSERT_TRUE(inst->Is<ir::Discard>());
}
-TEST_F(IR_DiscardTest, Fail_NullType) {
- EXPECT_FATAL_FAILURE({ Discard d(nullptr); }, "");
-}
+TEST_F(IR_DiscardTest, Result) {
+ auto* inst = b.Discard();
-TEST_F(IR_DiscardTest, Fail_NonVoidType) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Discard d(mod.Types().i32());
- },
- "");
+ EXPECT_FALSE(inst->HasResults());
+ EXPECT_FALSE(inst->HasMultiResults());
}
} // namespace
diff --git a/src/tint/ir/exit.cc b/src/tint/ir/exit.cc
new file mode 100644
index 0000000..fd39edd
--- /dev/null
+++ b/src/tint/ir/exit.cc
@@ -0,0 +1,43 @@
+// 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/exit.h"
+
+#include "src/tint/ir/control_instruction.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::Exit);
+
+namespace tint::ir {
+
+Exit::~Exit() = default;
+
+void Exit::Destroy() {
+ SetControlInstruction(nullptr);
+ Base::Destroy();
+}
+
+void Exit::SetControlInstruction(ir::ControlInstruction* ctrl_inst) {
+ if (ctrl_inst_ == ctrl_inst) {
+ return;
+ }
+ if (ctrl_inst_) {
+ ctrl_inst_->RemoveExit(this);
+ }
+ ctrl_inst_ = ctrl_inst;
+ if (ctrl_inst_) {
+ ctrl_inst_->AddExit(this);
+ }
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/exit.h b/src/tint/ir/exit.h
new file mode 100644
index 0000000..f9734fb
--- /dev/null
+++ b/src/tint/ir/exit.h
@@ -0,0 +1,49 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_EXIT_H_
+#define SRC_TINT_IR_EXIT_H_
+
+#include "src/tint/ir/branch.h"
+
+// Forward declarations
+namespace tint::ir {
+class ControlInstruction;
+} // namespace tint::ir
+
+namespace tint::ir {
+
+/// The base class for all exit terminators.
+class Exit : public utils::Castable<Exit, Branch> {
+ public:
+ ~Exit() override;
+
+ /// @copydoc Value::Destroy
+ void Destroy() override;
+
+ protected:
+ /// @return the control instruction that this exit is associated with
+ ir::ControlInstruction* ControlInstruction() { return ctrl_inst_; }
+
+ /// Sets control instruction that this exit is associated with
+ /// @param ctrl_inst the new ControlInstruction that this exit is associated with
+ void SetControlInstruction(ir::ControlInstruction* ctrl_inst);
+
+ private:
+ ir::ControlInstruction* ctrl_inst_ = nullptr;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_EXIT_H_
diff --git a/src/tint/ir/exit_if.cc b/src/tint/ir/exit_if.cc
index 391c786..7c36a05 100644
--- a/src/tint/ir/exit_if.cc
+++ b/src/tint/ir/exit_if.cc
@@ -23,15 +23,19 @@
namespace tint::ir {
-ExitIf::ExitIf(ir::If* i, utils::VectorRef<Value*> args /* = utils::Empty */) : if_(i) {
- TINT_ASSERT(IR, if_);
-
- if (if_) {
- if_->Merge()->AddInboundSiblingBranch(this);
- }
- AddOperands(std::move(args));
+ExitIf::ExitIf(ir::If* i, utils::VectorRef<Value*> args) {
+ SetIf(i);
+ AddOperands(ExitIf::kArgsOperandOffset, std::move(args));
}
ExitIf::~ExitIf() = default;
+void ExitIf::SetIf(ir::If* i) {
+ SetControlInstruction(i);
+}
+
+ir::If* ExitIf::If() {
+ return static_cast<ir::If*>(ControlInstruction());
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/exit_if.h b/src/tint/ir/exit_if.h
index 5ddaabf..e3cf9e7 100644
--- a/src/tint/ir/exit_if.h
+++ b/src/tint/ir/exit_if.h
@@ -15,7 +15,7 @@
#ifndef SRC_TINT_IR_EXIT_IF_H_
#define SRC_TINT_IR_EXIT_IF_H_
-#include "src/tint/ir/branch.h"
+#include "src/tint/ir/exit.h"
#include "src/tint/utils/castable.h"
// Forward declarations
@@ -26,19 +26,23 @@
namespace tint::ir {
/// A exit if instruction.
-class ExitIf : public utils::Castable<ExitIf, Branch> {
+class ExitIf : public utils::Castable<ExitIf, Exit> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
/// @param i the if being exited
/// @param args the branch arguments
explicit ExitIf(ir::If* i, utils::VectorRef<Value*> args = utils::Empty);
~ExitIf() override;
- /// @returns the if being exited
- ir::If* If() { return if_; }
+ /// Re-associates the exit with the given if instruction
+ /// @param i the new If to exit from
+ void SetIf(ir::If* i);
- private:
- ir::If* if_ = nullptr;
+ /// @returns the if being exited
+ ir::If* If();
};
} // namespace tint::ir
diff --git a/src/tint/ir/exit_if_test.cc b/src/tint/ir/exit_if_test.cc
index f496d6c..b37b95e 100644
--- a/src/tint/ir/exit_if_test.cc
+++ b/src/tint/ir/exit_if_test.cc
@@ -15,7 +15,6 @@
#include "src/tint/ir/exit_if.h"
#include "gmock/gmock.h"
-#include "gtest/gtest-spi.h"
#include "src/tint/ir/ir_test_helper.h"
namespace tint::ir {
@@ -32,26 +31,26 @@
EXPECT_THAT(arg1->Usages(), testing::UnorderedElementsAre(Usage{e, 0u}));
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{e, 1u}));
+ EXPECT_EQ(if_->Result(), nullptr);
}
-TEST_F(IR_ExitIfTest, Fail_NullIf) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.ExitIf(nullptr);
- },
- "");
+TEST_F(IR_ExitIfTest, Result) {
+ auto* arg1 = b.Constant(1_u);
+ auto* arg2 = b.Constant(2_u);
+ auto* if_ = b.If(true);
+ auto* e = b.ExitIf(if_, arg1, arg2);
+
+ EXPECT_FALSE(e->HasResults());
+ EXPECT_FALSE(e->HasMultiResults());
}
-TEST_F(IR_ExitIfTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.ExitIf(b.If(false), nullptr);
- },
- "");
+TEST_F(IR_ExitIfTest, Destroy) {
+ auto* if_ = b.If(true);
+ auto* exit = b.ExitIf(if_);
+ EXPECT_THAT(if_->Exits(), testing::UnorderedElementsAre(exit));
+ exit->Destroy();
+ EXPECT_TRUE(if_->Exits().IsEmpty());
+ EXPECT_FALSE(exit->Alive());
}
} // namespace
diff --git a/src/tint/ir/exit_loop.cc b/src/tint/ir/exit_loop.cc
index 865b25c..39a59e1 100644
--- a/src/tint/ir/exit_loop.cc
+++ b/src/tint/ir/exit_loop.cc
@@ -24,16 +24,19 @@
namespace tint::ir {
-ExitLoop::ExitLoop(ir::Loop* loop, utils::VectorRef<Value*> args /* = utils::Empty */)
- : loop_(loop) {
- TINT_ASSERT(IR, loop_);
-
- if (loop_) {
- loop_->Merge()->AddInboundSiblingBranch(this);
- }
- AddOperands(std::move(args));
+ExitLoop::ExitLoop(ir::Loop* loop, utils::VectorRef<Value*> args /* = utils::Empty */) {
+ SetLoop(loop);
+ AddOperands(ExitLoop::kArgsOperandOffset, std::move(args));
}
ExitLoop::~ExitLoop() = default;
+void ExitLoop::SetLoop(ir::Loop* l) {
+ SetControlInstruction(l);
+}
+
+ir::Loop* ExitLoop::Loop() {
+ return static_cast<ir::Loop*>(ControlInstruction());
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/exit_loop.h b/src/tint/ir/exit_loop.h
index 2e7f2ea..253655e 100644
--- a/src/tint/ir/exit_loop.h
+++ b/src/tint/ir/exit_loop.h
@@ -15,7 +15,7 @@
#ifndef SRC_TINT_IR_EXIT_LOOP_H_
#define SRC_TINT_IR_EXIT_LOOP_H_
-#include "src/tint/ir/branch.h"
+#include "src/tint/ir/exit.h"
#include "src/tint/utils/castable.h"
// Forward declarations
@@ -26,19 +26,23 @@
namespace tint::ir {
/// A exit loop instruction.
-class ExitLoop : public utils::Castable<ExitLoop, Branch> {
+class ExitLoop : public utils::Castable<ExitLoop, Exit> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
/// @param loop the loop being exited
/// @param args the branch arguments
explicit ExitLoop(ir::Loop* loop, utils::VectorRef<Value*> args = utils::Empty);
~ExitLoop() override;
- /// @returns the loop being exited
- ir::Loop* Loop() { return loop_; }
+ /// Re-associates the exit with the given loop instruction
+ /// @param l the new loop to exit from
+ void SetLoop(ir::Loop* l);
- private:
- ir::Loop* loop_ = nullptr;
+ /// @returns the loop being exited
+ ir::Loop* Loop();
};
} // namespace tint::ir
diff --git a/src/tint/ir/exit_loop_test.cc b/src/tint/ir/exit_loop_test.cc
index 2b8b3de..5a69d0f 100644
--- a/src/tint/ir/exit_loop_test.cc
+++ b/src/tint/ir/exit_loop_test.cc
@@ -15,7 +15,6 @@
#include "src/tint/ir/exit_loop.h"
#include "gmock/gmock.h"
-#include "gtest/gtest-spi.h"
#include "src/tint/ir/ir_test_helper.h"
namespace tint::ir {
@@ -32,26 +31,16 @@
EXPECT_THAT(arg1->Usages(), testing::UnorderedElementsAre(Usage{e, 0u}));
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{e, 1u}));
+ EXPECT_EQ(loop->Result(), nullptr);
}
-TEST_F(IR_ExitLoopTest, Fail_NullLoop) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.ExitLoop(nullptr);
- },
- "");
-}
-
-TEST_F(IR_ExitLoopTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.ExitLoop(b.Loop(), nullptr);
- },
- "");
+TEST_F(IR_ExitLoopTest, Destroy) {
+ auto* loop = b.Loop();
+ auto* exit = b.ExitLoop(loop);
+ EXPECT_THAT(loop->Exits(), testing::UnorderedElementsAre(exit));
+ exit->Destroy();
+ EXPECT_TRUE(loop->Exits().IsEmpty());
+ EXPECT_FALSE(exit->Alive());
}
} // namespace
diff --git a/src/tint/ir/exit_switch.cc b/src/tint/ir/exit_switch.cc
index 3372d6d..d56c310 100644
--- a/src/tint/ir/exit_switch.cc
+++ b/src/tint/ir/exit_switch.cc
@@ -23,16 +23,19 @@
namespace tint::ir {
-ExitSwitch::ExitSwitch(ir::Switch* sw, utils::VectorRef<Value*> args /* = utils::Empty */)
- : switch_(sw) {
- TINT_ASSERT(IR, switch_);
-
- if (switch_) {
- switch_->Merge()->AddInboundSiblingBranch(this);
- }
- AddOperands(std::move(args));
+ExitSwitch::ExitSwitch(ir::Switch* sw, utils::VectorRef<Value*> args /* = utils::Empty */) {
+ SetSwitch(sw);
+ AddOperands(ExitSwitch::kArgsOperandOffset, std::move(args));
}
ExitSwitch::~ExitSwitch() = default;
+void ExitSwitch::SetSwitch(ir::Switch* s) {
+ SetControlInstruction(s);
+}
+
+ir::Switch* ExitSwitch::Switch() {
+ return static_cast<ir::Switch*>(ControlInstruction());
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/exit_switch.h b/src/tint/ir/exit_switch.h
index 706ac69..9567a59 100644
--- a/src/tint/ir/exit_switch.h
+++ b/src/tint/ir/exit_switch.h
@@ -15,7 +15,7 @@
#ifndef SRC_TINT_IR_EXIT_SWITCH_H_
#define SRC_TINT_IR_EXIT_SWITCH_H_
-#include "src/tint/ir/branch.h"
+#include "src/tint/ir/exit.h"
#include "src/tint/utils/castable.h"
// Forward declarations
@@ -26,19 +26,23 @@
namespace tint::ir {
/// A exit switch instruction.
-class ExitSwitch : public utils::Castable<ExitSwitch, Branch> {
+class ExitSwitch : public utils::Castable<ExitSwitch, Exit> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
/// @param sw the switch being exited
/// @param args the branch arguments
explicit ExitSwitch(ir::Switch* sw, utils::VectorRef<Value*> args = utils::Empty);
~ExitSwitch() override;
- /// @returns the switch being exited
- ir::Switch* Switch() { return switch_; }
+ /// Re-associates the exit with the given switch instruction
+ /// @param s the new switch to exit from
+ void SetSwitch(ir::Switch* s);
- private:
- ir::Switch* switch_ = nullptr;
+ /// @returns the switch being exited
+ ir::Switch* Switch();
};
} // namespace tint::ir
diff --git a/src/tint/ir/exit_switch_test.cc b/src/tint/ir/exit_switch_test.cc
index 85cb228..3ab84df 100644
--- a/src/tint/ir/exit_switch_test.cc
+++ b/src/tint/ir/exit_switch_test.cc
@@ -15,7 +15,6 @@
#include "src/tint/ir/exit_switch.h"
#include "gmock/gmock.h"
-#include "gtest/gtest-spi.h"
#include "src/tint/ir/ir_test_helper.h"
namespace tint::ir {
@@ -32,26 +31,26 @@
EXPECT_THAT(arg1->Usages(), testing::UnorderedElementsAre(Usage{e, 0u}));
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{e, 1u}));
+ EXPECT_EQ(switch_->Result(), nullptr);
}
-TEST_F(IR_ExitSwitchTest, Fail_NullSwitch) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.ExitSwitch(nullptr);
- },
- "");
+TEST_F(IR_ExitSwitchTest, Result) {
+ auto* arg1 = b.Constant(1_u);
+ auto* arg2 = b.Constant(2_u);
+ auto* switch_ = b.Switch(true);
+ auto* e = b.ExitSwitch(switch_, arg1, arg2);
+
+ EXPECT_FALSE(e->HasResults());
+ EXPECT_FALSE(e->HasMultiResults());
}
-TEST_F(IR_ExitSwitchTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.ExitSwitch(b.Switch(false), nullptr);
- },
- "");
+TEST_F(IR_ExitSwitchTest, Destroy) {
+ auto* swch = b.Switch(1_i);
+ auto* exit = b.ExitSwitch(swch);
+ EXPECT_THAT(swch->Exits(), testing::UnorderedElementsAre(exit));
+ exit->Destroy();
+ EXPECT_TRUE(swch->Exits().IsEmpty());
+ EXPECT_FALSE(exit->Alive());
}
} // namespace
diff --git a/src/tint/ir/from_program.cc b/src/tint/ir/from_program.cc
index 8ffa513..c831d83 100644
--- a/src/tint/ir/from_program.cc
+++ b/src/tint/ir/from_program.cc
@@ -109,10 +109,6 @@
using ResultType = utils::Result<Module, diag::List>;
-bool IsConnected(MultiInBlock* b) {
- return b->InboundSiblingBranches().Length() > 0;
-}
-
/// Impl is the private-implementation of FromProgram().
class Impl {
public:
@@ -186,7 +182,7 @@
current_block_ = nullptr;
}
- Branch* FindEnclosingControl(ControlFlags flags) {
+ Instruction* FindEnclosingControl(ControlFlags flags) {
for (auto it = control_stack_.rbegin(); it != control_stack_.rend(); ++it) {
if ((*it)->Is<Loop>()) {
return *it;
@@ -421,7 +417,7 @@
}
ir_func->SetParams(params);
- current_block_ = ir_func->StartTarget();
+ TINT_SCOPED_ASSIGNMENT(current_block_, ir_func->StartTarget());
EmitBlock(ast_func->body);
// If the branch target has already been set then a `return` was called. Only set in
@@ -439,10 +435,9 @@
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 (!NeedBranch()) {
- break;
+ if (auto* sem = program_->Sem().Get(s);
+ sem && !sem->Behaviors().Contains(sem::Behavior::kNext)) {
+ break; // Unreachable statement.
}
}
}
@@ -508,7 +503,7 @@
auto* lhs_value = builder_.Load(lhs.Get());
current_block_->Append(lhs_value);
- auto* ty = lhs_value->Type();
+ auto* ty = lhs_value->Result()->Type();
auto* rhs =
ty->is_signed_integer_scalar() ? builder_.Constant(1_i) : builder_.Constant(1_u);
@@ -540,7 +535,7 @@
auto* lhs_value = builder_.Load(lhs.Get());
current_block_->Append(lhs_value);
- auto* ty = lhs_value->Type();
+ auto* ty = lhs_value->Result()->Type();
Binary* inst = nullptr;
switch (stmt->op) {
@@ -616,75 +611,59 @@
{
ControlStackScope scope(this, if_inst);
- current_block_ = if_inst->True();
- EmitBlock(stmt->body);
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True());
+ EmitBlock(stmt->body);
- // If the true branch did not execute control flow, then go to the Merge().target
- if (NeedBranch()) {
- SetBranch(builder_.ExitIf(if_inst));
+ // If the true block did not branch, then emit an exit_if
+ if (NeedBranch()) {
+ SetBranch(builder_.ExitIf(if_inst));
+ }
}
- current_block_ = if_inst->False();
if (stmt->else_statement) {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False());
EmitStatement(stmt->else_statement);
- }
- // If the false branch did not execute control flow, then go to the Merge().target
- if (NeedBranch()) {
- SetBranch(builder_.ExitIf(if_inst));
+ // If the false block did not branch, then emit an exit_if
+ if (NeedBranch()) {
+ SetBranch(builder_.ExitIf(if_inst));
+ }
}
}
- current_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_inst->Merge())) {
- current_block_ = if_inst->Merge();
- }
}
void EmitLoop(const ast::LoopStatement* stmt) {
auto* loop_inst = builder_.Loop();
current_block_->Append(loop_inst);
- {
- ControlStackScope scope(this, loop_inst);
- current_block_ = loop_inst->Body();
+ ControlStackScope scope(this, loop_inst);
- // 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());
+ // 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());
+
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Body());
+
EmitStatements(stmt->body->statements);
// The current block didn't `break`, `return` or `continue`, go to the continuing block.
if (NeedBranch()) {
SetBranch(builder_.Continue(loop_inst));
}
-
- if (IsConnected(loop_inst->Continuing())) {
- // Note, even if there is no continuing block, we may have branched into the
- // continue so we have to set the current block and then emit the branch if needed
- // below otherwise empty continuing blocks will fail to branch back to the start
- // block.
- current_block_ = loop_inst->Continuing();
- if (stmt->continuing) {
- EmitBlock(stmt->continuing);
- }
- // Branch back to the start node if the continue target didn't branch out already
- if (NeedBranch()) {
- SetBranch(builder_.NextIteration(loop_inst));
- }
- }
}
- // 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() block.
- current_block_ = loop_inst->Merge();
- if (!IsConnected(loop_inst->Merge())) {
- current_block_ = nullptr;
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Continuing());
+ if (stmt->continuing) {
+ EmitBlock(stmt->continuing);
+ }
+ // Branch back to the start block if the continue target didn't branch out already
+ if (NeedBranch()) {
+ SetBranch(builder_.NextIteration(loop_inst));
+ }
}
}
@@ -692,14 +671,16 @@
auto* loop_inst = builder_.Loop();
current_block_->Append(loop_inst);
+ ControlStackScope scope(this, loop_inst);
+
// Continue is always empty, just go back to the start
- current_block_ = loop_inst->Continuing();
- SetBranch(builder_.NextIteration(loop_inst));
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Continuing());
+ SetBranch(builder_.NextIteration(loop_inst));
+ }
{
- ControlStackScope scope(this, loop_inst);
-
- current_block_ = loop_inst->Body();
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Body());
// Emit the while condition into the Start().target of the loop
auto reg = EmitExpression(stmt->condition);
@@ -711,22 +692,20 @@
auto* if_inst = builder_.If(reg.Get());
current_block_->Append(if_inst);
- current_block_ = if_inst->True();
- SetBranch(builder_.ExitIf(if_inst));
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True());
+ SetBranch(builder_.ExitIf(if_inst));
+ }
- current_block_ = if_inst->False();
- SetBranch(builder_.ExitLoop(loop_inst));
-
- current_block_ = if_inst->Merge();
- EmitBlock(stmt->body);
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False());
+ SetBranch(builder_.ExitLoop(loop_inst));
+ }
if (NeedBranch()) {
SetBranch(builder_.Continue(loop_inst));
}
}
- // The while loop always has a path to the Merge().target as the break statement comes
- // before anything inside the loop.
- current_block_ = loop_inst->Merge();
}
void EmitForLoop(const ast::ForLoopStatement* stmt) {
@@ -737,52 +716,53 @@
scopes_.Push();
TINT_DEFER(scopes_.Pop());
- {
- ControlStackScope scope(this, loop_inst);
+ ControlStackScope scope(this, loop_inst);
- if (stmt->initializer) {
- // Emit the for initializer before branching to the body
- current_block_ = loop_inst->Initializer();
- EmitStatement(stmt->initializer);
- SetBranch(builder_.NextIteration(loop_inst));
- }
+ if (stmt->initializer) {
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Initializer());
- current_block_ = loop_inst->Body();
- if (stmt->condition) {
- // Emit the condition into the target target of the loop
- auto reg = EmitExpression(stmt->condition);
- if (!reg) {
- return;
- }
+ // Emit the for initializer before branching to the loop body
+ EmitStatement(stmt->initializer);
- // Create an `if (cond) {} else {break;}` control flow
- auto* if_inst = builder_.If(reg.Get());
- current_block_->Append(if_inst);
-
- current_block_ = if_inst->True();
- SetBranch(builder_.ExitIf(if_inst));
-
- current_block_ = if_inst->False();
- SetBranch(builder_.ExitLoop(loop_inst));
-
- current_block_ = if_inst->Merge();
- }
-
- EmitBlock(stmt->body);
if (NeedBranch()) {
- SetBranch(builder_.Continue(loop_inst));
- }
-
- if (stmt->continuing) {
- current_block_ = loop_inst->Continuing();
- EmitStatement(stmt->continuing);
SetBranch(builder_.NextIteration(loop_inst));
}
}
- // The while loop always has a path to the Merge().target as the break statement comes
- // before anything inside the loop.
- current_block_ = loop_inst->Merge();
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Body());
+
+ if (stmt->condition) {
+ // Emit the condition into the target target of the loop body
+ auto reg = EmitExpression(stmt->condition);
+ if (!reg) {
+ return;
+ }
+
+ // Create an `if (cond) {} else {break;}` control flow
+ auto* if_inst = builder_.If(reg.Get());
+ current_block_->Append(if_inst);
+
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True());
+ SetBranch(builder_.ExitIf(if_inst));
+ }
+
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False());
+ SetBranch(builder_.ExitLoop(loop_inst));
+ }
+ }
+
+ EmitBlock(stmt->body);
+ if (NeedBranch()) {
+ SetBranch(builder_.Continue(loop_inst));
+ }
+
+ if (stmt->continuing) {
+ TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Continuing());
+ EmitStatement(stmt->continuing);
+ SetBranch(builder_.NextIteration(loop_inst));
+ }
}
void EmitSwitch(const ast::SwitchStatement* stmt) {
@@ -794,32 +774,25 @@
auto* switch_inst = builder_.Switch(reg.Get());
current_block_->Append(switch_inst);
- {
- ControlStackScope scope(this, switch_inst);
+ ControlStackScope scope(this, switch_inst);
- 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_block_ = builder_.Case(switch_inst, selectors);
- EmitBlock(c->Body()->Declaration());
-
- if (NeedBranch()) {
- SetBranch(builder_.ExitSwitch(switch_inst));
+ 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_block_ = nullptr;
- if (IsConnected(switch_inst->Merge())) {
- current_block_ = switch_inst->Merge();
+ TINT_SCOPED_ASSIGNMENT(current_block_, builder_.Case(switch_inst, selectors));
+ EmitBlock(c->Body()->Declaration());
+
+ if (NeedBranch()) {
+ SetBranch(builder_.ExitSwitch(switch_inst));
+ }
}
}
@@ -885,7 +858,7 @@
struct AccessorInfo {
Value* object = nullptr;
- Instruction* result = nullptr;
+ Value* result = nullptr;
const type::Type* result_type = nullptr;
utils::Vector<Value*, 1> indices;
};
@@ -944,7 +917,7 @@
return info.result;
}
- Instruction* GenerateAccess(const AccessorInfo& info) {
+ Value* GenerateAccess(const AccessorInfo& info) {
// The access result type should match the source result type. If the source is a pointer,
// we generate a pointer.
const type::Type* ty = nullptr;
@@ -957,7 +930,7 @@
auto* a = builder_.Access(ty, info.object, info.indices);
current_block_->Append(a);
- return a;
+ return a->Result();
}
bool GenerateIndexAccessor(const ast::IndexAccessorExpression* expr, AccessorInfo& info) {
@@ -1005,14 +978,15 @@
if (auto* ptr = info.object->Type()->As<type::Pointer>()) {
auto* load = builder_.Load(info.object);
info.result_type = ptr->StoreType();
- info.object = load;
+ info.object = load->Result();
current_block_->Append(load);
}
}
- info.result = builder_.Swizzle(swizzle->Type()->Clone(clone_ctx_.type_ctx),
- info.object, std::move(indices));
- current_block_->Append(info.result);
+ auto* val = builder_.Swizzle(swizzle->Type()->Clone(clone_ctx_.type_ctx),
+ info.object, std::move(indices));
+ current_block_->Append(val);
+ info.result = val->Result();
info.object = info.result;
info.result_type = result_type;
@@ -1065,7 +1039,7 @@
if (result && sem->Is<sem::Load>()) {
auto* load = builder_.Load(result.Get());
current_block_->Append(load);
- return load;
+ return load->Result();
}
return result;
}
@@ -1097,7 +1071,7 @@
}
// Store the declaration so we can get the instruction to store too
- scopes_.Set(v->name->symbol, val);
+ scopes_.Set(v->name->symbol, val->Result());
// Record the original name of the var
builder_.ir.SetName(val, v->name->symbol.Name());
@@ -1162,10 +1136,10 @@
}
current_block_->Append(inst);
- return inst;
+ return inst->Result();
}
- // A short-circut needs special treatment. The short-circuit is decomposed into the relevant
+ // A short-circuit 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) {
@@ -1174,7 +1148,7 @@
break;
default:
TINT_ICE(IR, diagnostics_)
- << "invalid operation type for short-circut decomposition";
+ << "invalid operation type for short-circuit decomposition";
return utils::Failure;
}
@@ -1187,44 +1161,50 @@
auto* if_inst = builder_.If(lhs.Get());
current_block_->Append(if_inst);
- auto* result = builder_.BlockParam(builder_.ir.Types().bool_());
- if_inst->Merge()->SetParams({result});
+ auto* result = builder_.InstructionResult(builder_.ir.Types().bool_());
+ if_inst->SetResults(result);
- utils::Result<Value*> rhs;
- {
- ControlStackScope scope(this, if_inst);
+ ControlStackScope scope(this, if_inst);
- utils::Vector<Value*, 1> alt_args;
- alt_args.Push(lhs.Get());
-
- // 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) {
- // If the lhs is false, then that is the result we want to pass to the merge
- // block as our argument
- current_block_ = if_inst->False();
- SetBranch(builder_.ExitIf(if_inst, std::move(alt_args)));
-
- current_block_ = if_inst->True();
- } else {
- // If the lhs is true, then that is the result we want to pass to the merge
- // block as our argument
- current_block_ = if_inst->True();
- SetBranch(builder_.ExitIf(if_inst, std::move(alt_args)));
-
- current_block_ = if_inst->False();
+ if (expr->op == ast::BinaryOp::kLogicalAnd) {
+ // res = lhs && rhs;
+ //
+ // transform into:
+ //
+ // if (lhs) {
+ // res = rhs;
+ // } else {
+ // res = lhs;
+ // }
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True());
+ auto rhs = EmitExpression(expr->rhs);
+ SetBranch(builder_.ExitIf(if_inst, utils::Vector{rhs.Get()}));
}
-
- rhs = EmitExpression(expr->rhs);
- if (!rhs) {
- return utils::Failure;
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False());
+ SetBranch(builder_.ExitIf(if_inst, utils::Vector{lhs.Get()}));
}
- utils::Vector<Value*, 1> args;
- args.Push(rhs.Get());
-
- SetBranch(builder_.ExitIf(if_inst, std::move(args)));
+ } else {
+ // res = lhs || rhs;
+ //
+ // transform into:
+ //
+ // if (lhs) {
+ // res = lhs;
+ // } else {
+ // res = rhs;
+ // }
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True());
+ SetBranch(builder_.ExitIf(if_inst, utils::Vector{lhs.Get()}));
+ }
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False());
+ auto rhs = EmitExpression(expr->rhs);
+ SetBranch(builder_.ExitIf(if_inst, utils::Vector{rhs.Get()}));
+ }
}
- current_block_ = if_inst->Merge();
return result;
}
@@ -1307,7 +1287,7 @@
}
current_block_->Append(inst);
- return inst;
+ return inst->Result();
}
utils::Result<Value*> EmitBitcast(const ast::BitcastExpression* expr) {
@@ -1321,7 +1301,7 @@
auto* inst = builder_.Bitcast(ty, val.Get());
current_block_->Append(inst);
- return inst;
+ return inst->Result();
}
void EmitCall(const ast::CallStatement* stmt) { (void)EmitCall(stmt->expr); }
@@ -1384,7 +1364,7 @@
return utils::Failure;
}
current_block_->Append(inst);
- return inst;
+ return inst->Result();
}
utils::Result<Value*> EmitLiteral(const ast::LiteralExpression* lit) {
diff --git a/src/tint/ir/from_program_accessor_test.cc b/src/tint/ir/from_program_accessor_test.cc
index d8e6601..3628f10 100644
--- a/src/tint/ir/from_program_accessor_test.cc
+++ b/src/tint/ir/from_program_accessor_test.cc
@@ -24,7 +24,8 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using IR_FromProgramAccessorTest = ProgramTestHelper;
@@ -348,7 +349,7 @@
// let a: mat3x4<f32> = mat3x4<u32>()
// let b = a[2][3]
- auto* a = Let("a", ty.mat3x4<f32>(), mat3x4<f32>());
+ auto* a = Let("a", ty.mat3x4<f32>(), Call<mat3x4<f32>>());
auto* expr = Decl(Let("b", IndexAccessor(IndexAccessor(a, 2_u), 3_u)));
WrapInFunction(Block(utils::Vector{Decl(a), expr}));
@@ -448,7 +449,7 @@
Member("a", ty.i32()),
Member("foo", ty.array(ty.Of(inner), 4_u)),
});
- auto* a = Let("a", ty.array(ty.Of(outer), 4_u), array(ty.Of(outer), 4_u));
+ auto* a = Let("a", ty.array(ty.Of(outer), 4_u), Call(ty.array(ty.Of(outer), 4_u)));
auto* expr = Decl(Let(
"b",
MemberAccessor(IndexAccessor(MemberAccessor(IndexAccessor(a, 0_u), "foo"), 1_u), "bar")));
diff --git a/src/tint/ir/from_program_binary_test.cc b/src/tint/ir/from_program_binary_test.cc
index a3bcb1e..86570e4 100644
--- a/src/tint/ir/from_program_binary_test.cc
+++ b/src/tint/ir/from_program_binary_test.cc
@@ -451,8 +451,9 @@
TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_LogicalAnd) {
Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
- auto* expr = If(LogicalAnd(Call("my_func"), false), Block());
- WrapInFunction(expr);
+ auto* let = Let("logical_and", LogicalAnd(Call("my_func"), false));
+ auto* expr = If(let, Block());
+ WrapInFunction(let, expr);
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
@@ -465,37 +466,24 @@
%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = call %my_func
- if %3 [t: %b3, f: %b4, m: %b5]
+ %logical_and:bool = if %3 [t: %b3, f: %b4]
# True block
%b3 = block {
- exit_if %b5 false
+ exit_if false
}
# False block
%b4 = block {
- exit_if %b5 %3
+ exit_if %3
}
- # Merge block
- %b5 = block (%4:bool) {
- if %4:bool [t: %b6, f: %b7, m: %b8]
- # True block
- %b6 = block {
- exit_if %b8
- }
-
- # False block
- %b7 = block {
- exit_if %b8
- }
-
- # Merge block
- %b8 = block {
- ret
+ if %logical_and [t: %b5]
+ # True block
+ %b5 = block {
+ exit_if
}
- }
-
+ ret
}
}
)");
@@ -503,8 +491,9 @@
TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_LogicalOr) {
Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
- auto* expr = If(LogicalOr(Call("my_func"), true), Block());
- WrapInFunction(expr);
+ auto* let = Let("logical_or", LogicalOr(Call("my_func"), true));
+ auto* expr = If(let, Block());
+ WrapInFunction(let, expr);
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
@@ -517,37 +506,24 @@
%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = call %my_func
- if %3 [t: %b3, f: %b4, m: %b5]
+ %logical_or:bool = if %3 [t: %b3, f: %b4]
# True block
%b3 = block {
- exit_if %b5 %3
+ exit_if %3
}
# False block
%b4 = block {
- exit_if %b5 true
+ exit_if true
}
- # Merge block
- %b5 = block (%4:bool) {
- if %4:bool [t: %b6, f: %b7, m: %b8]
- # True block
- %b6 = block {
- exit_if %b8
- }
-
- # False block
- %b7 = block {
- exit_if %b8
- }
-
- # Merge block
- %b8 = block {
- ret
+ if %logical_or [t: %b5]
+ # True block
+ %b5 = block {
+ exit_if
}
- }
-
+ ret
}
}
)");
@@ -804,27 +780,23 @@
%b2 = block {
%3:f32 = call %my_func
%4:bool = lt %3, 2.0f
- if %4 [t: %b3, f: %b4, m: %b5]
+ %tint_symbol:bool = if %4 [t: %b3, f: %b4]
# True block
%b3 = block {
- %5:f32 = call %my_func
%6:f32 = call %my_func
- %7:f32 = mul 2.29999995231628417969f, %6
- %8:f32 = div %5, %7
- %9:bool = gt 2.5f, %8
- exit_if %b5 %9
+ %7:f32 = call %my_func
+ %8:f32 = mul 2.29999995231628417969f, %7
+ %9:f32 = div %6, %8
+ %10:bool = gt 2.5f, %9
+ exit_if %10
}
# False block
%b4 = block {
- exit_if %b5 %4
+ exit_if %4
}
- # Merge block
- %b5 = block (%tint_symbol:bool) {
- ret
- }
-
+ ret
}
}
)");
diff --git a/src/tint/ir/from_program_call_test.cc b/src/tint/ir/from_program_call_test.cc
index ce89975..1148f56 100644
--- a/src/tint/ir/from_program_call_test.cc
+++ b/src/tint/ir/from_program_call_test.cc
@@ -21,7 +21,8 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using IR_FromProgramCallTest = ProgramTestHelper;
@@ -92,7 +93,7 @@
TEST_F(IR_FromProgramCallTest, EmitExpression_Convert) {
auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i));
- auto* expr = Call(ty.f32(), i);
+ auto* expr = Call<f32>(i);
WrapInFunction(expr);
auto m = Build();
@@ -114,7 +115,7 @@
}
TEST_F(IR_FromProgramCallTest, EmitExpression_ConstructEmpty) {
- auto* expr = vec3(ty.f32());
+ auto* expr = Call<vec3<f32>>();
GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
auto m = Build();
@@ -130,7 +131,7 @@
TEST_F(IR_FromProgramCallTest, EmitExpression_Construct) {
auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
- auto* expr = vec3(ty.f32(), 2_f, 3_f, i);
+ auto* expr = Call<vec3<f32>>(2_f, 3_f, i);
WrapInFunction(expr);
auto m = Build();
diff --git a/src/tint/ir/from_program_function_test.cc b/src/tint/ir/from_program_function_test.cc
index c467f28..2fce0e7 100644
--- a/src/tint/ir/from_program_function_test.cc
+++ b/src/tint/ir/from_program_function_test.cc
@@ -21,12 +21,14 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using IR_FromProgramFunctionTest = ProgramTestHelper;
TEST_F(IR_FromProgramFunctionTest, EmitFunction_Vertex) {
- Func("test", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(vec4<f32>(0_f, 0_f, 0_f, 0_f))},
+ Func("test", utils::Empty, ty.vec4<f32>(),
+ utils::Vector{Return(Call<vec4<f32>>(0_f, 0_f, 0_f, 0_f))},
utils::Vector{Stage(ast::PipelineStage::kVertex)},
utils::Vector{Builtin(builtin::BuiltinValue::kPosition)});
@@ -73,8 +75,8 @@
}
TEST_F(IR_FromProgramFunctionTest, EmitFunction_Return) {
- Func("test", utils::Empty, ty.vec3<f32>(), utils::Vector{Return(vec3<f32>(0_f, 0_f, 0_f))},
- utils::Empty);
+ Func("test", utils::Empty, ty.vec3<f32>(),
+ utils::Vector{Return(Call<vec3<f32>>(0_f, 0_f, 0_f))}, utils::Empty);
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
@@ -88,7 +90,8 @@
}
TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnPosition) {
- Func("test", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(vec4<f32>(1_f, 2_f, 3_f, 4_f))},
+ Func("test", utils::Empty, ty.vec4<f32>(),
+ utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
utils::Vector{Stage(ast::PipelineStage::kVertex)},
utils::Vector{Builtin(builtin::BuiltinValue::kPosition)});
@@ -104,7 +107,8 @@
}
TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnPositionInvariant) {
- Func("test", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(vec4<f32>(1_f, 2_f, 3_f, 4_f))},
+ Func("test", utils::Empty, ty.vec4<f32>(),
+ utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
utils::Vector{Stage(ast::PipelineStage::kVertex)},
utils::Vector{Builtin(builtin::BuiltinValue::kPosition), Invariant()});
@@ -121,7 +125,8 @@
}
TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnLocation) {
- Func("test", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(vec4<f32>(1_f, 2_f, 3_f, 4_f))},
+ Func("test", utils::Empty, ty.vec4<f32>(),
+ utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
utils::Vector{Stage(ast::PipelineStage::kFragment)}, utils::Vector{Location(1_i)});
auto m = Build();
@@ -137,7 +142,8 @@
}
TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnLocation_Interpolate) {
- Func("test", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(vec4<f32>(1_f, 2_f, 3_f, 4_f))},
+ Func("test", utils::Empty, ty.vec4<f32>(),
+ utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
utils::Vector{Stage(ast::PipelineStage::kFragment)},
utils::Vector{Location(1_i), Interpolate(builtin::InterpolationType::kLinear,
builtin::InterpolationSampling::kCentroid)});
diff --git a/src/tint/ir/from_program_test.cc b/src/tint/ir/from_program_test.cc
index 679ec8a..1dd8f24 100644
--- a/src/tint/ir/from_program_test.cc
+++ b/src/tint/ir/from_program_test.cc
@@ -31,10 +31,10 @@
/// If multiple flow nodes are found with the type T, then an error is raised and the first is
/// returned.
template <typename T>
-T* FindSingleValue(Module& mod) {
+T* FindSingleInstruction(Module& mod) {
T* found = nullptr;
size_t count = 0;
- for (auto* node : mod.values.Objects()) {
+ for (auto* node : mod.instructions.Objects()) {
if (auto* as = node->As<T>()) {
count++;
if (!found) {
@@ -43,7 +43,7 @@
}
}
if (count > 1) {
- ADD_FAILURE() << "FindSingleValue() found " << count << " nodes of type "
+ ADD_FAILURE() << "FindSingleInstruction() found " << count << " nodes of type "
<< utils::TypeInfo::Of<T>().name;
}
return found;
@@ -135,31 +135,24 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* if_ = FindSingleValue<ir::If>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(2u, if_->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- if true [t: %b2, f: %b3, m: %b4]
+ if true [t: %b2, f: %b3]
# True block
%b2 = block {
- exit_if %b4
+ exit_if
}
# False block
%b3 = block {
- exit_if %b4
+ exit_if
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -173,31 +166,19 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* if_ = FindSingleValue<ir::If>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(1u, if_->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- if true [t: %b2, f: %b3, m: %b4]
+ if true [t: %b2]
# True block
%b2 = block {
ret
}
- # False block
- %b3 = block {
- exit_if %b4
- }
-
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -211,19 +192,16 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* if_ = FindSingleValue<ir::If>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(1u, if_->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- if true [t: %b2, f: %b3, m: %b4]
+ if true [t: %b2, f: %b3]
# True block
%b2 = block {
- exit_if %b4
+ exit_if
}
# False block
@@ -231,11 +209,7 @@
ret
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -249,12 +223,9 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* if_ = FindSingleValue<ir::If>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(0u, if_->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
@@ -269,6 +240,7 @@
ret
}
+ ret
}
}
)");
@@ -287,32 +259,24 @@
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- if true [t: %b2, f: %b3, m: %b4]
+ if true [t: %b2]
# True block
%b2 = block {
- loop [b: %b5, m: %b6]
+ loop [b: %b3, c: %b4]
# Body block
- %b5 = block {
- exit_loop %b6
+ %b3 = block {
+ exit_loop
}
- # Merge block
- %b6 = block {
- exit_if %b4
- }
+ # Continuing block
+ %b4 = block {
+ next_iteration %b3
+ }
+ exit_if
}
- # False block
- %b3 = block {
- exit_if %b4
- }
-
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -326,28 +290,28 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(0u, loop->Body()->InboundSiblingBranches().Length());
+ EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, m: %b3]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
- exit_loop %b3
+ exit_loop
}
- # Merge block
- %b3 = block {
- ret
- }
+ # Continuing block
+ %b3 = block {
+ next_iteration %b2
+ }
+ ret
}
}
)");
@@ -362,36 +326,26 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, c: %b3, m: %b4]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
- if true [t: %b5, f: %b6, m: %b7]
+ if true [t: %b4]
# True block
- %b5 = block {
- exit_loop %b4
+ %b4 = block {
+ exit_loop
}
- # False block
- %b6 = block {
- exit_if %b7
- }
-
- # Merge block
- %b7 = block {
- continue %b3
- }
-
+ continue %b3
}
# Continuing block
@@ -399,11 +353,7 @@
next_iteration %b2
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -418,18 +368,17 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, c: %b3, m: %b4]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
continue %b3
@@ -440,11 +389,7 @@
break_if true %b2
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -463,7 +408,7 @@
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, c: %b3, m: %b4]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
continue %b3
@@ -474,11 +419,7 @@
break_if true %b2
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -493,13 +434,12 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(0u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
@@ -507,22 +447,13 @@
loop [b: %b2, c: %b3]
# Body block
%b2 = block {
- if true [t: %b4, f: %b5, m: %b6]
+ if true [t: %b4]
# True block
%b4 = block {
ret
}
- # False block
- %b5 = block {
- exit_if %b6
- }
-
- # Merge block
- %b6 = block {
- continue %b3
- }
-
+ continue %b3
}
# Continuing block
@@ -530,6 +461,7 @@
next_iteration %b2
}
+ ret
}
}
)");
@@ -543,23 +475,28 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(0u, loop->Body()->InboundSiblingBranches().Length());
+ EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(0u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
ret
}
+ # Continuing block
+ %b3 = block {
+ next_iteration %b2
+ }
+
+ ret
}
}
)");
@@ -582,23 +519,34 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(0u, loop->Body()->InboundSiblingBranches().Length());
+ EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(0u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
ret
}
+ # Continuing block
+ %b3 = block {
+ break_if true %b2
+ }
+
+ if true [t: %b4]
+ # True block
+ %b4 = block {
+ ret
+ }
+
+ ret
}
}
)");
@@ -613,38 +561,39 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
- EXPECT_EQ(0u, loop->Body()->InboundSiblingBranches().Length());
- EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(2u, loop->Merge()->InboundSiblingBranches().Length());
+ EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
+ EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, m: %b3]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
if true [t: %b4, f: %b5]
# True block
%b4 = block {
- exit_loop %b3
+ exit_loop
}
# False block
%b5 = block {
- exit_loop %b3
+ exit_loop
}
+ continue %b3
}
- # Merge block
- %b3 = block {
- ret
- }
+ # Continuing block
+ %b3 = block {
+ next_iteration %b2
+ }
+ ret
}
}
)");
@@ -670,95 +619,61 @@
EXPECT_EQ(Disassemble(m.Get()),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, c: %b3, m: %b4]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
- loop [b: %b5, c: %b6, m: %b7]
+ loop [b: %b4, c: %b5]
# Body block
- %b5 = block {
- if true [t: %b8, f: %b9, m: %b10]
+ %b4 = block {
+ if true [t: %b6]
# True block
- %b8 = block {
- exit_loop %b7
+ %b6 = block {
+ exit_loop
}
- # False block
- %b9 = block {
- exit_if %b10
+ if true [t: %b7]
+ # True block
+ %b7 = block {
+ continue %b5
}
- # Merge block
- %b10 = block {
- if true [t: %b11, f: %b12, m: %b13]
- # True block
- %b11 = block {
- continue %b6
- }
-
- # False block
- %b12 = block {
- exit_if %b13
- }
-
- # Merge block
- %b13 = block {
- continue %b6
- }
-
- }
-
+ continue %b5
}
# Continuing block
- %b6 = block {
- loop [b: %b14, m: %b15]
+ %b5 = block {
+ loop [b: %b8, c: %b9]
# Body block
- %b14 = block {
- exit_loop %b15
+ %b8 = block {
+ exit_loop
}
- # Merge block
- %b15 = block {
- loop [b: %b16, c: %b17, m: %b18]
- # Body block
- %b16 = block {
- continue %b17
- }
-
- # Continuing block
- %b17 = block {
- break_if true %b16
- }
-
- # Merge block
- %b18 = block {
- next_iteration %b5
+ # Continuing block
+ %b9 = block {
+ next_iteration %b8
}
- }
+ loop [b: %b10, c: %b11]
+ # Body block
+ %b10 = block {
+ continue %b11
+ }
+ # Continuing block
+ %b11 = block {
+ break_if true %b10
+ }
+
+ next_iteration %b4
}
- # Merge block
- %b7 = block {
- if true [t: %b19, f: %b20, m: %b21]
- # True block
- %b19 = block {
- exit_loop %b4
- }
-
- # False block
- %b20 = block {
- exit_if %b21
- }
-
- # Merge block
- %b21 = block {
- continue %b3
+ if true [t: %b12]
+ # True block
+ %b12 = block {
+ exit_loop
}
- }
-
+ continue %b3
}
# Continuing block
@@ -766,11 +681,7 @@
next_iteration %b2
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -784,36 +695,31 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, c: %b3, m: %b4]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
- if false [t: %b5, f: %b6, m: %b7]
+ if false [t: %b4, f: %b5]
# True block
- %b5 = block {
- exit_if %b7
+ %b4 = block {
+ exit_if
}
# False block
- %b6 = block {
- exit_loop %b4
+ %b5 = block {
+ exit_loop
}
- # Merge block
- %b7 = block {
- continue %b3
- }
-
+ continue %b3
}
# Continuing block
@@ -821,11 +727,7 @@
next_iteration %b2
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -839,36 +741,31 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
- EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
+ EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, c: %b3, m: %b4]
+ loop [b: %b2, c: %b3]
# Body block
%b2 = block {
- if true [t: %b5, f: %b6, m: %b7]
+ if true [t: %b4, f: %b5]
# True block
- %b5 = block {
- exit_if %b7
+ %b4 = block {
+ exit_if
}
# False block
- %b6 = block {
- exit_loop %b4
+ %b5 = block {
+ exit_loop
}
- # Merge block
- %b7 = block {
- ret
- }
-
+ continue %b3
}
# Continuing block
@@ -876,11 +773,7 @@
next_iteration %b2
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -907,13 +800,12 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(2u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(1u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(2u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m), R"()");
}
@@ -926,18 +818,17 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(1u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [i: %b2, b: %b3, m: %b4]
+ loop [i: %b2, b: %b3]
# Initializer block
%b2 = block {
%i:ptr<function, i32, read_write> = var
@@ -946,14 +837,10 @@
# Body block
%b3 = block {
- exit_loop %b4
+ exit_loop
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -967,28 +854,23 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* loop = FindSingleValue<ir::Loop>(m);
+ auto* loop = FindSingleInstruction<ir::Loop>(m);
ASSERT_EQ(1u, m.functions.Length());
EXPECT_EQ(0u, loop->Body()->InboundSiblingBranches().Length());
EXPECT_EQ(0u, loop->Continuing()->InboundSiblingBranches().Length());
- EXPECT_EQ(1u, loop->Merge()->InboundSiblingBranches().Length());
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- loop [b: %b2, m: %b3]
+ loop [b: %b2]
# Body block
%b2 = block {
- exit_loop %b3
+ exit_loop
}
- # Merge block
- %b3 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -1005,7 +887,7 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* flow = FindSingleValue<ir::Switch>(m);
+ auto* flow = FindSingleInstruction<ir::Switch>(m);
ASSERT_EQ(1u, m.functions.Length());
@@ -1025,32 +907,26 @@
ASSERT_EQ(1u, cases[2].selectors.Length());
EXPECT_TRUE(cases[2].selectors[0].IsDefault());
- EXPECT_EQ(3u, flow->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- switch 1i [c: (0i, %b2), c: (1i, %b3), c: (default, %b4), m: %b5]
+ switch 1i [c: (0i, %b2), c: (1i, %b3), c: (default, %b4)]
# Case block
%b2 = block {
- exit_switch %b5
+ exit_switch
}
# Case block
%b3 = block {
- exit_switch %b5
+ exit_switch
}
# Case block
%b4 = block {
- exit_switch %b5
+ exit_switch
}
- # Merge block
- %b5 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -1068,7 +944,7 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* flow = FindSingleValue<ir::Switch>(m);
+ auto* flow = FindSingleInstruction<ir::Switch>(m);
ASSERT_EQ(1u, m.functions.Length());
@@ -1085,22 +961,16 @@
EXPECT_TRUE(cases[0].selectors[2].IsDefault());
- EXPECT_EQ(1u, flow->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- switch 1i [c: (0i 1i default, %b2), m: %b3]
+ switch 1i [c: (0i 1i default, %b2)]
# Case block
%b2 = block {
- exit_switch %b3
+ exit_switch
}
- # Merge block
- %b3 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -1114,7 +984,7 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* flow = FindSingleValue<ir::Switch>(m);
+ auto* flow = FindSingleInstruction<ir::Switch>(m);
ASSERT_EQ(1u, m.functions.Length());
@@ -1123,22 +993,16 @@
ASSERT_EQ(1u, cases[0].selectors.Length());
EXPECT_TRUE(cases[0].selectors[0].IsDefault());
- EXPECT_EQ(1u, flow->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- switch 1i [c: (default, %b2), m: %b3]
+ switch 1i [c: (default, %b2)]
# Case block
%b2 = block {
- exit_switch %b3
+ exit_switch
}
- # Merge block
- %b3 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -1154,7 +1018,7 @@
ASSERT_TRUE(res) << (!res ? res.Failure() : "");
auto m = res.Move();
- auto* flow = FindSingleValue<ir::Switch>(m);
+ auto* flow = FindSingleInstruction<ir::Switch>(m);
ASSERT_EQ(1u, m.functions.Length());
@@ -1168,28 +1032,23 @@
ASSERT_EQ(1u, cases[1].selectors.Length());
EXPECT_TRUE(cases[1].selectors[0].IsDefault());
- EXPECT_EQ(2u, flow->Merge()->InboundSiblingBranches().Length());
// This is 1 because the if is dead-code eliminated and the return doesn't happen.
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
- switch 1i [c: (0i, %b2), c: (default, %b3), m: %b4]
+ switch 1i [c: (0i, %b2), c: (default, %b3)]
# Case block
%b2 = block {
- exit_switch %b4
+ exit_switch
}
# Case block
%b3 = block {
- exit_switch %b4
+ exit_switch
}
- # Merge block
- %b4 = block {
- ret
- }
-
+ ret
}
}
)");
@@ -1207,7 +1066,7 @@
auto m = res.Move();
- auto* flow = FindSingleValue<ir::Switch>(m);
+ auto* flow = FindSingleInstruction<ir::Switch>(m);
ASSERT_EQ(1u, m.functions.Length());
@@ -1221,8 +1080,6 @@
ASSERT_EQ(1u, cases[1].selectors.Length());
EXPECT_TRUE(cases[1].selectors[0].IsDefault());
- EXPECT_EQ(0u, flow->Merge()->InboundSiblingBranches().Length());
-
EXPECT_EQ(Disassemble(m),
R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
@@ -1237,6 +1094,7 @@
ret
}
+ ret
}
}
)");
diff --git a/src/tint/ir/if.cc b/src/tint/ir/if.cc
index 7f34986..bc2e5b0 100644
--- a/src/tint/ir/if.cc
+++ b/src/tint/ir/if.cc
@@ -20,25 +20,29 @@
namespace tint::ir {
-If::If(Value* cond, ir::Block* t, ir::Block* f, ir::MultiInBlock* m)
- : true_(t), false_(f), merge_(m) {
- TINT_ASSERT(IR, cond);
+If::If(Value* cond, ir::Block* t, ir::Block* f) : true_(t), false_(f) {
TINT_ASSERT(IR, true_);
TINT_ASSERT(IR, false_);
- TINT_ASSERT(IR, merge_);
- AddOperand(cond);
+ AddOperand(If::kConditionOperandOffset, cond);
+
if (true_) {
true_->SetParent(this);
}
if (false_) {
false_->SetParent(this);
}
- if (merge_) {
- merge_->SetParent(this);
- }
}
If::~If() = default;
+void If::ForeachBlock(const std::function<void(ir::Block*)>& cb) {
+ if (true_) {
+ cb(true_);
+ }
+ if (false_) {
+ cb(false_);
+ }
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/if.h b/src/tint/ir/if.h
index 4434116..6b87463 100644
--- a/src/tint/ir/if.h
+++ b/src/tint/ir/if.h
@@ -35,11 +35,8 @@
/// │ True │ │ False │
/// | (optional) | | (optional) |
/// └────────────┘ └────────────┘
-/// ExitIf ┃ ┌──────────┐ ┃ ExitIf
-/// ┗━━━━▶│ Merge │◀━━━━┛
-/// │(optional)│
-/// └──────────┘
-/// ┃
+/// ExitIf ┃ ┃ ExitIf
+/// ┗━━━━━━━━━━┳━━━━━━━━━━┛
/// ▼
/// out
/// ```
@@ -52,12 +49,11 @@
/// @param cond the if condition
/// @param t the true block
/// @param f the false block
- /// @param m the merge block
- If(Value* cond, ir::Block* t, ir::Block* f, ir::MultiInBlock* m);
+ If(Value* cond, ir::Block* t, ir::Block* f);
~If() override;
- /// @returns the branch arguments
- utils::Slice<Value* const> Args() override { return utils::Slice<Value*>{}; }
+ /// @copydoc ControlInstruction::ForeachBlock
+ void ForeachBlock(const std::function<void(ir::Block*)>& cb) override;
/// @returns the if condition
Value* Condition() { return operands_[kConditionOperandOffset]; }
@@ -68,13 +64,9 @@
/// @returns the false branch block
ir::Block* False() { return false_; }
- /// @returns the merge branch block
- ir::MultiInBlock* Merge() { return merge_; }
-
private:
ir::Block* true_ = nullptr;
ir::Block* false_ = nullptr;
- ir::MultiInBlock* merge_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/if_test.cc b/src/tint/ir/if_test.cc
index 60915a6..934a58c 100644
--- a/src/tint/ir/if_test.cc
+++ b/src/tint/ir/if_test.cc
@@ -29,22 +29,18 @@
EXPECT_THAT(cond->Usages(), testing::UnorderedElementsAre(Usage{if_, 0u}));
}
+TEST_F(IR_IfTest, Result) {
+ auto* if_ = b.If(b.Constant(true));
+
+ EXPECT_FALSE(if_->HasResults());
+ EXPECT_FALSE(if_->HasMultiResults());
+}
+
TEST_F(IR_IfTest, Parent) {
auto* cond = b.Constant(true);
auto* if_ = b.If(cond);
EXPECT_EQ(if_->True()->Parent(), if_);
EXPECT_EQ(if_->False()->Parent(), if_);
- EXPECT_EQ(if_->Merge()->Parent(), if_);
-}
-
-TEST_F(IR_IfTest, Fail_NullCondition) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.If(nullptr);
- },
- "");
}
TEST_F(IR_IfTest, Fail_NullTrueBlock) {
@@ -52,7 +48,7 @@
{
Module mod;
Builder b{mod};
- If if_(b.Constant(false), nullptr, b.Block(), b.MultiInBlock());
+ If if_(b.Constant(false), nullptr, b.Block());
},
"");
}
@@ -62,17 +58,7 @@
{
Module mod;
Builder b{mod};
- If if_(b.Constant(false), b.Block(), nullptr, b.MultiInBlock());
- },
- "");
-}
-
-TEST_F(IR_IfTest, Fail_NullMultiInBlock) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- If if_(b.Constant(false), b.Block(), b.Block(), nullptr);
+ If if_(b.Constant(false), b.Block(), nullptr);
},
"");
}
diff --git a/src/tint/ir/instruction.cc b/src/tint/ir/instruction.cc
index ea9cf31..e8bc12c 100644
--- a/src/tint/ir/instruction.cc
+++ b/src/tint/ir/instruction.cc
@@ -25,6 +25,18 @@
Instruction::~Instruction() = default;
+void Instruction::Destroy() {
+ TINT_ASSERT(IR, Alive());
+ if (Block()) {
+ Remove();
+ }
+ for (auto* result : Results()) {
+ result->SetSource(nullptr);
+ result->Destroy();
+ }
+ alive_ = false;
+}
+
void Instruction::InsertBefore(Instruction* before) {
TINT_ASSERT_OR_RETURN(IR, before);
TINT_ASSERT_OR_RETURN(IR, before->Block() != nullptr);
diff --git a/src/tint/ir/instruction.h b/src/tint/ir/instruction.h
index 4cf7d70..8145258 100644
--- a/src/tint/ir/instruction.h
+++ b/src/tint/ir/instruction.h
@@ -15,6 +15,7 @@
#ifndef SRC_TINT_IR_INSTRUCTION_H_
#define SRC_TINT_IR_INSTRUCTION_H_
+#include "src/tint/ir/instruction_result.h"
#include "src/tint/ir/value.h"
#include "src/tint/utils/castable.h"
@@ -26,11 +27,38 @@
namespace tint::ir {
/// An instruction in the IR.
-class Instruction : public utils::Castable<Instruction, Value> {
+class Instruction : public utils::Castable<Instruction> {
public:
/// Destructor
~Instruction() override;
+ /// Set an operand at a given index.
+ /// @param index the operand index
+ /// @param value the value to use
+ virtual void SetOperand(size_t index, ir::Value* value) = 0;
+
+ /// @returns the operands of the instruction
+ virtual utils::VectorRef<ir::Value*> Operands() = 0;
+
+ /// @returns true if the instruction has result values
+ virtual bool HasResults() { return false; }
+ /// @returns true if the instruction has multiple values
+ virtual bool HasMultiResults() { return false; }
+
+ /// @returns the first result. Returns `nullptr` if there are no results, or if ther are
+ /// multi-results
+ virtual InstructionResult* Result() { return nullptr; }
+
+ /// @returns the result values for this instruction
+ virtual utils::VectorRef<InstructionResult*> Results() { return utils::Empty; }
+
+ /// Removes the instruction from the block, and destroys all the result values.
+ /// The result values must not be in use.
+ virtual void Destroy();
+
+ /// @returns true if the Instruction has not been destroyed with Destroy()
+ bool Alive() const { return alive_; }
+
/// Sets the block that owns this instruction
/// @param block the new owner block
void SetBlock(ir::Block* block) { block_ = block; }
@@ -50,10 +78,13 @@
/// Removes this instruction from the owning block
void Remove();
- /// Set an operand at a given index.
- /// @param index the operand index
- /// @param value the value to use
- virtual void SetOperand(uint32_t index, ir::Value* value) = 0;
+ /// @param idx the index of the result
+ /// @returns the result with index @p idx, or `nullptr` if there are no results or the index is
+ /// out of bounds.
+ Value* Result(size_t idx) {
+ auto res = Results();
+ return idx < res.Length() ? res[idx] : nullptr;
+ }
/// Pointer to the next instruction in the list
Instruction* next = nullptr;
@@ -66,6 +97,9 @@
/// The block that owns this instruction
ir::Block* block_ = nullptr;
+
+ private:
+ bool alive_ = true;
};
} // namespace tint::ir
diff --git a/src/tint/ir/instruction_result.cc b/src/tint/ir/instruction_result.cc
new file mode 100644
index 0000000..85eaafe
--- /dev/null
+++ b/src/tint/ir/instruction_result.cc
@@ -0,0 +1,35 @@
+// 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/instruction_result.h"
+
+#include "src/tint/ir/constant.h"
+#include "src/tint/ir/instruction.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::InstructionResult);
+
+namespace tint::ir {
+
+InstructionResult::InstructionResult(const type::Type* type) : type_(type) {
+ TINT_ASSERT(IR, type_ != nullptr);
+}
+
+InstructionResult::~InstructionResult() = default;
+
+void InstructionResult::Destroy() {
+ TINT_ASSERT(IR, source_ == nullptr);
+ Base::Destroy();
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/instruction_result.h b/src/tint/ir/instruction_result.h
new file mode 100644
index 0000000..0f6192a
--- /dev/null
+++ b/src/tint/ir/instruction_result.h
@@ -0,0 +1,53 @@
+// 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_INSTRUCTION_RESULT_H_
+#define SRC_TINT_IR_INSTRUCTION_RESULT_H_
+
+#include "src/tint/ir/value.h"
+#include "src/tint/utils/string_stream.h"
+
+namespace tint::ir {
+
+/// An instruction result in the IR.
+class InstructionResult : public utils::Castable<InstructionResult, Value> {
+ public:
+ /// Constructor
+ /// @param type the type of the value
+ explicit InstructionResult(const type::Type* type);
+
+ /// Destructor
+ ~InstructionResult() override;
+
+ /// @copydoc Value::Destroy
+ void Destroy() override;
+
+ /// @returns the type of the value
+ const type::Type* Type() override { return type_; }
+
+ /// Sets the source instruction for this value
+ /// @param inst the instruction to set
+ void SetSource(Instruction* inst) { source_ = inst; }
+
+ /// @returns the source instruction, if any
+ Instruction* Source() { return source_; }
+
+ private:
+ Instruction* source_ = nullptr;
+ const type::Type* type_ = nullptr;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_INSTRUCTION_RESULT_H_
diff --git a/src/tint/ir/instruction_result_test.cc b/src/tint/ir/instruction_result_test.cc
new file mode 100644
index 0000000..b21aaac
--- /dev/null
+++ b/src/tint/ir/instruction_result_test.cc
@@ -0,0 +1,39 @@
+// 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 "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "src/tint/ir/ir_test_helper.h"
+
+using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+
+namespace tint::ir {
+namespace {
+
+using IR_InstructionResultTest = IRTestHelper;
+
+TEST_F(IR_InstructionResultTest, Destroy_HasSource) {
+ EXPECT_FATAL_FAILURE(
+ {
+ Module mod;
+ Builder b{mod};
+ auto* val = b.Add(mod.Types().i32(), 1_i, 2_i)->Result();
+ val->Destroy();
+ },
+ "");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/ir_test_helper.h b/src/tint/ir/ir_test_helper.h
index 737a596..0406606 100644
--- a/src/tint/ir/ir_test_helper.h
+++ b/src/tint/ir/ir_test_helper.h
@@ -34,15 +34,6 @@
Builder b{mod};
/// The type manager
type::Manager& ty{mod.Types()};
-
- /// Alias to builtin::AddressSpace::kStorage
- static constexpr auto storage = builtin::AddressSpace::kStorage;
- /// Alias to builtin::AddressSpace::kUniform
- static constexpr auto uniform = builtin::AddressSpace::kUniform;
- /// Alias to builtin::AddressSpace::kPrivate
- static constexpr auto private_ = builtin::AddressSpace::kPrivate;
- /// Alias to builtin::AddressSpace::kFunction
- static constexpr auto function = builtin::AddressSpace::kFunction;
};
using IRTestHelper = IRTestHelperBase<testing::Test>;
diff --git a/src/tint/ir/load.cc b/src/tint/ir/load.cc
index 4beb11e..0918398 100644
--- a/src/tint/ir/load.cc
+++ b/src/tint/ir/load.cc
@@ -21,12 +21,12 @@
namespace tint::ir {
-Load::Load(Value* from) {
- TINT_ASSERT_OR_RETURN(IR, from);
- TINT_ASSERT_OR_RETURN(IR, tint::Is<type::Pointer>(from->Type()));
+Load::Load(InstructionResult* result, Value* from) {
+ TINT_ASSERT(IR, from->Type()->Is<type::Pointer>());
+ TINT_ASSERT(IR, from && from->Type()->UnwrapPtr() == result->Type());
- result_type_ = from->Type()->UnwrapPtr();
- AddOperand(from);
+ AddOperand(Load::kFromOperandOffset, from);
+ AddResult(result);
}
Load::~Load() = default;
diff --git a/src/tint/ir/load.h b/src/tint/ir/load.h
index 29b3b22..34438a5 100644
--- a/src/tint/ir/load.h
+++ b/src/tint/ir/load.h
@@ -21,22 +21,20 @@
namespace tint::ir {
/// A load instruction in the IR.
-class Load : public utils::Castable<Load, OperandInstruction<1>> {
+class Load : public utils::Castable<Load, OperandInstruction<1, 1>> {
public:
+ /// The offset in Operands() for the from value
+ static constexpr size_t kFromOperandOffset = 0;
+
/// Constructor (infers type)
+ /// @param result the result value
/// @param from the value being loaded from
- explicit Load(Value* from);
+ Load(InstructionResult* result, Value* from);
~Load() override;
- /// @returns the type of the value
- const type::Type* Type() override { return result_type_; }
-
/// @returns the value being loaded from
- Value* From() { return operands_[0]; }
-
- private:
- const type::Type* result_type_ = nullptr;
+ Value* From() { return operands_[kFromOperandOffset]; }
};
} // namespace tint::ir
diff --git a/src/tint/ir/load_test.cc b/src/tint/ir/load_test.cc
index 0cfba85..5e063a8 100644
--- a/src/tint/ir/load_test.cc
+++ b/src/tint/ir/load_test.cc
@@ -21,35 +21,44 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using IR_LoadTest = IRTestHelper;
TEST_F(IR_LoadTest, Create) {
auto* store_type = ty.i32();
- auto* var =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, store_type, builtin::Access::kReadWrite));
+ auto* var = b.Var(ty.ptr<function, i32>());
auto* inst = b.Load(var);
ASSERT_TRUE(inst->Is<Load>());
- ASSERT_EQ(inst->From(), var);
+ ASSERT_EQ(inst->From(), var->Result());
+ EXPECT_EQ(inst->Result()->Type(), store_type);
- EXPECT_EQ(inst->Type(), store_type);
-
- ASSERT_TRUE(inst->From()->Is<ir::Var>());
- EXPECT_EQ(inst->From(), var);
+ auto* result = inst->From()->As<InstructionResult>();
+ ASSERT_NE(result, nullptr);
+ ASSERT_TRUE(result->Source()->Is<ir::Var>());
+ EXPECT_EQ(result->Source(), var);
}
TEST_F(IR_LoadTest, Usage) {
- auto* store_type = ty.i32();
- auto* var =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, store_type, builtin::Access::kReadWrite));
+ auto* var = b.Var(ty.ptr<function, i32>());
auto* inst = b.Load(var);
ASSERT_NE(inst->From(), nullptr);
EXPECT_THAT(inst->From()->Usages(), testing::UnorderedElementsAre(Usage{inst, 0u}));
}
+TEST_F(IR_LoadTest, Results) {
+ auto* var = b.Var(ty.ptr<function, i32>());
+ auto* inst = b.Load(var);
+
+ EXPECT_TRUE(inst->HasResults());
+ EXPECT_FALSE(inst->HasMultiResults());
+ EXPECT_TRUE(inst->Result()->Is<InstructionResult>());
+ EXPECT_EQ(inst->Result()->Source(), inst);
+}
+
TEST_F(IR_LoadTest, Fail_NonPtr_Builder) {
EXPECT_FATAL_FAILURE(
{
@@ -60,25 +69,5 @@
"");
}
-TEST_F(IR_LoadTest, Fail_NullValue_Builder) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Load(nullptr);
- },
- "");
-}
-
-TEST_F(IR_LoadTest, Fail_NullValue) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- Load l(nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/loop.cc b/src/tint/ir/loop.cc
index 4f25fcd..4b931b4 100644
--- a/src/tint/ir/loop.cc
+++ b/src/tint/ir/loop.cc
@@ -22,12 +22,11 @@
namespace tint::ir {
-Loop::Loop(ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c, ir::MultiInBlock* m)
- : initializer_(i), body_(b), continuing_(c), merge_(m) {
+Loop::Loop(ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c)
+ : initializer_(i), body_(b), continuing_(c) {
TINT_ASSERT(IR, initializer_);
TINT_ASSERT(IR, body_);
TINT_ASSERT(IR, continuing_);
- TINT_ASSERT(IR, merge_);
if (initializer_) {
initializer_->SetParent(this);
@@ -38,13 +37,22 @@
if (continuing_) {
continuing_->SetParent(this);
}
- if (merge_) {
- merge_->SetParent(this);
- }
}
Loop::~Loop() = default;
+void Loop::ForeachBlock(const std::function<void(ir::Block*)>& cb) {
+ if (initializer_) {
+ cb(initializer_);
+ }
+ if (body_) {
+ cb(body_);
+ }
+ if (continuing_) {
+ cb(continuing_);
+ }
+}
+
bool Loop::HasInitializer() {
return initializer_->HasBranchTarget();
}
diff --git a/src/tint/ir/loop.h b/src/tint/ir/loop.h
index 31f18fe..f5e2ea4 100644
--- a/src/tint/ir/loop.h
+++ b/src/tint/ir/loop.h
@@ -51,12 +51,6 @@
/// ┃ ┃ BreakIf(true)
/// ┗━━━━━━━━━━▶┃
/// ▼
-/// ┌────────────────┐
-/// │ Merge │
-/// │ (optional) │
-/// └────────────────┘
-/// ┃
-/// ▼
/// out
///
/// ```
@@ -66,10 +60,12 @@
/// @param i the initializer block
/// @param b the body block
/// @param c the continuing block
- /// @param m the merge block
- Loop(ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c, ir::MultiInBlock* m);
+ Loop(ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c);
~Loop() override;
+ /// @copydoc ControlInstruction::ForeachBlock
+ void ForeachBlock(const std::function<void(ir::Block*)>& cb) override;
+
/// @returns the switch initializer block
ir::Block* Initializer() { return initializer_; }
@@ -83,14 +79,10 @@
/// @returns the switch continuing block
ir::MultiInBlock* Continuing() { return continuing_; }
- /// @returns the switch merge branch
- ir::MultiInBlock* Merge() { return merge_; }
-
private:
ir::Block* initializer_ = nullptr;
ir::MultiInBlock* body_ = nullptr;
ir::MultiInBlock* continuing_ = nullptr;
- ir::MultiInBlock* merge_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/loop_test.cc b/src/tint/ir/loop_test.cc
index 38fecfa..1746c8d 100644
--- a/src/tint/ir/loop_test.cc
+++ b/src/tint/ir/loop_test.cc
@@ -27,7 +27,12 @@
EXPECT_EQ(loop->Initializer()->Parent(), loop);
EXPECT_EQ(loop->Body()->Parent(), loop);
EXPECT_EQ(loop->Continuing()->Parent(), loop);
- EXPECT_EQ(loop->Merge()->Parent(), loop);
+}
+
+TEST_F(IR_LoopTest, Result) {
+ auto* loop = b.Loop();
+ EXPECT_FALSE(loop->HasResults());
+ EXPECT_FALSE(loop->HasMultiResults());
}
TEST_F(IR_LoopTest, Fail_NullInitializerBlock) {
@@ -35,7 +40,7 @@
{
Module mod;
Builder b{mod};
- Loop loop(nullptr, b.MultiInBlock(), b.MultiInBlock(), b.MultiInBlock());
+ Loop loop(nullptr, b.MultiInBlock(), b.MultiInBlock());
},
"");
}
@@ -45,7 +50,7 @@
{
Module mod;
Builder b{mod};
- Loop loop(b.Block(), nullptr, b.MultiInBlock(), b.MultiInBlock());
+ Loop loop(b.Block(), nullptr, b.MultiInBlock());
},
"");
}
@@ -55,17 +60,7 @@
{
Module mod;
Builder b{mod};
- Loop loop(b.Block(), b.MultiInBlock(), nullptr, b.MultiInBlock());
- },
- "");
-}
-
-TEST_F(IR_LoopTest, Fail_NullMultiInBlock) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- Loop loop(b.Block(), b.MultiInBlock(), b.MultiInBlock(), nullptr);
+ Loop loop(b.Block(), b.MultiInBlock(), nullptr);
},
"");
}
diff --git a/src/tint/ir/module.cc b/src/tint/ir/module.cc
index 3b86a80..1ad7c88 100644
--- a/src/tint/ir/module.cc
+++ b/src/tint/ir/module.cc
@@ -26,10 +26,20 @@
Module& Module::operator=(Module&&) = default;
+Symbol Module::NameOf(Instruction* inst) {
+ TINT_ASSERT(IR, inst->HasResults() && !inst->HasMultiResults());
+ return NameOf(inst->Result());
+}
+
Symbol Module::NameOf(Value* value) {
return value_to_id_.Get(value).value_or(Symbol{});
}
+Symbol Module::SetName(Instruction* inst, std::string_view name) {
+ TINT_ASSERT(IR, inst->HasResults() && !inst->HasMultiResults());
+ return SetName(inst->Result(), name);
+}
+
Symbol Module::SetName(Value* value, std::string_view name) {
TINT_ASSERT(IR, !name.empty());
diff --git a/src/tint/ir/module.h b/src/tint/ir/module.h
index 4f33f26..e5e292d 100644
--- a/src/tint/ir/module.h
+++ b/src/tint/ir/module.h
@@ -58,10 +58,21 @@
/// @returns a reference to this module
Module& operator=(Module&& o);
+ /// @param inst the instruction
+ /// @return the name of the given instruction, or an invalid symbol if the instruction is not
+ /// named. Requires that the instruction only has a single return value.
+ Symbol NameOf(Instruction* inst);
+
/// @param value the value
/// @return the name of the given value, or an invalid symbol if the value is not named.
Symbol NameOf(Value* value);
+ /// @param inst the instruction to set the name of
+ /// @param name the desired name of the value. May be suffixed on collision.
+ /// @return the unique symbol of the given value
+ /// @note requires the instruction be a single result instruction.
+ Symbol SetName(Instruction* inst, std::string_view name);
+
/// @param value the value to name.
/// @param name the desired name of the value. May be suffixed on collision.
/// @return the unique symbol of the given value.
@@ -76,6 +87,9 @@
/// The constant value manager
constant::Manager constant_values;
+ /// The instruction allocator
+ utils::BlockAllocator<Instruction> instructions;
+
/// The value allocator
utils::BlockAllocator<Value> values;
diff --git a/src/tint/ir/module_test.cc b/src/tint/ir/module_test.cc
index 61cd5d4..4d24881 100644
--- a/src/tint/ir/module_test.cc
+++ b/src/tint/ir/module_test.cc
@@ -19,43 +19,39 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
-class IR_ModuleTest : public IRTestHelper {
- protected:
- const type::Pointer* ptr(const type::Type* elem) {
- return ty.ptr(builtin::AddressSpace::kFunction, elem, builtin::Access::kReadWrite);
- }
-};
+using IR_ModuleTest = IRTestHelper;
TEST_F(IR_ModuleTest, NameOfUnnamed) {
- auto* v = mod.values.Create<ir::Var>(ptr(ty.i32()));
+ auto* v = b.Var(ty.ptr<function, i32>());
EXPECT_FALSE(mod.NameOf(v).IsValid());
}
TEST_F(IR_ModuleTest, SetName) {
- auto* v = mod.values.Create<ir::Var>(ptr(ty.i32()));
+ auto* v = b.Var(ty.ptr<function, i32>());
EXPECT_EQ(mod.SetName(v, "a").Name(), "a");
EXPECT_EQ(mod.NameOf(v).Name(), "a");
}
TEST_F(IR_ModuleTest, SetNameRename) {
- auto* v = mod.values.Create<ir::Var>(ptr(ty.i32()));
+ auto* v = b.Var(ty.ptr<function, i32>());
EXPECT_EQ(mod.SetName(v, "a").Name(), "a");
EXPECT_EQ(mod.SetName(v, "b").Name(), "b");
EXPECT_EQ(mod.NameOf(v).Name(), "b");
}
TEST_F(IR_ModuleTest, SetNameCollision) {
- auto* a = mod.values.Create<ir::Var>(ptr(ty.i32()));
- auto* b = mod.values.Create<ir::Var>(ptr(ty.i32()));
- auto* c = mod.values.Create<ir::Var>(ptr(ty.i32()));
- EXPECT_EQ(mod.SetName(a, "x").Name(), "x");
- EXPECT_EQ(mod.SetName(b, "x_1").Name(), "x_1");
- EXPECT_EQ(mod.SetName(c, "x").Name(), "x_2");
- EXPECT_EQ(mod.NameOf(a).Name(), "x");
- EXPECT_EQ(mod.NameOf(b).Name(), "x_1");
- EXPECT_EQ(mod.NameOf(c).Name(), "x_2");
+ auto* v1 = b.Var(ty.ptr<function, i32>());
+ auto* v2 = b.Var(ty.ptr<function, i32>());
+ auto* v3 = b.Var(ty.ptr<function, i32>());
+ EXPECT_EQ(mod.SetName(v1, "x").Name(), "x");
+ EXPECT_EQ(mod.SetName(v2, "x_1").Name(), "x_1");
+ EXPECT_EQ(mod.SetName(v3, "x").Name(), "x_2");
+ EXPECT_EQ(mod.NameOf(v1).Name(), "x");
+ EXPECT_EQ(mod.NameOf(v2).Name(), "x_1");
+ EXPECT_EQ(mod.NameOf(v3).Name(), "x_2");
}
} // namespace
diff --git a/src/tint/ir/multi_in_block.cc b/src/tint/ir/multi_in_block.cc
index a86db11..94e7f59 100644
--- a/src/tint/ir/multi_in_block.cc
+++ b/src/tint/ir/multi_in_block.cc
@@ -26,14 +26,10 @@
void MultiInBlock::SetParams(utils::VectorRef<BlockParam*> params) {
params_ = std::move(params);
-
- TINT_ASSERT(IR, !params_.Any(utils::IsNull));
}
void MultiInBlock::SetParams(std::initializer_list<BlockParam*> params) {
params_ = std::move(params);
-
- TINT_ASSERT(IR, !params_.Any(utils::IsNull));
}
void MultiInBlock::AddInboundSiblingBranch(ir::Branch* node) {
diff --git a/src/tint/ir/multi_in_block.h b/src/tint/ir/multi_in_block.h
index 6f9b3ee..e0d807f 100644
--- a/src/tint/ir/multi_in_block.h
+++ b/src/tint/ir/multi_in_block.h
@@ -27,10 +27,8 @@
namespace tint::ir {
/// A block that can be the target of multiple branches.
-/// MultiInBlocks maintain a list of inbound branches from branch instructions excluding ir::If,
-/// ir::Switch and ir::Loop which implicitly branch to the internal block.
-/// MultiInBlocks hold a number of BlockParam parameters, used to pass values from the branch source
-/// to this target.
+/// MultiInBlocks maintain a list of inbound branches and a number of BlockParam parameters, used to
+/// pass values from the branch source to this target.
class MultiInBlock : public utils::Castable<MultiInBlock, Block> {
public:
/// Constructor
diff --git a/src/tint/ir/multi_in_block_test.cc b/src/tint/ir/multi_in_block_test.cc
index 2d82715..ef9438c 100644
--- a/src/tint/ir/multi_in_block_test.cc
+++ b/src/tint/ir/multi_in_block_test.cc
@@ -23,18 +23,6 @@
using namespace tint::number_suffixes; // NOLINT
using IR_MultiInBlockTest = IRTestHelper;
-TEST_F(IR_MultiInBlockTest, Fail_NullBlockParam) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
-
- auto* blk = b.MultiInBlock();
- blk->SetParams({nullptr});
- },
- "");
-}
-
TEST_F(IR_MultiInBlockTest, Fail_NullInboundBranch) {
EXPECT_FATAL_FAILURE(
{
diff --git a/src/tint/ir/next_iteration.cc b/src/tint/ir/next_iteration.cc
index dc1ccd2..c7f1e80 100644
--- a/src/tint/ir/next_iteration.cc
+++ b/src/tint/ir/next_iteration.cc
@@ -26,10 +26,12 @@
NextIteration::NextIteration(ir::Loop* loop, utils::VectorRef<Value*> args /* = utils::Empty */)
: loop_(loop) {
TINT_ASSERT(IR, loop_);
+
+ AddOperands(NextIteration::kArgsOperandOffset, std::move(args));
+
if (loop_) {
loop_->Body()->AddInboundSiblingBranch(this);
}
- AddOperands(std::move(args));
}
NextIteration::~NextIteration() = default;
diff --git a/src/tint/ir/next_iteration.h b/src/tint/ir/next_iteration.h
index e80f628..6b01634 100644
--- a/src/tint/ir/next_iteration.h
+++ b/src/tint/ir/next_iteration.h
@@ -28,6 +28,9 @@
/// A next iteration instruction.
class NextIteration : public utils::Castable<NextIteration, Branch> {
public:
+ /// The base offset in Operands() for the args
+ static constexpr size_t kArgsOperandOffset = 0;
+
/// Constructor
/// @param loop the loop being iterated
/// @param args the branch arguments
diff --git a/src/tint/ir/next_iteration_test.cc b/src/tint/ir/next_iteration_test.cc
index c0d821c..5c6d16d 100644
--- a/src/tint/ir/next_iteration_test.cc
+++ b/src/tint/ir/next_iteration_test.cc
@@ -32,14 +32,11 @@
"");
}
-TEST_F(IR_NextIterationTest, Fail_NullValue) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.NextIteration(b.Loop(), nullptr);
- },
- "");
+TEST_F(IR_NextIterationTest, Result) {
+ auto* inst = b.NextIteration(b.Loop());
+
+ EXPECT_FALSE(inst->HasResults());
+ EXPECT_FALSE(inst->HasMultiResults());
}
} // namespace
diff --git a/src/tint/ir/operand_instruction.cc b/src/tint/ir/operand_instruction.cc
index 7d56ed2..9a1f4aa 100644
--- a/src/tint/ir/operand_instruction.cc
+++ b/src/tint/ir/operand_instruction.cc
@@ -14,10 +14,18 @@
#include "src/tint/ir/operand_instruction.h"
-TINT_INSTANTIATE_TYPEINFO(tint::ir::OperandInstruction<1>);
-TINT_INSTANTIATE_TYPEINFO(tint::ir::OperandInstruction<2>);
-TINT_INSTANTIATE_TYPEINFO(tint::ir::OperandInstruction<3>);
-TINT_INSTANTIATE_TYPEINFO(tint::ir::OperandInstruction<4>);
-TINT_INSTANTIATE_TYPEINFO(tint::ir::OperandInstruction<8>);
+using Op10 = tint::ir::OperandInstruction<1, 0>;
+using Op11 = tint::ir::OperandInstruction<1, 1>;
+using Op20 = tint::ir::OperandInstruction<2, 0>;
+using Op21 = tint::ir::OperandInstruction<2, 1>;
+using Op31 = tint::ir::OperandInstruction<3, 1>;
+using Op41 = tint::ir::OperandInstruction<4, 1>;
+
+TINT_INSTANTIATE_TYPEINFO(Op10);
+TINT_INSTANTIATE_TYPEINFO(Op11);
+TINT_INSTANTIATE_TYPEINFO(Op20);
+TINT_INSTANTIATE_TYPEINFO(Op21);
+TINT_INSTANTIATE_TYPEINFO(Op31);
+TINT_INSTANTIATE_TYPEINFO(Op41);
namespace tint::ir {} // namespace tint::ir
diff --git a/src/tint/ir/operand_instruction.h b/src/tint/ir/operand_instruction.h
index 8a121f7..82957c0 100644
--- a/src/tint/ir/operand_instruction.h
+++ b/src/tint/ir/operand_instruction.h
@@ -15,21 +15,32 @@
#ifndef SRC_TINT_IR_OPERAND_INSTRUCTION_H_
#define SRC_TINT_IR_OPERAND_INSTRUCTION_H_
+#include <utility>
+
#include "src/tint/ir/instruction.h"
+#include "src/tint/ir/instruction_result.h"
namespace tint::ir {
/// An instruction in the IR that expects one or more operands.
-template <unsigned N>
-class OperandInstruction : public utils::Castable<OperandInstruction<N>, Instruction> {
+/// @tparam N the number of operands before spilling to the heap
+/// @tparam R the number of result values before spilling to the heap
+template <unsigned N, unsigned R>
+class OperandInstruction : public utils::Castable<OperandInstruction<N, R>, Instruction> {
public:
/// Destructor
~OperandInstruction() override = default;
+ /// @copydoc tint::ir::Value::Destroy
+ void Destroy() override {
+ ClearOperands();
+ Instruction::Destroy();
+ }
+
/// Set an operand at a given index.
/// @param index the operand index
/// @param value the value to use
- void SetOperand(uint32_t index, ir::Value* value) override {
+ void SetOperand(size_t index, ir::Value* value) override {
TINT_ASSERT(IR, index < operands_.Length());
if (operands_[index]) {
operands_[index]->RemoveUsage({this, index});
@@ -38,30 +49,85 @@
if (value) {
value->AddUsage({this, index});
}
- return;
}
+ /// Sets the operands to @p operands
+ /// @param operands the new operands for the instruction
+ void SetOperands(utils::VectorRef<ir::Value*> operands) {
+ ClearOperands();
+ operands_ = std::move(operands);
+ for (size_t i = 0; i < operands_.Length(); i++) {
+ operands_[i]->AddUsage({this, static_cast<uint32_t>(i)});
+ }
+ }
+
+ /// Removes all operands from the instruction
+ void ClearOperands() {
+ for (uint32_t i = 0; i < operands_.Length(); i++) {
+ operands_[i]->RemoveUsage({this, i});
+ }
+ operands_.Clear();
+ }
+
+ /// @returns the operands of the instruction
+ utils::VectorRef<ir::Value*> Operands() override { return operands_; }
+
+ /// @returns true if the instruction has result values
+ bool HasResults() override { return !results_.IsEmpty(); }
+ /// @returns true if the instruction has multiple values
+ bool HasMultiResults() override { return results_.Length() > 1; }
+
+ /// @returns the first result. Returns `nullptr` if there are no results, or if ther are
+ /// multi-results
+ InstructionResult* Result() override {
+ if (!HasResults() || HasMultiResults()) {
+ return nullptr;
+ }
+ return results_[0];
+ }
+
+ using Instruction::Result;
+
+ /// @returns the result values for this instruction
+ utils::VectorRef<InstructionResult*> Results() override { return results_; }
+
protected:
/// Append a new operand to the operand list for this instruction.
+ /// @param idx the index the operand should be at
/// @param value the operand value to append
- void AddOperand(ir::Value* value) {
+ void AddOperand(size_t idx, ir::Value* value) {
+ TINT_ASSERT(IR, idx == operands_.Length());
+
if (value) {
value->AddUsage({this, static_cast<uint32_t>(operands_.Length())});
}
operands_.Push(value);
}
- /// Append a list of non-null operands to the operand list for this instruction.
+ /// Append a list of operands to the operand list for this instruction.
+ /// @param start_idx the index from which the values should start
/// @param values the operand values to append
- void AddOperands(utils::VectorRef<ir::Value*> values) {
+ void AddOperands(size_t start_idx, utils::VectorRef<ir::Value*> values) {
+ size_t idx = start_idx;
for (auto* val : values) {
- TINT_ASSERT(IR, val != nullptr);
- AddOperand(val);
+ AddOperand(idx, val);
+ idx += 1;
}
}
+ /// Appends a result value to the instruction
+ /// @param value the value to append
+ void AddResult(InstructionResult* value) {
+ if (value) {
+ value->SetSource(this);
+ }
+ results_.Push(value);
+ }
+
/// The operands to this instruction.
utils::Vector<ir::Value*, N> operands_;
+ /// The results of this instruction.
+ utils::Vector<ir::InstructionResult*, R> results_;
};
} // namespace tint::ir
diff --git a/src/tint/ir/operand_instruction_test.cc b/src/tint/ir/operand_instruction_test.cc
new file mode 100644
index 0000000..9d05a07
--- /dev/null
+++ b/src/tint/ir/operand_instruction_test.cc
@@ -0,0 +1,45 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gmock/gmock.h"
+#include "src/tint/ir/ir_test_helper.h"
+
+namespace tint::ir {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+
+using IR_OperandInstructionTest = IRTestHelper;
+
+TEST_F(IR_OperandInstructionTest, Destroy) {
+ auto* block = b.Block();
+ auto* inst = b.Add(ty.i32(), 1_i, 2_i);
+ block->Append(inst);
+ auto* lhs = inst->LHS();
+ auto* rhs = inst->RHS();
+ EXPECT_EQ(inst->Block(), block);
+ EXPECT_THAT(lhs->Usages(), testing::ElementsAre(Usage{inst, 0u}));
+ EXPECT_THAT(rhs->Usages(), testing::ElementsAre(Usage{inst, 1u}));
+ EXPECT_TRUE(inst->Result()->Alive());
+
+ inst->Destroy();
+
+ EXPECT_EQ(inst->Block(), nullptr);
+ EXPECT_TRUE(lhs->Usages().IsEmpty());
+ EXPECT_TRUE(rhs->Usages().IsEmpty());
+ EXPECT_FALSE(inst->Result()->Alive());
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/program_test_helper.h b/src/tint/ir/program_test_helper.h
index 3ce88f0..d982366 100644
--- a/src/tint/ir/program_test_helper.h
+++ b/src/tint/ir/program_test_helper.h
@@ -20,9 +20,9 @@
#include <utility>
#include "gtest/gtest.h"
+#include "src/tint/builtin/number.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"
diff --git a/src/tint/ir/return.cc b/src/tint/ir/return.cc
index 8c0de42..325f283 100644
--- a/src/tint/ir/return.cc
+++ b/src/tint/ir/return.cc
@@ -22,19 +22,13 @@
namespace tint::ir {
-Return::Return(Function* func) : func_(func) {
- TINT_ASSERT_OR_RETURN(IR, func_);
-
- func_->AddUsage({this, 0u});
+Return::Return(Function* func) {
+ AddOperand(Return::kFunctionOperandOffset, func);
}
-Return::Return(Function* func, Value* arg) : func_(func) {
- TINT_ASSERT_OR_RETURN(IR, func_);
- TINT_ASSERT_OR_RETURN(IR, arg);
-
- func_->AddUsage({this, 0u});
-
- AddOperand(arg);
+Return::Return(Function* func, ir::Value* arg) {
+ AddOperand(Return::kFunctionOperandOffset, func);
+ AddOperand(Return::kArgOperandOffset, arg);
}
Return::~Return() = default;
diff --git a/src/tint/ir/return.h b/src/tint/ir/return.h
index 55463e2..403a215 100644
--- a/src/tint/ir/return.h
+++ b/src/tint/ir/return.h
@@ -28,6 +28,12 @@
/// A return instruction.
class Return : public utils::Castable<Return, Branch> {
public:
+ /// The offset in Operands() for the function being returned
+ static constexpr size_t kFunctionOperandOffset = 0;
+
+ /// The offset in Operands() for the return argument
+ static constexpr size_t kArgOperandOffset = 1;
+
/// Constructor (no return value)
/// @param func the function being returned
explicit Return(Function* func);
@@ -35,15 +41,26 @@
/// Constructor
/// @param func the function being returned
/// @param arg the return value
- Return(Function* func, Value* arg);
+ Return(Function* func, ir::Value* arg);
~Return() override;
/// @returns the function being returned
- Function* Func() { return func_; }
+ Function* Func() { return operands_[kFunctionOperandOffset]->As<Function>(); }
- private:
- Function* func_ = nullptr;
+ /// @returns the return value, or nullptr
+ ir::Value* Value() const {
+ return operands_.Length() > kArgOperandOffset ? operands_[kArgOperandOffset] : nullptr;
+ }
+
+ /// Sets the return value
+ /// @param val the new return value
+ void SetValue(ir::Value* val) { SetOperand(kArgOperandOffset, val); }
+
+ /// @returns the branch arguments
+ utils::Slice<ir::Value* const> Args() override {
+ return operands_.Slice().Offset(kArgOperandOffset);
+ }
};
} // namespace tint::ir
diff --git a/src/tint/ir/return_test.cc b/src/tint/ir/return_test.cc
index fbe3330..159e94d 100644
--- a/src/tint/ir/return_test.cc
+++ b/src/tint/ir/return_test.cc
@@ -24,37 +24,42 @@
using namespace tint::number_suffixes; // NOLINT
using IR_ReturnTest = IRTestHelper;
-TEST_F(IR_ReturnTest, Fail_NullFunction) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Return(nullptr);
- },
- "");
-}
-
-TEST_F(IR_ReturnTest, Fail_NullValue) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- mod.values.Create<Return>(b.Function("myfunc", mod.Types().void_()), nullptr);
- },
- "");
-}
-
TEST_F(IR_ReturnTest, ImplicitNoValue) {
- auto* ret = b.Return(b.Function("myfunc", ty.void_()));
+ auto* func = b.Function("myfunc", ty.void_());
+ auto* ret = b.Return(func);
+ ASSERT_EQ(ret->Func(), func);
EXPECT_TRUE(ret->Args().IsEmpty());
+ EXPECT_EQ(ret->Value(), nullptr);
+ EXPECT_THAT(func->Usages(), testing::UnorderedElementsAre(Usage{ret, 0u}));
}
TEST_F(IR_ReturnTest, WithValue) {
+ auto* func = b.Function("myfunc", ty.i32());
auto* val = b.Constant(42_i);
- auto* ret = b.Return(b.Function("myfunc", ty.i32()), val);
+ auto* ret = b.Return(func, val);
+ ASSERT_EQ(ret->Func(), func);
ASSERT_EQ(ret->Args().Length(), 1u);
EXPECT_EQ(ret->Args()[0], val);
- EXPECT_THAT(val->Usages(), testing::UnorderedElementsAre(Usage{ret, 0u}));
+ EXPECT_EQ(ret->Value(), val);
+ EXPECT_THAT(func->Usages(), testing::UnorderedElementsAre(Usage{ret, 0u}));
+ EXPECT_THAT(val->Usages(), testing::UnorderedElementsAre(Usage{ret, 1u}));
+}
+
+TEST_F(IR_ReturnTest, Result) {
+ auto* vfunc = b.Function("vfunc", ty.void_());
+ auto* ifunc = b.Function("ifunc", ty.i32());
+
+ {
+ auto* ret1 = b.Return(vfunc);
+ EXPECT_FALSE(ret1->HasResults());
+ EXPECT_FALSE(ret1->HasMultiResults());
+ }
+
+ {
+ auto* ret2 = b.Return(ifunc, b.Constant(42_i));
+ EXPECT_FALSE(ret2->HasResults());
+ EXPECT_FALSE(ret2->HasMultiResults());
+ }
}
} // namespace
diff --git a/src/tint/ir/store.cc b/src/tint/ir/store.cc
index 958f1e4..d1ea611 100644
--- a/src/tint/ir/store.cc
+++ b/src/tint/ir/store.cc
@@ -20,11 +20,8 @@
namespace tint::ir {
Store::Store(Value* to, Value* from) {
- TINT_ASSERT(IR, to);
- TINT_ASSERT(IR, from);
-
- AddOperand(to);
- AddOperand(from);
+ AddOperand(Store::kToOperandOffset, to);
+ AddOperand(Store::kFromOperandOffset, from);
}
Store::~Store() = default;
diff --git a/src/tint/ir/store.h b/src/tint/ir/store.h
index 41289f2..e14a58f 100644
--- a/src/tint/ir/store.h
+++ b/src/tint/ir/store.h
@@ -21,8 +21,14 @@
namespace tint::ir {
/// A store instruction in the IR.
-class Store : public utils::Castable<Store, OperandInstruction<2>> {
+class Store : public utils::Castable<Store, OperandInstruction<2, 0>> {
public:
+ /// The offset in Operands() for the `to` value
+ static constexpr size_t kToOperandOffset = 0;
+
+ /// The offset in Operands() for the `from` value
+ static constexpr size_t kFromOperandOffset = 1;
+
/// Constructor
/// @param to the value to store too
/// @param from the value being stored from
@@ -30,10 +36,10 @@
~Store() override;
/// @returns the value being stored too
- Value* To() { return operands_[0]; }
+ Value* To() { return operands_[kToOperandOffset]; }
/// @returns the value being stored
- Value* From() { return operands_[1]; }
+ Value* From() { return operands_[kFromOperandOffset]; }
};
} // namespace tint::ir
diff --git a/src/tint/ir/store_test.cc b/src/tint/ir/store_test.cc
index 5578005..1bf40cb 100644
--- a/src/tint/ir/store_test.cc
+++ b/src/tint/ir/store_test.cc
@@ -21,17 +21,17 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using IR_StoreTest = IRTestHelper;
TEST_F(IR_StoreTest, CreateStore) {
- auto* to = b.Var(mod.Types().ptr(builtin::AddressSpace::kPrivate, mod.Types().i32(),
- builtin::Access::kReadWrite));
+ auto* to = b.Var(ty.ptr<private_, i32>());
auto* inst = b.Store(to, 4_i);
ASSERT_TRUE(inst->Is<Store>());
- ASSERT_EQ(inst->To(), to);
+ ASSERT_EQ(inst->To(), to->Result());
ASSERT_TRUE(inst->From()->Is<Constant>());
auto lhs = inst->From()->As<Constant>()->Value();
@@ -39,8 +39,8 @@
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
}
-TEST_F(IR_StoreTest, Store_Usage) {
- auto* to = b.Discard();
+TEST_F(IR_StoreTest, Usage) {
+ auto* to = b.Var(ty.ptr<private_, i32>());
auto* inst = b.Store(to, 4_i);
ASSERT_NE(inst->To(), nullptr);
@@ -50,26 +50,12 @@
EXPECT_THAT(inst->From()->Usages(), testing::UnorderedElementsAre(Usage{inst, 1u}));
}
-TEST_F(IR_StoreTest, Fail_NullTo) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Store(nullptr, 1_u);
- },
- "");
-}
+TEST_F(IR_StoreTest, Result) {
+ auto* to = b.Var(ty.ptr<private_, i32>());
+ auto* inst = b.Store(to, 4_i);
-TEST_F(IR_StoreTest, Fail_NullFrom) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- auto* to = b.Var(mod.Types().ptr(builtin::AddressSpace::kPrivate, mod.Types().i32(),
- builtin::Access::kReadWrite));
- b.Store(to, nullptr);
- },
- "");
+ EXPECT_FALSE(inst->HasResults());
+ EXPECT_FALSE(inst->HasMultiResults());
}
} // namespace
diff --git a/src/tint/ir/switch.cc b/src/tint/ir/switch.cc
index 8b70cfc..9d9e75d 100644
--- a/src/tint/ir/switch.cc
+++ b/src/tint/ir/switch.cc
@@ -16,21 +16,20 @@
TINT_INSTANTIATE_TYPEINFO(tint::ir::Switch);
-#include "src/tint/ir/multi_in_block.h"
-
namespace tint::ir {
-Switch::Switch(Value* cond, ir::MultiInBlock* m) : merge_(m) {
+Switch::Switch(Value* cond) {
TINT_ASSERT(IR, cond);
- TINT_ASSERT(IR, merge_);
- AddOperand(cond);
-
- if (merge_) {
- merge_->SetParent(this);
- }
+ AddOperand(Switch::kConditionOperandOffset, cond);
}
Switch::~Switch() = default;
+void Switch::ForeachBlock(const std::function<void(ir::Block*)>& cb) {
+ for (auto& c : cases_) {
+ cb(c.Block());
+ }
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/switch.h b/src/tint/ir/switch.h
index 7791c2c..1d16b89 100644
--- a/src/tint/ir/switch.h
+++ b/src/tint/ir/switch.h
@@ -35,17 +35,17 @@
/// │ Case A │ │ Case B │ │ Case C │
/// └────────┘ └────────┘ └────────┘
/// ExitSwitch ┃ ExitSwitch ┃ ExitSwitch ┃
-/// ┃ ▼ ┃
-/// ┃ ┌────────────┐ ┃
-/// ╌╌╌╌╌╌╌╌┺━━━━━━▶│ Merge │◀━━━━━━━┹╌╌╌╌╌╌╌╌
-/// │ (optional) │
-/// └────────────┘
+/// ┃ ┃ ┃
+/// ╌╌╌╌╌╌╌╌┺━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━┹╌╌╌╌╌╌╌╌
/// ┃
/// ▼
/// out
/// ```
class Switch : public utils::Castable<Switch, ControlInstruction> {
public:
+ /// The offset in Operands() for the condition
+ static constexpr size_t kConditionOperandOffset = 0;
+
/// A case selector
struct CaseSelector {
/// @returns true if this is a default selector
@@ -59,33 +59,28 @@
struct Case {
/// The case selector for this node
utils::Vector<CaseSelector, 4> selectors;
- /// The start block for the case block.
- ir::Block* start = nullptr;
+ /// The case block.
+ ir::Block* block = nullptr;
- /// @returns the case start target
- ir::Block* Start() { return start; }
+ /// @returns the case block
+ ir::Block* Block() { return block; }
};
/// Constructor
/// @param cond the condition
- /// @param m the merge block
- explicit Switch(Value* cond, ir::MultiInBlock* m);
+ explicit Switch(Value* cond);
~Switch() override;
- /// @returns the switch merge branch
- ir::MultiInBlock* Merge() { return merge_; }
+ /// @copydoc ControlInstruction::ForeachBlock
+ void ForeachBlock(const std::function<void(ir::Block*)>& cb) override;
/// @returns the switch cases
utils::Vector<Case, 4>& Cases() { return cases_; }
- /// @returns the branch arguments
- utils::Slice<Value* const> Args() override { return {}; }
-
/// @returns the condition
- Value* Condition() { return operands_[0]; }
+ Value* Condition() { return operands_[kConditionOperandOffset]; }
private:
- ir::MultiInBlock* merge_ = nullptr;
utils::Vector<Case, 4> cases_;
};
diff --git a/src/tint/ir/switch_test.cc b/src/tint/ir/switch_test.cc
index 72e0dda..d881247 100644
--- a/src/tint/ir/switch_test.cc
+++ b/src/tint/ir/switch_test.cc
@@ -30,31 +30,17 @@
EXPECT_THAT(cond->Usages(), testing::UnorderedElementsAre(Usage{switch_, 0u}));
}
+TEST_F(IR_SwitchTest, Results) {
+ auto* cond = b.Constant(true);
+ auto* switch_ = b.Switch(cond);
+ EXPECT_FALSE(switch_->HasResults());
+ EXPECT_FALSE(switch_->HasMultiResults());
+}
+
TEST_F(IR_SwitchTest, Parent) {
auto* switch_ = b.Switch(1_i);
b.Case(switch_, {Switch::CaseSelector{nullptr}});
- EXPECT_THAT(switch_->Merge()->Parent(), switch_);
- EXPECT_THAT(switch_->Cases().Front().Start()->Parent(), switch_);
-}
-
-TEST_F(IR_SwitchTest, Fail_NullCondition) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Switch(nullptr);
- },
- "");
-}
-
-TEST_F(IR_SwitchTest, Fail_NullMultiInBlock) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- Switch switch_(b.Constant(false), nullptr);
- },
- "");
+ EXPECT_THAT(switch_->Cases().Front().Block()->Parent(), switch_);
}
} // namespace
diff --git a/src/tint/ir/swizzle.cc b/src/tint/ir/swizzle.cc
index 58cecb2..e6996bc 100644
--- a/src/tint/ir/swizzle.cc
+++ b/src/tint/ir/swizzle.cc
@@ -22,14 +22,13 @@
namespace tint::ir {
-Swizzle::Swizzle(const type::Type* ty, Value* object, utils::VectorRef<uint32_t> indices)
- : result_type_(ty), indices_(std::move(indices)) {
- TINT_ASSERT(IR, object != nullptr);
- TINT_ASSERT(IR, result_type_ != nullptr);
+Swizzle::Swizzle(InstructionResult* result, Value* object, utils::VectorRef<uint32_t> indices)
+ : indices_(std::move(indices)) {
TINT_ASSERT(IR, !indices.IsEmpty());
TINT_ASSERT(IR, indices.Length() <= 4);
- AddOperand(object);
+ AddOperand(Swizzle::kObjectOperandOffset, object);
+ AddResult(result);
for (auto idx : indices_) {
TINT_ASSERT(IR, idx < 4);
diff --git a/src/tint/ir/swizzle.h b/src/tint/ir/swizzle.h
index f340a01..c2ab06e 100644
--- a/src/tint/ir/swizzle.h
+++ b/src/tint/ir/swizzle.h
@@ -21,26 +21,25 @@
namespace tint::ir {
/// A swizzle instruction in the IR.
-class Swizzle : public utils::Castable<Swizzle, OperandInstruction<1>> {
+class Swizzle : public utils::Castable<Swizzle, OperandInstruction<1, 1>> {
public:
+ /// The offset in Operands() for the object being swizzled
+ static constexpr size_t kObjectOperandOffset = 0;
+
/// Constructor
- /// @param result_type the result type
+ /// @param result the result value
/// @param object the object being swizzled
/// @param indices the indices to swizzle
- Swizzle(const type::Type* result_type, Value* object, utils::VectorRef<uint32_t> indices);
+ Swizzle(InstructionResult* result, Value* object, utils::VectorRef<uint32_t> indices);
~Swizzle() override;
- /// @returns the type of the value
- const type::Type* Type() override { return result_type_; }
-
/// @returns the object used for the access
- Value* Object() { return operands_[0]; }
+ Value* Object() { return operands_[kObjectOperandOffset]; }
/// @returns the swizzle indices
utils::VectorRef<uint32_t> Indices() { return indices_; }
private:
- const type::Type* result_type_ = nullptr;
utils::Vector<uint32_t, 4> indices_;
};
diff --git a/src/tint/ir/swizzle_test.cc b/src/tint/ir/swizzle_test.cc
index ada269d..ab45e8c 100644
--- a/src/tint/ir/swizzle_test.cc
+++ b/src/tint/ir/swizzle_test.cc
@@ -18,6 +18,8 @@
#include "gtest/gtest-spi.h"
#include "src/tint/ir/ir_test_helper.h"
+using namespace tint::builtin::fluent_types; // NOLINT
+
namespace tint::ir {
namespace {
@@ -27,7 +29,17 @@
auto* var = b.Var(ty.ptr<function, i32>());
auto* a = b.Swizzle(mod.Types().i32(), var, {1u});
- EXPECT_THAT(var->Usages(), testing::UnorderedElementsAre(Usage{a, 0u}));
+ EXPECT_THAT(var->Result()->Usages(), testing::UnorderedElementsAre(Usage{a, 0u}));
+}
+
+TEST_F(IR_SwizzleTest, Results) {
+ auto* var = b.Var(ty.ptr<function, i32>());
+ auto* a = b.Swizzle(mod.Types().i32(), var, {1u});
+
+ EXPECT_TRUE(a->HasResults());
+ EXPECT_FALSE(a->HasMultiResults());
+ EXPECT_TRUE(a->Result()->Is<InstructionResult>());
+ EXPECT_EQ(a->Result()->Source(), a);
}
TEST_F(IR_SwizzleTest, Fail_NullType) {
@@ -41,16 +53,6 @@
"");
}
-TEST_F(IR_SwizzleTest, Fail_NullObject) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Swizzle(mod.Types().i32(), nullptr, {1u});
- },
- "");
-}
-
TEST_F(IR_SwizzleTest, Fail_EmptyIndices) {
EXPECT_FATAL_FAILURE(
{
diff --git a/src/tint/ir/to_program.cc b/src/tint/ir/to_program.cc
index c536ae6..a286702 100644
--- a/src/tint/ir/to_program.cc
+++ b/src/tint/ir/to_program.cc
@@ -22,6 +22,7 @@
#include "src/tint/ir/call.h"
#include "src/tint/ir/constant.h"
#include "src/tint/ir/exit_if.h"
+#include "src/tint/ir/exit_switch.h"
#include "src/tint/ir/if.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/load.h"
@@ -45,6 +46,7 @@
#include "src/tint/type/texture.h"
#include "src/tint/utils/hashmap.h"
#include "src/tint/utils/predicates.h"
+#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/utils/transform.h"
#include "src/tint/utils/vector.h"
@@ -86,13 +88,16 @@
/// A hashmap of value to symbol used in the emitted AST
utils::Hashmap<Value*, Symbol, 32> value_names_;
- // The nesting depth of the currently generated AST
- // 0 is module scope
- // 1 is root-level function scope
- // 2+ is within control flow
+ /// The nesting depth of the currently generated AST
+ /// 0 is module scope
+ /// 1 is root-level function scope
+ /// 2+ is within control flow
uint32_t nesting_depth_ = 0;
- const ast::Function* Fn(Function* fn) {
+ /// The current switch case block
+ ir::Block* current_switch_case_ = nullptr;
+
+ const ast::Function* Fn(ir::Function* fn) {
SCOPED_NESTING();
// TODO(crbug.com/tint/1915): Properly implement this when we've fleshed out Function
@@ -105,43 +110,23 @@
auto name = AssignNameTo(fn);
auto ret_ty = Type(fn->ReturnType());
- auto* body = BlockGraph(fn->StartTarget());
+ auto* body = Block(fn->StartTarget());
utils::Vector<const ast::Attribute*, 1> attrs{};
utils::Vector<const ast::Attribute*, 1> ret_attrs{};
return b.Func(name, std::move(params), ret_ty, body, std::move(attrs),
std::move(ret_attrs));
}
- const ast::BlockStatement* BlockGraph(ir::Block* start_node) {
- // TODO(crbug.com/tint/1902): Check if the block is dead
- utils::Vector<const ast::Statement*,
- decltype(ast::BlockStatement::statements)::static_length>
- stmts;
-
- ir::Block* block = start_node;
+ const ast::BlockStatement* Block(ir::Block* block) {
+ static constexpr size_t N = decltype(ast::BlockStatement::statements)::static_length;
+ utils::Vector<const ast::Statement*, N> stmts;
// TODO(crbug.com/tint/1902): Handle block arguments.
- while (block) {
- TINT_ASSERT(IR, block->HasBranchTarget());
-
- for (auto* inst : *block) {
- if (auto* stmt = Stmt(inst)) {
- stmts.Push(stmt);
- }
+ for (auto* inst : *block) {
+ if (auto stmt = Stmt(inst)) {
+ stmts.Push(stmt);
}
- if (auto* if_ = block->Branch()->As<ir::If>()) {
- if (if_->Merge()->HasBranchTarget()) {
- block = if_->Merge();
- continue;
- }
- } else if (auto* switch_ = block->Branch()->As<ir::Switch>()) {
- if (switch_->Merge()->HasBranchTarget()) {
- block = switch_->Merge();
- continue;
- }
- }
- break;
}
return b.Block(std::move(stmts));
@@ -158,16 +143,17 @@
/// @return an ast::Statement from @p inst, or nullptr if there was an error
const ast::Statement* Stmt(ir::Instruction* inst) {
return tint::Switch(
- inst, //
- [&](ir::Store* i) { return Store(i); }, //
- [&](ir::Call* i) { return CallStmt(i); }, //
- [&](ir::Var* i) { return Var(i); }, //
- [&](ir::If* if_) { return If(if_); }, //
- [&](ir::Switch* switch_) { return Switch(switch_); }, //
- [&](ir::Return* ret) { return Return(ret); }, //
- [&](ir::Value*) { return ValueStmt(inst); },
- // TODO(dsinclair): Remove when branch is only a parent ...
- [&](ir::Branch*) { return nullptr; },
+ inst, //
+ [&](ir::Call* i) { return CallStmt(i); }, //
+ [&](ir::Var* i) { return Var(i); }, //
+ [&](ir::Load*) { return nullptr; }, //
+ [&](ir::Store* i) { return Store(i); }, //
+ [&](ir::If* if_) { return If(if_); }, //
+ [&](ir::Switch* switch_) { return Switch(switch_); }, //
+ [&](ir::Return* ret) { return Return(ret); }, //
+ [&](ir::ExitSwitch* e) { return ExitSwitch(e); }, //
+ [&](ir::ExitIf*) { return nullptr; }, //
+ [&](ir::Instruction* i) { return ValueStmt(i->Result()); }, //
[&](Default) {
UNHANDLED_CASE(inst);
return nullptr;
@@ -179,33 +165,31 @@
const ast::IfStatement* If(ir::If* i) {
SCOPED_NESTING();
auto* cond = Expr(i->Condition());
- auto* t = BlockGraph(i->True());
+ auto* t = Block(i->True());
if (TINT_UNLIKELY(!t)) {
return nullptr;
}
- auto* false_blk = i->False();
- if (false_blk->Length() > 1 || (false_blk->Length() == 1 && false_blk->HasBranchTarget() &&
- !false_blk->Branch()->Is<ir::ExitIf>())) {
- // If the else target is an `if` which has a merge target that just bounces to the outer
- // if merge target then emit an 'else if' instead of a block statement for the else.
- if (auto* inst = i->False()->Instructions(); inst && inst->As<ir::If>()) {
- auto* if_ = inst->As<ir::If>();
- if (auto* br = if_->Merge()->Branch()->As<ir::ExitIf>(); br && br->If() == i) {
- auto* f = If(if_);
+ if (auto* false_blk = i->False(); false_blk && !false_blk->IsEmpty()) {
+ bool maybe_elseif = (false_blk->Length() == 1) ||
+ (false_blk->Length() == 2 && false_blk->Back()->Is<ir::Branch>());
+ if (maybe_elseif) {
+ if (auto* else_if = false_blk->Front()->As<ir::If>()) {
+ auto* f = If(else_if);
if (!f) {
return nullptr;
}
return b.If(cond, t, b.Else(f));
}
- } else {
- auto* f = BlockGraph(i->False());
- if (!f) {
- return nullptr;
- }
- return b.If(cond, t, b.Else(f));
}
+
+ auto* f = Block(i->False());
+ if (!f) {
+ return nullptr;
+ }
+ return b.If(cond, t, b.Else(f));
}
+
return b.If(cond, t);
}
@@ -223,7 +207,12 @@
utils::Transform(s->Cases(), //
[&](ir::Switch::Case c) -> const tint::ast::CaseStatement* {
SCOPED_NESTING();
- auto* body = BlockGraph(c.start);
+
+ const ast::BlockStatement* body = nullptr;
+ {
+ TINT_SCOPED_ASSIGNMENT(current_switch_case_, c.Block());
+ body = Block(c.Block());
+ }
if (!body) {
return nullptr;
}
@@ -253,6 +242,13 @@
return b.Switch(cond, std::move(cases));
}
+ const ast::BreakStatement* ExitSwitch(const ir::ExitSwitch* e) {
+ if (current_switch_case_ && current_switch_case_->Branch() == e) {
+ return nullptr; // No need to emit
+ }
+ return b.Break();
+ }
+
/// @param ret the ir::Return
/// @return an ast::ReturnStatement from @p ret, or nullptr if there was an error
const ast::ReturnStatement* Return(ir::Return* ret) {
@@ -290,7 +286,7 @@
/// @return an ast::VariableDeclStatement from @p var
const ast::VariableDeclStatement* Var(ir::Var* var) {
Symbol name = AssignNameTo(var);
- auto* ptr = var->Type();
+ auto* ptr = var->Result()->Type()->As<type::Pointer>();
auto ty = Type(ptr->StoreType());
const ast::Expression* init = nullptr;
if (var->Initializer()) {
@@ -321,8 +317,8 @@
// Determine whether the value should be placed into a let, or inlined in its single place
// of usage. Currently a value is inlined if it has a single usage and is unnamed.
- // TODO(crbug.com/tint/1902): This logic needs to check that the sequence of side-effecting
- // expressions is not changed by inlining the expression. This needs fixing.
+ // TODO(crbug.com/tint/1902): This logic needs to check that the sequence of side -
+ // effecting expressions is not changed by inlining the expression. This needs fixing.
bool create_let = val->Usages().Count() > 1 || mod.NameOf(val).IsValid();
if (create_let) {
auto* init = Expr(val); // Must come before giving the value a name
@@ -342,20 +338,36 @@
// This prevents littering the ToProgram logic with expensive error checking code.
////////////////////////////////////////////////////////////////////////////////////////////////
- /// @param val the ir::Expression
- /// @return an ast::Expression from @p val.
- /// @note May be a semantically-invalid placeholder expression on error.
+ /// @param val the value
+ /// @returns the ast::Expression from the values source instruction
const ast::Expression* Expr(ir::Value* val) {
if (auto name = value_names_.Get(val)) {
return b.Expr(name.value());
}
return tint::Switch(
- val, //
- [&](ir::Constant* c) { return ConstExpr(c); }, //
- [&](ir::Load* l) { return LoadExpr(l); }, //
- [&](ir::Unary* u) { return UnaryExpr(u); }, //
- [&](ir::Binary* u) { return BinaryExpr(u); }, //
+ val, //
+ [&](ir::Constant* c) { return ConstExpr(c); }, //
+ [&](ir::InstructionResult* r) { return Expr(r->Source()); }, //
+ [&](Default) -> const ast::Expression* {
+ UNHANDLED_CASE(val);
+ return b.Expr("<error>");
+ });
+ }
+
+ /// @param val the ir::Expression
+ /// @return an ast::Expression from @p val.
+ /// @note May be a semantically-invalid placeholder expression on error.
+ const ast::Expression* Expr(ir::Instruction* val) {
+ if (auto name = value_names_.Get(val->Result())) {
+ return b.Expr(name.value());
+ }
+
+ return tint::Switch(
+ val, //
+ [&](ir::Load* l) { return LoadExpr(l); }, //
+ [&](ir::Unary* u) { return UnaryExpr(u); }, //
+ [&](ir::Binary* u) { return BinaryExpr(u); }, //
[&](Default) {
UNHANDLED_CASE(val);
return b.Expr("<error>");
@@ -554,6 +566,11 @@
// Helpers
////////////////////////////////////////////////////////////////////////////////////////////////
+ /// Creates and returns a new, unique name for the instructions result value, or returns the
+ /// previously created name. Must not be called with a multi-result instruction.
+ /// @return the instruction values name
+ Symbol AssignNameTo(Instruction* inst) { return AssignNameTo(inst->Result()); }
+
/// Creates and returns a new, unique name for the given value, or returns the previously
/// created name.
/// @return the value's name
diff --git a/src/tint/ir/transform/add_empty_entry_point.cc b/src/tint/ir/transform/add_empty_entry_point.cc
index 7a5506d..3c28e59 100644
--- a/src/tint/ir/transform/add_empty_entry_point.cc
+++ b/src/tint/ir/transform/add_empty_entry_point.cc
@@ -37,7 +37,7 @@
ir::Builder builder(*ir);
auto* ep = builder.Function("unused_entry_point", ir->Types().void_(),
Function::PipelineStage::kCompute, std::array{1u, 1u, 1u});
- ep->StartTarget()->SetInstructions({builder.Return(ep)});
+ ep->StartTarget()->Append(builder.Return(ep));
ir->functions.Push(ep);
}
diff --git a/src/tint/ir/transform/add_empty_entry_point_test.cc b/src/tint/ir/transform/add_empty_entry_point_test.cc
index 558e2af..c5c60a1 100644
--- a/src/tint/ir/transform/add_empty_entry_point_test.cc
+++ b/src/tint/ir/transform/add_empty_entry_point_test.cc
@@ -39,7 +39,7 @@
TEST_F(IR_AddEmptyEntryPointTest, ExistingEntryPoint) {
auto* ep = b.Function("main", mod.Types().void_(), Function::PipelineStage::kFragment);
- ep->StartTarget()->SetInstructions({b.Return(ep)});
+ ep->StartTarget()->Append(b.Return(ep));
mod.functions.Push(ep);
auto* expect = R"(
diff --git a/src/tint/ir/transform/block_decorated_structs.cc b/src/tint/ir/transform/block_decorated_structs.cc
index 5c466a5..40805b5 100644
--- a/src/tint/ir/transform/block_decorated_structs.cc
+++ b/src/tint/ir/transform/block_decorated_structs.cc
@@ -45,7 +45,7 @@
if (!var) {
continue;
}
- auto* ptr = var->Type()->As<type::Pointer>();
+ auto* ptr = var->Result()->Type()->As<type::Pointer>();
if (!ptr || !(ptr->AddressSpace() == builtin::AddressSpace::kStorage ||
ptr->AddressSpace() == builtin::AddressSpace::kUniform)) {
continue;
@@ -55,7 +55,7 @@
// Now process the buffer variables.
for (auto* var : buffer_variables) {
- auto* ptr = var->Type()->As<type::Pointer>();
+ auto* ptr = var->Result()->Type()->As<type::Pointer>();
auto* store_ty = ptr->StoreType();
bool wrapped = false;
@@ -98,15 +98,15 @@
var->ReplaceWith(new_var);
// Replace uses of the old variable.
- var->ReplaceAllUsesWith([&](Usage use) -> Value* {
+ var->Result()->ReplaceAllUsesWith([&](Usage use) -> Value* {
if (wrapped) {
// The structure has been wrapped, so replace all uses of the old variable with a
// member accessor on the new variable.
- auto* access = builder.Access(var->Type(), new_var, 0_u);
+ auto* access = builder.Access(var->Result()->Type(), new_var, 0_u);
access->InsertBefore(use.instruction);
- return access;
+ return access->Result();
}
- return new_var;
+ return new_var->Result();
});
}
}
diff --git a/src/tint/ir/transform/block_decorated_structs_test.cc b/src/tint/ir/transform/block_decorated_structs_test.cc
index e86c563..92e3922 100644
--- a/src/tint/ir/transform/block_decorated_structs_test.cc
+++ b/src/tint/ir/transform/block_decorated_structs_test.cc
@@ -24,9 +24,10 @@
namespace tint::ir::transform {
namespace {
-using IR_BlockDecoratedStructsTest = TransformTest;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
-using namespace tint::number_suffixes; // NOLINT
+using IR_BlockDecoratedStructsTest = TransformTest;
TEST_F(IR_BlockDecoratedStructsTest, NoRootBlock) {
auto* func = b.Function("foo", ty.void_());
@@ -52,6 +53,7 @@
b.RootBlock()->Append(buffer);
auto* func = b.Function("foo", ty.i32());
+
auto* block = func->StartTarget();
auto* load = block->Append(b.Load(buffer));
block->Append(b.Return(func, load));
@@ -116,15 +118,17 @@
}
TEST_F(IR_BlockDecoratedStructsTest, RuntimeArray) {
- auto* buffer = b.Var(ty.ptr(storage, ty.runtime_array(ty.i32()), builtin::Access::kReadWrite));
+ auto* buffer = b.Var(ty.ptr<storage, array<i32>>());
buffer->SetBindingPoint(0, 0);
b.RootBlock()->Append(buffer);
auto* func = b.Function("foo", ty.void_());
- auto* block = func->StartTarget();
- auto* access = block->Append(b.Access(ty.ptr<storage, i32>(), buffer, 1_u));
- block->Append(b.Store(access, 42_i));
- block->Append(b.Return(func));
+
+ auto sb = b.With(func->StartTarget());
+ auto* access = sb.Access(ty.ptr<storage, i32>(), buffer, 1_u);
+ sb.Store(access, 42_i);
+ sb.Return(func);
+
mod.functions.Push(func);
auto* expect = R"(
@@ -153,12 +157,11 @@
}
TEST_F(IR_BlockDecoratedStructsTest, RuntimeArray_InStruct) {
- utils::Vector<const type::StructMember*, 4> members;
- members.Push(ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}));
- members.Push(ty.Get<type::StructMember>(mod.symbols.New(), ty.runtime_array(ty.i32()), 1u, 4u,
- 4u, 4u, type::StructMemberAttributes{}));
- auto* structure = ty.Get<type::Struct>(mod.symbols.New(), members, 4u, 8u, 8u);
+ auto* structure =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("i"), ty.i32()},
+ {mod.symbols.New("arr"), ty.array<i32>()},
+ });
auto* buffer = b.Var(ty.ptr(storage, structure, builtin::Access::kReadWrite));
buffer->SetBindingPoint(0, 0);
@@ -167,28 +170,30 @@
auto* i32_ptr = ty.ptr<storage, i32>();
auto* func = b.Function("foo", ty.void_());
- auto* block = func->StartTarget();
- auto* val_ptr = block->Append(b.Access(i32_ptr, buffer, 0_u));
- auto* load = block->Append(b.Load(val_ptr));
- auto* elem_ptr = block->Append(b.Access(i32_ptr, buffer, 1_u, 3_u));
- block->Append(b.Store(elem_ptr, load));
- block->Append(b.Return(func));
+
+ auto sb = b.With(func->StartTarget());
+ auto* val_ptr = sb.Access(i32_ptr, buffer, 0_u);
+ auto* load = sb.Load(val_ptr);
+ auto* elem_ptr = sb.Access(i32_ptr, buffer, 1_u, 3_u);
+ sb.Store(elem_ptr, load);
+ sb.Return(func);
+
mod.functions.Push(func);
auto* expect = R"(
-tint_symbol_2 = struct @align(4) {
- tint_symbol:i32 @offset(0)
- tint_symbol_1:array<i32> @offset(4)
+MyStruct = struct @align(4) {
+ i:i32 @offset(0)
+ arr:array<i32> @offset(4)
}
-tint_symbol_3 = struct @align(4), @block {
- tint_symbol:i32 @offset(0)
- tint_symbol_1:array<i32> @offset(4)
+tint_symbol = struct @align(4), @block {
+ i:i32 @offset(0)
+ arr:array<i32> @offset(4)
}
# Root block
%b1 = block {
- %1:ptr<storage, tint_symbol_3, read_write> = var @binding_point(0, 0)
+ %1:ptr<storage, tint_symbol, read_write> = var @binding_point(0, 0)
}
%foo = func():void -> %b2 {
@@ -208,19 +213,16 @@
}
TEST_F(IR_BlockDecoratedStructsTest, StructUsedElsewhere) {
- utils::Vector<const type::StructMember*, 4> members;
- members.Push(ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}));
- members.Push(ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 1u, 4u, 4u, 4u,
- type::StructMemberAttributes{}));
- auto* structure = ty.Get<type::Struct>(mod.symbols.New(), members, 4u, 8u, 8u);
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), ty.i32()},
+ {mod.symbols.New("b"), ty.i32()},
+ });
auto* buffer = b.Var(ty.ptr(storage, structure, builtin::Access::kReadWrite));
buffer->SetBindingPoint(0, 0);
b.RootBlock()->Append(buffer);
- auto* private_var =
- b.Var(ty.ptr(builtin::AddressSpace::kPrivate, structure, builtin::Access::kReadWrite));
+ auto* private_var = b.Var(ty.ptr<private_, read_write>(structure));
b.RootBlock()->Append(private_var);
auto* func = b.Function("foo", ty.void_());
@@ -229,24 +231,24 @@
mod.functions.Push(func);
auto* expect = R"(
-tint_symbol_2 = struct @align(4) {
- tint_symbol:i32 @offset(0)
- tint_symbol_1:i32 @offset(4)
+MyStruct = struct @align(4) {
+ a:i32 @offset(0)
+ b:i32 @offset(4)
}
-tint_symbol_4 = struct @align(4), @block {
- tint_symbol_3:tint_symbol_2 @offset(0)
+tint_symbol_1 = struct @align(4), @block {
+ tint_symbol:MyStruct @offset(0)
}
# Root block
%b1 = block {
- %1:ptr<storage, tint_symbol_4, read_write> = var @binding_point(0, 0)
- %2:ptr<private, tint_symbol_2, read_write> = var
+ %1:ptr<storage, tint_symbol_1, read_write> = var @binding_point(0, 0)
+ %2:ptr<private, MyStruct, read_write> = var
}
%foo = func():void -> %b2 {
%b2 = block {
- %4:ptr<storage, tint_symbol_2, read_write> = access %1, 0u
+ %4:ptr<storage, MyStruct, read_write> = access %1, 0u
store %4, %2
ret
}
diff --git a/src/tint/ir/transform/merge_return.cc b/src/tint/ir/transform/merge_return.cc
new file mode 100644
index 0000000..0b95a3a
--- /dev/null
+++ b/src/tint/ir/transform/merge_return.cc
@@ -0,0 +1,298 @@
+// 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/transform/merge_return.h"
+
+#include <utility>
+
+#include "src/tint/ir/builder.h"
+#include "src/tint/ir/module.h"
+#include "src/tint/switch.h"
+#include "src/tint/utils/reverse.h"
+#include "src/tint/utils/transform.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::transform::MergeReturn);
+
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
+namespace tint::ir::transform {
+
+MergeReturn::MergeReturn() = default;
+
+MergeReturn::~MergeReturn() = default;
+
+/// PIMPL state for the transform, for a single function.
+struct MergeReturn::State {
+ /// The IR module.
+ Module* ir = nullptr;
+
+ /// The IR builder.
+ Builder b{*ir};
+
+ /// The type manager.
+ type::Manager& ty{ir->Types()};
+
+ /// The "has not returned" flag.
+ Var* continue_execution = nullptr;
+
+ /// The variable that holds the return value.
+ /// Null when the function does not return a value.
+ Var* return_val = nullptr;
+
+ /// The final return at the end of the function block.
+ /// May be null when the function returns in all blocks of a control instruction.
+ Return* fn_return = nullptr;
+
+ /// A set of control instructions that transitively hold a return instruction
+ utils::Hashset<ControlInstruction*, 8> holds_return_;
+
+ /// Constructor
+ /// @param mod the module
+ explicit State(Module* mod) : ir(mod) {}
+
+ /// Process the function.
+ /// @param fn the function to process
+ void Process(Function* fn) {
+ // Find all of the nested return instructions in the function.
+ for (const auto& usage : fn->Usages()) {
+ if (auto* ret = usage.instruction->As<Return>()) {
+ TransitivelyMarkAsReturning(ret->Block()->Parent());
+ }
+ }
+
+ if (holds_return_.IsEmpty()) {
+ // No control instructions hold a return statement, so nothing needs to be done.
+ return;
+ }
+
+ // Create a boolean variable that can be used to check whether the function is returning.
+ continue_execution = b.Var(ty.ptr<function, bool>());
+ continue_execution->SetInitializer(b.Constant(true));
+ fn->StartTarget()->Prepend(continue_execution);
+ ir->SetName(continue_execution, "continue_execution");
+
+ // Create a variable to hold the return value if needed.
+ if (!fn->ReturnType()->Is<type::Void>()) {
+ return_val = b.Var(ty.ptr(function, fn->ReturnType()));
+ fn->StartTarget()->Prepend(return_val);
+ ir->SetName(return_val, "return_value");
+ }
+
+ // Look to see if the function ends with a return
+ fn_return = tint::As<Return>(fn->StartTarget()->Branch());
+
+ // Process the function's block.
+ // This will traverse into control instructions that hold returns, and apply the necessary
+ // changes to remove returns.
+ ProcessBlock(fn->StartTarget());
+
+ // If the function didn't end with a return, add one
+ if (!fn_return) {
+ AppendFinalReturn(fn);
+ }
+
+ // Cleanup - if 'continue_execution' was only ever assigned, remove it.
+ continue_execution->DestroyIfOnlyAssigned();
+ }
+
+ /// Marks all the control instructions from ctrl to the function as holding a return.
+ /// @param ctrl the control instruction to mark as returning, along with all ancestor control
+ /// instructions.
+ void TransitivelyMarkAsReturning(ControlInstruction* ctrl) {
+ for (; ctrl; ctrl = ctrl->Block()->Parent()) {
+ if (!holds_return_.Add(ctrl)) {
+ return;
+ }
+ }
+ }
+
+ /// Walks the instructions of @p block, processing control instructions that are marked as
+ /// holding a return instruction. After processing a control instruction with a return, the
+ /// instructions following the control instruction will be wrapped in a 'if' that only executes
+ /// if a return was not reached.
+ /// @param block the block to process
+ void ProcessBlock(Block* block) {
+ If* inner_if = nullptr;
+ for (auto* inst = *block->begin(); inst;) { // For each instruction in 'block'
+ // As we're modifying the block that we're iterating over, grab the pointer to the next
+ // instruction before (potentially) moving 'inst' to another block.
+ auto* next = inst->next;
+ TINT_DEFER(inst = next);
+
+ if (auto* ret = inst->As<Return>()) {
+ // Note: Return instructions are processed without being moved into the 'if' block.
+ ProcessReturn(ret, inner_if);
+ break; // All instructions processed.
+ }
+
+ if (inst->Is<Unreachable>()) {
+ // Unreachable can become reachable once returns are turned into exits.
+ // As this is the terminator for the branch, simply stop processing the
+ // instructions. A appropriate terminator will be created for this block below.
+ inst->Remove();
+ break;
+ }
+
+ // If we've already passed a control instruction holding a return, then we need to move
+ // the instructions that follow the control instruction into the inner-most 'if'.
+ if (inner_if) {
+ inst->Remove();
+ inner_if->True()->Append(inst);
+ }
+
+ // Control instructions holding a return need to be processed, and then a new 'if' needs
+ // to be created to hold the instructions that are between the control instruction and
+ // the block's terminating instruction.
+ if (auto* ctrl = inst->As<ControlInstruction>()) {
+ if (holds_return_.Contains(ctrl)) {
+ // Control instruction transitively holds a return.
+ ctrl->ForeachBlock([&](Block* ctrl_block) { ProcessBlock(ctrl_block); });
+ if (next && next != fn_return && !utils::IsAnyOf<Exit, Unreachable>(next)) {
+ inner_if = CreateIfContinueExecution(ctrl);
+ }
+ }
+ }
+ }
+
+ if (inner_if) {
+ // new_value_with_type returns a new RuntimeValue with the same type as 'v'
+ auto new_value_with_type = [&](Value* v) { return b.InstructionResult(v->Type()); };
+
+ if (inner_if->True()->HasBranchTarget()) {
+ if (auto* exit_if = inner_if->True()->Branch()->As<ExitIf>()) {
+ // Ensure the associated 'if' is updated.
+ exit_if->SetIf(inner_if);
+
+ if (!exit_if->Args().IsEmpty()) {
+ // Inner-most 'if' has a 'exit_if' that returns values.
+ // These need propagating through the if stack.
+ inner_if->SetResults(
+ utils::Transform<8>(exit_if->Args(), new_value_with_type));
+ }
+ }
+ } else {
+ // Inner-most if doesn't have a terminating instruction. Add an 'exit_if'.
+ inner_if->True()->Append(b.ExitIf(inner_if));
+ }
+
+ // Loop over the 'if' instructions, starting with the inner-most, and add any missing
+ // terminating instructions to the blocks holding the 'if'.
+ for (auto* i = inner_if; i; i = tint::As<If>(i->Block()->Parent())) {
+ if (!i->Block()->HasBranchTarget()) {
+ // Append the exit instruction to the block holding the 'if'.
+ utils::Vector<InstructionResult*, 8> exit_args = i->Results();
+ if (!i->HasResults()) {
+ i->SetResults(utils::Transform(exit_args, new_value_with_type));
+ }
+ auto* exit = b.Exit(i->Block()->Parent(), std::move(exit_args));
+ i->Block()->Append(exit);
+ }
+ }
+ }
+ }
+
+ /// Transforms a return instruction.
+ /// @param ret the return instruction
+ /// @param cond the possibly null 'if(continue_execution)' instruction for the current block.
+ /// @note unlike other instructions, return instructions are not automatically moved into the
+ /// 'if(continue_execution)' block.
+ void ProcessReturn(Return* ret, If* cond) {
+ if (ret == fn_return) {
+ // 'ret' is the final instruction for the function.
+ ProcessFunctionBlockReturn(ret, cond);
+ } else {
+ // Return is in a nested block
+ ProcessNestedReturn(ret, cond);
+ }
+ }
+
+ /// Transforms the return instruction that is the last instruction in the function's block.
+ /// @param ret the return instruction
+ /// @param cond the possibly null 'if(continue_execution)' instruction for the current block.
+ void ProcessFunctionBlockReturn(Return* ret, If* cond) {
+ if (!return_val) {
+ return; // No need to transform non-value, end-of-function returns
+ }
+
+ // Assign the return's value to 'return_val' inside a 'if(continue_execution)'
+ if (!cond) {
+ cond = CreateIfContinueExecution(ret->prev);
+ }
+ cond->True()->Append(b.Store(return_val, ret->Value()));
+ cond->True()->Append(b.ExitIf(cond));
+
+ // Change the function return to unconditionally load 'return_val' and return it
+ auto* load = b.Load(return_val);
+ load->InsertBefore(ret);
+ ret->SetValue(load->Result());
+ }
+
+ /// Transforms the return instruction that is found in a control instruction.
+ /// @param ret the return instruction
+ /// @param cond the possibly null 'if(continue_execution)' instruction for the current block.
+ void ProcessNestedReturn(Return* ret, If* cond) {
+ // If we have a 'if(continue_execution)' block, then insert instructions into that,
+ // otherwise insert into the block holding the return.
+ auto* block = cond ? cond->True() : ret->Block();
+
+ // Set the 'continue_execution' flag to false, and store the return value into 'return_val',
+ // if present.
+ block->Append(b.Store(continue_execution, false));
+ if (return_val) {
+ block->Append(b.Store(return_val, ret->Args()[0]));
+ }
+
+ // If the outermost control instruction is expecting exit values, then return them as
+ // 'undef' values.
+ auto* ctrl = block->Parent();
+ utils::Vector<Value*, 8> exit_args;
+ exit_args.Resize(ctrl->Results().Length());
+
+ // Replace the return instruction with an exit instruction.
+ block->Append(b.Exit(ctrl, std::move(exit_args)));
+ ret->Destroy();
+ }
+
+ /// Builds instructions to create a 'if(continue_execution)' conditional.
+ /// @param after new instructions will be inserted after this instruction
+ /// @return the 'If' control instruction
+ If* CreateIfContinueExecution(Instruction* after) {
+ auto* load = b.Load(continue_execution);
+ auto* cond = b.If(load);
+ load->InsertAfter(after);
+ cond->InsertAfter(load);
+ return cond;
+ }
+
+ /// Adds a final return instruction to the end of @p fn
+ /// @param fn the function
+ void AppendFinalReturn(Function* fn) {
+ auto fb = b.With(fn->StartTarget());
+ if (return_val) {
+ fb.Return(fn, fb.Load(return_val));
+ } else {
+ fb.Return(fn);
+ }
+ }
+};
+
+void MergeReturn::Run(Module* ir, const DataMap&, DataMap&) const {
+ // Process each function.
+ for (auto* fn : ir->functions) {
+ State{ir}.Process(fn);
+ }
+}
+
+} // namespace tint::ir::transform
diff --git a/src/tint/ir/transform/merge_return.h b/src/tint/ir/transform/merge_return.h
new file mode 100644
index 0000000..d127366
--- /dev/null
+++ b/src/tint/ir/transform/merge_return.h
@@ -0,0 +1,40 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_TRANSFORM_MERGE_RETURN_H_
+#define SRC_TINT_IR_TRANSFORM_MERGE_RETURN_H_
+
+#include "src/tint/ir/transform/transform.h"
+
+namespace tint::ir::transform {
+
+/// MergeReturn is a transform merges multiple return statements in a function into a single return
+/// at the end of the function.
+class MergeReturn final : public utils::Castable<MergeReturn, Transform> {
+ public:
+ /// Constructor
+ MergeReturn();
+ /// Destructor
+ ~MergeReturn() override;
+
+ /// @copydoc Transform::Run
+ void Run(ir::Module* module, const DataMap& inputs, DataMap& outputs) const override;
+
+ private:
+ struct State;
+};
+
+} // namespace tint::ir::transform
+
+#endif // SRC_TINT_IR_TRANSFORM_MERGE_RETURN_H_
diff --git a/src/tint/ir/transform/merge_return_test.cc b/src/tint/ir/transform/merge_return_test.cc
new file mode 100644
index 0000000..cf2a2cc
--- /dev/null
+++ b/src/tint/ir/transform/merge_return_test.cc
@@ -0,0 +1,2134 @@
+// 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/transform/merge_return.h"
+
+#include <utility>
+
+#include "src/tint/ir/transform/test_helper.h"
+
+namespace tint::ir::transform {
+namespace {
+
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
+using IR_MergeReturnTest = TransformTest;
+
+TEST_F(IR_MergeReturnTest, NoModify_SingleReturnInRootBlock) {
+ auto* in = b.FunctionParam(ty.i32());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({in});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+ sb.Return(func, sb.Add(ty.i32(), in, 1_i));
+
+ auto* src = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ %3:i32 = add %2, 1i
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, NoModify_SingleReturnInMergeBlock) {
+ auto* in = b.FunctionParam(ty.i32());
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({in});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ ifelse->SetResults(b.InstructionResult(ty.i32()));
+ auto tb = b.With(ifelse->True());
+ tb.ExitIf(ifelse, tb.Add(ty.i32(), in, 1_i));
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse, fb.Add(ty.i32(), in, 2_i));
+
+ sb.Return(func, ifelse->Result(0));
+
+ auto* src = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ %3:i32 = if %4 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ %5:i32 = add %2, 1i
+ exit_if %5
+ }
+
+ # False block
+ %b3 = block {
+ %6:i32 = add %2, 2i
+ exit_if %6
+ }
+
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, NoModify_SingleReturnInNestedMergeBlock) {
+ auto* in = b.FunctionParam(ty.i32());
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({in});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* swtch = sb.Switch(in);
+ b.Case(swtch, {Switch::CaseSelector{}})->Append(b.ExitSwitch(swtch));
+
+ sb.Loop();
+
+ auto* ifelse = sb.If(cond);
+ ifelse->SetResults(b.InstructionResult(ty.i32()));
+ auto tb = b.With(ifelse->True());
+ tb.ExitIf(ifelse, tb.Add(ty.i32(), in, 1_i));
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse, fb.Add(ty.i32(), in, 2_i));
+
+ sb.Return(func, ifelse->Result(0));
+
+ auto* src = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ switch %2 [c: (default, %b2)]
+ # Case block
+ %b2 = block {
+ exit_switch
+ }
+
+ loop []
+ %3:i32 = if %4 [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ %5:i32 = add %2, 1i
+ exit_if %5
+ }
+
+ # False block
+ %b4 = block {
+ %6:i32 = add %2, 2i
+ exit_if %6
+ }
+
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_OneSideReturns) {
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ auto tb = b.With(ifelse->True());
+ tb.Return(func);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+
+ sb.Return(func);
+
+ auto* src = R"(
+%foo = func(%2:bool):void -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ ret
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:bool):void -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ exit_if
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+// This is the same as the above tests, but we create the return instructions in a different order
+// to make sure that creation order doesn't matter.
+TEST_F(IR_MergeReturnTest, IfElse_OneSideReturns_ReturnsCreatedInDifferentOrder) {
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ sb.Return(func);
+
+ auto tb = b.With(ifelse->True());
+ tb.Return(func);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+
+ auto* src = R"(
+%foo = func(%2:bool):void -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ ret
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:bool):void -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ exit_if
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_OneSideReturns_WithValue) {
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 1_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+
+ sb.Return(func, 2_i);
+
+ auto* src = R"(
+%foo = func(%2:bool):i32 -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ ret 1i
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ ret 2i
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:bool):i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ %5:bool = load %continue_execution
+ if %5 [t: %b4]
+ # True block
+ %b4 = block {
+ store %return_value, 2i
+ exit_if
+ }
+
+ %6:i32 = load %return_value
+ ret %6
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_OneSideReturns_WithValue_MergeHasBasicBlockArguments) {
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ ifelse->SetResults(b.InstructionResult(ty.i32()));
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 1_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse, 2_i);
+
+ sb.Return(func, ifelse->Result(0));
+
+ auto* src = R"(
+%foo = func(%2:bool):i32 -> %b1 {
+ %b1 = block {
+ %3:i32 = if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ ret 1i
+ }
+
+ # False block
+ %b3 = block {
+ exit_if 2i
+ }
+
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:bool):i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ %5:i32 = if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if undef
+ }
+
+ # False block
+ %b3 = block {
+ exit_if 2i
+ }
+
+ %6:bool = load %continue_execution
+ if %6 [t: %b4]
+ # True block
+ %b4 = block {
+ store %return_value, %5
+ exit_if
+ }
+
+ %7:i32 = load %return_value
+ ret %7
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_OneSideReturns_WithValue_MergeHasUndefBasicBlockArguments) {
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ ifelse->SetResults(b.InstructionResult(ty.i32()));
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 1_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse, b.Constant(8_i));
+
+ sb.Return(func, ifelse->Result(0));
+
+ auto* src = R"(
+%foo = func(%2:bool):i32 -> %b1 {
+ %b1 = block {
+ %3:i32 = if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ ret 1i
+ }
+
+ # False block
+ %b3 = block {
+ exit_if 8i
+ }
+
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:bool):i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ %5:i32 = if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if undef
+ }
+
+ # False block
+ %b3 = block {
+ exit_if 8i
+ }
+
+ %6:bool = load %continue_execution
+ if %6 [t: %b4]
+ # True block
+ %b4 = block {
+ store %return_value, %5
+ exit_if
+ }
+
+ %7:i32 = load %return_value
+ ret %7
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_BothSidesReturn) {
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ auto tb = b.With(ifelse->True());
+ tb.Return(func);
+ auto fb = b.With(ifelse->False());
+ fb.Return(func);
+
+ sb.Unreachable();
+
+ auto* src = R"(
+%foo = func(%2:bool):void -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ ret
+ }
+
+ # False block
+ %b3 = block {
+ ret
+ }
+
+ unreachable
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:bool):void -> %b1 {
+ %b1 = block {
+ if %2 [t: %b2, f: %b3]
+ # True block
+ %b2 = block {
+ exit_if
+ }
+
+ # False block
+ %b3 = block {
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_ThenStatements) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ auto tb = b.With(ifelse->True());
+ tb.Return(func);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+
+ sb.Store(global, 42_i);
+ sb.Return(func);
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):void -> %b2 {
+ %b2 = block {
+ if %3 [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ ret
+ }
+
+ # False block
+ %b4 = block {
+ exit_if
+ }
+
+ store %1, 42i
+ ret
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):void -> %b2 {
+ %b2 = block {
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ if %3 [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ exit_if
+ }
+
+ # False block
+ %b4 = block {
+ exit_if
+ }
+
+ %5:bool = load %continue_execution
+ if %5 [t: %b5]
+ # True block
+ %b5 = block {
+ store %1, 42i
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+// This is the same as the above tests, but we create the return instructions in a different order
+// to make sure that creation order doesn't matter.
+TEST_F(IR_MergeReturnTest, IfElse_ThenStatements_ReturnsCreatedInDifferentOrder) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse = sb.If(cond);
+ sb.Store(global, 42_i);
+ sb.Return(func);
+
+ auto tb = b.With(ifelse->True());
+ tb.Return(func);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):void -> %b2 {
+ %b2 = block {
+ if %3 [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ ret
+ }
+
+ # False block
+ %b4 = block {
+ exit_if
+ }
+
+ store %1, 42i
+ ret
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):void -> %b2 {
+ %b2 = block {
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ if %3 [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ exit_if
+ }
+
+ # False block
+ %b4 = block {
+ exit_if
+ }
+
+ %5:bool = load %continue_execution
+ if %5 [t: %b5]
+ # True block
+ %b5 = block {
+ store %1, 42i
+ exit_if
+ }
+
+ ret
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_Nested) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* func = b.Function("foo", ty.i32());
+ auto* condA = b.FunctionParam(ty.bool_());
+ auto* condB = b.FunctionParam(ty.bool_());
+ auto* condC = b.FunctionParam(ty.bool_());
+ mod.SetName(condA, "condA");
+ mod.SetName(condB, "condB");
+ mod.SetName(condC, "condC");
+ func->SetParams({condA, condB, condC});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse_outer = sb.If(condA);
+ auto outer_true = b.With(ifelse_outer->True());
+ outer_true.Return(func, 3_i);
+ auto outer_false = b.With(ifelse_outer->False());
+ auto* ifelse_middle = outer_false.If(condB);
+
+ sb.Store(global, 3_i);
+ sb.Return(func, sb.Add(ty.i32(), 5_i, 6_i));
+
+ auto middle_true = b.With(ifelse_middle->True());
+ auto* ifelse_inner = middle_true.If(condC);
+ auto middle_false = b.With(ifelse_middle->False());
+ middle_false.ExitIf(ifelse_middle);
+
+ outer_false.Store(global, 2_i);
+ outer_false.ExitIf(ifelse_outer);
+
+ auto inner_true = b.With(ifelse_inner->True());
+ inner_true.Return(func, 1_i);
+ auto inner_false = b.With(ifelse_inner->False());
+ inner_false.ExitIf(ifelse_inner);
+
+ middle_true.Store(global, 1_i);
+ middle_true.Return(func, 2_i);
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%condA:bool, %condB:bool, %condC:bool):i32 -> %b2 {
+ %b2 = block {
+ if %condA [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ ret 3i
+ }
+
+ # False block
+ %b4 = block {
+ if %condB [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ if %condC [t: %b7, f: %b8]
+ # True block
+ %b7 = block {
+ ret 1i
+ }
+
+ # False block
+ %b8 = block {
+ exit_if
+ }
+
+ store %1, 1i
+ ret 2i
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ store %1, 2i
+ exit_if
+ }
+
+ store %1, 3i
+ %6:i32 = add 5i, 6i
+ ret %6
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%condA:bool, %condB:bool, %condC:bool):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ if %condA [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ store %return_value, 3i
+ exit_if
+ }
+
+ # False block
+ %b4 = block {
+ if %condB [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ if %condC [t: %b7, f: %b8]
+ # True block
+ %b7 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if
+ }
+
+ # False block
+ %b8 = block {
+ exit_if
+ }
+
+ %8:bool = load %continue_execution
+ if %8 [t: %b9]
+ # True block
+ %b9 = block {
+ store %1, 1i
+ store %continue_execution, false
+ store %return_value, 2i
+ exit_if
+ }
+
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ %9:bool = load %continue_execution
+ if %9 [t: %b10]
+ # True block
+ %b10 = block {
+ store %1, 2i
+ exit_if
+ }
+
+ exit_if
+ }
+
+ %10:bool = load %continue_execution
+ if %10 [t: %b11]
+ # True block
+ %b11 = block {
+ store %1, 3i
+ %11:i32 = add 5i, 6i
+ store %return_value, %11
+ exit_if
+ }
+
+ %12:i32 = load %return_value
+ ret %12
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_Nested_TrivialMerge) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* func = b.Function("foo", ty.i32());
+ auto* condA = b.FunctionParam(ty.bool_());
+ auto* condB = b.FunctionParam(ty.bool_());
+ auto* condC = b.FunctionParam(ty.bool_());
+ mod.SetName(condA, "condA");
+ mod.SetName(condB, "condB");
+ mod.SetName(condC, "condC");
+ func->SetParams({condA, condB, condC});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse_outer = sb.If(condA);
+ auto outer_true = b.With(ifelse_outer->True());
+ outer_true.Return(func, 3_i);
+ auto outer_false = b.With(ifelse_outer->False());
+ auto* ifelse_middle = outer_false.If(condB);
+
+ sb.Return(func, 3_i);
+
+ auto middle_true = b.With(ifelse_middle->True());
+ auto* ifelse_inner = middle_true.If(condC);
+ auto middle_false = b.With(ifelse_middle->False());
+ middle_false.ExitIf(ifelse_middle);
+
+ outer_false.ExitIf(ifelse_outer);
+
+ auto inner_true = b.With(ifelse_inner->True());
+ inner_true.Return(func, 1_i);
+ auto inner_false = b.With(ifelse_inner->False());
+ inner_false.ExitIf(ifelse_inner);
+
+ middle_true.ExitIf(ifelse_middle);
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%condA:bool, %condB:bool, %condC:bool):i32 -> %b2 {
+ %b2 = block {
+ if %condA [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ ret 3i
+ }
+
+ # False block
+ %b4 = block {
+ if %condB [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ if %condC [t: %b7, f: %b8]
+ # True block
+ %b7 = block {
+ ret 1i
+ }
+
+ # False block
+ %b8 = block {
+ exit_if
+ }
+
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ exit_if
+ }
+
+ ret 3i
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%condA:bool, %condB:bool, %condC:bool):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ if %condA [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ store %return_value, 3i
+ exit_if
+ }
+
+ # False block
+ %b4 = block {
+ if %condB [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ if %condC [t: %b7, f: %b8]
+ # True block
+ %b7 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if
+ }
+
+ # False block
+ %b8 = block {
+ exit_if
+ }
+
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ exit_if
+ }
+
+ %8:bool = load %continue_execution
+ if %8 [t: %b9]
+ # True block
+ %b9 = block {
+ store %return_value, 3i
+ exit_if
+ }
+
+ %9:i32 = load %return_value
+ ret %9
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, IfElse_Nested_WithBasicBlockArguments) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* func = b.Function("foo", ty.i32());
+ auto* condA = b.FunctionParam(ty.bool_());
+ auto* condB = b.FunctionParam(ty.bool_());
+ auto* condC = b.FunctionParam(ty.bool_());
+ mod.SetName(condA, "condA");
+ mod.SetName(condB, "condB");
+ mod.SetName(condC, "condC");
+ func->SetParams({condA, condB, condC});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* ifelse_outer = sb.If(condA);
+ ifelse_outer->SetResults(b.InstructionResult(ty.i32()));
+ auto outer_true = b.With(ifelse_outer->True());
+ outer_true.Return(func, 3_i);
+ auto outer_false = b.With(ifelse_outer->False());
+ auto* ifelse_middle = outer_false.If(condB);
+ ifelse_middle->SetResults(b.InstructionResult(ty.i32()));
+
+ sb.Return(func, sb.Add(ty.i32(), ifelse_outer->Result(0), 1_i));
+
+ auto middle_true = b.With(ifelse_middle->True());
+ auto* ifelse_inner = middle_true.If(condC);
+ auto middle_false = b.With(ifelse_middle->False());
+ middle_false.ExitIf(ifelse_middle, middle_false.Add(ty.i32(), 43_i, 2_i));
+
+ outer_false.ExitIf(ifelse_outer, outer_false.Add(ty.i32(), ifelse_middle->Result(0), 1_i));
+
+ auto inner_true = b.With(ifelse_inner->True());
+ inner_true.Return(func, 1_i);
+ auto inner_false = b.With(ifelse_inner->False());
+ inner_false.ExitIf(ifelse_inner);
+
+ middle_true.ExitIf(ifelse_middle, middle_true.Add(ty.i32(), 42_i, 1_i));
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%condA:bool, %condB:bool, %condC:bool):i32 -> %b2 {
+ %b2 = block {
+ %6:i32 = if %condA [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ ret 3i
+ }
+
+ # False block
+ %b4 = block {
+ %7:i32 = if %condB [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ if %condC [t: %b7, f: %b8]
+ # True block
+ %b7 = block {
+ ret 1i
+ }
+
+ # False block
+ %b8 = block {
+ exit_if
+ }
+
+ %8:i32 = add 42i, 1i
+ exit_if %8
+ }
+
+ # False block
+ %b6 = block {
+ %9:i32 = add 43i, 2i
+ exit_if %9
+ }
+
+ %10:i32 = add %7, 1i
+ exit_if %10
+ }
+
+ %11:i32 = add %6, 1i
+ ret %11
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%condA:bool, %condB:bool, %condC:bool):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ %8:i32 = if %condA [t: %b3, f: %b4]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ store %return_value, 3i
+ exit_if undef
+ }
+
+ # False block
+ %b4 = block {
+ %9:i32 = if %condB [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ if %condC [t: %b7, f: %b8]
+ # True block
+ %b7 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if
+ }
+
+ # False block
+ %b8 = block {
+ exit_if
+ }
+
+ %10:bool = load %continue_execution
+ %11:i32 = if %10 [t: %b9]
+ # True block
+ %b9 = block {
+ %12:i32 = add 42i, 1i
+ exit_if %12
+ }
+
+ exit_if %11
+ }
+
+ # False block
+ %b6 = block {
+ %13:i32 = add 43i, 2i
+ exit_if %13
+ }
+
+ %14:bool = load %continue_execution
+ %15:i32 = if %14 [t: %b10]
+ # True block
+ %b10 = block {
+ %16:i32 = add %9, 1i
+ exit_if %16
+ }
+
+ exit_if %15
+ }
+
+ %17:bool = load %continue_execution
+ if %17 [t: %b11]
+ # True block
+ %b11 = block {
+ %18:i32 = add %8, 1i
+ store %return_value, %18
+ exit_if
+ }
+
+ %19:i32 = load %return_value
+ ret %19
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Loop_UnconditionalReturnInBody) {
+ auto* func = b.Function("foo", ty.i32());
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* loop = sb.Loop();
+ loop->Body()->Append(b.Return(func, 42_i));
+
+ sb.Unreachable();
+
+ auto* src = R"(
+%foo = func():i32 -> %b1 {
+ %b1 = block {
+ loop [b: %b2]
+ # Body block
+ %b2 = block {
+ ret 42i
+ }
+
+ unreachable
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func():i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ loop [b: %b2]
+ # Body block
+ %b2 = block {
+ store %return_value, 42i
+ exit_loop
+ }
+
+ %3:i32 = load %return_value
+ ret %3
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Loop_ConditionalReturnInBody) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* loop = sb.Loop();
+ auto lb = b.With(loop->Body());
+ auto* ifelse = lb.If(cond);
+ {
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 42_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+ }
+ lb.Store(global, 2_i);
+ lb.Continue(loop);
+
+ auto cb = b.With(loop->Continuing());
+ cb.Store(global, 1_i);
+ cb.BreakIf(true, loop);
+
+ sb.Store(global, 3_i);
+ sb.Return(func, 43_i);
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):i32 -> %b2 {
+ %b2 = block {
+ loop [b: %b3, c: %b4]
+ # Body block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ ret 42i
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ store %1, 2i
+ continue %b4
+ }
+
+ # Continuing block
+ %b4 = block {
+ store %1, 1i
+ break_if true %b3
+ }
+
+ store %1, 3i
+ ret 43i
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ loop [b: %b3, c: %b4]
+ # Body block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ store %continue_execution, false
+ store %return_value, 42i
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ %6:bool = load %continue_execution
+ if %6 [t: %b7]
+ # True block
+ %b7 = block {
+ store %1, 2i
+ continue %b4
+ }
+
+ exit_loop
+ }
+
+ # Continuing block
+ %b4 = block {
+ store %1, 1i
+ break_if true %b3
+ }
+
+ %7:bool = load %continue_execution
+ if %7 [t: %b8]
+ # True block
+ %b8 = block {
+ store %1, 3i
+ store %return_value, 43i
+ exit_if
+ }
+
+ %8:i32 = load %return_value
+ ret %8
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Loop_ConditionalReturnInBody_UnreachableMerge) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* loop = sb.Loop();
+ auto lb = b.With(loop->Body());
+ auto* ifelse = lb.If(cond);
+ {
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 42_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+ }
+ lb.Store(global, 2_i);
+ lb.Continue(loop);
+
+ auto cb = b.With(loop->Continuing());
+ cb.Store(global, 1_i);
+ cb.NextIteration(loop);
+
+ sb.Unreachable();
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):i32 -> %b2 {
+ %b2 = block {
+ loop [b: %b3, c: %b4]
+ # Body block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ ret 42i
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ store %1, 2i
+ continue %b4
+ }
+
+ # Continuing block
+ %b4 = block {
+ store %1, 1i
+ next_iteration %b3
+ }
+
+ unreachable
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ loop [b: %b3, c: %b4]
+ # Body block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ store %continue_execution, false
+ store %return_value, 42i
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ %6:bool = load %continue_execution
+ if %6 [t: %b7]
+ # True block
+ %b7 = block {
+ store %1, 2i
+ continue %b4
+ }
+
+ exit_loop
+ }
+
+ # Continuing block
+ %b4 = block {
+ store %1, 1i
+ next_iteration %b3
+ }
+
+ %7:i32 = load %return_value
+ ret %7
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Loop_WithBasicBlockArgumentsOnMerge) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* cond = b.FunctionParam(ty.bool_());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* loop = sb.Loop();
+ loop->SetResults(b.InstructionResult(ty.i32()));
+ auto lb = b.With(loop->Body());
+ auto* ifelse = lb.If(cond);
+ {
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 42_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+ }
+ lb.Store(global, 2_i);
+ lb.Continue(loop);
+
+ auto cb = b.With(loop->Continuing());
+ cb.Store(global, 1_i);
+ cb.BreakIf(true, loop, 4_i);
+
+ sb.Store(global, 3_i);
+ sb.Return(func, loop->Result(0));
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):i32 -> %b2 {
+ %b2 = block {
+ loop [b: %b3, c: %b4]
+ # Body block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ ret 42i
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ store %1, 2i
+ continue %b4
+ }
+
+ # Continuing block
+ %b4 = block {
+ store %1, 1i
+ break_if true %b3 4i
+ }
+
+ store %1, 3i
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:bool):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ loop [b: %b3, c: %b4]
+ # Body block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ store %continue_execution, false
+ store %return_value, 42i
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ %6:bool = load %continue_execution
+ if %6 [t: %b7]
+ # True block
+ %b7 = block {
+ store %1, 2i
+ continue %b4
+ }
+
+ exit_loop
+ }
+
+ # Continuing block
+ %b4 = block {
+ store %1, 1i
+ break_if true %b3 4i
+ }
+
+ %7:bool = load %continue_execution
+ if %7 [t: %b8]
+ # True block
+ %b8 = block {
+ store %1, 3i
+ store %return_value, %8
+ exit_if
+ }
+
+ %9:i32 = load %return_value
+ ret %9
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Switch_UnconditionalReturnInCase) {
+ auto* cond = b.FunctionParam(ty.i32());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* sw = sb.Switch(cond);
+ auto caseA = b.With(b.Case(sw, {Switch::CaseSelector{b.Constant(1_i)}}));
+ caseA.Return(func, 42_i);
+ auto caseB = b.With(b.Case(sw, {Switch::CaseSelector{}}));
+ caseB.ExitSwitch(sw);
+
+ sb.Return(func, 0_i);
+
+ auto* src = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ switch %2 [c: (1i, %b2), c: (default, %b3)]
+ # Case block
+ %b2 = block {
+ ret 42i
+ }
+
+ # Case block
+ %b3 = block {
+ exit_switch
+ }
+
+ ret 0i
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ switch %2 [c: (1i, %b2), c: (default, %b3)]
+ # Case block
+ %b2 = block {
+ store %continue_execution, false
+ store %return_value, 42i
+ exit_switch
+ }
+
+ # Case block
+ %b3 = block {
+ exit_switch
+ }
+
+ %5:bool = load %continue_execution
+ if %5 [t: %b4]
+ # True block
+ %b4 = block {
+ store %return_value, 0i
+ exit_if
+ }
+
+ %6:i32 = load %return_value
+ ret %6
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Switch_ConditionalReturnInBody) {
+ auto* global = b.Var(ty.ptr<private_, i32>());
+ b.RootBlock()->Append(global);
+
+ auto* cond = b.FunctionParam(ty.i32());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* sw = sb.Switch(cond);
+ auto caseA = b.With(b.Case(sw, {Switch::CaseSelector{b.Constant(1_i)}}));
+ auto* ifelse = caseA.If(cond);
+ {
+ auto tb = b.With(ifelse->True());
+ tb.Return(func, 42_i);
+ auto fb = b.With(ifelse->False());
+ fb.ExitIf(ifelse);
+ }
+ caseA.Store(global, 2_i);
+ caseA.ExitSwitch(sw);
+
+ auto caseB = b.With(b.Case(sw, {Switch::CaseSelector{}}));
+ caseB.ExitSwitch(sw);
+
+ sb.Return(func, 0_i);
+
+ auto* src = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:i32):i32 -> %b2 {
+ %b2 = block {
+ switch %3 [c: (1i, %b3), c: (default, %b4)]
+ # Case block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ ret 42i
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ store %1, 2i
+ exit_switch
+ }
+
+ # Case block
+ %b4 = block {
+ exit_switch
+ }
+
+ ret 0i
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+# Root block
+%b1 = block {
+ %1:ptr<private, i32, read_write> = var
+}
+
+%foo = func(%3:i32):i32 -> %b2 {
+ %b2 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ switch %3 [c: (1i, %b3), c: (default, %b4)]
+ # Case block
+ %b3 = block {
+ if %3 [t: %b5, f: %b6]
+ # True block
+ %b5 = block {
+ store %continue_execution, false
+ store %return_value, 42i
+ exit_if
+ }
+
+ # False block
+ %b6 = block {
+ exit_if
+ }
+
+ %6:bool = load %continue_execution
+ if %6 [t: %b7]
+ # True block
+ %b7 = block {
+ store %1, 2i
+ exit_switch
+ }
+
+ exit_switch
+ }
+
+ # Case block
+ %b4 = block {
+ exit_switch
+ }
+
+ %7:bool = load %continue_execution
+ if %7 [t: %b8]
+ # True block
+ %b8 = block {
+ store %return_value, 0i
+ exit_if
+ }
+
+ %8:i32 = load %return_value
+ ret %8
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, Switch_WithBasicBlockArgumentsOnMerge) {
+ auto* cond = b.FunctionParam(ty.i32());
+ auto* func = b.Function("foo", ty.i32());
+ func->SetParams({cond});
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+
+ auto* sw = sb.Switch(cond);
+ sw->SetResults(b.InstructionResult(ty.i32())); // NOLINT: false detection of std::tuple
+ auto caseA = b.With(b.Case(sw, {Switch::CaseSelector{b.Constant(1_i)}}));
+ caseA.Return(func, 42_i);
+ auto caseB = b.With(b.Case(sw, {Switch::CaseSelector{b.Constant(2_i)}}));
+ caseB.Return(func, 99_i);
+ auto caseC = b.With(b.Case(sw, {Switch::CaseSelector{b.Constant(3_i)}}));
+ caseC.ExitSwitch(sw, 1_i);
+ auto caseD = b.With(b.Case(sw, {Switch::CaseSelector{}}));
+ caseD.ExitSwitch(sw, 0_i);
+
+ sb.Return(func, sw->Result(0));
+
+ auto* src = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ switch %2 [c: (1i, %b2), c: (2i, %b3), c: (3i, %b4), c: (default, %b5)]
+ # Case block
+ %b2 = block {
+ ret 42i
+ }
+
+ # Case block
+ %b3 = block {
+ ret 99i
+ }
+
+ # Case block
+ %b4 = block {
+ exit_switch 1i
+ }
+
+ # Case block
+ %b5 = block {
+ exit_switch 0i
+ }
+
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%2:i32):i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ switch %2 [c: (1i, %b2), c: (2i, %b3), c: (3i, %b4), c: (default, %b5)]
+ # Case block
+ %b2 = block {
+ store %continue_execution, false
+ store %return_value, 42i
+ exit_switch undef
+ }
+
+ # Case block
+ %b3 = block {
+ store %continue_execution, false
+ store %return_value, 99i
+ exit_switch undef
+ }
+
+ # Case block
+ %b4 = block {
+ exit_switch 1i
+ }
+
+ # Case block
+ %b5 = block {
+ exit_switch 0i
+ }
+
+ %5:bool = load %continue_execution
+ if %5 [t: %b6]
+ # True block
+ %b6 = block {
+ store %return_value, %6
+ exit_if
+ }
+
+ %7:i32 = load %return_value
+ ret %7
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, LoopIfReturnThenContinue) {
+ auto* func = b.Function("foo", ty.void_());
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+ {
+ auto* loop = sb.Loop();
+ auto lb = sb.With(loop->Body());
+ {
+ auto ib = lb.With(lb.If(true)->True());
+ ib.Return(func);
+ }
+ lb.Continue(loop);
+ }
+ sb.Unreachable();
+
+ auto* src = R"(
+%foo = func():void -> %b1 {
+ %b1 = block {
+ loop [b: %b2]
+ # Body block
+ %b2 = block {
+ if true [t: %b3]
+ # True block
+ %b3 = block {
+ ret
+ }
+
+ continue %b4
+ }
+
+ unreachable
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func():void -> %b1 {
+ %b1 = block {
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ loop [b: %b2]
+ # Body block
+ %b2 = block {
+ if true [t: %b3]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ exit_if
+ }
+
+ %3:bool = load %continue_execution
+ if %3 [t: %b4]
+ # True block
+ %b4 = block {
+ continue %b5
+ }
+
+ exit_loop
+ }
+
+ ret
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_MergeReturnTest, NestedIfsWithReturns) {
+ auto* func = b.Function("foo", ty.i32());
+ mod.functions.Push(func);
+
+ auto sb = b.With(func->StartTarget());
+ {
+ auto outer = b.With(sb.If(true)->True());
+ {
+ auto inner = b.With(outer.If(true)->True());
+ inner.Return(func, 1_i);
+ }
+ outer.Return(func, 2_i);
+ }
+ sb.Return(func, 3_i);
+
+ auto* src = R"(
+%foo = func():i32 -> %b1 {
+ %b1 = block {
+ if true [t: %b2]
+ # True block
+ %b2 = block {
+ if true [t: %b3]
+ # True block
+ %b3 = block {
+ ret 1i
+ }
+
+ ret 2i
+ }
+
+ ret 3i
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func():i32 -> %b1 {
+ %b1 = block {
+ %return_value:ptr<function, i32, read_write> = var
+ %continue_execution:ptr<function, bool, read_write> = var, true
+ if true [t: %b2]
+ # True block
+ %b2 = block {
+ if true [t: %b3]
+ # True block
+ %b3 = block {
+ store %continue_execution, false
+ store %return_value, 1i
+ exit_if
+ }
+
+ %4:bool = load %continue_execution
+ if %4 [t: %b4]
+ # True block
+ %b4 = block {
+ store %continue_execution, false
+ store %return_value, 2i
+ exit_if
+ }
+
+ exit_if
+ }
+
+ %5:bool = load %continue_execution
+ if %5 [t: %b5]
+ # True block
+ %b5 = block {
+ store %return_value, 3i
+ exit_if
+ }
+
+ %6:i32 = load %return_value
+ ret %6
+ }
+}
+)";
+
+ Run<MergeReturn>();
+
+ EXPECT_EQ(expect, str());
+}
+
+} // namespace
+} // namespace tint::ir::transform
diff --git a/src/tint/ir/transform/test_helper.h b/src/tint/ir/transform/test_helper.h
index ea75fcf..5cb6392 100644
--- a/src/tint/ir/transform/test_helper.h
+++ b/src/tint/ir/transform/test_helper.h
@@ -24,6 +24,7 @@
#include "src/tint/ir/builder.h"
#include "src/tint/ir/disassembler.h"
#include "src/tint/ir/transform/transform.h"
+#include "src/tint/ir/validate.h"
#include "src/tint/transform/manager.h"
namespace tint::ir::transform {
@@ -39,10 +40,28 @@
Transform::DataMap Run(const Transform::DataMap& data = {}) {
tint::transform::Manager manager;
tint::transform::DataMap outputs;
+
+ // Validate the input IR.
+ {
+ auto res = ir::Validate(mod);
+ EXPECT_TRUE(res) << res.Failure().str();
+ if (!res) {
+ return outputs;
+ }
+ }
+
+ // Run the transforms.
for (auto* transform_ptr : std::initializer_list<Transform*>{new TRANSFORMS()...}) {
manager.append(std::unique_ptr<Transform>(transform_ptr));
}
manager.Run(&mod, data, outputs);
+
+ // Validate the output IR.
+ {
+ auto res = ir::Validate(mod);
+ EXPECT_TRUE(res) << res.Failure().str();
+ }
+
return outputs;
}
@@ -59,18 +78,6 @@
ir::Builder b{mod};
/// The type manager.
type::Manager& ty{mod.Types()};
-
- /// Alias to builtin::AddressSpace::kStorage
- static constexpr auto storage = builtin::AddressSpace::kStorage;
- /// Alias to builtin::AddressSpace::kUniform
- static constexpr auto uniform = builtin::AddressSpace::kUniform;
- /// Alias to builtin::AddressSpace::kPrivate
- static constexpr auto private_ = builtin::AddressSpace::kPrivate;
- /// Alias to builtin::AddressSpace::kFunction
- static constexpr auto function = builtin::AddressSpace::kFunction;
-
- private:
- std::vector<std::unique_ptr<Source::File>> files_;
};
using TransformTest = TransformTestBase<testing::Test>;
diff --git a/src/tint/ir/transform/transform.h b/src/tint/ir/transform/transform.h
index a09fe77..e95a7b7 100644
--- a/src/tint/ir/transform/transform.h
+++ b/src/tint/ir/transform/transform.h
@@ -19,6 +19,7 @@
#include <utility>
+#include "src/tint/builtin/address_space.h"
#include "src/tint/utils/castable.h"
// Forward declarations
diff --git a/src/tint/ir/transform/var_for_dynamic_index.cc b/src/tint/ir/transform/var_for_dynamic_index.cc
index b72dc34..27ddec4 100644
--- a/src/tint/ir/transform/var_for_dynamic_index.cc
+++ b/src/tint/ir/transform/var_for_dynamic_index.cc
@@ -63,7 +63,7 @@
};
std::optional<AccessToReplace> ShouldReplace(Access* access) {
- if (access->Type()->Is<type::Pointer>()) {
+ if (access->Result()->Type()->Is<type::Pointer>()) {
// No need to modify accesses into pointer types.
return {};
}
@@ -101,7 +101,7 @@
// Find the access instructions that need replacing.
utils::Vector<AccessToReplace, 4> worklist;
- for (auto* inst : ir->values.Objects()) {
+ for (auto* inst : ir->instructions.Objects()) {
if (auto* access = inst->As<Access>()) {
if (auto to_replace = ShouldReplace(access)) {
worklist.Push(to_replace.value());
@@ -125,7 +125,7 @@
auto* intermediate_source = builder.Access(to_replace.dynamic_index_source_type,
source_object, partial_access.indices);
intermediate_source->InsertBefore(access);
- return intermediate_source;
+ return intermediate_source->Result();
});
}
@@ -136,14 +136,14 @@
builtin::Access::kReadWrite));
decl->SetInitializer(source_object);
decl->InsertBefore(access);
- return decl;
+ return decl->Result();
});
// Create a new access instruction using the local variable as the source.
utils::Vector<Value*, 4> indices{access->Indices().Offset(to_replace.first_dynamic_index)};
auto* new_access =
- builder.Access(ir->Types().ptr(builtin::AddressSpace::kFunction, access->Type(),
- builtin::Access::kReadWrite),
+ builder.Access(ir->Types().ptr(builtin::AddressSpace::kFunction,
+ access->Result()->Type(), builtin::Access::kReadWrite),
local, indices);
access->ReplaceWith(new_access);
@@ -152,7 +152,7 @@
load->InsertAfter(new_access);
// Replace all uses of the old access instruction with the loaded result.
- access->ReplaceAllUsesWith([&](Usage) { return load; });
+ access->Result()->ReplaceAllUsesWith([&](Usage) { return load->Result(); });
}
}
diff --git a/src/tint/ir/transform/var_for_dynamic_index_test.cc b/src/tint/ir/transform/var_for_dynamic_index_test.cc
index 6b64025..785927d 100644
--- a/src/tint/ir/transform/var_for_dynamic_index_test.cc
+++ b/src/tint/ir/transform/var_for_dynamic_index_test.cc
@@ -24,14 +24,10 @@
namespace tint::ir::transform {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
-class IR_VarForDynamicIndexTest : public TransformTest {
- protected:
- const type::Type* ptr(const type::Type* elem) {
- return ty.ptr(builtin::AddressSpace::kFunction, elem, builtin::Access::kReadWrite);
- }
-};
+using IR_VarForDynamicIndexTest = TransformTest;
TEST_F(IR_VarForDynamicIndexTest, NoModify_ConstantIndex_ArrayValue) {
auto* arr = b.FunctionParam(ty.array<i32, 4u>());
@@ -82,13 +78,13 @@
}
TEST_F(IR_VarForDynamicIndexTest, NoModify_DynamicIndex_ArrayPointer) {
- auto* arr = b.FunctionParam(ptr(ty.array<i32, 4u>()));
+ auto* arr = b.FunctionParam(ty.ptr<function, array<i32, 4u>>());
auto* idx = b.FunctionParam(ty.i32());
auto* func = b.Function("foo", ty.i32());
func->SetParams({arr, idx});
auto* block = func->StartTarget();
- auto* access = block->Append(b.Access(ptr(ty.i32()), arr, idx));
+ auto* access = block->Append(b.Access(ty.ptr<function, i32>(), arr, idx));
auto* load = block->Append(b.Load(access));
block->Append(b.Return(func, load));
mod.functions.Push(func);
@@ -109,13 +105,13 @@
}
TEST_F(IR_VarForDynamicIndexTest, NoModify_DynamicIndex_MatrixPointer) {
- auto* mat = b.FunctionParam(ptr(ty.mat2x2<f32>()));
+ auto* mat = b.FunctionParam(ty.ptr<function, mat2x2<f32>>());
auto* idx = b.FunctionParam(ty.i32());
auto* func = b.Function("foo", ty.f32());
func->SetParams({mat, idx});
auto* block = func->StartTarget();
- auto* access = block->Append(b.Access(ptr(ty.f32()), mat, idx, idx));
+ auto* access = block->Append(b.Access(ty.ptr<function, f32>(), mat, idx, idx));
auto* load = block->Append(b.Load(access));
block->Append(b.Return(func, load));
mod.functions.Push(func);
@@ -188,22 +184,22 @@
}
TEST_F(IR_VarForDynamicIndexTest, DynamicIndex_MatrixValue) {
- auto* arr = b.FunctionParam(ty.mat2x2<f32>());
+ auto* mat = b.FunctionParam(ty.mat2x2<f32>());
auto* idx = b.FunctionParam(ty.i32());
- auto* func = b.Function("foo", ty.f32());
- func->SetParams({arr, idx});
+ auto* func = b.Function("foo", ty.vec2<f32>());
+ func->SetParams({mat, idx});
auto* block = func->StartTarget();
- auto* access = block->Append(b.Access(ty.f32(), arr, idx));
+ auto* access = block->Append(b.Access(ty.vec2<f32>(), mat, idx));
block->Append(b.Return(func, access));
mod.functions.Push(func);
auto* expect = R"(
-%foo = func(%2:mat2x2<f32>, %3:i32):f32 -> %b1 {
+%foo = func(%2:mat2x2<f32>, %3:i32):vec2<f32> -> %b1 {
%b1 = block {
%4:ptr<function, mat2x2<f32>, read_write> = var, %2
- %5:ptr<function, f32, read_write> = access %4, %3
- %6:f32 = load %5
+ %5:ptr<function, vec2<f32>, read_write> = access %4, %3
+ %6:vec2<f32> = load %5
ret %6
}
}
@@ -298,17 +294,12 @@
}
TEST_F(IR_VarForDynamicIndexTest, AccessChain_SkipConstantIndices_Struct) {
- auto* str_ty = ty.Get<type::Struct>(
- mod.symbols.Register("MyStruct"),
- utils::Vector{
- ty.Get<type::StructMember>(mod.symbols.Register("arr1"), ty.array<f32, 1024>(), 0u, 0u,
- 4u, 4096u, type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.Register("mat"), ty.mat4x4<f32>(), 1u, 4096u,
- 16u, 64u, type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.Register("arr2"), ty.array<f32, 1024>(), 2u,
- 4160u, 4u, 4096u, type::StructMemberAttributes{}),
- },
- 16u, 32u, 32u);
+ auto* str_ty = ty.Struct(mod.symbols.Register("MyStruct"),
+ {
+ {mod.symbols.Register("arr1"), ty.array<f32, 1024>()},
+ {mod.symbols.Register("mat"), ty.mat4x4<f32>()},
+ {mod.symbols.Register("arr2"), ty.array<f32, 1024>()},
+ });
auto* str_val = b.FunctionParam(str_ty);
auto* idx = b.FunctionParam(ty.i32());
auto* func = b.Function("foo", ty.f32());
diff --git a/src/tint/ir/unary.cc b/src/tint/ir/unary.cc
index 90509e0..f5952ea 100644
--- a/src/tint/ir/unary.cc
+++ b/src/tint/ir/unary.cc
@@ -19,11 +19,9 @@
namespace tint::ir {
-Unary::Unary(enum Kind k, const type::Type* res_ty, Value* val) : kind_(k), result_type_(res_ty) {
- TINT_ASSERT(IR, val != nullptr);
- TINT_ASSERT(IR, result_type_ != nullptr);
-
- AddOperand(val);
+Unary::Unary(InstructionResult* result, enum Kind k, Value* val) : kind_(k) {
+ AddOperand(Unary::kValueOperandOffset, val);
+ AddResult(result);
}
Unary::~Unary() = default;
diff --git a/src/tint/ir/unary.h b/src/tint/ir/unary.h
index baf1218..3f09a3e 100644
--- a/src/tint/ir/unary.h
+++ b/src/tint/ir/unary.h
@@ -21,8 +21,11 @@
namespace tint::ir {
/// A unary instruction in the IR.
-class Unary : public utils::Castable<Unary, OperandInstruction<1>> {
+class Unary : public utils::Castable<Unary, OperandInstruction<1, 1>> {
public:
+ /// The offset in Operands() for the value
+ static constexpr size_t kValueOperandOffset = 0;
+
/// The kind of instruction.
enum class Kind {
kComplement,
@@ -30,24 +33,20 @@
};
/// Constructor
+ /// @param result the result value
/// @param kind the kind of unary instruction
- /// @param result_type the result type
/// @param val the input value for the instruction
- Unary(enum Kind kind, const type::Type* result_type, Value* val);
+ Unary(InstructionResult* result, enum Kind kind, Value* val);
~Unary() override;
- /// @returns the type of the value
- const type::Type* Type() override { return result_type_; }
-
/// @returns the value for the instruction
- Value* Val() { return operands_[0]; }
+ Value* Val() { return operands_[kValueOperandOffset]; }
/// @returns the kind of unary instruction
enum Kind Kind() { return kind_; }
private:
enum Kind kind_;
- const type::Type* result_type_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/unary_test.cc b/src/tint/ir/unary_test.cc
index 7802dd4..b13cc09 100644
--- a/src/tint/ir/unary_test.cc
+++ b/src/tint/ir/unary_test.cc
@@ -49,7 +49,7 @@
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
}
-TEST_F(IR_UnaryTest, Unary_Usage) {
+TEST_F(IR_UnaryTest, Usage) {
auto* inst = b.Negation(mod.Types().i32(), 4_i);
EXPECT_EQ(inst->Kind(), Unary::Kind::kNegation);
@@ -58,6 +58,14 @@
EXPECT_THAT(inst->Val()->Usages(), testing::UnorderedElementsAre(Usage{inst, 0u}));
}
+TEST_F(IR_UnaryTest, Result) {
+ auto* inst = b.Negation(mod.Types().i32(), 4_i);
+ EXPECT_TRUE(inst->HasResults());
+ EXPECT_FALSE(inst->HasMultiResults());
+ EXPECT_TRUE(inst->Result()->Is<InstructionResult>());
+ EXPECT_EQ(inst->Result()->Source(), inst);
+}
+
TEST_F(IR_UnaryTest, Fail_NullType) {
EXPECT_FATAL_FAILURE(
{
@@ -68,15 +76,5 @@
"");
}
-TEST_F(IR_UnaryTest, Fail_NullValue) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Negation(mod.Types().i32(), nullptr);
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/unreachable.cc b/src/tint/ir/unreachable.cc
new file mode 100644
index 0000000..b1aadfd
--- /dev/null
+++ b/src/tint/ir/unreachable.cc
@@ -0,0 +1,23 @@
+// 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/unreachable.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ir::Unreachable);
+
+namespace tint::ir {
+
+Unreachable::~Unreachable() = default;
+
+} // namespace tint::ir
diff --git a/src/tint/ir/unreachable.h b/src/tint/ir/unreachable.h
new file mode 100644
index 0000000..51fdc24
--- /dev/null
+++ b/src/tint/ir/unreachable.h
@@ -0,0 +1,30 @@
+// 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_UNREACHABLE_H_
+#define SRC_TINT_IR_UNREACHABLE_H_
+
+#include "src/tint/ir/branch.h"
+
+namespace tint::ir {
+
+/// An unreachable instruction in the IR.
+class Unreachable : public utils::Castable<Unreachable, Branch> {
+ public:
+ ~Unreachable() override;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_UNREACHABLE_H_
diff --git a/src/tint/ir/user_call.cc b/src/tint/ir/user_call.cc
index e963e14..a1ddfee 100644
--- a/src/tint/ir/user_call.cc
+++ b/src/tint/ir/user_call.cc
@@ -22,12 +22,10 @@
namespace tint::ir {
-UserCall::UserCall(const type::Type* ty, Function* func, utils::VectorRef<Value*> arguments)
- : Base(ty) {
- TINT_ASSERT(IR, func);
-
- AddOperand(func);
- AddOperands(std::move(arguments));
+UserCall::UserCall(InstructionResult* result, Function* func, utils::VectorRef<Value*> arguments) {
+ AddOperand(UserCall::kFunctionOperandOffset, func);
+ AddOperands(UserCall::kArgsOperandOffset, std::move(arguments));
+ AddResult(result);
}
UserCall::~UserCall() = default;
diff --git a/src/tint/ir/user_call.h b/src/tint/ir/user_call.h
index 2d08482..9d3ea24 100644
--- a/src/tint/ir/user_call.h
+++ b/src/tint/ir/user_call.h
@@ -24,20 +24,26 @@
/// A user call instruction in the IR.
class UserCall : public utils::Castable<UserCall, Call> {
public:
+ /// The offset in Operands() for the function being called
+ static constexpr size_t kFunctionOperandOffset = 0;
+
+ /// The base offset in Operands() for the call arguments
+ static constexpr size_t kArgsOperandOffset = 1;
+
/// Constructor
- /// @param type the result type
+ /// @param result the result value
/// @param func the function being called
/// @param args the function arguments
- UserCall(const type::Type* type, Function* func, utils::VectorRef<Value*> args);
+ UserCall(InstructionResult* result, Function* func, utils::VectorRef<Value*> args);
~UserCall() override;
/// @returns the call arguments
- utils::Slice<Value* const> Args() override { return operands_.Slice().Offset(1); }
+ utils::Slice<Value* const> Args() override {
+ return operands_.Slice().Offset(kArgsOperandOffset);
+ }
/// @returns the called function name
- Function* Func() { return operands_.Front()->As<ir::Function>(); }
-
- private:
+ Function* Func() { return operands_[kFunctionOperandOffset]->As<ir::Function>(); }
};
} // namespace tint::ir
diff --git a/src/tint/ir/user_call_test.cc b/src/tint/ir/user_call_test.cc
index 6b73272..eb2cedb 100644
--- a/src/tint/ir/user_call_test.cc
+++ b/src/tint/ir/user_call_test.cc
@@ -34,6 +34,18 @@
EXPECT_THAT(arg2->Usages(), testing::UnorderedElementsAre(Usage{e, 2u}));
}
+TEST_F(IR_UserCallTest, Results) {
+ auto* func = b.Function("myfunc", mod.Types().void_());
+ auto* arg1 = b.Constant(1_u);
+ auto* arg2 = b.Constant(2_u);
+ auto* e = b.Call(mod.Types().void_(), func, utils::Vector{arg1, arg2});
+
+ EXPECT_TRUE(e->HasResults());
+ EXPECT_FALSE(e->HasMultiResults());
+ EXPECT_TRUE(e->Result()->Is<InstructionResult>());
+ EXPECT_EQ(e->Result()->Source(), e);
+}
+
TEST_F(IR_UserCallTest, Fail_NullType) {
EXPECT_FATAL_FAILURE(
{
@@ -44,26 +56,5 @@
"");
}
-TEST_F(IR_UserCallTest, Fail_NullFunction) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Call(mod.Types().f32(), nullptr);
- },
- "");
-}
-
-TEST_F(IR_UserCallTest, Fail_NullArg) {
- EXPECT_FATAL_FAILURE(
- {
- Module mod;
- Builder b{mod};
- b.Call(mod.Types().void_(), b.Function("myfunc", mod.Types().void_()),
- utils::Vector<Value*, 1>{nullptr});
- },
- "");
-}
-
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/validate.cc b/src/tint/ir/validate.cc
index 19beb21..7d4a15c 100644
--- a/src/tint/ir/validate.cc
+++ b/src/tint/ir/validate.cc
@@ -41,6 +41,7 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/swizzle.h"
#include "src/tint/ir/unary.h"
+#include "src/tint/ir/unreachable.h"
#include "src/tint/ir/user_call.h"
#include "src/tint/ir/var.h"
#include "src/tint/switch.h"
@@ -186,8 +187,11 @@
[&](Binary*) {}, //
[&](Branch* b) { CheckBranch(b); }, //
[&](Call* c) { CheckCall(c); }, //
+ [&](If* if_) { CheckIf(if_); }, //
[&](Load*) {}, //
+ [&](Loop*) {}, //
[&](Store*) {}, //
+ [&](Switch*) {}, //
[&](Swizzle*) {}, //
[&](Unary*) {}, //
[&](Var*) {}, //
@@ -267,8 +271,8 @@
}
}
- auto* want_ty = a->Type()->UnwrapPtr();
- bool want_ptr = a->Type()->Is<type::Pointer>();
+ auto* want_ty = a->Result()->Type()->UnwrapPtr();
+ bool want_ptr = a->Result()->Type()->Is<type::Pointer>();
if (TINT_UNLIKELY(ty != want_ty || is_ptr != want_ptr)) {
std::string want =
want_ptr ? "ptr<" + want_ty->FriendlyName() + ">" : want_ty->FriendlyName();
@@ -280,21 +284,19 @@
void CheckBranch(ir::Branch* b) {
tint::Switch(
- b, //
- [&](BreakIf*) {}, //
- [&](Continue*) {}, //
- [&](ExitIf*) {}, //
- [&](ExitLoop*) {}, //
- [&](ExitSwitch*) {}, //
- [&](If* if_) { CheckIf(if_); }, //
- [&](Loop*) {}, //
- [&](NextIteration*) {}, //
- [&](Return* ret) {
+ b, //
+ [&](ir::BreakIf*) {}, //
+ [&](ir::Continue*) {}, //
+ [&](ir::ExitIf*) {}, //
+ [&](ir::ExitLoop*) {}, //
+ [&](ir::ExitSwitch*) {}, //
+ [&](ir::NextIteration*) {}, //
+ [&](ir::Return* ret) {
if (ret->Func() == nullptr) {
AddError("return: null function");
}
- }, //
- [&](Switch*) {}, //
+ },
+ [&](ir::Unreachable*) {}, //
[&](Default) {
AddError(std::string("missing validation of branch: ") + b->TypeInfo().name);
});
diff --git a/src/tint/ir/validate_test.cc b/src/tint/ir/validate_test.cc
index d2f07d0..c05674a 100644
--- a/src/tint/ir/validate_test.cc
+++ b/src/tint/ir/validate_test.cc
@@ -25,14 +25,14 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using IR_ValidateTest = IRTestHelper;
TEST_F(IR_ValidateTest, RootBlock_Var) {
mod.root_block = b.RootBlock();
- mod.root_block->Append(
- b.Var(ty.ptr(builtin::AddressSpace::kPrivate, ty.i32(), builtin::Access::kReadWrite)));
+ mod.root_block->Append(b.Var(ty.ptr<private_, i32>()));
auto res = ir::Validate(mod);
EXPECT_TRUE(res) << res.Failure().str();
}
@@ -73,7 +73,8 @@
mod.functions.Push(f);
f->SetParams({b.FunctionParam(ty.i32()), b.FunctionParam(ty.f32())});
- f->StartTarget()->SetInstructions({b.Return(f)});
+ f->StartTarget()->Append(b.Return(f));
+
auto res = ir::Validate(mod);
EXPECT_TRUE(res) << res.Failure().str();
}
@@ -102,8 +103,9 @@
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.f32(), obj, 1_u, 0_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.f32(), obj, 1_u, 0_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
EXPECT_TRUE(res) << res.Failure().str();
@@ -111,13 +113,13 @@
TEST_F(IR_ValidateTest, Valid_Access_Ptr) {
auto* f = b.Function("my_func", ty.void_());
- auto* obj = b.FunctionParam(
- ty.ptr(builtin::AddressSpace::kPrivate, ty.mat3x2<f32>(), builtin::Access::kReadWrite));
+ auto* obj = b.FunctionParam(ty.ptr<private_, mat3x2<f32>>());
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.ptr<private_, f32>(), obj, 1_u, 0_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.ptr<private_, f32>(), obj, 1_u, 0_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
EXPECT_TRUE(res) << res.Failure().str();
@@ -129,8 +131,9 @@
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.f32(), obj, -1_i));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.f32(), obj, -1_i);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -158,8 +161,9 @@
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.f32(), obj, 1_u, 3_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.f32(), obj, 1_u, 3_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -187,13 +191,13 @@
TEST_F(IR_ValidateTest, Access_OOB_Index_Ptr) {
auto* f = b.Function("my_func", ty.void_());
- auto* obj = b.FunctionParam(
- ty.ptr(builtin::AddressSpace::kPrivate, ty.mat3x2<f32>(), builtin::Access::kReadWrite));
+ auto* obj = b.FunctionParam(ty.ptr<private_, mat3x2<f32>>());
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.ptr<private_, f32>(), obj, 1_u, 3_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.ptr<private_, f32>(), obj, 1_u, 3_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -226,8 +230,9 @@
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.f32(), obj, 1_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.f32(), obj, 1_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -255,8 +260,9 @@
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.ptr<private_, f32>(), obj, 1_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.ptr<private_, f32>(), obj, 1_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -279,13 +285,10 @@
}
TEST_F(IR_ValidateTest, Access_DynamicallyUnindexableType_Value) {
- utils::Vector members{
- ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 1u, 4u, 4u, 4u,
- type::StructMemberAttributes{}),
- };
- auto* str_ty = ty.Get<type::Struct>(mod.symbols.New(), std::move(members), 4u, 8u, 8u);
+ auto* str_ty = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), ty.i32()},
+ {mod.symbols.New("b"), ty.i32()},
+ });
auto* f = b.Function("my_func", ty.void_());
auto* obj = b.FunctionParam(str_ty);
@@ -293,13 +296,14 @@
f->SetParams({obj, idx});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.i32(), obj, idx));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.i32(), obj, idx);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
EXPECT_EQ(res.Failure().str(),
- R"(:8:25 error: access: type tint_symbol_2 cannot be dynamically indexed
+ R"(:8:25 error: access: type MyStruct cannot be dynamically indexed
%4:i32 = access %2, %3
^^
@@ -308,12 +312,12 @@
^^^^^^^^^^^
note: # Disassembly
-tint_symbol_2 = struct @align(4) {
- tint_symbol:i32 @offset(0)
- tint_symbol_1:i32 @offset(4)
+MyStruct = struct @align(4) {
+ a:i32 @offset(0)
+ b:i32 @offset(4)
}
-%my_func = func(%2:tint_symbol_2, %3:i32):void -> %b1 {
+%my_func = func(%2:MyStruct, %3:i32):void -> %b1 {
%b1 = block {
%4:i32 = access %2, %3
ret
@@ -323,28 +327,25 @@
}
TEST_F(IR_ValidateTest, Access_DynamicallyUnindexableType_Ptr) {
- utils::Vector members{
- ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.New(), ty.i32(), 1u, 4u, 4u, 4u,
- type::StructMemberAttributes{}),
- };
- auto* str_ty = ty.Get<type::Struct>(mod.symbols.New(), std::move(members), 4u, 8u, 8u);
+ auto* str_ty = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), ty.i32()},
+ {mod.symbols.New("b"), ty.i32()},
+ });
auto* f = b.Function("my_func", ty.void_());
- auto* obj = b.FunctionParam(
- ty.ptr(builtin::AddressSpace::kPrivate, str_ty, builtin::Access::kReadWrite));
+ auto* obj = b.FunctionParam(ty.ptr<private_, read_write>(str_ty));
auto* idx = b.FunctionParam(ty.i32());
f->SetParams({obj, idx});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.i32(), obj, idx));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.i32(), obj, idx);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
EXPECT_EQ(res.Failure().str(),
- R"(:8:25 error: access: type ptr<tint_symbol_2> cannot be dynamically indexed
+ R"(:8:25 error: access: type ptr<MyStruct> cannot be dynamically indexed
%4:i32 = access %2, %3
^^
@@ -353,12 +354,12 @@
^^^^^^^^^^^
note: # Disassembly
-tint_symbol_2 = struct @align(4) {
- tint_symbol:i32 @offset(0)
- tint_symbol_1:i32 @offset(4)
+MyStruct = struct @align(4) {
+ a:i32 @offset(0)
+ b:i32 @offset(4)
}
-%my_func = func(%2:ptr<private, tint_symbol_2, read_write>, %3:i32):void -> %b1 {
+%my_func = func(%2:ptr<private, MyStruct, read_write>, %3:i32):void -> %b1 {
%b1 = block {
%4:i32 = access %2, %3
ret
@@ -373,8 +374,9 @@
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.i32(), obj, 1_u, 1_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.i32(), obj, 1_u, 1_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -399,13 +401,13 @@
TEST_F(IR_ValidateTest, Access_Incorrect_Type_Ptr_Ptr) {
auto* f = b.Function("my_func", ty.void_());
- auto* obj = b.FunctionParam(
- ty.ptr(builtin::AddressSpace::kPrivate, ty.mat3x2<f32>(), builtin::Access::kReadWrite));
+ auto* obj = b.FunctionParam(ty.ptr<private_, mat3x2<f32>>());
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.ptr<private_, i32>(), obj, 1_u, 1_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.ptr<private_, i32>(), obj, 1_u, 1_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -431,13 +433,13 @@
TEST_F(IR_ValidateTest, Access_Incorrect_Type_Ptr_Value) {
auto* f = b.Function("my_func", ty.void_());
- auto* obj = b.FunctionParam(
- ty.ptr(builtin::AddressSpace::kPrivate, ty.mat3x2<f32>(), builtin::Access::kReadWrite));
+ auto* obj = b.FunctionParam(ty.ptr<private_, mat3x2<f32>>());
f->SetParams({obj});
mod.functions.Push(f);
- f->StartTarget()->Append(b.Access(ty.f32(), obj, 1_u, 1_u));
- f->StartTarget()->Append(b.Return(f));
+ auto sb = b.With(f->StartTarget());
+ sb.Access(ty.f32(), obj, 1_u, 1_u);
+ sb.Return(f);
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -465,7 +467,10 @@
auto* f = b.Function("my_func", ty.void_());
mod.functions.Push(f);
- f->StartTarget()->SetInstructions({b.Return(f), b.Return(f)});
+ auto sb = b.With(f->StartTarget());
+ sb.Return(f);
+ sb.Return(f);
+
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
EXPECT_EQ(res.Failure().str(), R"(:3:5 error: block: branch which isn't the final instruction
@@ -495,6 +500,7 @@
if_->False()->Append(b.Return(f));
f->StartTarget()->Append(if_);
+ f->StartTarget()->Append(b.Return(f));
auto res = ir::Validate(mod);
ASSERT_FALSE(res);
@@ -520,6 +526,7 @@
ret
}
+ ret
}
}
)");
diff --git a/src/tint/ir/value.cc b/src/tint/ir/value.cc
index 5eb2e1e..1471681 100644
--- a/src/tint/ir/value.cc
+++ b/src/tint/ir/value.cc
@@ -25,6 +25,12 @@
Value::~Value() = default;
+void Value::Destroy() {
+ TINT_ASSERT(IR, Alive());
+ TINT_ASSERT(IR, Usages().Count() == 0);
+ alive_ = false;
+}
+
void Value::ReplaceAllUsesWith(std::function<Value*(Usage use)> replacer) {
while (!uses_.IsEmpty()) {
auto& use = *uses_.begin();
@@ -33,4 +39,11 @@
}
}
+void Value::ReplaceAllUsesWith(Value* replacement) {
+ while (!uses_.IsEmpty()) {
+ auto& use = *uses_.begin();
+ use.instruction->SetOperand(use.operand_index, replacement);
+ }
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/value.h b/src/tint/ir/value.h
index 1d7f88d..0efa6d0 100644
--- a/src/tint/ir/value.h
+++ b/src/tint/ir/value.h
@@ -31,7 +31,7 @@
/// The instruction that is using the value;
Instruction* instruction = nullptr;
/// The index of the operand that is the value being used.
- uint32_t operand_index = 0u;
+ size_t operand_index = 0u;
/// A specialization of utils::Hasher for Usage.
struct Hasher {
@@ -56,6 +56,16 @@
/// Destructor
~Value() override;
+ /// @returns the type of the value
+ virtual const type::Type* Type() { return nullptr; }
+
+ /// Destroys the Value. Once called, the Value must not be used again.
+ /// The Value must not be in use by any instruction.
+ virtual void Destroy();
+
+ /// @returns true if the Value has not been destroyed with Destroy()
+ bool Alive() const { return alive_; }
+
/// Adds a usage of this value.
/// @param u the usage
void AddUsage(Usage u) { uses_.Add(u); }
@@ -68,19 +78,21 @@
/// uses the value for multiple different operands.
const utils::Hashset<Usage, 4, Usage::Hasher>& Usages() { return uses_; }
- /// @returns the type of the value
- virtual const type::Type* Type() { return nullptr; }
-
/// Replace all uses of the value.
/// @param replacer a function which returns a replacement for a given use
void ReplaceAllUsesWith(std::function<Value*(Usage use)> replacer);
+ /// Replace all uses of the value.
+ /// @param replacement the replacement value
+ void ReplaceAllUsesWith(Value* replacement);
+
protected:
/// Constructor
Value();
private:
utils::Hashset<Usage, 4, Usage::Hasher> uses_;
+ bool alive_ = true;
};
} // namespace tint::ir
diff --git a/src/tint/ir/value_test.cc b/src/tint/ir/value_test.cc
new file mode 100644
index 0000000..fc0d2fc
--- /dev/null
+++ b/src/tint/ir/value_test.cc
@@ -0,0 +1,80 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "src/tint/ir/ir_test_helper.h"
+
+using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+
+namespace tint::ir {
+namespace {
+
+using IR_ValueTest = IRTestHelper;
+
+TEST_F(IR_ValueTest, ReplaceAllUsesWith_Value) {
+ auto* val_old = b.InstructionResult(ty.i32());
+ auto* val_new = b.InstructionResult(ty.i32());
+ auto* inst = b.Add(mod.Types().i32(), val_old, 1_i);
+ EXPECT_EQ(inst->LHS(), val_old);
+ val_old->ReplaceAllUsesWith(val_new);
+ EXPECT_EQ(inst->LHS(), val_new);
+}
+
+TEST_F(IR_ValueTest, ReplaceAllUsesWith_Fn) {
+ auto* val_old = b.InstructionResult(ty.i32());
+ auto* val_new = b.InstructionResult(ty.i32());
+ auto* inst = b.Add(mod.Types().i32(), val_old, 1_i);
+ EXPECT_EQ(inst->LHS(), val_old);
+ val_old->ReplaceAllUsesWith([&](Usage use) {
+ EXPECT_EQ(use.instruction, inst);
+ EXPECT_EQ(use.operand_index, 0u);
+ return val_new;
+ });
+ EXPECT_EQ(inst->LHS(), val_new);
+}
+
+TEST_F(IR_ValueTest, Destroy) {
+ auto* val = b.InstructionResult(ty.i32());
+ EXPECT_TRUE(val->Alive());
+ val->Destroy();
+ EXPECT_FALSE(val->Alive());
+}
+
+TEST_F(IR_ValueTest, Destroy_HasUsage) {
+ EXPECT_FATAL_FAILURE(
+ {
+ Module mod;
+ Builder b{mod};
+ auto* val = b.InstructionResult(mod.Types().i32());
+ b.Add(mod.Types().i32(), val, 1_i);
+ val->Destroy();
+ },
+ "");
+}
+
+TEST_F(IR_ValueTest, Destroy_HasSource) {
+ EXPECT_FATAL_FAILURE(
+ {
+ Module mod;
+ Builder b{mod};
+ auto* val = b.Add(mod.Types().i32(), 1_i, 2_i)->Result();
+ val->Destroy();
+ },
+ "");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/var.cc b/src/tint/ir/var.cc
index 4dd00ce..38cafb0 100644
--- a/src/tint/ir/var.cc
+++ b/src/tint/ir/var.cc
@@ -14,22 +14,37 @@
#include "src/tint/ir/var.h"
#include "src/tint/debug.h"
+#include "src/tint/ir/store.h"
TINT_INSTANTIATE_TYPEINFO(tint::ir::Var);
namespace tint::ir {
-Var::Var(const type::Pointer* ty) : type_(ty) {
- TINT_ASSERT(IR, type_ != nullptr);
+Var::Var(InstructionResult* result) {
+ if (result && result->Type()) {
+ TINT_ASSERT(IR, result->Type()->Is<type::Pointer>());
+ }
// Default to no initializer.
- AddOperand(nullptr);
+ AddOperand(Var::kInitializerOperandOffset, nullptr);
+ AddResult(result);
}
Var::~Var() = default;
void Var::SetInitializer(Value* initializer) {
- SetOperand(0, initializer);
+ SetOperand(Var::kInitializerOperandOffset, initializer);
+}
+
+void Var::DestroyIfOnlyAssigned() {
+ auto* result = Result();
+ if (result->Usages().All([](const Usage& u) { return u.instruction->Is<ir::Store>(); })) {
+ while (!result->Usages().IsEmpty()) {
+ auto& usage = *result->Usages().begin();
+ usage.instruction->Destroy();
+ }
+ Destroy();
+ }
}
} // namespace tint::ir
diff --git a/src/tint/ir/var.h b/src/tint/ir/var.h
index 6f22c7d..0e76756 100644
--- a/src/tint/ir/var.h
+++ b/src/tint/ir/var.h
@@ -26,21 +26,21 @@
namespace tint::ir {
/// A var instruction in the IR.
-class Var : public utils::Castable<Var, OperandInstruction<1>> {
+class Var : public utils::Castable<Var, OperandInstruction<1, 1>> {
public:
- /// Constructor
- /// @param type the type of the var
- explicit Var(const type::Pointer* type);
- ~Var() override;
+ /// The offset in Operands() for the initializer
+ static constexpr size_t kInitializerOperandOffset = 0;
- /// @returns the type of the var
- const type::Pointer* Type() override { return type_; }
+ /// Constructor
+ /// @param result the result value
+ explicit Var(InstructionResult* result);
+ ~Var() override;
/// Sets the var initializer
/// @param initializer the initializer
void SetInitializer(Value* initializer);
/// @returns the initializer
- Value* Initializer() { return operands_[0]; }
+ Value* Initializer() { return operands_[kInitializerOperandOffset]; }
/// Sets the binding point
/// @param group the group
@@ -49,8 +49,10 @@
/// @returns the binding points if `Attributes` contains `kBindingPoint`
std::optional<struct BindingPoint> BindingPoint() { return binding_point_; }
+ /// Destroys this instruction along with any assignment instructions, if the var is never read.
+ void DestroyIfOnlyAssigned();
+
private:
- const type::Pointer* type_ = nullptr;
std::optional<struct BindingPoint> binding_point_;
};
diff --git a/src/tint/ir/var_test.cc b/src/tint/ir/var_test.cc
index 7173237..5674213 100644
--- a/src/tint/ir/var_test.cc
+++ b/src/tint/ir/var_test.cc
@@ -23,7 +23,9 @@
namespace tint::ir {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using IR_VarTest = IRTestHelper;
TEST_F(IR_VarTest, Fail_NullType) {
@@ -36,6 +38,14 @@
"");
}
+TEST_F(IR_VarTest, Results) {
+ auto* var = b.Var(ty.ptr<function, f32>());
+ EXPECT_TRUE(var->HasResults());
+ EXPECT_FALSE(var->HasMultiResults());
+ EXPECT_TRUE(var->Result()->Is<InstructionResult>());
+ EXPECT_EQ(var->Result()->Source(), var);
+}
+
TEST_F(IR_VarTest, Initializer_Usage) {
Module mod;
Builder b{mod};
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 52a73b3..f8866ac 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -50,6 +50,7 @@
#include "src/tint/ast/if_statement.h"
#include "src/tint/ast/increment_decrement_statement.h"
#include "src/tint/ast/index_accessor_expression.h"
+#include "src/tint/ast/index_attribute.h"
#include "src/tint/ast/int_literal_expression.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/invariant_attribute.h"
@@ -76,10 +77,11 @@
#include "src/tint/ast/while_statement.h"
#include "src/tint/ast/workgroup_attribute.h"
#include "src/tint/builtin/extension.h"
+#include "src/tint/builtin/fluent_types.h"
#include "src/tint/builtin/interpolation_sampling.h"
#include "src/tint/builtin/interpolation_type.h"
+#include "src/tint/builtin/number.h"
#include "src/tint/constant/manager.h"
-#include "src/tint/number.h"
#include "src/tint/program.h"
#include "src/tint/program_id.h"
#include "src/tint/sem/array_count.h"
@@ -117,13 +119,10 @@
namespace tint {
-// A sentinel type used by some template arguments to signal that the a type should be inferred.
-struct Infer {};
-
/// Evaluates to true if T is a Infer, AInt or AFloat.
template <typename T>
static constexpr const bool IsInferOrAbstract =
- std::is_same_v<std::decay_t<T>, Infer> || IsAbstract<std::decay_t<T>>;
+ std::is_same_v<std::decay_t<T>, builtin::fluent_types::Infer> || IsAbstract<std::decay_t<T>>;
// Forward declare metafunction that evaluates to true iff T can be wrapped in a statement.
template <typename T, typename = void>
@@ -1007,17 +1006,6 @@
return array(builder->source_, subtype, std::move(attrs));
}
- /// @param subtype the array element type
- /// @param n the array size. nullptr represents a runtime-array
- /// @param attrs the optional attributes for the array
- /// @return an array of size `n` of type `T`
- template <typename COUNT, typename = DisableIfVectorLike<COUNT>>
- ast::Type array(ast::Type subtype,
- COUNT&& n,
- utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
- return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
- }
-
/// @param source the Source of the node
/// @param subtype the array element type
/// @param attrs the optional attributes for the array
@@ -1033,6 +1021,17 @@
std::move(attrs)))};
}
+ /// @param subtype the array element type
+ /// @param n the array size. nullptr represents a runtime-array
+ /// @param attrs the optional attributes for the array
+ /// @return an array of size `n` of type `T`
+ template <typename COUNT, typename = DisableIfVectorLike<COUNT>>
+ ast::Type array(ast::Type subtype,
+ COUNT&& n,
+ utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
+ return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
+ }
+
/// @param source the Source of the node
/// @param subtype the array element type
/// @param n the array size. nullptr represents a runtime-array
@@ -1054,53 +1053,47 @@
/// @param source the Source of the node
/// @return a inferred-size or runtime-sized array of type `T`
- template <typename T, typename = EnableIfInferOrAbstract<T>>
+ template <typename T, int N = 0, typename = EnableIfInferOrAbstract<T>>
ast::Type array(const Source& source) const {
+ static_assert(N == 0, "arrays with a count cannot be inferred");
return (*this)(source, "array");
}
/// @return a inferred-size or runtime-sized array of type `T`
- template <typename T, typename = EnableIfInferOrAbstract<T>>
+ template <typename T, int N = 0, typename = EnableIfInferOrAbstract<T>>
ast::Type array() const {
+ static_assert(N == 0, "arrays with a count cannot be inferred");
return array<T>(builder->source_);
}
/// @param source the Source of the node
/// @param attrs the optional attributes for the array
/// @return a inferred-size or runtime-sized array of type `T`
- template <typename T, typename = DisableIfInferOrAbstract<T>>
+ template <typename T, int N = 0, typename = DisableIfInferOrAbstract<T>>
ast::Type array(const Source& source,
utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
- return ast::Type{builder->Expr(
- builder->create<ast::TemplatedIdentifier>(source, builder->Sym("array"),
- utils::Vector<const ast::Expression*, 1>{
- Of<T>().expr,
- },
- std::move(attrs)))};
- }
-
- /// @param attrs the optional attributes for the array
- /// @return a inferred-size or runtime-sized array of type `T`
- template <typename T, typename = DisableIfInferOrAbstract<T>>
- ast::Type array(utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
- return array<T>(builder->source_, std::move(attrs));
- }
-
- /// @param source the Source of the node
- /// @param attrs the optional attributes for the array
- /// @return an array of size `N` of type `T`
- template <typename T, int N>
- ast::Type array(const Source& source,
- utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
- static_assert(!IsInferOrAbstract<T>, "arrays with a count cannot be inferred");
- return array(source, Of<T>(), tint::u32(N), std::move(attrs));
+ if constexpr (N == 0) {
+ return ast::Type{builder->Expr(builder->create<ast::TemplatedIdentifier>(
+ source, builder->Sym("array"),
+ utils::Vector<const ast::Expression*, 1>{
+ Of<T>().expr,
+ },
+ std::move(attrs)))};
+ } else {
+ return ast::Type{builder->Expr(builder->create<ast::TemplatedIdentifier>(
+ source, builder->Sym("array"),
+ utils::Vector{
+ Of<T>().expr,
+ builder->Expr(builder->source_, tint::u32(N)),
+ },
+ std::move(attrs)))};
+ }
}
/// @param attrs the optional attributes for the array
/// @return an array of size `N` of type `T`
- template <typename T, int N>
+ template <typename T, int N = 0, typename = DisableIfInferOrAbstract<T>>
ast::Type array(utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
- static_assert(!IsInferOrAbstract<T>, "arrays with a count cannot be inferred");
return array<T, N>(builder->source_, std::move(attrs));
}
@@ -1160,9 +1153,48 @@
}
/// @param source the Source of the node
+ /// @return the pointer to type `T` with the builtin::AddressSpace `ADDRESS` and access
+ /// control `ACCESS`.
+ template <builtin::AddressSpace ADDRESS,
+ typename T,
+ builtin::Access ACCESS = builtin::Access::kUndefined>
+ ast::Type ptr(const Source& source) const {
+ return ptr<T>(source, ADDRESS, ACCESS);
+ }
+
+ /// @param type the type of the pointer
+ /// @return the pointer to the given type with the builtin::AddressSpace `ADDRESS` and
+ /// access control `ACCESS`.
+ template <builtin::AddressSpace ADDRESS,
+ builtin::Access ACCESS = builtin::Access::kUndefined>
+ ast::Type ptr(ast::Type type) const {
+ return ptr(builder->source_, ADDRESS, type, ACCESS);
+ }
+
+ /// @param source the Source of the node
+ /// @param type the type of the pointer
+ /// @return the pointer to the given type with the builtin::AddressSpace `ADDRESS` and
+ /// access control `ACCESS`.
+ template <builtin::AddressSpace ADDRESS,
+ builtin::Access ACCESS = builtin::Access::kUndefined>
+ ast::Type ptr(const Source& source, ast::Type type) const {
+ return ptr(source, ADDRESS, type, ACCESS);
+ }
+
+ /// @return the pointer to type `T` with the builtin::AddressSpace `ADDRESS` and access
+ /// control `ACCESS`.
+ template <builtin::AddressSpace ADDRESS,
+ typename T,
+ builtin::Access ACCESS = builtin::Access::kUndefined>
+ ast::Type ptr() const {
+ return ptr<T>(builder->source_, ADDRESS, ACCESS);
+ }
+
+ /// @param source the Source of the node
/// @param address_space the address space of the pointer
/// @param access the optional access control of the pointer
- /// @return the pointer to type `T` with the given builtin::AddressSpace.
+ /// @return the pointer to type `T` the builtin::AddressSpace `ADDRESS` and access control
+ /// `ACCESS`.
template <typename T>
ast::Type ptr(const Source& source,
builtin::AddressSpace address_space,
@@ -1654,325 +1686,6 @@
return Call(source, ty.vec(type, size), std::forward<ARGS>(args)...);
}
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 2-element vector of type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* vec2(ARGS&&... args) {
- return vec2<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the vector source
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 2-element vector of type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* vec2(const Source& source, ARGS&&... args) {
- return Call(source, ty.vec2<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param type the element type of the vector
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 2-element vector of type @p type, constructed with the
- /// values @p args.
- template <typename... ARGS>
- const ast::CallExpression* vec2(ast::Type type, ARGS&&... args) {
- return vec2(source_, type, std::forward<ARGS>(args)...);
- }
-
- /// @param source the vector source
- /// @param type the element type of the vector
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 2-element vector of type @p type, constructed with the
- /// values @p args.
- template <typename... ARGS>
- const ast::CallExpression* vec2(const Source& source, ast::Type type, ARGS&&... args) {
- return Call(source, ty.vec2(type), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 3-element vector of type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* vec3(ARGS&&... args) {
- return vec3<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the vector source
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 3-element vector of type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* vec3(const Source& source, ARGS&&... args) {
- return Call(source, ty.vec3<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param type the element type of the vector
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 3-element vector of type @p type, constructed with the
- /// values @p args.
- template <typename... ARGS>
- const ast::CallExpression* vec3(ast::Type type, ARGS&&... args) {
- return vec3(source_, type, std::forward<ARGS>(args)...);
- }
-
- /// @param source the vector source
- /// @param type the element type of the vector
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 3-element vector of type @p type, constructed with the
- /// values @p args.
- template <typename... ARGS>
- const ast::CallExpression* vec3(const Source& source, ast::Type type, ARGS&&... args) {
- return Call(source, ty.vec3(type), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 4-element vector of type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* vec4(ARGS&&... args) {
- return vec4<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the vector source
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 4-element vector of type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* vec4(const Source& source, ARGS&&... args) {
- return Call(source, ty.vec4<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param type the element type of the vector
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 4-element vector of type @p type, constructed with the
- /// values @p args.
- template <typename... ARGS>
- const ast::CallExpression* vec4(ast::Type type, ARGS&&... args) {
- return vec4(source_, type, std::forward<ARGS>(args)...);
- }
-
- /// @param source the vector source
- /// @param type the element type of the vector
- /// @param args the arguments for the vector constructor
- /// @return an `ast::CallExpression` of a 4-element vector of type @p type, constructed with the
- /// values @p args.
- template <typename... ARGS>
- const ast::CallExpression* vec4(const Source& source, ast::Type type, ARGS&&... args) {
- return Call(source, ty.vec4(type), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 2x2 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat2x2(ARGS&&... args) {
- return mat2x2<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 2x2 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat2x2(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat2x2<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 2x3 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat2x3(ARGS&&... args) {
- return mat2x3<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 2x3 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat2x3(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat2x3<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 2x4 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat2x4(ARGS&&... args) {
- return mat2x4<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 2x4 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat2x4(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat2x4<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 3x2 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat3x2(ARGS&&... args) {
- return mat3x2<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 3x2 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat3x2(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat3x2<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 3x3 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat3x3(ARGS&&... args) {
- return mat3x3<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 3x3 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat3x3(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat3x3<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 3x4 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat3x4(ARGS&&... args) {
- return mat3x4<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 3x4 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat3x4(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat3x4<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 4x2 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat4x2(ARGS&&... args) {
- return mat4x2<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 4x2 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat4x2(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat4x2<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 4x3 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat4x3(ARGS&&... args) {
- return mat4x3<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 4x3 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat4x3(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat4x3<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 4x4 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* mat4x4(ARGS&&... args) {
- return mat4x4<T>(source_, std::forward<ARGS>(args)...);
- }
-
- /// @param source the matrix source
- /// @param args the arguments for the matrix constructor
- /// @return an `ast::CallExpression` of a 4x4 matrix of type
- /// `T`, constructed with the values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* mat4x4(const Source& source, ARGS&&... args) {
- return Call(source, ty.mat4x4<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the array constructor
- /// @return an `ast::CallExpression` of an array with element type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* array(ARGS&&... args) {
- return Call(ty.array<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param source the array source
- /// @param args the arguments for the array constructor
- /// @return an `ast::CallExpression` of an array with element type `T`, constructed with the
- /// values @p args.
- template <typename T, typename... ARGS>
- const ast::CallExpression* array(const Source& source, ARGS&&... args) {
- return Call(source, ty.array<T>(), std::forward<ARGS>(args)...);
- }
-
- /// @param args the arguments for the array constructor
- /// @return an `ast::CallExpression` of an array with element type `T` and size `N`, constructed
- /// with the values @p args.
- template <typename T, int N, typename... ARGS, typename = DisableIfSource<ARGS...>>
- const ast::CallExpression* array(ARGS&&... args) {
- return Call(ty.array<T, N>(), std::forward<ARGS>(args)...);
- }
-
- /// @param source the array source
- /// @param args the arguments for the array constructor
- /// @return an `ast::CallExpression` of an array with element type `T` and size `N`, constructed
- /// with the values @p args.
- template <typename T, int N, typename... ARGS>
- const ast::CallExpression* array(const Source& source, ARGS&&... args) {
- return Call(source, ty.array<T, N>(), std::forward<ARGS>(args)...);
- }
-
- /// @param subtype the array element type
- /// @param n the array size. nullptr represents a runtime-array.
- /// @param args the arguments for the array constructor
- /// @return an `ast::CallExpression` of an array with element type
- /// `subtype`, constructed with the values @p args.
- template <typename EXPR, typename... ARGS>
- const ast::CallExpression* array(ast::Type subtype, EXPR&& n, ARGS&&... args) {
- return Call(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
- }
-
- /// @param source the array source
- /// @param subtype the array element type
- /// @param n the array size. nullptr represents a runtime-array.
- /// @param args the arguments for the array constructor
- /// @return an `ast::CallExpression` of an array with element type
- /// `subtype`, constructed with the values @p args.
- template <typename EXPR, typename... ARGS>
- const ast::CallExpression* array(const Source& source,
- ast::Type subtype,
- EXPR&& n,
- ARGS&&... args) {
- return Call(source, ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
- }
-
/// Adds the extension to the list of enable directives at the top of the module.
/// @param extension the extension to enable
/// @return an `ast::Enable` enabling the given extension.
@@ -3552,6 +3265,23 @@
return create<ast::LocationAttribute>(source_, Expr(std::forward<EXPR>(location)));
}
+ /// Creates an ast::IndexAttribute
+ /// @param source the source information
+ /// @param index the index value expression
+ /// @returns the index attribute pointer
+ template <typename EXPR>
+ const ast::IndexAttribute* Index(const Source& source, EXPR&& index) {
+ return create<ast::IndexAttribute>(source, Expr(std::forward<EXPR>(index)));
+ }
+
+ /// Creates an ast::IndexAttribute
+ /// @param index the index value expression
+ /// @returns the index attribute pointer
+ template <typename EXPR>
+ const ast::IndexAttribute* Index(EXPR&& index) {
+ return create<ast::IndexAttribute>(source_, Expr(std::forward<EXPR>(index)));
+ }
+
/// Creates an ast::IdAttribute
/// @param source the source information
/// @param id the id value
@@ -3933,6 +3663,28 @@
struct ProgramBuilder::TypesBuilder::CToAST<bool> {
static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
};
+template <typename T, uint32_t N>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::array<T, N>> {
+ static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->array<T, N>(); }
+};
+template <typename T>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::atomic<T>> {
+ static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->atomic<T>(); }
+};
+template <uint32_t C, uint32_t R, typename T>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::mat<C, R, T>> {
+ static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->mat<T>(C, R); }
+};
+template <uint32_t N, typename T>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::vec<N, T>> {
+ static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->vec<T, N>(); }
+};
+template <builtin::AddressSpace ADDRESS, typename T, builtin::Access ACCESS>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::ptr<ADDRESS, T, ACCESS>> {
+ static ast::Type get(const ProgramBuilder::TypesBuilder* t) {
+ return t->ptr<ADDRESS, T, ACCESS>();
+ }
+};
//! @endcond
/// @param builder the ProgramBuilder
diff --git a/src/tint/program_id.h b/src/tint/program_id.h
index 4169ba1..35ab476 100644
--- a/src/tint/program_id.h
+++ b/src/tint/program_id.h
@@ -103,11 +103,11 @@
/// valid program identifiers.
#if TINT_CHECK_FOR_CROSS_PROGRAM_LEAKS
#define TINT_ASSERT_PROGRAM_IDS_EQUAL(system, a, b) \
- detail::AssertProgramIDsEqual( \
+ tint::detail::AssertProgramIDsEqual( \
ProgramIDOf(a), ProgramIDOf(b), false, tint::diag::System::system, \
"TINT_ASSERT_PROGRAM_IDS_EQUAL(" #system "," #a ", " #b ")", __FILE__, __LINE__)
#define TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(system, a, b) \
- detail::AssertProgramIDsEqual( \
+ tint::detail::AssertProgramIDsEqual( \
ProgramIDOf(a), ProgramIDOf(b), true, tint::diag::System::system, \
"TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(" #system ", " #a ", " #b ")", __FILE__, __LINE__)
#else
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index c78b9a0..6f56081 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -3895,14 +3895,31 @@
if (op == spv::Op::OpCompositeConstruct) {
ExpressionList operands;
+ bool all_same = true;
+ uint32_t first_id = 0u;
for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
auto operand = MakeOperand(inst, iarg);
if (!operand) {
return {};
}
operands.Push(operand.expr);
+
+ // Check if this argument is different from the others.
+ auto arg_id = inst.GetSingleWordInOperand(iarg);
+ if (first_id != 0u) {
+ if (arg_id != first_id) {
+ all_same = false;
+ }
+ } else {
+ first_id = arg_id;
+ }
}
- return {ast_type, builder_.Call(ast_type->Build(builder_), std::move(operands))};
+ if (all_same && ast_type->Is<Vector>()) {
+ // We're constructing a vector and all the operands were the same, so use a splat.
+ return {ast_type, builder_.Call(ast_type->Build(builder_), operands[0])};
+ } else {
+ return {ast_type, builder_.Call(ast_type->Build(builder_), std::move(operands))};
+ }
}
if (op == spv::Op::OpCompositeExtract) {
@@ -4693,40 +4710,68 @@
const auto vec0_len = type_mgr_->GetType(vec0.type_id())->AsVector()->element_count();
const auto vec1_len = type_mgr_->GetType(vec1.type_id())->AsVector()->element_count();
- // Idiomatic vector accessors.
+ // Helper to get the name for the component index `i`.
+ auto component_name = [](uint32_t i) {
+ constexpr const char* names[] = {"x", "y", "z", "w"};
+ TINT_ASSERT(Reader, i < 4);
+ return names[i];
+ };
- // Generate an ast::TypeInitializer expression.
+ // Build a swizzle for each consecutive set of indices that fall within the same vector.
// Assume the literal indices are valid, and there is a valid number of them.
auto source = GetSourceForInst(inst);
const Vector* result_type = As<Vector>(parser_impl_.ConvertType(inst.type_id()));
+ uint32_t last_vec_id = 0u;
+ std::string swizzle;
ExpressionList values;
for (uint32_t i = 2; i < inst.NumInOperands(); ++i) {
- const auto index = inst.GetSingleWordInOperand(i);
+ // Select the source vector and determine the index within it.
+ uint32_t vec_id = 0u;
+ uint32_t index = inst.GetSingleWordInOperand(i);
if (index < vec0_len) {
- auto expr = MakeExpression(vec0_id);
- if (!expr) {
- return {};
- }
- values.Push(create<ast::MemberAccessorExpression>(source, expr.expr, Swizzle(index)));
+ vec_id = vec0_id;
} else if (index < vec0_len + vec1_len) {
- const auto sub_index = index - vec0_len;
- TINT_ASSERT(Reader, sub_index < kMaxVectorLen);
- auto expr = MakeExpression(vec1_id);
- if (!expr) {
- return {};
- }
- values.Push(
- create<ast::MemberAccessorExpression>(source, expr.expr, Swizzle(sub_index)));
+ vec_id = vec1_id;
+ index -= vec0_len;
+ TINT_ASSERT(Reader, index < kMaxVectorLen);
} else if (index == 0xFFFFFFFF) {
- // By rule, this maps to OpUndef. Instead, make it zero.
- values.Push(parser_impl_.MakeNullValue(result_type->type));
+ // By rule, this maps to OpUndef. Instead, take the first component of the first vector.
+ vec_id = vec0_id;
+ index = 0u;
} else {
Fail() << "invalid vectorshuffle ID %" << inst.result_id()
<< ": index too large: " << index;
return {};
}
+
+ if (vec_id != last_vec_id && !swizzle.empty()) {
+ // The source vector has changed, so emit the swizzle so far.
+ auto expr = MakeExpression(last_vec_id);
+ if (!expr) {
+ return {};
+ }
+ values.Push(builder_.MemberAccessor(source, expr.expr, builder_.Ident(swizzle)));
+ swizzle.clear();
+ }
+ swizzle += component_name(index);
+ last_vec_id = vec_id;
}
- return {result_type, builder_.Call(source, result_type->Build(builder_), std::move(values))};
+
+ // Emit the final swizzle.
+ auto expr = MakeExpression(last_vec_id);
+ if (!expr) {
+ return {};
+ }
+ values.Push(builder_.MemberAccessor(source, expr.expr, builder_.Ident(swizzle)));
+
+ if (values.Length() == 1) {
+ // There's only one swizzle, so just return it.
+ return {result_type, values[0]};
+ } else {
+ // There's multiple swizzles, so generate a type constructor expression to combine them.
+ return {result_type,
+ builder_.Call(source, result_type->Build(builder_), std::move(values))};
+ }
}
bool FunctionEmitter::RegisterSpecialBuiltInVariables() {
diff --git a/src/tint/reader/spirv/function_composite_test.cc b/src/tint/reader/spirv/function_composite_test.cc
index 442d6fc..3d311f1 100644
--- a/src/tint/reader/spirv/function_composite_test.cc
+++ b/src/tint/reader/spirv/function_composite_test.cc
@@ -101,6 +101,27 @@
)"));
}
+TEST_F(SpvParserTest_Composite_Construct, VectorSplat) {
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCompositeConstruct %v4uint %uint_10 %uint_10 %uint_10 %uint_10
+ %2 = OpCompositeConstruct %v2int %int_30 %int_30
+ %3 = OpCompositeConstruct %v2float %float_50 %float_50
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ auto fe = p->function_emitter(100);
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ auto ast_body = fe.ast_body();
+ EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr(R"(let x_1 = vec4u(10u);
+let x_2 = vec2i(30i);
+let x_3 = vec2f(50.0f);
+)"));
+}
+
TEST_F(SpvParserTest_Composite_Construct, Matrix) {
const auto assembly = Preamble() + R"(
%100 = OpFunction %void None %voidfn
@@ -117,7 +138,7 @@
EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_1 = mat3x2f("
"vec2f(50.0f, 60.0f), "
"vec2f(60.0f, 50.0f), "
- "vec2f(70.0f, 70.0f));"));
+ "vec2f(70.0f));"));
}
TEST_F(SpvParserTest_Composite_Construct, Array) {
@@ -779,7 +800,46 @@
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_10 = vec4u(x_2.y, x_2.x, x_1.y, x_1.x);"));
+ HasSubstr("let x_10 = vec4u(x_2.yx, x_1.yx);"));
+}
+
+TEST_F(SpvParserTest_VectorShuffle, FunctionScopeOperands_UseBoth_Swizzle) {
+ // Use the same vector for both source operands.
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCopyObject %v2uint %v2uint_3_4
+ %10 = OpVectorShuffle %v4uint %1 %1 1 0 2 3
+ OpReturn
+ OpFunctionEnd
+)";
+
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ auto fe = p->function_emitter(100);
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ auto ast_body = fe.ast_body();
+ EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_10 = x_1.yxxy;"));
+}
+
+TEST_F(SpvParserTest_VectorShuffle, FunctionScopeOperands_UseOne_Swizzle) {
+ // Only use the first vector operand.
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCopyObject %v2uint %v2uint_3_4
+ %2 = OpUndef %v2uint
+ %10 = OpVectorShuffle %v4uint %1 %2 1 0 0 1
+ OpReturn
+ OpFunctionEnd
+)";
+
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ auto fe = p->function_emitter(100);
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ auto ast_body = fe.ast_body();
+ EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_10 = x_1.yxxy;"));
}
TEST_F(SpvParserTest_VectorShuffle, ConstantOperands_UseBoth) {
@@ -796,11 +856,8 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_10 = vec4u("
- "vec2u(4u, 3u).y, "
- "vec2u(4u, 3u).x, "
- "vec2u(3u, 4u).y, "
- "vec2u(3u, 4u).x);"));
+ EXPECT_THAT(test::ToString(p->program(), ast_body),
+ HasSubstr("let x_10 = vec4u(vec2u(4u, 3u).yx, vec2u(3u, 4u).yx);"));
}
TEST_F(SpvParserTest_VectorShuffle, ConstantOperands_AllOnesMapToNull) {
@@ -818,7 +875,7 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_10 = vec2u(0u, x_1.y);"));
+ EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_10 = x_1.xy;"));
}
TEST_F(SpvParserTest_VectorShuffle, FunctionScopeOperands_MixedInputOperandSizes) {
diff --git a/src/tint/reader/spirv/function_memory_test.cc b/src/tint/reader/spirv/function_memory_test.cc
index b75a3bc..a35aa8c 100644
--- a/src/tint/reader/spirv/function_memory_test.cc
+++ b/src/tint/reader/spirv/function_memory_test.cc
@@ -499,8 +499,7 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody());
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("myvar[2u] = vec4f(42.0f, 42.0f, 42.0f, 42.0f);"));
+ EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("myvar[2u] = vec4f(42.0f);"));
}
TEST_F(SpvParserMemoryTest, EmitStatement_AccessChain_Array) {
@@ -531,8 +530,7 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody());
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("myvar[2u] = vec4f(42.0f, 42.0f, 42.0f, 42.0f);"));
+ EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("myvar[2u] = vec4f(42.0f);"));
}
TEST_F(SpvParserMemoryTest, EmitStatement_AccessChain_Struct) {
diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc
index 7a3089d..0c61368 100644
--- a/src/tint/reader/spirv/parser_impl.cc
+++ b/src/tint/reader/spirv/parser_impl.cc
@@ -1920,7 +1920,16 @@
return {original_ast_type, builder_.Expr(itr->second)};
}
+ const auto* spirv_const = constant_mgr_->FindDeclaredConstant(id);
+ if (spirv_const->IsZero()) {
+ // All zeros, so just use a zero value constructor and always inline it.
+ return {original_ast_type,
+ builder_.Call(source, original_ast_type->Build(builder_))};
+ }
+
// Generate a composite from explicit components.
+ bool all_same = true;
+ uint32_t first_id = 0u;
ExpressionList ast_components;
if (!inst->WhileEachInId([&](const uint32_t* id_ref) -> bool {
auto component = MakeConstantExpression(*id_ref);
@@ -1929,14 +1938,30 @@
return false;
}
ast_components.Push(component.expr);
+
+ // Check if this argument is different from the others.
+ if (first_id != 0u) {
+ if (*id_ref != first_id) {
+ all_same = false;
+ }
+ } else {
+ first_id = *id_ref;
+ }
+
return true;
})) {
// We've already emitted a diagnostic.
return {};
}
- auto* expr = builder_.Call(source, original_ast_type->Build(builder_),
- std::move(ast_components));
+ const ast::Expression* expr = nullptr;
+ if (all_same && original_ast_type->Is<Vector>()) {
+ // We're constructing a vector and all the operands were the same, so use a splat.
+ expr = builder_.Call(source, original_ast_type->Build(builder_), ast_components[0]);
+ } else {
+ expr = builder_.Call(source, original_ast_type->Build(builder_),
+ std::move(ast_components));
+ }
if (def_use_mgr_->NumUses(id) == 1) {
// The constant is only used once, so just inline its use.
diff --git a/src/tint/reader/spirv/parser_impl_handle_test.cc b/src/tint/reader/spirv/parser_impl_handle_test.cc
index 206e258..4f1e1a6 100644
--- a/src/tint/reader/spirv/parser_impl_handle_test.cc
+++ b/src/tint/reader/spirv/parser_impl_handle_test.cc
@@ -4160,7 +4160,7 @@
const auto got = test::ToString(p->program(), ast_body);
auto* expect = R"(var x_24 : vec2f;
var x_26 : i32;
-x_24 = vec2f(0.0f, 0.0f);
+x_24 = vec2f();
x_26 = 0i;
loop {
var x_27 : i32;
@@ -4171,11 +4171,11 @@
continuing {
x_27 = (x_26 + 1i);
- x_24 = vec2f(1.0f, 1.0f);
+ x_24 = vec2f(1.0f);
x_26 = x_27;
}
}
-textureStore(Output2Texture2D, vec2i(vec2u(1u, 1u)), vec4f(x_24, 0.0f, 0.0f));
+textureStore(Output2Texture2D, vec2i(vec2u(1u)), vec4f(x_24, 0.0f, 0.0f));
return;
)";
ASSERT_EQ(expect, got);
@@ -4250,7 +4250,7 @@
}
}
let x_21 = select(0.0f, x_14, (x_14 > 1.0f));
-x_1 = vec4f(x_21, x_21, x_21, x_21);
+x_1 = vec4f(x_21);
return;
)";
ASSERT_EQ(expect, got);
diff --git a/src/tint/reader/wgsl/lexer.cc b/src/tint/reader/wgsl/lexer.cc
index 304a545..ac42988 100644
--- a/src/tint/reader/wgsl/lexer.cc
+++ b/src/tint/reader/wgsl/lexer.cc
@@ -25,8 +25,8 @@
#include <type_traits>
#include <utility>
+#include "src/tint/builtin/number.h"
#include "src/tint/debug.h"
-#include "src/tint/number.h"
#include "src/tint/utils/parse_num.h"
#include "src/tint/utils/unicode.h"
diff --git a/src/tint/reader/wgsl/lexer_test.cc b/src/tint/reader/wgsl/lexer_test.cc
index 8d49bf8..a705de0 100644
--- a/src/tint/reader/wgsl/lexer_test.cc
+++ b/src/tint/reader/wgsl/lexer_test.cc
@@ -19,7 +19,7 @@
#include <vector>
#include "gtest/gtest.h"
-#include "src/tint/number.h"
+#include "src/tint/builtin/number.h"
namespace tint::reader::wgsl {
namespace {
diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h
index b167f56..1151fc4 100644
--- a/src/tint/reader/wgsl/parser_impl.h
+++ b/src/tint/reader/wgsl/parser_impl.h
@@ -121,9 +121,9 @@
/// std::unique_ptr, operator->() automatically dereferences so that the
/// return type will always be a pointer to a non-pointer type. #errored
/// must be false to call.
- inline typename detail::OperatorArrow<T>::type operator->() {
+ inline typename wgsl::detail::OperatorArrow<T>::type operator->() {
TINT_ASSERT(Reader, !errored);
- return detail::OperatorArrow<T>::ptr(value);
+ return wgsl::detail::OperatorArrow<T>::ptr(value);
}
/// The expected value of a successful parse.
@@ -183,9 +183,9 @@
/// std::unique_ptr, operator->() automatically dereferences so that the
/// return type will always be a pointer to a non-pointer type. #errored
/// must be false to call.
- inline typename detail::OperatorArrow<T>::type operator->() {
+ inline typename wgsl::detail::OperatorArrow<T>::type operator->() {
TINT_ASSERT(Reader, !errored);
- return detail::OperatorArrow<T>::ptr(value);
+ return wgsl::detail::OperatorArrow<T>::ptr(value);
}
/// The value of a successful parse.
diff --git a/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc b/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
index 3c63a02..621206f 100644
--- a/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
@@ -164,7 +164,7 @@
// Error when unknown extension found
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
-Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
+Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_dual_source_blending', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@@ -178,7 +178,7 @@
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Did you mean 'f16'?
-Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
+Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_dual_source_blending', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@@ -226,7 +226,7 @@
p->translation_unit();
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
-Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
+Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_dual_source_blending', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@@ -237,7 +237,7 @@
p->translation_unit();
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
-Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
+Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_dual_source_blending', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@@ -249,7 +249,7 @@
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Did you mean 'f16'?
-Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
+Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_dual_source_blending', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
diff --git a/src/tint/reader/wgsl/parser_impl_error_resync_test.cc b/src/tint/reader/wgsl/parser_impl_error_resync_test.cc
index f3e306a..9817bec 100644
--- a/src/tint/reader/wgsl/parser_impl_error_resync_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_error_resync_test.cc
@@ -54,7 +54,7 @@
^
test.wgsl:4:2 error: expected attribute
-Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
+Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
@_ fn -> {}
^
)");
@@ -122,7 +122,7 @@
^^^^
test.wgsl:7:6 error: expected attribute
-Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
+Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
@- x : i32,
^
)");
diff --git a/src/tint/reader/wgsl/parser_impl_function_attribute_list_test.cc b/src/tint/reader/wgsl/parser_impl_function_attribute_list_test.cc
index ae43a0f..52d7da1 100644
--- a/src/tint/reader/wgsl/parser_impl_function_attribute_list_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_function_attribute_list_test.cc
@@ -53,7 +53,7 @@
EXPECT_TRUE(attrs.value.IsEmpty());
EXPECT_EQ(p->error(), R"(1:2: expected attribute
Did you mean 'invariant'?
-Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
+Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
}
} // namespace
diff --git a/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc b/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc
index 1751e98..76c27e7 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc
@@ -51,7 +51,7 @@
EXPECT_TRUE(attrs.value.IsEmpty());
EXPECT_EQ(p->error(), R"(1:2: expected attribute
Did you mean 'invariant'?
-Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
+Possible values: 'align', 'binding', 'builtin', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
}
} // namespace
diff --git a/src/tint/reflection.h b/src/tint/reflection.h
index d341f98..e965200 100644
--- a/src/tint/reflection.h
+++ b/src/tint/reflection.h
@@ -36,7 +36,7 @@
/// Is true if the class T has reflected its fields with TINT_REFLECT()
template <typename T>
-static constexpr bool HasReflection = detail::HasReflection<T>::value;
+static constexpr bool HasReflection = tint::detail::HasReflection<T>::value;
/// Calls @p callback with each field of @p object
/// @param object the object
diff --git a/src/tint/resolver/address_space_layout_validation_test.cc b/src/tint/resolver/address_space_layout_validation_test.cc
index 9a621e3..1006120 100644
--- a/src/tint/resolver/address_space_layout_validation_test.cc
+++ b/src/tint/resolver/address_space_layout_validation_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
#include "src/tint/resolver/resolver_test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverAddressSpaceLayoutValidationTest = ResolverTest;
// Detect unaligned member for storage buffers
@@ -430,7 +431,7 @@
// @group(0) @binding(0)
// var<uniform> a : Outer;
- Alias("Inner", ty.array(ty.vec2<f32>(), 10_u));
+ Alias("Inner", ty.array<vec2<f32>, 10>());
Structure(Source{{12, 34}}, "Outer",
utils::Vector{
@@ -739,7 +740,7 @@
Structure(Source{{12, 34}}, "Outer",
utils::Vector{
- Member("arr", ty.array(ty.vec3<f16>(), 10_u)),
+ Member("arr", ty.array<vec3<f16>, 10>()),
});
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), builtin::AddressSpace::kUniform, Group(0_a),
diff --git a/src/tint/resolver/address_space_validation_test.cc b/src/tint/resolver/address_space_validation_test.cc
index fae4a25..a5bd21e 100644
--- a/src/tint/resolver/address_space_validation_test.cc
+++ b/src/tint/resolver/address_space_validation_test.cc
@@ -18,11 +18,12 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/sem/struct.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ::testing::HasSubstr;
using ResolverAddressSpaceValidationTest = ResolverTest;
@@ -67,8 +68,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Private_RuntimeArray) {
// type t : ptr<private, array<i32>>;
- Alias("t", ty.ptr(Source{{56, 78}}, builtin::AddressSpace::kPrivate,
- ty.array(Source{{12, 34}}, ty.i32())));
+ Alias("t", ty.ptr<private_>(Source{{56, 78}}, ty.array(Source{{12, 34}}, ty.i32())));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -93,7 +93,7 @@
// struct S { m : array<i32> };
// type t = ptr<private, S>;
Structure("S", utils::Vector{Member(Source{{12, 34}}, "m", ty.array(ty.i32()))});
- Alias("t", ty.ptr(builtin::AddressSpace::kPrivate, ty("S")));
+ Alias("t", ty.ptr<private_>(ty("S")));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -115,7 +115,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Workgroup_RuntimeArray) {
// type t = ptr<workgroup, array<i32>>;
- Alias("t", ty.ptr(builtin::AddressSpace::kWorkgroup, ty.array(Source{{12, 34}}, ty.i32())));
+ Alias("t", ty.ptr<workgroup>(ty.array(Source{{12, 34}}, ty.i32())));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -140,7 +140,7 @@
// struct S { m : array<i32> };
// type t = ptr<workgroup, S>;
Structure("S", utils::Vector{Member(Source{{12, 34}}, "m", ty.array(ty.i32()))});
- Alias(Source{{56, 78}}, "t", ty.ptr(builtin::AddressSpace::kWorkgroup, ty("S")));
+ Alias(Source{{56, 78}}, "t", ty.ptr<workgroup>(ty("S")));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -164,8 +164,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_Bool) {
// type t = ptr<storage, bool>;
- Alias(Source{{56, 78}}, "t",
- ty.ptr(builtin::AddressSpace::kStorage, ty.bool_(Source{{12, 34}})));
+ Alias(Source{{56, 78}}, "t", ty.ptr<storage>(ty.bool_(Source{{12, 34}})));
ASSERT_FALSE(r()->Resolve());
@@ -194,8 +193,7 @@
// type a = bool;
// type t = ptr<storage, a>;
Alias("a", ty.bool_());
- Alias(Source{{56, 78}}, "t",
- ty.ptr(builtin::AddressSpace::kStorage, ty(Source{{12, 34}}, "a")));
+ Alias(Source{{56, 78}}, "t", ty.ptr<storage>(ty(Source{{12, 34}}, "a")));
ASSERT_FALSE(r()->Resolve());
@@ -207,8 +205,7 @@
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariable_Storage_Pointer) {
// var<storage> g : ptr<private, f32>;
- GlobalVar(Source{{56, 78}}, "g",
- ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.f32()),
+ GlobalVar(Source{{56, 78}}, "g", ty.ptr<private_, f32>(Source{{12, 34}}),
builtin::AddressSpace::kStorage, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve());
@@ -221,8 +218,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_Pointer) {
// type t = ptr<storage, ptr<private, f32>>;
- Alias("t", ty.ptr(Source{{56, 78}}, builtin::AddressSpace::kStorage,
- ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.f32())));
+ Alias("t", ty.ptr<storage>(Source{{56, 78}}, ty.ptr<private_, f32>(Source{{12, 34}})));
ASSERT_FALSE(r()->Resolve());
@@ -241,7 +237,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_IntScalar) {
// type t = ptr<storage, i32;
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.i32()));
+ Alias("t", ty.ptr<storage, i32>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -261,7 +257,7 @@
// type t = ptr<storage, f16>;
Enable(builtin::Extension::kF16);
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.f16()));
+ Alias("t", ty.ptr<storage, f16>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -285,7 +281,7 @@
Enable(builtin::Extension::kF16);
Alias("a", ty.f16());
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty("a")));
+ Alias("t", ty.ptr<storage>(ty("a")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -299,7 +295,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_VectorF32) {
// type t = ptr<storage, vec4<f32>>;
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.vec4<f32>()));
+ Alias("t", ty.ptr<storage, vec4<f32>>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -315,7 +311,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_VectorF16) {
// type t = ptr<storage, vec4<f16>>;
Enable(builtin::Extension::kF16);
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.vec(ty.f16(), 4u)));
+ Alias("t", ty.ptr<storage, vec4<f32>>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -334,7 +330,7 @@
// struct S{ a : f32 };
// type t = ptr<storage, array<S, 3u>>;
Structure("S", utils::Vector{Member("a", ty.f32())});
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.array(ty("S"), 3_u)));
+ Alias("t", ty.ptr<storage>(ty.array(ty("S"), 3_u)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -359,8 +355,7 @@
Enable(builtin::Extension::kF16);
Structure("S", utils::Vector{Member("a", ty.f16())});
- Alias("t",
- ty.ptr(builtin::AddressSpace::kStorage, ty.array(ty("S"), 3_u), builtin::Access::kRead));
+ Alias("t", ty.ptr<storage, read>(ty.array(ty("S"), 3_u)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -379,7 +374,7 @@
// struct S { x : i32 };
// type t = ptr<storage, S, read>;
Structure("S", utils::Vector{Member("x", ty.i32())});
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty("S"), builtin::Access::kRead));
+ Alias("t", ty.ptr<storage, read>(ty("S")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -404,7 +399,7 @@
Structure("S", utils::Vector{Member("x", ty.i32())});
Alias("a1", ty("S"));
Alias("a2", ty("a1"));
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty("a2"), builtin::Access::kRead));
+ Alias("t", ty.ptr<storage, read>(ty("a2")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -427,7 +422,7 @@
Enable(builtin::Extension::kF16);
Structure("S", utils::Vector{Member("x", ty.f16())});
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty("S"), builtin::Access::kRead));
+ Alias("t", ty.ptr<storage, read>(ty("S")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -456,7 +451,7 @@
Structure("S", utils::Vector{Member("x", ty.f16())});
Alias("a1", ty("S"));
Alias("a2", ty("a1"));
- Alias("g", ty.ptr(builtin::AddressSpace::kStorage, ty("a2"), builtin::Access::kRead));
+ Alias("g", ty.ptr<storage, read>(ty("a2")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -475,8 +470,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_NotStorage_AccessMode) {
// type t = ptr<private, i32, read>;
- Alias("t", ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.i32(),
- builtin::Access::kRead));
+ Alias("t", ty.ptr<private_, i32, read>(Source{{12, 34}}));
ASSERT_FALSE(r()->Resolve());
@@ -495,7 +489,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_ReadAccessMode) {
// type t = ptr<storage, i32, read>;
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.i32(), builtin::Access::kRead));
+ Alias("t", ty.ptr<storage, i32, read>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -510,7 +504,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_ReadWriteAccessMode) {
// type t = ptr<storage, i32, read_write>;
- Alias("t", ty.ptr(builtin::AddressSpace::kStorage, ty.i32(), builtin::Access::kReadWrite));
+ Alias("t", ty.ptr<storage, i32, read_write>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -527,9 +521,8 @@
}
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_Storage_WriteAccessMode) {
- // type t = ptr<storage, i32, read_write>;
- Alias("t", ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kStorage, ty.i32(),
- builtin::Access::kWrite));
+ // type t = ptr<storage, i32, write>;
+ Alias("t", ty.ptr<storage, i32, write>(Source{{12, 34}}));
ASSERT_FALSE(r()->Resolve());
@@ -561,7 +554,7 @@
Structure("S",
utils::Vector{Member(Source{{56, 78}}, "m", ty.array(Source{{12, 34}}, ty.i32()))});
- Alias("t", ty.ptr(Source{{90, 12}}, builtin::AddressSpace::kUniform, ty("S")));
+ Alias("t", ty.ptr<uniform>(Source{{90, 12}}, ty("S")));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
@@ -589,8 +582,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_UniformBufferBool) {
// type t = ptr<uniform, bool>;
- Alias("t",
- ty.ptr(Source{{56, 78}}, builtin::AddressSpace::kUniform, ty.bool_(Source{{12, 34}})));
+ Alias("t", ty.ptr<uniform>(Source{{56, 78}}, ty.bool_(Source{{12, 34}})));
ASSERT_FALSE(r()->Resolve());
@@ -619,8 +611,7 @@
// type a = bool;
// type t = ptr<uniform, a>;
Alias("a", ty.bool_());
- Alias("t",
- ty.ptr(Source{{56, 78}}, builtin::AddressSpace::kUniform, ty(Source{{12, 34}}, "a")));
+ Alias("t", ty.ptr<uniform>(Source{{56, 78}}, ty(Source{{12, 34}}, "a")));
ASSERT_FALSE(r()->Resolve());
@@ -632,8 +623,7 @@
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariable_UniformPointer) {
// var<uniform> g : ptr<private, f32>;
- GlobalVar(Source{{56, 78}}, "g",
- ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.f32()),
+ GlobalVar(Source{{56, 78}}, "g", ty.ptr<private_, f32>(Source{{12, 34}}),
builtin::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve());
@@ -646,8 +636,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_UniformPointer) {
// type t = ptr<uniform, ptr<private, f32>>;
- Alias("t", ty.ptr(Source{{56, 78}}, builtin::AddressSpace::kUniform,
- ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.f32())));
+ Alias("t", ty.ptr<uniform>(Source{{56, 78}}, ty.ptr<private_, f32>(Source{{12, 34}})));
ASSERT_FALSE(r()->Resolve());
@@ -667,7 +656,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_UniformBufferIntScalar) {
// type t = ptr<uniform, i32>;
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty.i32()));
+ Alias("t", ty.ptr<uniform, i32>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -687,7 +676,7 @@
// type t = ptr<uniform, f16>;
Enable(builtin::Extension::kF16);
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty.f16()));
+ Alias("t", ty.ptr<uniform, f16>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -701,7 +690,7 @@
TEST_F(ResolverAddressSpaceValidationTest, PointerAlias_UniformBufferVectorF32) {
// type t = ptr<uniform, vec4<f32>>;
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty.vec4<f32>()));
+ Alias("t", ty.ptr<uniform, vec4<f32>>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -721,7 +710,7 @@
// type t = ptr<uniform, vec4<f16>>;
Enable(builtin::Extension::kF16);
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty.vec4<f16>()));
+ Alias("t", ty.ptr<uniform, f16>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -744,7 +733,7 @@
// }
// type t = ptr<uniform, array<S, 3u>>;
Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(16_a)})});
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty.array(ty("S"), 3_u)));
+ Alias("t", ty.ptr<uniform>(ty.array(ty("S"), 3_u)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -773,7 +762,7 @@
Enable(builtin::Extension::kF16);
Structure("S", utils::Vector{Member("a", ty.f16(), utils::Vector{MemberSize(16_a)})});
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty.array(ty("S"), 3_u)));
+ Alias("t", ty.ptr<uniform>(ty.array(ty("S"), 3_u)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -791,7 +780,7 @@
// struct S { x : i32 };
// type t = ptr<uniform, S>;
Structure("S", utils::Vector{Member("x", ty.i32())});
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty("S")));
+ Alias("t", ty.ptr<uniform>(ty("S")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -813,7 +802,7 @@
// type t = ptr<uniform, a1>;
Structure("S", utils::Vector{Member("x", ty.i32())});
Alias("a1", ty("S"));
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty("a1")));
+ Alias("t", ty.ptr<uniform>(ty("a1")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -837,7 +826,7 @@
Enable(builtin::Extension::kF16);
Structure("S", utils::Vector{Member("x", ty.f16())});
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty("S")));
+ Alias("t", ty.ptr<uniform>(ty("S")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -865,7 +854,7 @@
Structure("S", utils::Vector{Member("x", ty.f16())});
Alias("a1", ty("S"));
- Alias("t", ty.ptr(builtin::AddressSpace::kUniform, ty("a1")));
+ Alias("t", ty.ptr<uniform>(ty("a1")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -888,8 +877,7 @@
// enable chromium_experimental_push_constant;
// type t = ptr<push_constant, bool>;
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
- Alias(Source{{56, 78}}, "t",
- ty.ptr(builtin::AddressSpace::kPushConstant, ty.bool_(Source{{12, 34}})));
+ Alias(Source{{56, 78}}, "t", ty.ptr<push_constant>(ty.bool_(Source{{12, 34}})));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
@@ -917,7 +905,7 @@
// type t = ptr<push_constant, f16>;
Enable(builtin::Extension::kF16);
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
- Alias("t", ty.ptr(builtin::AddressSpace::kPushConstant, ty.f16(Source{{56, 78}})));
+ Alias("t", ty.ptr<push_constant>(ty.f16(Source{{56, 78}})));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -928,8 +916,7 @@
// enable chromium_experimental_push_constant;
// var<push_constant> g : ptr<private, f32>;
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
- GlobalVar(Source{{56, 78}}, "g",
- ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.f32()),
+ GlobalVar(Source{{56, 78}}, "g", ty.ptr<private_, f32>(Source{{12, 34}}),
builtin::AddressSpace::kPushConstant);
ASSERT_FALSE(r()->Resolve());
@@ -943,9 +930,7 @@
// enable chromium_experimental_push_constant;
// type t = ptr<push_constant, ptr<private, f32>>;
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
- Alias(Source{{56, 78}}, "t",
- ty.ptr(builtin::AddressSpace::kPushConstant,
- ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kPrivate, ty.f32())));
+ Alias(Source{{56, 78}}, "t", ty.ptr<push_constant>(ty.ptr<private_, f32>(Source{{12, 34}})));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
@@ -967,7 +952,7 @@
// enable chromium_experimental_push_constant;
// type t = ptr<push_constant, i32>;
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
- Alias("t", ty.ptr(builtin::AddressSpace::kPushConstant, ty.i32()));
+ Alias("t", ty.ptr<push_constant, i32>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -985,7 +970,7 @@
// enable chromium_experimental_push_constant;
// var<push_constant> g : vec4<f32>;
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
- Alias("t", ty.ptr(builtin::AddressSpace::kPushConstant, ty.vec4<f32>()));
+ Alias("t", ty.ptr<push_constant, vec4<f32>>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -1007,7 +992,7 @@
// type t = ptr<push_constant, array<S, 3u>>;
Enable(builtin::Extension::kChromiumExperimentalPushConstant);
Structure("S", utils::Vector{Member("a", ty.f32())});
- Alias("t", ty.ptr(builtin::AddressSpace::kPushConstant, ty.array(ty("S"), 3_u)));
+ Alias("t", ty.ptr<push_constant>(ty.array(ty("S"), 3_u)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
diff --git a/src/tint/resolver/alias_analysis_test.cc b/src/tint/resolver/alias_analysis_test.cc
index 7eab9bc..1145304 100644
--- a/src/tint/resolver/alias_analysis_test.cc
+++ b/src/tint/resolver/alias_analysis_test.cc
@@ -18,11 +18,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
struct ResolverAliasAnalysisTest : public resolver::TestHelper, public testing::Test {};
// Base test harness for tests that pass two pointers to a function.
@@ -726,8 +727,8 @@
Structure("S", utils::Vector{Member("a", ty.i32())});
Func("f2",
utils::Vector{
- Param("p1", ty.ptr(builtin::AddressSpace::kFunction, ty("S"))),
- Param("p2", ty.ptr(builtin::AddressSpace::kFunction, ty("S"))),
+ Param("p1", ty.ptr<function>(ty("S"))),
+ Param("p2", ty.ptr<function>(ty("S"))),
},
ty.void_(),
utils::Vector{
@@ -755,8 +756,8 @@
Structure("S", utils::Vector{Member("a", ty.i32())});
Func("f2",
utils::Vector{
- Param("p1", ty.ptr(builtin::AddressSpace::kFunction, ty("S"))),
- Param("p2", ty.ptr(builtin::AddressSpace::kFunction, ty("S"))),
+ Param("p1", ty.ptr<function>(ty("S"))),
+ Param("p2", ty.ptr<function>(ty("S"))),
},
ty.void_(),
utils::Vector{
@@ -787,8 +788,8 @@
Structure("S", utils::Vector{Member("a", ty.i32())});
Func("f2",
utils::Vector{
- Param("p1", ty.ptr(builtin::AddressSpace::kFunction, ty("S"))),
- Param("p2", ty.ptr(builtin::AddressSpace::kFunction, ty("S"))),
+ Param("p1", ty.ptr<function>(ty("S"))),
+ Param("p2", ty.ptr<function>(ty("S"))),
},
ty.void_(),
utils::Vector{
@@ -818,13 +819,13 @@
Structure("S", utils::Vector{Member("a", ty.i32())});
Func("f2",
utils::Vector{
- Param("p1", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>())),
- Param("p2", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>())),
+ Param("p1", ty.ptr<function, vec4<f32>>()),
+ Param("p2", ty.ptr<function, vec4<f32>>()),
},
ty.void_(),
utils::Vector{
Assign(Phony(), MemberAccessor(Deref("p2"), "zy")),
- Assign(Deref("p1"), Call(ty.vec4<f32>())),
+ Assign(Deref("p1"), Call<vec4<f32>>()),
});
Func("f1", utils::Empty, ty.void_(),
utils::Vector{
diff --git a/src/tint/resolver/array_accessor_test.cc b/src/tint/resolver/array_accessor_test.cc
index 118bcff..3b12afd 100644
--- a/src/tint/resolver/array_accessor_test.cc
+++ b/src/tint/resolver/array_accessor_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/sem/index_accessor_expression.h"
#include "src/tint/type/reference.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverIndexAccessorTest = ResolverTest;
TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) {
@@ -65,7 +66,7 @@
}
TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic) {
- GlobalConst("my_const", ty.mat2x3<f32>(), Call(ty.mat2x3<f32>()));
+ GlobalConst("my_const", ty.mat2x3<f32>(), Call<mat2x3<f32>>());
auto* idx = Var("idx", ty.i32(), Call<i32>());
auto* acc = IndexAccessor("my_const", Expr(Source{{12, 34}}, idx));
WrapInFunction(Decl(idx), acc);
@@ -80,7 +81,7 @@
}
TEST_F(ResolverIndexAccessorTest, Matrix_XDimension_Dynamic) {
- GlobalConst("my_const", ty.mat4x4<f32>(), Call(ty.mat4x4<f32>()));
+ GlobalConst("my_const", ty.mat4x4<f32>(), Call<mat4x4<f32>>());
auto* idx = Var("idx", ty.u32(), Expr(3_u));
auto* acc = IndexAccessor("my_const", Expr(Source{{12, 34}}, idx));
WrapInFunction(Decl(idx), acc);
@@ -90,7 +91,7 @@
}
TEST_F(ResolverIndexAccessorTest, Matrix_BothDimension_Dynamic) {
- GlobalConst("my_const", ty.mat4x4<f32>(), Call(ty.mat4x4<f32>()));
+ GlobalConst("my_const", ty.mat4x4<f32>(), Call<mat4x4<f32>>());
auto* idx = Var("idy", ty.u32(), Expr(2_u));
auto* acc = IndexAccessor(IndexAccessor("my_const", Expr(Source{{12, 34}}, idx)), 1_i);
WrapInFunction(Decl(idx), acc);
@@ -158,7 +159,7 @@
}
TEST_F(ResolverIndexAccessorTest, Vector_Dynamic) {
- GlobalConst("my_const", ty.vec3<f32>(), Call(ty.vec3<f32>()));
+ GlobalConst("my_const", ty.vec3<f32>(), Call<vec3<f32>>());
auto* idx = Var("idx", ty.i32(), Expr(2_i));
auto* acc = IndexAccessor("my_const", Expr(Source{{12, 34}}, idx));
WrapInFunction(Decl(idx), acc);
@@ -242,7 +243,7 @@
}
TEST_F(ResolverIndexAccessorTest, Array_Constant) {
- GlobalConst("my_const", ty.array<f32, 3>(), array<f32, 3>());
+ GlobalConst("my_const", ty.array<f32, 3>(), Call<array<f32, 3>>());
auto* acc = IndexAccessor("my_const", 2_i);
WrapInFunction(acc);
@@ -257,7 +258,7 @@
// let a : array<f32, 3> = 0;
// var idx : i32 = 0;
// var f : f32 = a[idx];
- auto* a = Let("a", ty.array<f32, 3>(), array<f32, 3>());
+ auto* a = Let("a", ty.array<f32, 3>(), Call<array<f32, 3>>());
auto* idx = Var("idx", ty.i32(), Call<i32>());
auto* acc = IndexAccessor("a", Expr(Source{{12, 34}}, idx));
auto* f = Var("f", ty.f32(), acc);
@@ -280,7 +281,7 @@
TEST_F(ResolverIndexAccessorTest, Array_Literal_F32) {
// let a : array<f32, 3>;
// var f : f32 = a[2.0f];
- auto* a = Let("a", ty.array<f32, 3>(), array<f32, 3>());
+ auto* a = Let("a", ty.array<f32, 3>(), Call<array<f32, 3>>());
auto* f = Var("a_2", ty.f32(), IndexAccessor("a", Expr(Source{{12, 34}}, 2_f)));
Func("my_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -294,7 +295,7 @@
TEST_F(ResolverIndexAccessorTest, Array_Literal_I32) {
// let a : array<f32, 3>;
// var f : f32 = a[2i];
- auto* a = Let("a", ty.array<f32, 3>(), array<f32, 3>());
+ auto* a = Let("a", ty.array<f32, 3>(), Call<array<f32, 3>>());
auto* acc = IndexAccessor("a", 2_i);
auto* f = Var("a_2", ty.f32(), acc);
Func("my_func", utils::Empty, ty.void_(),
@@ -316,7 +317,7 @@
// let x: f32 = (*p)[idx];
// return x;
// }
- auto* p = Param("p", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>()));
+ auto* p = Param("p", ty.ptr<function, vec4<f32>>());
auto* idx = Let("idx", ty.u32(), Call<u32>());
auto* star_p = Deref(p);
auto* acc = IndexAccessor(Source{{12, 34}}, star_p, idx);
@@ -337,7 +338,7 @@
// let x: f32 = *p[idx];
// return x;
// }
- auto* p = Param("p", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>()));
+ auto* p = Param("p", ty.ptr<function, vec4<f32>>());
auto* idx = Let("idx", ty.u32(), Call<u32>());
auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
auto* star_p = Deref(accessor_expr);
diff --git a/src/tint/resolver/assignment_validation_test.cc b/src/tint/resolver/assignment_validation_test.cc
index bd4cd71..f1251cb 100644
--- a/src/tint/resolver/assignment_validation_test.cc
+++ b/src/tint/resolver/assignment_validation_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/type/storage_texture.h"
#include "src/tint/type/texture_dimension.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverAssignmentValidationTest = ResolverTest;
TEST_F(ResolverAssignmentValidationTest, ReadOnlyBuffer) {
@@ -182,9 +183,8 @@
// var a : i32;
// let b : ptr<function,i32> = &a;
// *b = 2i;
- const auto func = builtin::AddressSpace::kFunction;
- WrapInFunction(Var("a", ty.i32(), func, Expr(2_i)), //
- Let("b", ty.ptr<i32>(func), AddressOf(Expr("a"))), //
+ WrapInFunction(Var("a", ty.i32(), builtin::AddressSpace::kFunction, Expr(2_i)), //
+ Let("b", ty.ptr<function, i32>(), AddressOf(Expr("a"))), //
Assign(Deref("b"), 2_i));
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -194,9 +194,8 @@
// var a : i32;
// let b : ptr<function,i32> = &a;
// *b = 2;
- const auto func = builtin::AddressSpace::kFunction;
- auto* var_a = Var("a", ty.i32(), func, Expr(2_i));
- auto* var_b = Let("b", ty.ptr<i32>(func), AddressOf(Expr("a")));
+ auto* var_a = Var("a", ty.i32(), builtin::AddressSpace::kFunction, Expr(2_i));
+ auto* var_b = Let("b", ty.ptr<function, i32>(), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b, Assign(Deref("b"), 2_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -433,9 +432,9 @@
Assign(Phony(), 3_f), //
Assign(Phony(), 4_a), //
Assign(Phony(), 5.0_a), //
- Assign(Phony(), vec2<Infer>(6_a)), //
- Assign(Phony(), vec3<Infer>(7.0_a)), //
- Assign(Phony(), vec4<bool>()), //
+ Assign(Phony(), Call<vec2<Infer>>(6_a)), //
+ Assign(Phony(), Call<vec3<Infer>>(7.0_a)), //
+ Assign(Phony(), Call<vec4<bool>>()), //
Assign(Phony(), "tex"), //
Assign(Phony(), "smp"), //
Assign(Phony(), AddressOf("s")), //
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 97af866..5997b71 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -22,25 +22,14 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
// Helpers and typedefs
template <typename T>
using DataType = builder::DataType<T>;
-template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-template <typename T>
-using mat2x2 = builder::mat2x2<T>;
-template <typename T>
-using mat3x3 = builder::mat3x3<T>;
-template <typename T>
-using mat4x4 = builder::mat4x4<T>;
template <typename T, int ID = 0>
using alias = builder::alias<T, ID>;
template <typename T>
@@ -353,7 +342,7 @@
auto* p = Param("a", ty.vec4<f32>(), attrs);
Func("vertex_main", utils::Vector{p}, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
@@ -404,7 +393,7 @@
auto& params = GetParam();
Func("main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>(), 1_f)),
+ Return(Call<vec4<f32>>(1_f)),
},
utils::Vector{
Stage(ast::PipelineStage::kCompute),
@@ -456,7 +445,7 @@
auto& params = GetParam();
auto attrs = createAttributes(Source{{12, 34}}, *this, params.kind);
attrs.Push(Location(Source{{34, 56}}, 2_a));
- Func("frag_main", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(Call(ty.vec4<f32>()))},
+ Func("frag_main", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(Call<vec4<f32>>())},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
},
@@ -513,7 +502,7 @@
}
Func("vertex_main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
@@ -1602,8 +1591,10 @@
Func("F", utils::Empty, ty.void_(),
utils::Vector{
- Decl(Var("a", ty.vec4<f32>(), Call("textureLoad", "A", vec2<i32>(1_i, 2_i), 0_i))),
- Decl(Var("b", ty.vec4<f32>(), Call("textureLoad", "B", vec2<i32>(1_i, 2_i), 0_i))),
+ Decl(Var("a", ty.vec4<f32>(),
+ Call("textureLoad", "A", Call<vec2<i32>>(1_i, 2_i), 0_i))),
+ Decl(Var("b", ty.vec4<f32>(),
+ Call("textureLoad", "B", Call<vec2<i32>>(1_i, 2_i), 0_i))),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -1624,14 +1615,16 @@
Func("F_A", utils::Empty, ty.void_(),
utils::Vector{
- Decl(Var("a", ty.vec4<f32>(), Call("textureLoad", "A", vec2<i32>(1_i, 2_i), 0_i))),
+ Decl(Var("a", ty.vec4<f32>(),
+ Call("textureLoad", "A", Call<vec2<i32>>(1_i, 2_i), 0_i))),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
});
Func("F_B", utils::Empty, ty.void_(),
utils::Vector{
- Decl(Var("b", ty.vec4<f32>(), Call("textureLoad", "B", vec2<i32>(1_i, 2_i), 0_i))),
+ Decl(Var("b", ty.vec4<f32>(),
+ Call("textureLoad", "B", Call<vec2<i32>>(1_i, 2_i), 0_i))),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -1663,7 +1656,7 @@
});
Func("main", utils::Vector{param}, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -1682,7 +1675,7 @@
});
Func("main", utils::Vector{param}, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -1705,7 +1698,7 @@
TEST_F(MustUseAttributeTests, MustUse) {
Func("main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
MustUse(Source{{12, 34}}),
@@ -1964,7 +1957,7 @@
TEST_F(InterpolateTest, MissingLocationAttribute_ReturnType) {
Func("main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
diff --git a/src/tint/resolver/bitcast_validation_test.cc b/src/tint/resolver/bitcast_validation_test.cc
index fb0b960..c979c55 100644
--- a/src/tint/resolver/bitcast_validation_test.cc
+++ b/src/tint/resolver/bitcast_validation_test.cc
@@ -21,6 +21,8 @@
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+
struct Type {
template <typename T>
static constexpr Type Create() {
@@ -39,36 +41,36 @@
Type::Create<u32>(),
};
static constexpr Type kVec2NumericScalars[] = {
- Type::Create<builder::vec2<f32>>(),
- Type::Create<builder::vec2<i32>>(),
- Type::Create<builder::vec2<u32>>(),
+ Type::Create<vec2<f32>>(),
+ Type::Create<vec2<i32>>(),
+ Type::Create<vec2<u32>>(),
};
static constexpr Type kVec3NumericScalars[] = {
- Type::Create<builder::vec3<f32>>(),
- Type::Create<builder::vec3<i32>>(),
- Type::Create<builder::vec3<u32>>(),
+ Type::Create<vec3<f32>>(),
+ Type::Create<vec3<i32>>(),
+ Type::Create<vec3<u32>>(),
};
static constexpr Type kVec4NumericScalars[] = {
- Type::Create<builder::vec4<f32>>(),
- Type::Create<builder::vec4<i32>>(),
- Type::Create<builder::vec4<u32>>(),
+ Type::Create<vec4<f32>>(),
+ Type::Create<vec4<i32>>(),
+ Type::Create<vec4<u32>>(),
};
static constexpr Type kInvalid[] = {
// A non-exhaustive selection of uncastable types
Type::Create<bool>(),
- Type::Create<builder::vec2<bool>>(),
- Type::Create<builder::vec3<bool>>(),
- Type::Create<builder::vec4<bool>>(),
- Type::Create<builder::array<2, i32>>(),
- Type::Create<builder::array<3, u32>>(),
- Type::Create<builder::array<4, f32>>(),
- Type::Create<builder::array<5, bool>>(),
- Type::Create<builder::mat2x2<f32>>(),
- Type::Create<builder::mat3x3<f32>>(),
- Type::Create<builder::mat4x4<f32>>(),
- Type::Create<builder::ptr<i32>>(),
- Type::Create<builder::ptr<builder::array<2, i32>>>(),
- Type::Create<builder::ptr<builder::mat2x2<f32>>>(),
+ Type::Create<vec2<bool>>(),
+ Type::Create<vec3<bool>>(),
+ Type::Create<vec4<bool>>(),
+ Type::Create<array<i32, 2>>(),
+ Type::Create<array<u32, 3>>(),
+ Type::Create<array<f32, 4>>(),
+ Type::Create<array<bool, 5>>(),
+ Type::Create<mat2x2<f32>>(),
+ Type::Create<mat3x3<f32>>(),
+ Type::Create<mat4x4<f32>>(),
+ Type::Create<ptr<private_, i32>>(),
+ Type::Create<ptr<private_, array<i32, 2>>>(),
+ Type::Create<ptr<private_, mat2x2<f32>>>(),
};
using ResolverBitcastValidationTest = ResolverTestWithParam<std::tuple<Type, Type>>;
diff --git a/src/tint/resolver/builtin_test.cc b/src/tint/resolver/builtin_test.cc
index 5a23354..07abb21 100644
--- a/src/tint/resolver/builtin_test.cc
+++ b/src/tint/resolver/builtin_test.cc
@@ -43,11 +43,12 @@
using ::testing::ElementsAre;
using ::testing::HasSubstr;
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ExpressionList = utils::Vector<const ast::Expression*, 8>;
using ResolverBuiltinTest = ResolverTest;
@@ -156,8 +157,9 @@
}
TEST_F(ResolverBuiltinTest, Select_Error_Matrix) {
- auto* expr = Call("select", mat2x2<f32>(vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f)),
- mat2x2<f32>(vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f)), Expr(true));
+ auto* expr =
+ Call("select", Call<mat2x2<f32>>(Call<vec2<f32>>(1_f, 1_f), Call<vec2<f32>>(1_f, 1_f)),
+ Call<mat2x2<f32>>(Call<vec2<f32>>(1_f, 1_f), Call<vec2<f32>>(1_f, 1_f)), Expr(true));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve());
@@ -173,7 +175,7 @@
}
TEST_F(ResolverBuiltinTest, Select_Error_MismatchTypes) {
- auto* expr = Call("select", 1_f, vec2<f32>(2_f, 3_f), Expr(true));
+ auto* expr = Call("select", 1_f, Call<vec2<f32>>(2_f, 3_f), Expr(true));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve());
@@ -189,7 +191,7 @@
}
TEST_F(ResolverBuiltinTest, Select_Error_MismatchVectorSize) {
- auto* expr = Call("select", vec2<f32>(1_f, 2_f), vec3<f32>(3_f, 4_f, 5_f), Expr(true));
+ auto* expr = Call("select", Call<vec2<f32>>(1_f, 2_f), Call<vec3<f32>>(3_f, 4_f, 5_f), true);
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve());
@@ -304,8 +306,8 @@
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, OneParam_Vector_f32) {
auto param = GetParam();
- auto val = param.name == std::string("acosh") ? vec3<f32>(1.0_f, 2.0_f, 3.0_f)
- : vec3<f32>(0.5_f, 0.5_f, 0.8_f);
+ auto val = param.name == std::string("acosh") ? Call<vec3<f32>>(1.0_f, 2.0_f, 3.0_f)
+ : Call<vec3<f32>>(0.5_f, 0.5_f, 0.8_f);
auto* call = Call(param.name, val);
WrapInFunction(call);
@@ -352,7 +354,7 @@
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, TwoParams_Vector_f32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call(param.name, Call<vec3<f32>>(1_f, 1_f, 3_f), Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
if (param.args_number == 2u) {
@@ -397,8 +399,8 @@
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Vector_f32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<f32>(0_f, 0_f, 0_f), vec3<f32>(1_f, 1_f, 1_f),
- vec3<f32>(2_f, 2_f, 2_f));
+ auto* call = Call(param.name, Call<vec3<f32>>(0_f, 0_f, 0_f), Call<vec3<f32>>(1_f, 1_f, 1_f),
+ Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(call);
if (param.args_number == 3u) {
@@ -444,8 +446,8 @@
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, FourParams_Vector_f32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f),
- vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call(param.name, Call<vec3<f32>>(1_f, 1_f, 3_f), Call<vec3<f32>>(1_f, 1_f, 3_f),
+ Call<vec3<f32>>(1_f, 1_f, 3_f), Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
if (param.args_number == 4u) {
@@ -500,8 +502,8 @@
Enable(builtin::Extension::kF16);
- auto val = param.name == std::string("acosh") ? vec3<f16>(1.0_h, 2.0_h, 3.0_h)
- : vec3<f16>(0.5_h, 0.5_h, 0.8_h);
+ auto val = param.name == std::string("acosh") ? Call<vec3<f16>>(1.0_h, 2.0_h, 3.0_h)
+ : Call<vec3<f16>>(0.5_h, 0.5_h, 0.8_h);
auto* call = Call(param.name, val);
WrapInFunction(call);
@@ -552,7 +554,7 @@
Enable(builtin::Extension::kF16);
- auto* call = Call(param.name, vec3<f16>(1_h, 1_h, 3_h), vec3<f16>(1_h, 1_h, 3_h));
+ auto* call = Call(param.name, Call<vec3<f16>>(1_h, 1_h, 3_h), Call<vec3<f16>>(1_h, 1_h, 3_h));
WrapInFunction(call);
if (param.args_number == 2u) {
@@ -601,8 +603,8 @@
Enable(builtin::Extension::kF16);
- auto* call = Call(param.name, vec3<f16>(0_h, 0_h, 0_h), vec3<f16>(1_h, 1_h, 1_h),
- vec3<f16>(2_h, 2_h, 2_h));
+ auto* call = Call(param.name, Call<vec3<f16>>(0_h, 0_h, 0_h), Call<vec3<f16>>(1_h, 1_h, 1_h),
+ Call<vec3<f16>>(2_h, 2_h, 2_h));
WrapInFunction(call);
if (param.args_number == 3u) {
@@ -652,8 +654,8 @@
Enable(builtin::Extension::kF16);
- auto* call = Call(param.name, vec3<f16>(1_h, 1_h, 3_h), vec3<f16>(1_h, 1_h, 3_h),
- vec3<f16>(1_h, 1_h, 3_h), vec3<f16>(1_h, 1_h, 3_h));
+ auto* call = Call(param.name, Call<vec3<f16>>(1_h, 1_h, 3_h), Call<vec3<f16>>(1_h, 1_h, 3_h),
+ Call<vec3<f16>>(1_h, 1_h, 3_h), Call<vec3<f16>>(1_h, 1_h, 3_h));
WrapInFunction(call);
if (param.args_number == 4u) {
@@ -732,7 +734,7 @@
// cross: (vec3<T>, vec3<T>) -> vec3<T>
TEST_F(ResolverBuiltinFloatTest, Cross_f32) {
- auto* call = Call("cross", vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(1_f, 2_f, 3_f));
+ auto* call = Call("cross", Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(1_f, 2_f, 3_f));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -746,7 +748,7 @@
TEST_F(ResolverBuiltinFloatTest, Cross_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("cross", vec3<f16>(1_h, 2_h, 3_h), vec3<f16>(1_h, 2_h, 3_h));
+ auto* call = Call("cross", Call<vec3<f16>>(1_h, 2_h, 3_h), Call<vec3<f16>>(1_h, 2_h, 3_h));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -784,7 +786,7 @@
}
TEST_F(ResolverBuiltinFloatTest, Cross_Error_Vec3Int) {
- auto* call = Call("cross", vec3<i32>(1_i, 2_i, 3_i), vec3<i32>(1_i, 2_i, 3_i));
+ auto* call = Call("cross", Call<vec3<i32>>(1_i, 2_i, 3_i), Call<vec3<i32>>(1_i, 2_i, 3_i));
WrapInFunction(call);
EXPECT_FALSE(r()->Resolve());
@@ -798,7 +800,8 @@
}
TEST_F(ResolverBuiltinFloatTest, Cross_Error_Vec4) {
- auto* call = Call("cross", vec4<f32>(1_f, 2_f, 3_f, 4_f), vec4<f32>(1_f, 2_f, 3_f, 4_f));
+ auto* call =
+ Call("cross", Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f), Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f));
WrapInFunction(call);
@@ -813,8 +816,8 @@
}
TEST_F(ResolverBuiltinFloatTest, Cross_Error_TooManyParams) {
- auto* call =
- Call("cross", vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(1_f, 2_f, 3_f));
+ auto* call = Call("cross", Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(1_f, 2_f, 3_f));
WrapInFunction(call);
@@ -852,7 +855,7 @@
}
TEST_F(ResolverBuiltinFloatTest, Distance_Vector_f32) {
- auto* call = Call("distance", vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call("distance", Call<vec3<f32>>(1_f, 1_f, 3_f), Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -864,7 +867,7 @@
TEST_F(ResolverBuiltinFloatTest, Distance_Vector_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("distance", vec3<f16>(1_h, 1_h, 3_h), vec3<f16>(1_h, 1_h, 3_h));
+ auto* call = Call("distance", Call<vec3<f16>>(1_h, 1_h, 3_h), Call<vec3<f16>>(1_h, 1_h, 3_h));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -874,8 +877,8 @@
}
TEST_F(ResolverBuiltinFloatTest, Distance_TooManyParams) {
- auto* call = Call("distance", vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f),
- vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call("distance", Call<vec3<f32>>(1_f, 1_f, 3_f), Call<vec3<f32>>(1_f, 1_f, 3_f),
+ Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
EXPECT_FALSE(r()->Resolve());
@@ -889,7 +892,7 @@
}
TEST_F(ResolverBuiltinFloatTest, Distance_TooFewParams) {
- auto* call = Call("distance", vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call("distance", Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
EXPECT_FALSE(r()->Resolve());
@@ -979,7 +982,7 @@
}
TEST_F(ResolverBuiltinFloatTest, FrexpVector_f32) {
- auto* call = Call("frexp", vec3<f32>());
+ auto* call = Call("frexp", Call<vec3<f32>>());
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1014,7 +1017,7 @@
TEST_F(ResolverBuiltinFloatTest, FrexpVector_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("frexp", vec3<f16>());
+ auto* call = Call("frexp", Call<vec3<f16>>());
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1086,7 +1089,7 @@
}
TEST_F(ResolverBuiltinFloatTest, Length_FloatVector_f32) {
- auto* call = Call("length", vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call("length", Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1098,7 +1101,7 @@
TEST_F(ResolverBuiltinFloatTest, Length_FloatVector_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("length", vec3<f16>(1_h, 1_h, 3_h));
+ auto* call = Call("length", Call<vec3<f16>>(1_h, 1_h, 3_h));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1138,7 +1141,7 @@
// mix(vecN<T>, vecN<T>, T) -> vecN<T>. Other overloads are tested in
// ResolverBuiltinTest_FloatBuiltin_IdenticalType above.
TEST_F(ResolverBuiltinFloatTest, Mix_VectorScalar_f32) {
- auto* call = Call("mix", vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f), 4_f);
+ auto* call = Call("mix", Call<vec3<f32>>(1_f, 1_f, 3_f), Call<vec3<f32>>(1_f, 1_f, 3_f), 4_f);
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1153,7 +1156,7 @@
TEST_F(ResolverBuiltinFloatTest, Mix_VectorScalar_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("mix", vec3<f16>(1_h, 1_h, 1_h), vec3<f16>(1_h, 1_h, 1_h), 4_h);
+ auto* call = Call("mix", Call<vec3<f16>>(1_h, 1_h, 1_h), Call<vec3<f16>>(1_h, 1_h, 1_h), 4_h);
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1228,7 +1231,7 @@
}
TEST_F(ResolverBuiltinFloatTest, ModfVector_f32) {
- auto* call = Call("modf", vec3<f32>());
+ auto* call = Call("modf", Call<vec3<f32>>());
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1263,7 +1266,7 @@
TEST_F(ResolverBuiltinFloatTest, ModfVector_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("modf", vec3<f16>());
+ auto* call = Call("modf", Call<vec3<f16>>());
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1343,7 +1346,7 @@
TEST_F(ResolverBuiltinFloatTest, Modf_Error_VectorSizesDontMatch) {
GlobalVar("whole", ty.vec4<f32>(), builtin::AddressSpace::kWorkgroup);
- auto* call = Call("modf", vec2<f32>(1_f, 2_f), AddressOf("whole"));
+ auto* call = Call("modf", Call<vec2<f32>>(1_f, 2_f), AddressOf("whole"));
WrapInFunction(call);
EXPECT_FALSE(r()->Resolve());
@@ -1359,7 +1362,7 @@
// normalize: (vecN<T>) -> vecN<T>
TEST_F(ResolverBuiltinFloatTest, Normalize_Vector_f32) {
- auto* call = Call("normalize", vec3<f32>(1_f, 1_f, 3_f));
+ auto* call = Call("normalize", Call<vec3<f32>>(1_f, 1_f, 3_f));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1373,7 +1376,7 @@
TEST_F(ResolverBuiltinFloatTest, Normalize_Vector_f16) {
Enable(builtin::Extension::kF16);
- auto* call = Call("normalize", vec3<f16>(1_h, 1_h, 3_h));
+ auto* call = Call("normalize", Call<vec3<f16>>(1_h, 1_h, 3_h));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1455,7 +1458,7 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, OneParams_Vector_i32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<i32>(1_i, 1_i, 3_i));
+ auto* call = Call(param.name, Call<vec3<i32>>(1_i, 1_i, 3_i));
WrapInFunction(call);
if (param.args_number == 1u) {
@@ -1500,7 +1503,7 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, OneParams_Vector_u32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<u32>(1_u, 1_u, 3_u));
+ auto* call = Call(param.name, Call<vec3<u32>>(1_u, 1_u, 3_u));
WrapInFunction(call);
if (param.args_number == 1u) {
@@ -1545,7 +1548,7 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, TwoParams_Vector_i32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<i32>(1_i, 1_i, 3_i), vec3<i32>(1_i, 1_i, 3_i));
+ auto* call = Call(param.name, Call<vec3<i32>>(1_i, 1_i, 3_i), Call<vec3<i32>>(1_i, 1_i, 3_i));
WrapInFunction(call);
if (param.args_number == 2u) {
@@ -1590,7 +1593,7 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, TwoParams_Vector_u32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<u32>(1_u, 1_u, 3_u), vec3<u32>(1_u, 1_u, 3_u));
+ auto* call = Call(param.name, Call<vec3<u32>>(1_u, 1_u, 3_u), Call<vec3<u32>>(1_u, 1_u, 3_u));
WrapInFunction(call);
if (param.args_number == 2u) {
@@ -1635,8 +1638,8 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, ThreeParams_Vector_i32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<i32>(1_i, 1_i, 3_i), vec3<i32>(1_i, 1_i, 3_i),
- vec3<i32>(1_i, 1_i, 3_i));
+ auto* call = Call(param.name, Call<vec3<i32>>(1_i, 1_i, 3_i), Call<vec3<i32>>(1_i, 1_i, 3_i),
+ Call<vec3<i32>>(1_i, 1_i, 3_i));
WrapInFunction(call);
if (param.args_number == 3u) {
@@ -1682,8 +1685,8 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, ThreeParams_Vector_u32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<u32>(1_u, 1_u, 3_u), vec3<u32>(1_u, 1_u, 3_u),
- vec3<u32>(1_u, 1_u, 3_u));
+ auto* call = Call(param.name, Call<vec3<u32>>(1_u, 1_u, 3_u), Call<vec3<u32>>(1_u, 1_u, 3_u),
+ Call<vec3<u32>>(1_u, 1_u, 3_u));
WrapInFunction(call);
if (param.args_number == 3u) {
@@ -1729,8 +1732,8 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, FourParams_Vector_i32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<i32>(1_i, 1_i, 3_i), vec3<i32>(1_i, 1_i, 3_i),
- vec3<i32>(1_i, 1_i, 3_i), vec3<i32>(1_i, 1_i, 3_i));
+ auto* call = Call(param.name, Call<vec3<i32>>(1_i, 1_i, 3_i), Call<vec3<i32>>(1_i, 1_i, 3_i),
+ Call<vec3<i32>>(1_i, 1_i, 3_i), Call<vec3<i32>>(1_i, 1_i, 3_i));
WrapInFunction(call);
if (param.args_number == 4u) {
@@ -1776,8 +1779,8 @@
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, FourParams_Vector_u32) {
auto param = GetParam();
- auto* call = Call(param.name, vec3<u32>(1_u, 1_u, 3_u), vec3<u32>(1_u, 1_u, 3_u),
- vec3<u32>(1_u, 1_u, 3_u), vec3<u32>(1_u, 1_u, 3_u));
+ auto* call = Call(param.name, Call<vec3<u32>>(1_u, 1_u, 3_u), Call<vec3<u32>>(1_u, 1_u, 3_u),
+ Call<vec3<u32>>(1_u, 1_u, 3_u), Call<vec3<u32>>(1_u, 1_u, 3_u));
WrapInFunction(call);
if (param.args_number == 4u) {
@@ -2188,10 +2191,9 @@
ResolverBuiltinTest_Texture,
testing::ValuesIn(ast::test::TextureOverloadCase::ValidCases()));
-static std::string to_str(const std::string& function,
- utils::VectorRef<const sem::Parameter*> params) {
+static std::string to_str(const std::string& func, utils::VectorRef<const sem::Parameter*> params) {
utils::StringStream out;
- out << function << "(";
+ out << func << "(";
bool first = true;
for (auto* param : params) {
if (!first) {
@@ -2556,8 +2558,8 @@
bool pack4 = param.builtin == builtin::Function::kPack4X8Snorm ||
param.builtin == builtin::Function::kPack4X8Unorm;
- auto* call = pack4 ? Call(param.name, vec4<f32>(1_f, 2_f, 3_f, 4_f))
- : Call(param.name, vec2<f32>(1_f, 2_f));
+ auto* call = pack4 ? Call(param.name, Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))
+ : Call(param.name, Call<vec2<f32>>(1_f, 2_f));
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2571,8 +2573,8 @@
bool pack4 = param.builtin == builtin::Function::kPack4X8Snorm ||
param.builtin == builtin::Function::kPack4X8Unorm;
- auto* call = pack4 ? Call(param.name, vec4<i32>(1_i, 2_i, 3_i, 4_i))
- : Call(param.name, vec2<i32>(1_i, 2_i));
+ auto* call = pack4 ? Call(param.name, Call<vec4<i32>>(1_i, 2_i, 3_i, 4_i))
+ : Call(param.name, Call<vec2<i32>>(1_i, 2_i));
WrapInFunction(call);
EXPECT_FALSE(r()->Resolve());
@@ -2597,8 +2599,8 @@
bool pack4 = param.builtin == builtin::Function::kPack4X8Snorm ||
param.builtin == builtin::Function::kPack4X8Unorm;
- auto* call = pack4 ? Call(param.name, vec4<f32>(1_f, 2_f, 3_f, 4_f), 1_f)
- : Call(param.name, vec2<f32>(1_f, 2_f), 1_f);
+ auto* call = pack4 ? Call(param.name, Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f), 1_f)
+ : Call(param.name, Call<vec2<f32>>(1_f, 2_f), 1_f);
WrapInFunction(call);
EXPECT_FALSE(r()->Resolve());
@@ -2669,7 +2671,7 @@
TEST_P(ResolverBuiltinTest_Barrier, Error_TooManyParams) {
auto param = GetParam();
- auto* call = Call(param.name, vec4<f32>(1_f, 2_f, 3_f, 4_f), 1_f);
+ auto* call = Call(param.name, Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f), 1_f);
WrapInFunction(CallStmt(call));
EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/builtin_validation_test.cc b/src/tint/resolver/builtin_validation_test.cc
index fbe5a5f..3996aa9 100644
--- a/src/tint/resolver/builtin_validation_test.cc
+++ b/src/tint/resolver/builtin_validation_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/sem/value_constructor.h"
#include "src/tint/utils/string_stream.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverBuiltinValidationTest = ResolverTest;
TEST_F(ResolverBuiltinValidationTest, FunctionTypeMustMatchReturnStatementType_void_fail) {
@@ -250,10 +251,10 @@
i32(values[2]));
case Kind::kVec3_Scalar_Vec2:
return b.Call(src, b.ty.vec3<i32>(), i32(values[0]),
- b.vec2<i32>(i32(values[1]), i32(values[2])));
+ b.Call<vec2<i32>>(i32(values[1]), i32(values[2])));
case Kind::kVec3_Vec2_Scalar:
- return b.Call(src, b.ty.vec3<i32>(), b.vec2<i32>(i32(values[0]), i32(values[1])),
- i32(values[2]));
+ return b.Call(src, b.ty.vec3<i32>(),
+ b.Call<vec2<i32>>(i32(values[0]), i32(values[1])), i32(values[2]));
case Kind::kEmptyVec2:
return b.Call(src, b.ty.vec2<i32>());
case Kind::kEmptyVec3:
diff --git a/src/tint/resolver/builtins_validation_test.cc b/src/tint/resolver/builtins_validation_test.cc
index d5f8c4f..a1cc2e2 100644
--- a/src/tint/resolver/builtins_validation_test.cc
+++ b/src/tint/resolver/builtins_validation_test.cc
@@ -17,20 +17,14 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/utils/string_stream.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
template <typename T>
using DataType = builder::DataType<T>;
-template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-
class ResolverBuiltinsValidationTest : public resolver::TestHelper, public testing::Test {};
namespace StageTest {
struct Params {
@@ -870,21 +864,21 @@
}
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec2) {
- auto* builtin = Call("length", vec2<f32>(1_f, 1_f));
+ auto* builtin = Call("length", Call<vec2<f32>>(1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec3) {
- auto* builtin = Call("length", vec3<f32>(1_f, 1_f, 1_f));
+ auto* builtin = Call("length", Call<vec3<f32>>(1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec4) {
- auto* builtin = Call("length", vec4<f32>(1_f, 1_f, 1_f, 1_f));
+ auto* builtin = Call("length", Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -898,46 +892,50 @@
}
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec2) {
- auto* builtin = Call("distance", vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f));
+ auto* builtin = Call("distance", Call<vec2<f32>>(1_f, 1_f), Call<vec2<f32>>(1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec3) {
- auto* builtin = Call("distance", vec3<f32>(1_f, 1_f, 1_f), vec3<f32>(1_f, 1_f, 1_f));
+ auto* builtin =
+ Call("distance", Call<vec3<f32>>(1_f, 1_f, 1_f), Call<vec3<f32>>(1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec4) {
- auto* builtin = Call("distance", vec4<f32>(1_f, 1_f, 1_f, 1_f), vec4<f32>(1_f, 1_f, 1_f, 1_f));
+ auto* builtin =
+ Call("distance", Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f), Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat2x2) {
- auto* builtin = Call("determinant", mat2x2<f32>(vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f)));
+ auto* builtin = Call("determinant",
+ Call<mat2x2<f32>>(Call<vec2<f32>>(1_f, 1_f), Call<vec2<f32>>(1_f, 1_f)));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat3x3) {
- auto* builtin = Call(
- "determinant",
- mat3x3<f32>(vec3<f32>(1_f, 1_f, 1_f), vec3<f32>(1_f, 1_f, 1_f), vec3<f32>(1_f, 1_f, 1_f)));
+ auto* builtin = Call("determinant", Call<mat3x3<f32>>(Call<vec3<f32>>(1_f, 1_f, 1_f),
+ Call<vec3<f32>>(1_f, 1_f, 1_f),
+ Call<vec3<f32>>(1_f, 1_f, 1_f)));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat4x4) {
- auto* builtin = Call("determinant",
- mat4x4<f32>(vec4<f32>(1_f, 1_f, 1_f, 1_f), vec4<f32>(1_f, 1_f, 1_f, 1_f),
- vec4<f32>(1_f, 1_f, 1_f, 1_f), vec4<f32>(1_f, 1_f, 1_f, 1_f)));
+ auto* builtin = Call("determinant", Call<mat4x4<f32>>(Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f),
+ Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f),
+ Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f),
+ Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f)));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -957,7 +955,7 @@
}
TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec2) {
- auto* builtin = Call("frexp", vec2<f32>(1_f, 1_f));
+ auto* builtin = Call("frexp", Call<vec2<f32>>(1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -974,7 +972,7 @@
}
TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec3) {
- auto* builtin = Call("frexp", vec3<f32>(1_f, 1_f, 1_f));
+ auto* builtin = Call("frexp", Call<vec3<f32>>(1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -991,7 +989,7 @@
}
TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec4) {
- auto* builtin = Call("frexp", vec4<f32>(1_f, 1_f, 1_f, 1_f));
+ auto* builtin = Call("frexp", Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1021,7 +1019,7 @@
}
TEST_F(ResolverBuiltinsValidationTest, Modf_Vec2) {
- auto* builtin = Call("modf", vec2<f32>(1_f, 1_f));
+ auto* builtin = Call("modf", Call<vec2<f32>>(1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1038,7 +1036,7 @@
}
TEST_F(ResolverBuiltinsValidationTest, Modf_Vec3) {
- auto* builtin = Call("modf", vec3<f32>(1_f, 1_f, 1_f));
+ auto* builtin = Call("modf", Call<vec3<f32>>(1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1055,7 +1053,7 @@
}
TEST_F(ResolverBuiltinsValidationTest, Modf_Vec4) {
- auto* builtin = Call("modf", vec4<f32>(1_f, 1_f, 1_f, 1_f));
+ auto* builtin = Call("modf", Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1072,28 +1070,29 @@
}
TEST_F(ResolverBuiltinsValidationTest, Cross_Float_Vec3) {
- auto* builtin = Call("cross", vec3<f32>(1_f, 1_f, 1_f), vec3<f32>(1_f, 1_f, 1_f));
+ auto* builtin = Call("cross", Call<vec3<f32>>(1_f, 1_f, 1_f), Call<vec3<f32>>(1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec2) {
- auto* builtin = Call("dot", vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f));
+ auto* builtin = Call("dot", Call<vec2<f32>>(1_f, 1_f), Call<vec2<f32>>(1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec3) {
- auto* builtin = Call("dot", vec3<f32>(1_f, 1_f, 1_f), vec3<f32>(1_f, 1_f, 1_f));
+ auto* builtin = Call("dot", Call<vec3<f32>>(1_f, 1_f, 1_f), Call<vec3<f32>>(1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec4) {
- auto* builtin = Call("dot", vec4<f32>(1_f, 1_f, 1_f, 1_f), vec4<f32>(1_f, 1_f, 1_f, 1_f));
+ auto* builtin =
+ Call("dot", Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f), Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1121,24 +1120,24 @@
}
TEST_F(ResolverBuiltinsValidationTest, Select_Float_Vec2) {
- auto* builtin =
- Call("select", vec2<f32>(1_f, 1_f), vec2<f32>(1_f, 1_f), vec2<bool>(true, true));
+ auto* builtin = Call("select", Call<vec2<f32>>(1_f, 1_f), Call<vec2<f32>>(1_f, 1_f),
+ Call<vec2<bool>>(true, true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Integer_Vec2) {
- auto* builtin =
- Call("select", vec2<i32>(1_i, 1_i), vec2<i32>(1_i, 1_i), vec2<bool>(true, true));
+ auto* builtin = Call("select", Call<vec2<i32>>(1_i, 1_i), Call<vec2<i32>>(1_i, 1_i),
+ Call<vec2<bool>>(true, true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Boolean_Vec2) {
- auto* builtin =
- Call("select", vec2<bool>(true, true), vec2<bool>(true, true), vec2<bool>(true, true));
+ auto* builtin = Call("select", Call<vec2<bool>>(true, true), Call<vec2<bool>>(true, true),
+ Call<vec2<bool>>(true, true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1178,7 +1177,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec2<f32>(f32(i + 1), f32(i + 1)));
+ params.Push(Call<vec2<f32>>(f32(i + 1), f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
@@ -1199,7 +1198,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec3<f32>(f32(i + 1), f32(i + 1), f32(i + 1)));
+ params.Push(Call<vec3<f32>>(f32(i + 1), f32(i + 1), f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
@@ -1220,7 +1219,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec4<f32>(f32(i + 1), f32(i + 1), f32(i + 1), f32(i + 1)));
+ params.Push(Call<vec4<f32>>(f32(i + 1), f32(i + 1), f32(i + 1), f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
@@ -1302,7 +1301,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec2<u32>(1_u, 1_u));
+ params.Push(Call<vec2<u32>>(1_u, 1_u));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1317,7 +1316,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec3<u32>(1_u, 1_u, 1_u));
+ params.Push(Call<vec3<u32>>(1_u, 1_u, 1_u));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1332,7 +1331,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec4<u32>(1_u, 1_u, 1_u, 1_u));
+ params.Push(Call<vec4<u32>>(1_u, 1_u, 1_u, 1_u));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1362,7 +1361,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec2<i32>(1_i, 1_i));
+ params.Push(Call<vec2<i32>>(1_i, 1_i));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1377,7 +1376,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec3<i32>(1_i, 1_i, 1_i));
+ params.Push(Call<vec3<i32>>(1_i, 1_i, 1_i));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1392,7 +1391,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec4<i32>(1_i, 1_i, 1_i, 1_i));
+ params.Push(Call<vec4<i32>>(1_i, 1_i, 1_i, 1_i));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1419,7 +1418,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec2<bool>(true, true));
+ params.Push(Call<vec2<bool>>(true, true));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1433,7 +1432,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec3<bool>(true, true, true));
+ params.Push(Call<vec3<bool>>(true, true, true));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1447,7 +1446,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec4<bool>(true, true, true, true));
+ params.Push(Call<vec4<bool>>(true, true, true, true));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
@@ -1463,7 +1462,7 @@
TEST_P(DataPacking4x8, Float_Vec4) {
auto name = GetParam();
- auto* builtin = Call(name, vec4<f32>(1_f, 1_f, 1_f, 1_f));
+ auto* builtin = Call(name, Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
@@ -1476,7 +1475,7 @@
TEST_P(DataPacking2x16, Float_Vec2) {
auto name = GetParam();
- auto* builtin = Call(name, vec2<f32>(1_f, 1_f));
+ auto* builtin = Call(name, Call<vec2<f32>>(1_f, 1_f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
diff --git a/src/tint/resolver/call_test.cc b/src/tint/resolver/call_test.cc
index 25f4814..6ebd629 100644
--- a/src/tint/resolver/call_test.cc
+++ b/src/tint/resolver/call_test.cc
@@ -18,39 +18,21 @@
#include "src/tint/ast/call_statement.h"
#include "src/tint/resolver/resolver_test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
-// Helpers and typedefs
-template <typename T>
-using DataType = builder::DataType<T>;
-template <int N, typename T>
-using vec = builder::vec<N, T>;
-template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-template <int N, int M, typename T>
-using mat = builder::mat<N, M, T>;
-template <typename T>
-using mat2x2 = builder::mat2x2<T>;
-template <typename T>
-using mat2x3 = builder::mat2x3<T>;
-template <typename T>
-using mat3x2 = builder::mat3x2<T>;
-template <typename T>
-using mat3x3 = builder::mat3x3<T>;
-template <typename T>
-using mat4x4 = builder::mat4x4<T>;
+
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
template <typename T, int ID = 0>
using alias = builder::alias<T, ID>;
+
template <typename T>
using alias1 = builder::alias1<T>;
+
template <typename T>
using alias2 = builder::alias2<T>;
+
template <typename T>
using alias3 = builder::alias3<T>;
@@ -63,7 +45,7 @@
template <typename T>
constexpr Params ParamsFor() {
- return Params{DataType<T>::ExprFromDouble, DataType<T>::AST};
+ return Params{builder::DataType<T>::ExprFromDouble, builder::DataType<T>::AST};
}
static constexpr Params all_param_types[] = {
diff --git a/src/tint/resolver/call_validation_test.cc b/src/tint/resolver/call_validation_test.cc
index bf533cc..100e9c4 100644
--- a/src/tint/resolver/call_validation_test.cc
+++ b/src/tint/resolver/call_validation_test.cc
@@ -18,11 +18,12 @@
#include "src/tint/ast/call_statement.h"
#include "src/tint/resolver/resolver_test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverCallValidationTest = ResolverTest;
TEST_F(ResolverCallValidationTest, TooFewArgs) {
@@ -103,7 +104,7 @@
// var z: i32 = 1i;
// foo(&z);
// }
- auto* param = Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction));
+ auto* param = Param("p", ty.ptr<function, i32>());
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -120,7 +121,7 @@
// let z: i32 = 1i;
// foo(&z);
// }
- auto* param = Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction));
+ auto* param = Param("p", ty.ptr<function, i32>());
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -142,7 +143,7 @@
auto* S = Structure("S", utils::Vector{
Member("m", ty.i32()),
});
- auto* param = Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction));
+ auto* param = Param("p", ty.ptr<function, i32>());
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -169,7 +170,7 @@
auto* S = Structure("S", utils::Vector{
Member("m", ty.i32()),
});
- auto* param = Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction));
+ auto* param = Param("p", ty.ptr<function, i32>());
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -189,7 +190,7 @@
auto* S = Structure("S", utils::Vector{
Member("m", ty.i32()),
});
- auto* param = Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction));
+ auto* param = Param("p", ty.ptr<function, i32>());
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -208,12 +209,12 @@
// }
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("bar",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(),
utils::Vector{
@@ -235,12 +236,12 @@
// }
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("bar",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(),
utils::Vector{
@@ -268,13 +269,13 @@
// }
Func("x",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
Decl(Var("v", ty.i32())),
- Decl(Let("p", ty.ptr(builtin::AddressSpace::kFunction, ty.i32()), AddressOf("v"))),
+ Decl(Let("p", ty.ptr<function, i32>(), AddressOf("v"))),
CallStmt(Call("x", "p")),
},
utils::Vector{
@@ -293,13 +294,13 @@
// }
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kPrivate)),
+ Param("p", ty.ptr<private_, i32>()),
},
ty.void_(), utils::Empty);
GlobalVar("v", ty.i32(), builtin::AddressSpace::kPrivate);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
- Decl(Let("p", ty.ptr(builtin::AddressSpace::kPrivate, ty.i32()), AddressOf("v"))),
+ Decl(Let("p", ty.ptr<private_, i32>(), AddressOf("v"))),
CallStmt(Call("foo", Expr(Source{{12, 34}}, "p"))),
},
utils::Vector{
@@ -318,14 +319,13 @@
// }
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
Decl(Var("v", ty.array<i32, 4>())),
- Decl(Let("p", ty.ptr(builtin::AddressSpace::kFunction, ty.i32()),
- AddressOf(IndexAccessor("v", 0_a)))),
+ Decl(Let("p", ty.ptr<function, i32>(), AddressOf(IndexAccessor("v", 0_a)))),
CallStmt(Call("foo", Expr(Source{{12, 34}}, "p"))),
},
utils::Vector{
@@ -349,14 +349,13 @@
Enable(builtin::Extension::kChromiumExperimentalFullPtrParameters);
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
Decl(Var("v", ty.array<i32, 4>())),
- Decl(Let("p", ty.ptr(builtin::AddressSpace::kFunction, ty.i32()),
- AddressOf(IndexAccessor("v", 0_a)))),
+ Decl(Let("p", ty.ptr<function, i32>(), AddressOf(IndexAccessor("v", 0_a)))),
CallStmt(Call("foo", Expr(Source{{12, 34}}, "p"))),
},
utils::Vector{
@@ -377,7 +376,7 @@
// }
Func("foo",
utils::Vector{
- Param("p", ty.ptr(builtin::AddressSpace::kFunction, ty.array<i32, 4>())),
+ Param("p", ty.ptr<function, array<i32, 4>>()),
},
ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
@@ -406,7 +405,7 @@
// }
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
@@ -440,7 +439,7 @@
Enable(builtin::Extension::kChromiumExperimentalFullPtrParameters);
Func("foo",
utils::Vector{
- Param("p", ty.ptr<i32>(builtin::AddressSpace::kFunction)),
+ Param("p", ty.ptr<function, i32>()),
},
ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(),
diff --git a/src/tint/resolver/compound_assignment_validation_test.cc b/src/tint/resolver/compound_assignment_validation_test.cc
index 0343f08..0acf993 100644
--- a/src/tint/resolver/compound_assignment_validation_test.cc
+++ b/src/tint/resolver/compound_assignment_validation_test.cc
@@ -18,13 +18,13 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/type/storage_texture.h"
-using ::testing::HasSubstr;
-
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverCompoundAssignmentValidationTest = ResolverTest;
TEST_F(ResolverCompoundAssignmentValidationTest, CompatibleTypes) {
@@ -51,9 +51,8 @@
// var a : i32;
// let b : ptr<function,i32> = &a;
// *b += 2;
- const auto func = builtin::AddressSpace::kFunction;
- auto* var_a = Var("a", ty.i32(), func, Expr(2_i));
- auto* var_b = Let("b", ty.ptr<i32>(func), AddressOf(Expr("a")));
+ auto* var_a = Var("a", ty.i32(), builtin::AddressSpace::kFunction, Expr(2_i));
+ auto* var_b = Let("b", ty.ptr<function, i32>(), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b,
CompoundAssign(Source{{12, 34}}, Deref("b"), 2_i, ast::BinaryOp::kAdd));
@@ -116,7 +115,7 @@
auto* var = Var("a", ty.f32());
- auto* assign = CompoundAssign(Source{{12, 34}}, "a", vec4<f32>(), ast::BinaryOp::kAdd);
+ auto* assign = CompoundAssign(Source{{12, 34}}, "a", Call<vec4<f32>>(), ast::BinaryOp::kAdd);
WrapInFunction(var, assign);
ASSERT_FALSE(r()->Resolve());
@@ -146,7 +145,8 @@
auto* var = Var("a", ty.f32());
- auto* assign = CompoundAssign(Source{{12, 34}}, "a", mat4x4<f32>(), ast::BinaryOp::kMultiply);
+ auto* assign =
+ CompoundAssign(Source{{12, 34}}, "a", Call<mat4x4<f32>>(), ast::BinaryOp::kMultiply);
WrapInFunction(var, assign);
ASSERT_FALSE(r()->Resolve());
@@ -162,7 +162,8 @@
auto* var = Var("a", ty.vec4<f32>());
- auto* assign = CompoundAssign(Source{{12, 34}}, "a", mat4x4<f32>(), ast::BinaryOp::kMultiply);
+ auto* assign =
+ CompoundAssign(Source{{12, 34}}, "a", Call<mat4x4<f32>>(), ast::BinaryOp::kMultiply);
WrapInFunction(var, assign);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -176,7 +177,8 @@
auto* var = Var("a", ty.vec4<f32>());
- auto* assign = CompoundAssign(Source{{12, 34}}, "a", mat4x2<f32>(), ast::BinaryOp::kMultiply);
+ auto* assign =
+ CompoundAssign(Source{{12, 34}}, "a", Call<mat4x2<f32>>(), ast::BinaryOp::kMultiply);
WrapInFunction(var, assign);
ASSERT_FALSE(r()->Resolve());
@@ -194,7 +196,8 @@
auto* var = Var("a", ty.vec4<f32>());
- auto* assign = CompoundAssign(Source{{12, 34}}, "a", mat2x4<f32>(), ast::BinaryOp::kMultiply);
+ auto* assign =
+ CompoundAssign(Source{{12, 34}}, "a", Call<mat2x4<f32>>(), ast::BinaryOp::kMultiply);
WrapInFunction(var, assign);
ASSERT_FALSE(r()->Resolve());
@@ -210,7 +213,8 @@
auto* var = Var("a", ty.mat4x4<f32>());
- auto* assign = CompoundAssign(Source{{12, 34}}, "a", vec4<f32>(), ast::BinaryOp::kMultiply);
+ auto* assign =
+ CompoundAssign(Source{{12, 34}}, "a", Call<vec4<f32>>(), ast::BinaryOp::kMultiply);
WrapInFunction(var, assign);
ASSERT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index 3fa71cd..73e274b 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -22,11 +22,11 @@
#include <type_traits>
#include <utility>
+#include "src/tint/builtin/number.h"
#include "src/tint/constant/composite.h"
#include "src/tint/constant/scalar.h"
#include "src/tint/constant/splat.h"
#include "src/tint/constant/value.h"
-#include "src/tint/number.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/value_constructor.h"
diff --git a/src/tint/resolver/const_eval.h b/src/tint/resolver/const_eval.h
index 9303656..0253d30 100644
--- a/src/tint/resolver/const_eval.h
+++ b/src/tint/resolver/const_eval.h
@@ -18,7 +18,7 @@
#include <stddef.h>
#include <string>
-#include "src/tint/number.h"
+#include "src/tint/builtin/number.h"
#include "src/tint/type/type.h"
#include "src/tint/utils/result.h"
#include "src/tint/utils/vector.h"
diff --git a/src/tint/resolver/const_eval_binary_op_test.cc b/src/tint/resolver/const_eval_binary_op_test.cc
index e61599f..dac78ce 100644
--- a/src/tint/resolver/const_eval_binary_op_test.cc
+++ b/src/tint/resolver/const_eval_binary_op_test.cc
@@ -17,7 +17,8 @@
#include "src/tint/reader/wgsl/parser.h"
#include "src/tint/utils/result.h"
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using ::testing::HasSubstr;
namespace tint::resolver {
@@ -1690,7 +1691,7 @@
// const i = 4;
// const result = (one == 0) && (a[i] == 0);
GlobalConst("one", Expr(1_a));
- GlobalConst("a", array<i32, 3>(1_i, 2_i, 3_i));
+ GlobalConst("a", Call<array<i32, 3>>(1_i, 2_i, 3_i));
GlobalConst("i", Expr(4_a));
auto* lhs = Equal("one", 0_a);
auto* rhs = Equal(IndexAccessor("a", "i"), 0_a);
@@ -1707,7 +1708,7 @@
// const i = 3;
// const result = (one == 1) && (a[i] == 0);
GlobalConst("one", Expr(1_a));
- GlobalConst("a", array<i32, 3>(1_i, 2_i, 3_i));
+ GlobalConst("a", Call<array<i32, 3>>(1_i, 2_i, 3_i));
GlobalConst("i", Expr(3_a));
auto* lhs = Equal("one", 1_a);
auto* rhs = Equal(IndexAccessor("a", Expr(Source{{12, 34}}, "i")), 0_a);
@@ -1724,7 +1725,7 @@
// const i = 3;
// const result = (one == 0) && (a[i] == 0.0f);
GlobalConst("one", Expr(1_a));
- GlobalConst("a", array<i32, 3>(1_i, 2_i, 3_i));
+ GlobalConst("a", Call<array<i32, 3>>(1_i, 2_i, 3_i));
GlobalConst("i", Expr(3_a));
auto* lhs = Equal("one", 0_a);
auto* rhs = Equal(Source{{12, 34}}, IndexAccessor("a", "i"), 0.0_f);
@@ -1747,7 +1748,7 @@
// const i = 4;
// const result = (one == 1) || (a[i] == 0);
GlobalConst("one", Expr(1_a));
- GlobalConst("a", array<i32, 3>(1_i, 2_i, 3_i));
+ GlobalConst("a", Call<array<i32, 3>>(1_i, 2_i, 3_i));
GlobalConst("i", Expr(4_a));
auto* lhs = Equal("one", 1_a);
auto* rhs = Equal(IndexAccessor("a", "i"), 0_a);
@@ -1764,7 +1765,7 @@
// const i = 3;
// const result = (one == 0) || (a[i] == 0);
GlobalConst("one", Expr(1_a));
- GlobalConst("a", array<i32, 3>(1_i, 2_i, 3_i));
+ GlobalConst("a", Call<array<i32, 3>>(1_i, 2_i, 3_i));
GlobalConst("i", Expr(3_a));
auto* lhs = Equal("one", 0_a);
auto* rhs = Equal(IndexAccessor("a", Expr(Source{{12, 34}}, "i")), 0_a);
@@ -1781,7 +1782,7 @@
// const i = 3;
// const result = (one == 1) || (a[i] == 0.0f);
GlobalConst("one", Expr(1_a));
- GlobalConst("a", array<i32, 3>(1_i, 2_i, 3_i));
+ GlobalConst("a", Call<array<i32, 3>>(1_i, 2_i, 3_i));
GlobalConst("i", Expr(3_a));
auto* lhs = Equal("one", 1_a);
auto* rhs = Equal(Source{{12, 34}}, IndexAccessor("a", "i"), 0.0_f);
@@ -1914,7 +1915,8 @@
// const result = (one == 0) && (vec2<f32>(1.0, true).x == 0.0);
GlobalConst("one", Expr(1_a));
auto* lhs = Equal("one", 0_a);
- auto* rhs = Equal(MemberAccessor(vec2<f32>(Source{{12, 34}}, 1.0_a, Expr(true)), "x"), 0.0_a);
+ auto* rhs =
+ Equal(MemberAccessor(Call<vec2<f32>>(Source{{12, 34}}, 1.0_a, Expr(true)), "x"), 0.0_a);
GlobalConst("result", LogicalAnd(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
@@ -1942,7 +1944,8 @@
// const result = (one == 1) || (vec2<f32>(1.0, true).x == 0.0);
GlobalConst("one", Expr(1_a));
auto* lhs = Equal("one", 0_a);
- auto* rhs = Equal(MemberAccessor(vec2<f32>(Source{{12, 34}}, 1.0_a, Expr(true)), "x"), 0.0_a);
+ auto* rhs =
+ Equal(MemberAccessor(Call<vec2<f32>>(Source{{12, 34}}, 1.0_a, Expr(true)), "x"), 0.0_a);
GlobalConst("result", LogicalOr(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
@@ -2328,7 +2331,8 @@
// const result = (one == 0) && (vec2(1, 2).z == 0);
GlobalConst("one", Expr(1_a));
auto* lhs = Equal("one", 0_a);
- auto* rhs = Equal(MemberAccessor(vec2<Infer>(1_a, 2_a), Ident(Source{{12, 34}}, "z")), 0_a);
+ auto* rhs =
+ Equal(MemberAccessor(Call<vec2<Infer>>(1_a, 2_a), Ident(Source{{12, 34}}, "z")), 0_a);
GlobalConst("result", LogicalAnd(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
@@ -2340,7 +2344,8 @@
// const result = (one == 1) || (vec2(1, 2).z == 0);
GlobalConst("one", Expr(1_a));
auto* lhs = Equal("one", 1_a);
- auto* rhs = Equal(MemberAccessor(vec2<Infer>(1_a, 2_a), Ident(Source{{12, 34}}, "z")), 0_a);
+ auto* rhs =
+ Equal(MemberAccessor(Call<vec2<Infer>>(1_a, 2_a), Ident(Source{{12, 34}}, "z")), 0_a);
GlobalConst("result", LogicalOr(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/const_eval_bitcast_test.cc b/src/tint/resolver/const_eval_bitcast_test.cc
index cbb09d5..c52e2e3 100644
--- a/src/tint/resolver/const_eval_bitcast_test.cc
+++ b/src/tint/resolver/const_eval_bitcast_test.cc
@@ -14,11 +14,12 @@
#include "src/tint/resolver/const_eval_test.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
struct Case {
Value input;
struct Success {
@@ -169,24 +170,24 @@
Vec(0_i, 0x3F800000_i, 0x42F60000_i)),
// Unrepresentable
- Failure<f32>(Val(nan_as_u32)), //
- Failure<f32>(Val(nan_as_i32)), //
- Failure<f32>(Val(inf_as_u32)), //
- Failure<f32>(Val(inf_as_i32)), //
- Failure<f32>(Val(neg_inf_as_u32)), //
- Failure<f32>(Val(neg_inf_as_i32)), //
- Failure<builder::vec2<f32>>(Vec(nan_as_u32, 0_u)), //
- Failure<builder::vec2<f32>>(Vec(nan_as_i32, 0_i)), //
- Failure<builder::vec2<f32>>(Vec(inf_as_u32, 0_u)), //
- Failure<builder::vec2<f32>>(Vec(inf_as_i32, 0_i)), //
- Failure<builder::vec2<f32>>(Vec(neg_inf_as_u32, 0_u)), //
- Failure<builder::vec2<f32>>(Vec(neg_inf_as_i32, 0_i)), //
- Failure<builder::vec2<f32>>(Vec(0_u, nan_as_u32)), //
- Failure<builder::vec2<f32>>(Vec(0_i, nan_as_i32)), //
- Failure<builder::vec2<f32>>(Vec(0_u, inf_as_u32)), //
- Failure<builder::vec2<f32>>(Vec(0_i, inf_as_i32)), //
- Failure<builder::vec2<f32>>(Vec(0_u, neg_inf_as_u32)), //
- Failure<builder::vec2<f32>>(Vec(0_i, neg_inf_as_i32)), //
+ Failure<f32>(Val(nan_as_u32)), //
+ Failure<f32>(Val(nan_as_i32)), //
+ Failure<f32>(Val(inf_as_u32)), //
+ Failure<f32>(Val(inf_as_i32)), //
+ Failure<f32>(Val(neg_inf_as_u32)), //
+ Failure<f32>(Val(neg_inf_as_i32)), //
+ Failure<vec2<f32>>(Vec(nan_as_u32, 0_u)), //
+ Failure<vec2<f32>>(Vec(nan_as_i32, 0_i)), //
+ Failure<vec2<f32>>(Vec(inf_as_u32, 0_u)), //
+ Failure<vec2<f32>>(Vec(inf_as_i32, 0_i)), //
+ Failure<vec2<f32>>(Vec(neg_inf_as_u32, 0_u)), //
+ Failure<vec2<f32>>(Vec(neg_inf_as_i32, 0_i)), //
+ Failure<vec2<f32>>(Vec(0_u, nan_as_u32)), //
+ Failure<vec2<f32>>(Vec(0_i, nan_as_i32)), //
+ Failure<vec2<f32>>(Vec(0_u, inf_as_u32)), //
+ Failure<vec2<f32>>(Vec(0_i, inf_as_i32)), //
+ Failure<vec2<f32>>(Vec(0_u, neg_inf_as_u32)), //
+ Failure<vec2<f32>>(Vec(0_i, neg_inf_as_i32)), //
}));
} // namespace
diff --git a/src/tint/resolver/const_eval_construction_test.cc b/src/tint/resolver/const_eval_construction_test.cc
index 3d59514..4ecca7f 100644
--- a/src/tint/resolver/const_eval_construction_test.cc
+++ b/src/tint/resolver/const_eval_construction_test.cc
@@ -14,11 +14,12 @@
#include "src/tint/resolver/const_eval_test.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
TEST_F(ResolverConstEvalTest, Scalar_AFloat) {
auto* expr = Expr(99.0_a);
auto* a = Const("a", expr);
@@ -189,26 +190,26 @@
C<f32>(),
C<f16>(),
C<bool>(),
- C<builder::vec2<AInt>>(),
- C<builder::vec3<AInt>>(),
- C<builder::vec4<AInt>>(),
- C<builder::vec3<u32>>(),
- C<builder::vec3<i32>>(),
- C<builder::vec3<f32>>(),
- C<builder::vec3<f16>>(),
- C<builder::mat2x2<f32>>(),
- C<builder::mat2x2<f16>>(),
- C<builder::array<3, u32>>(),
- C<builder::array<3, i32>>(),
- C<builder::array<3, f32>>(),
- C<builder::array<3, f16>>(),
- C<builder::array<3, bool>>(),
+ C<vec2<AInt>>(),
+ C<vec3<AInt>>(),
+ C<vec4<AInt>>(),
+ C<vec3<u32>>(),
+ C<vec3<i32>>(),
+ C<vec3<f32>>(),
+ C<vec3<f16>>(),
+ C<mat2x2<f32>>(),
+ C<mat2x2<f16>>(),
+ C<array<u32, 3>>(),
+ C<array<i32, 3>>(),
+ C<array<f32, 3>>(),
+ C<array<f16, 3>>(),
+ C<array<bool, 3>>(),
}));
} // namespace ZeroInit
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_i32) {
- auto* expr = vec3<i32>();
+ auto* expr = Call<vec3<i32>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -237,7 +238,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_u32) {
- auto* expr = vec3<u32>();
+ auto* expr = Call<vec3<u32>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -266,7 +267,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_f32) {
- auto* expr = vec3<f32>();
+ auto* expr = Call<vec3<f32>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -297,7 +298,7 @@
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>();
+ auto* expr = Call<vec3<f16>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -326,7 +327,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_bool) {
- auto* expr = vec3<bool>();
+ auto* expr = Call<vec3<bool>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -355,7 +356,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Splat_i32) {
- auto* expr = vec3<i32>(99_i);
+ auto* expr = Call<vec3<i32>>(99_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -384,7 +385,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Splat_u32) {
- auto* expr = vec3<u32>(99_u);
+ auto* expr = Call<vec3<u32>>(99_u);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -413,7 +414,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Splat_f32) {
- auto* expr = vec3<f32>(9.9_f);
+ auto* expr = Call<vec3<f32>>(9.9_f);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -444,7 +445,7 @@
TEST_F(ResolverConstEvalTest, Vec3_Splat_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(9.9_h);
+ auto* expr = Call<vec3<f16>>(9.9_h);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -474,7 +475,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Splat_bool) {
- auto* expr = vec3<bool>(true);
+ auto* expr = Call<vec3<bool>>(true);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -503,7 +504,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_AInt) {
- auto* expr = vec3<Infer>(1_a, 2_a, 3_a);
+ auto* expr = Call<vec3<Infer>>(1_a, 2_a, 3_a);
auto* a = Const("a", expr);
WrapInFunction(a);
@@ -533,7 +534,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_AFloat) {
- auto* expr = vec3<Infer>(1.0_a, 2.0_a, 3.0_a);
+ auto* expr = Call<vec3<Infer>>(1.0_a, 2.0_a, 3.0_a);
auto* a = Const("a", expr);
WrapInFunction(a);
@@ -563,7 +564,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_i32) {
- auto* expr = vec3<i32>(1_i, 2_i, 3_i);
+ auto* expr = Call<vec3<i32>>(1_i, 2_i, 3_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -592,7 +593,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_u32) {
- auto* expr = vec3<u32>(1_u, 2_u, 3_u);
+ auto* expr = Call<vec3<u32>>(1_u, 2_u, 3_u);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -621,7 +622,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_f32) {
- auto* expr = vec3<f32>(1_f, 2_f, 3_f);
+ auto* expr = Call<vec3<f32>>(1_f, 2_f, 3_f);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -652,7 +653,7 @@
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(1_h, 2_h, 3_h);
+ auto* expr = Call<vec3<f16>>(1_h, 2_h, 3_h);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -681,7 +682,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_bool) {
- auto* expr = vec3<bool>(true, false, true);
+ auto* expr = Call<vec3<bool>>(true, false, true);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -710,7 +711,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_i32) {
- auto* expr = vec3<i32>(1_i, vec2<i32>(2_i, 3_i));
+ auto* expr = Call<vec3<i32>>(1_i, Call<vec2<i32>>(2_i, 3_i));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -739,7 +740,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_u32) {
- auto* expr = vec3<u32>(vec2<u32>(1_u, 2_u), 3_u);
+ auto* expr = Call<vec3<u32>>(Call<vec2<u32>>(1_u, 2_u), 3_u);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -768,7 +769,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32) {
- auto* expr = vec3<f32>(1_f, vec2<f32>(2_f, 3_f));
+ auto* expr = Call<vec3<f32>>(1_f, Call<vec2<f32>>(2_f, 3_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -797,7 +798,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_all_10) {
- auto* expr = vec3<f32>(10_f, vec2<f32>(10_f, 10_f));
+ auto* expr = Call<vec3<f32>>(10_f, Call<vec2<f32>>(10_f, 10_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -826,7 +827,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_all_positive_0) {
- auto* expr = vec3<f32>(0_f, vec2<f32>(0_f, 0_f));
+ auto* expr = Call<vec3<f32>>(0_f, Call<vec2<f32>>(0_f, 0_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -855,7 +856,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_all_negative_0) {
- auto* expr = vec3<f32>(vec2<f32>(-0_f, -0_f), -0_f);
+ auto* expr = Call<vec3<f32>>(Call<vec2<f32>>(-0_f, -0_f), -0_f);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -884,7 +885,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_mixed_sign_0) {
- auto* expr = vec3<f32>(0_f, vec2<f32>(-0_f, 0_f));
+ auto* expr = Call<vec3<f32>>(0_f, Call<vec2<f32>>(-0_f, 0_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -915,7 +916,7 @@
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(1_h, vec2<f16>(2_h, 3_h));
+ auto* expr = Call<vec3<f16>>(1_h, Call<vec2<f16>>(2_h, 3_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -946,7 +947,7 @@
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_all_10) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(10_h, vec2<f16>(10_h, 10_h));
+ auto* expr = Call<vec3<f16>>(10_h, Call<vec2<f16>>(10_h, 10_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -977,7 +978,7 @@
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_all_positive_0) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(0_h, vec2<f16>(0_h, 0_h));
+ auto* expr = Call<vec3<f16>>(0_h, Call<vec2<f16>>(0_h, 0_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1008,7 +1009,7 @@
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_all_negative_0) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(vec2<f16>(-0_h, -0_h), -0_h);
+ auto* expr = Call<vec3<f16>>(Call<vec2<f16>>(-0_h, -0_h), -0_h);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1039,7 +1040,7 @@
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_mixed_sign_0) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(0_h, vec2<f16>(-0_h, 0_h));
+ auto* expr = Call<vec3<f16>>(0_h, Call<vec2<f16>>(-0_h, 0_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1068,7 +1069,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_bool) {
- auto* expr = vec3<bool>(vec2<bool>(true, false), true);
+ auto* expr = Call<vec3<bool>>(Call<vec2<bool>>(true, false), true);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1097,7 +1098,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_all_true) {
- auto* expr = vec3<bool>(true, vec2<bool>(true, true));
+ auto* expr = Call<vec3<bool>>(true, Call<vec2<bool>>(true, true));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1126,7 +1127,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_all_false) {
- auto* expr = vec3<bool>(false, vec2<bool>(false, false));
+ auto* expr = Call<vec3<bool>>(false, Call<vec2<bool>>(false, false));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1155,7 +1156,7 @@
}
TEST_F(ResolverConstEvalTest, Mat2x3_ZeroInit_f32) {
- auto* expr = mat2x3<f32>();
+ auto* expr = Call<mat2x3<f32>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1199,7 +1200,7 @@
TEST_F(ResolverConstEvalTest, Mat2x3_ZeroInit_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = mat2x3<f16>();
+ auto* expr = Call<mat2x3<f16>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1241,7 +1242,7 @@
}
TEST_F(ResolverConstEvalTest, Mat3x2_Construct_Scalars_af) {
- auto* expr = Call(ty.mat3x2<Infer>(), 1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a);
+ auto* expr = Call<mat3x2<Infer>>(1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1283,10 +1284,10 @@
}
TEST_F(ResolverConstEvalTest, Mat3x2_Construct_Columns_af) {
- auto* expr = Call(ty.mat<Infer>(3, 2), //
- vec2<Infer>(1.0_a, 2.0_a), //
- vec2<Infer>(3.0_a, 4.0_a), //
- vec2<Infer>(5.0_a, 6.0_a));
+ auto* expr = Call<mat<3, 2, Infer>>( //
+ Call<vec2<Infer>>(1.0_a, 2.0_a), //
+ Call<vec2<Infer>>(3.0_a, 4.0_a), //
+ Call<vec2<Infer>>(5.0_a, 6.0_a));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1328,7 +1329,7 @@
}
TEST_F(ResolverConstEvalTest, Array_i32_Zero) {
- auto* expr = Call(ty.array<i32, 4>());
+ auto* expr = Call<array<i32, 4>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1360,7 +1361,7 @@
}
TEST_F(ResolverConstEvalTest, Array_f32_Zero) {
- auto* expr = Call(ty.array<f32, 4>());
+ auto* expr = Call<array<f32, 4>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1392,7 +1393,7 @@
}
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Zero) {
- auto* expr = Call(ty.array(ty.vec3<f32>(), 2_u));
+ auto* expr = Call<array<vec3<f32>, 2>>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1468,7 +1469,7 @@
}
TEST_F(ResolverConstEvalTest, Array_i32_Elements) {
- auto* expr = Call(ty.array<i32, 4>(), 10_i, 20_i, 30_i, 40_i);
+ auto* expr = Call<array<i32, 4>>(10_i, 20_i, 30_i, 40_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1592,7 +1593,7 @@
}
TEST_F(ResolverConstEvalTest, Array_f32_Elements) {
- auto* expr = Call(ty.array<f32, 4>(), 10_f, 20_f, 30_f, 40_f);
+ auto* expr = Call<array<f32, 4>>(10_f, 20_f, 30_f, 40_f);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1624,8 +1625,8 @@
}
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Elements) {
- auto* expr = Call(ty.array(ty.vec3<f32>(), 2_u), //
- vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f));
+ auto* expr =
+ Call<array<vec3<f32>, 2>>(Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2083,8 +2084,8 @@
Member("m4", ty.vec3<f16>()),
Member("m5", ty.vec2<bool>()),
});
- auto* expr = Call("S", vec2<i32>(1_i), vec3<u32>(2_u), vec4<f32>(3_f), vec3<f16>(4_h),
- vec2<bool>(false));
+ auto* expr = Call("S", Call<vec2<i32>>(1_i), Call<vec3<u32>>(2_u), Call<vec4<f32>>(3_f),
+ Call<vec3<f16>>(4_h), Call<vec2<bool>>(false));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2192,7 +2193,7 @@
Member("m2", ty.array<f32, 3>()),
});
auto* expr = Call("S", //
- Call(ty.array<i32, 2>(), 1_i, 2_i), Call(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
+ Call<array<i32, 2>>(1_i, 2_i), Call<array<f32, 3>>(1_f, 2_f, 3_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
diff --git a/src/tint/resolver/const_eval_conversion_test.cc b/src/tint/resolver/const_eval_conversion_test.cc
index 468d2b4..57d6c43 100644
--- a/src/tint/resolver/const_eval_conversion_test.cc
+++ b/src/tint/resolver/const_eval_conversion_test.cc
@@ -16,11 +16,12 @@
#include "src/tint/resolver/const_eval_test.h"
#include "src/tint/sem/materialize.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
enum class Kind {
kScalar,
kVector,
@@ -75,7 +76,7 @@
auto* input_val = input.Expr(*this);
auto* expr = Call(type.ast(*this), input_val);
if (kind == Kind::kVector) {
- expr = Call(ty.vec<Infer>(3), expr);
+ expr = Call<vec3<Infer>>(expr);
}
WrapInFunction(expr);
@@ -225,7 +226,7 @@
})));
TEST_F(ResolverConstEvalTest, Vec3_Convert_f32_to_i32) {
- auto* expr = vec3<i32>(vec3<f32>(1.1_f, 2.2_f, 3.3_f));
+ auto* expr = Call<vec3<i32>>(Call<vec3<f32>>(1.1_f, 2.2_f, 3.3_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -254,7 +255,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Convert_u32_to_f32) {
- auto* expr = vec3<f32>(vec3<u32>(10_u, 20_u, 30_u));
+ auto* expr = Call<vec3<f32>>(Call<vec3<u32>>(10_u, 20_u, 30_u));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -285,7 +286,7 @@
TEST_F(ResolverConstEvalTest, Vec3_Convert_f16_to_i32) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<i32>(vec3<f16>(1.1_h, 2.2_h, 3.3_h));
+ auto* expr = Call<vec3<i32>>(Call<vec3<f16>>(1.1_h, 2.2_h, 3.3_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -316,7 +317,7 @@
TEST_F(ResolverConstEvalTest, Vec3_Convert_u32_to_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(vec3<u32>(10_u, 20_u, 30_u));
+ auto* expr = Call<vec3<f16>>(Call<vec3<u32>>(10_u, 20_u, 30_u));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -345,7 +346,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_i32) {
- auto* expr = vec3<i32>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
+ auto* expr = Call<vec3<i32>>(Call<vec3<f32>>(1e10_f, -1e20_f, 1e30_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -374,7 +375,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_u32) {
- auto* expr = vec3<u32>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
+ auto* expr = Call<vec3<u32>>(Call<vec3<f32>>(1e10_f, -1e20_f, 1e30_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -405,7 +406,7 @@
TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(Source{{12, 34}}, vec3<f32>(1e10_f, 0_f, 0_f));
+ auto* expr = Call<vec3<f16>>(Source{{12, 34}}, Call<vec3<f32>>(1e10_f, 0_f, 0_f));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve());
@@ -415,7 +416,7 @@
TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = vec3<f16>(vec3<f32>(1e-20_f, -2e-30_f, 3e-40_f));
+ auto* expr = Call<vec3<f16>>(Call<vec3<f32>>(1e-20_f, -2e-30_f, 3e-40_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
diff --git a/src/tint/resolver/const_eval_indexing_test.cc b/src/tint/resolver/const_eval_indexing_test.cc
index d311d30..a67843b 100644
--- a/src/tint/resolver/const_eval_indexing_test.cc
+++ b/src/tint/resolver/const_eval_indexing_test.cc
@@ -14,13 +14,14 @@
#include "src/tint/resolver/const_eval_test.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
TEST_F(ResolverConstEvalTest, Vec3_Index) {
- auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), 2_i);
+ auto* expr = IndexAccessor(Call<vec3<i32>>(1_i, 2_i, 3_i), 2_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -35,7 +36,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Index_OOB_High) {
- auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), Expr(Source{{12, 34}}, 3_i));
+ auto* expr = IndexAccessor(Call<vec3<i32>>(1_i, 2_i, 3_i), Expr(Source{{12, 34}}, 3_i));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve()) << r()->error();
@@ -43,7 +44,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Index_OOB_Low) {
- auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), Expr(Source{{12, 34}}, -3_i));
+ auto* expr = IndexAccessor(Call<vec3<i32>>(1_i, 2_i, 3_i), Expr(Source{{12, 34}}, -3_i));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve()) << r()->error();
@@ -123,7 +124,7 @@
} // namespace Swizzle
TEST_F(ResolverConstEvalTest, Vec3_Swizzle_Scalar) {
- auto* expr = MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "y");
+ auto* expr = MemberAccessor(Call<vec3<i32>>(1_i, 2_i, 3_i), "y");
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -138,7 +139,7 @@
}
TEST_F(ResolverConstEvalTest, Vec3_Swizzle_Vector) {
- auto* expr = MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "zx");
+ auto* expr = MemberAccessor(Call<vec3<i32>>(1_i, 2_i, 3_i), "zx");
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -161,7 +162,8 @@
TEST_F(ResolverConstEvalTest, Vec3_Swizzle_Chain) {
auto* expr = // (1, 2, 3) -> (2, 3, 1) -> (3, 2) -> 2
- MemberAccessor(MemberAccessor(MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "gbr"), "yx"), "y");
+ MemberAccessor(MemberAccessor(MemberAccessor(Call<vec3<i32>>(1_i, 2_i, 3_i), "gbr"), "yx"),
+ "y");
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -176,8 +178,10 @@
}
TEST_F(ResolverConstEvalTest, Mat3x2_Index) {
- auto* expr = IndexAccessor(
- mat3x2<f32>(vec2<f32>(1._a, 2._a), vec2<f32>(3._a, 4._a), vec2<f32>(5._a, 6._a)), 2_i);
+ auto* expr =
+ IndexAccessor(Call<mat3x2<f32>>(Call<vec2<f32>>(1._a, 2._a), Call<vec2<f32>>(3._a, 4._a),
+ Call<vec2<f32>>(5._a, 6._a)),
+ 2_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -199,9 +203,10 @@
}
TEST_F(ResolverConstEvalTest, Mat3x2_Index_OOB_High) {
- auto* expr = IndexAccessor(
- mat3x2<f32>(vec2<f32>(1._a, 2._a), vec2<f32>(3._a, 4._a), vec2<f32>(5._a, 6._a)),
- Expr(Source{{12, 34}}, 3_i));
+ auto* expr =
+ IndexAccessor(Call<mat3x2<f32>>(Call<vec2<f32>>(1._a, 2._a), Call<vec2<f32>>(3._a, 4._a),
+ Call<vec2<f32>>(5._a, 6._a)),
+ Expr(Source{{12, 34}}, 3_i));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve()) << r()->error();
@@ -209,9 +214,10 @@
}
TEST_F(ResolverConstEvalTest, Mat3x2_Index_OOB_Low) {
- auto* expr = IndexAccessor(
- mat3x2<f32>(vec2<f32>(1._a, 2._a), vec2<f32>(3._a, 4._a), vec2<f32>(5._a, 6._a)),
- Expr(Source{{12, 34}}, -3_i));
+ auto* expr =
+ IndexAccessor(Call<mat3x2<f32>>(Call<vec2<f32>>(1._a, 2._a), Call<vec2<f32>>(3._a, 4._a),
+ Call<vec2<f32>>(5._a, 6._a)),
+ Expr(Source{{12, 34}}, -3_i));
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve()) << r()->error();
@@ -219,8 +225,9 @@
}
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index) {
- auto* expr = IndexAccessor(Call(ty.array(ty.vec3<f32>(), 2_u), //
- vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
+ auto* expr = IndexAccessor(Call<array<vec3<f32>, 2>>( //
+ Call<vec3<f32>>(1_f, 2_f, 3_f), //
+ Call<vec3<f32>>(4_f, 5_f, 6_f)),
1_i);
WrapInFunction(expr);
@@ -248,8 +255,9 @@
}
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index_OOB_High) {
- auto* expr = IndexAccessor(Call(ty.array(ty.vec3<f32>(), 2_u), //
- vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
+ auto* expr = IndexAccessor(Call<array<vec3<f32>, 2>>( //
+ Call<vec3<f32>>(1_f, 2_f, 3_f), //
+ Call<vec3<f32>>(4_f, 5_f, 6_f)),
Expr(Source{{12, 34}}, 2_i));
WrapInFunction(expr);
@@ -258,8 +266,9 @@
}
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index_OOB_Low) {
- auto* expr = IndexAccessor(Call(ty.array(ty.vec3<f32>(), 2_u), //
- vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
+ auto* expr = IndexAccessor(Call<array<vec3<f32>, 2>>( //
+ Call<vec3<f32>>(1_f, 2_f, 3_f), //
+ Call<vec3<f32>>(4_f, 5_f, 6_f)),
Expr(Source{{12, 34}}, -2_i));
WrapInFunction(expr);
@@ -268,7 +277,7 @@
}
TEST_F(ResolverConstEvalTest, RuntimeArray_vec3_f32_Index_OOB_Low) {
- auto* sb = GlobalVar("sb", ty.array(ty.vec3<f32>()), Group(0_a), Binding(0_a),
+ auto* sb = GlobalVar("sb", ty.array<vec3<f32>>(), Group(0_a), Binding(0_a),
builtin::AddressSpace::kStorage);
auto* expr = IndexAccessor(sb, Expr(Source{{12, 34}}, -2_i));
WrapInFunction(expr);
@@ -278,11 +287,11 @@
}
TEST_F(ResolverConstEvalTest, ChainedIndex) {
- auto* arr_expr = Call(ty.array(ty.mat2x3<f32>(), 2_u), // array<mat2x3<f32>, 2u>
- mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), //
- vec3<f32>(4_f, 5_f, 6_f)), //
- mat2x3<f32>(vec3<f32>(7_f, 0_f, 9_f), //
- vec3<f32>(10_f, 11_f, 12_f)));
+ auto* arr_expr = Call<array<mat2x3<f32>, 2>>( //
+ Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f), //
+ Call<vec3<f32>>(4_f, 5_f, 6_f)), //
+ Call<mat2x3<f32>>(Call<vec3<f32>>(7_f, 0_f, 9_f), //
+ Call<vec3<f32>>(10_f, 11_f, 12_f)));
auto* mat_expr = IndexAccessor(arr_expr, 1_i); // arr[1]
auto* vec_expr = IndexAccessor(mat_expr, 0_i); // arr[1][0]
diff --git a/src/tint/resolver/const_eval_member_access_test.cc b/src/tint/resolver/const_eval_member_access_test.cc
index ee92714..3eb9644 100644
--- a/src/tint/resolver/const_eval_member_access_test.cc
+++ b/src/tint/resolver/const_eval_member_access_test.cc
@@ -14,11 +14,12 @@
#include "src/tint/resolver/const_eval_test.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
TEST_F(ResolverConstEvalTest, StructMemberAccess) {
Structure("Inner", utils::Vector{
Member("i1", ty.i32()),
@@ -68,9 +69,9 @@
}
TEST_F(ResolverConstEvalTest, Matrix_AFloat_Construct_From_AInt_Vectors) {
- auto* c = Const("a", Call(ty.mat2x2<Infer>(), //
- Call(ty.vec<Infer>(2), Expr(1_a), Expr(2_a)),
- Call(ty.vec<Infer>(2), Expr(3_a), Expr(4_a))));
+ auto* c = Const("a", Call<mat2x2<Infer>>( //
+ Call<vec2<Infer>>(1_a, 2_a), //
+ Call<vec2<Infer>>(3_a, 4_a)));
WrapInFunction(c);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -93,18 +94,18 @@
}
TEST_F(ResolverConstEvalTest, MatrixMemberAccess_AFloat) {
- auto* c = Const("a", Call(ty.mat2x3<Infer>(), //
- Call(ty.vec3<Infer>(), Expr(1.0_a), Expr(2.0_a), Expr(3.0_a)),
- Call(ty.vec3<Infer>(), Expr(4.0_a), Expr(5.0_a), Expr(6.0_a))));
+ auto* c = Const("a", Call<mat2x3<Infer>>( //
+ Call<vec3<Infer>>(1.0_a, 2.0_a, 3.0_a), //
+ Call<vec3<Infer>>(4.0_a, 5.0_a, 6.0_a)));
- auto* col_0 = Const("col_0", IndexAccessor("a", Expr(0_i)));
- auto* col_1 = Const("col_1", IndexAccessor("a", Expr(1_i)));
- auto* e00 = Const("e00", IndexAccessor("col_0", Expr(0_i)));
- auto* e01 = Const("e01", IndexAccessor("col_0", Expr(1_i)));
- auto* e02 = Const("e02", IndexAccessor("col_0", Expr(2_i)));
- auto* e10 = Const("e10", IndexAccessor("col_1", Expr(0_i)));
- auto* e11 = Const("e11", IndexAccessor("col_1", Expr(1_i)));
- auto* e12 = Const("e12", IndexAccessor("col_1", Expr(2_i)));
+ auto* col_0 = Const("col_0", IndexAccessor("a", 0_i));
+ auto* col_1 = Const("col_1", IndexAccessor("a", 1_i));
+ auto* e00 = Const("e00", IndexAccessor("col_0", 0_i));
+ auto* e01 = Const("e01", IndexAccessor("col_0", 1_i));
+ auto* e02 = Const("e02", IndexAccessor("col_0", 2_i));
+ auto* e10 = Const("e10", IndexAccessor("col_1", 0_i));
+ auto* e11 = Const("e11", IndexAccessor("col_1", 1_i));
+ auto* e12 = Const("e12", IndexAccessor("col_1", 2_i));
(void)col_0;
(void)col_1;
@@ -169,18 +170,18 @@
}
TEST_F(ResolverConstEvalTest, MatrixMemberAccess_f32) {
- auto* c = Const("a", Call(ty.mat2x3<Infer>(), //
- Call(ty.vec3<Infer>(), Expr(1.0_f), Expr(2.0_f), Expr(3.0_f)),
- Call(ty.vec3<Infer>(), Expr(4.0_f), Expr(5.0_f), Expr(6.0_f))));
+ auto* c = Const("a", Call<mat2x3<Infer>>( //
+ Call<vec3<Infer>>(1.0_f, 2.0_f, 3.0_f), //
+ Call<vec3<Infer>>(4.0_f, 5.0_f, 6.0_f)));
- auto* col_0 = Const("col_0", IndexAccessor("a", Expr(0_i)));
- auto* col_1 = Const("col_1", IndexAccessor("a", Expr(1_i)));
- auto* e00 = Const("e00", IndexAccessor("col_0", Expr(0_i)));
- auto* e01 = Const("e01", IndexAccessor("col_0", Expr(1_i)));
- auto* e02 = Const("e02", IndexAccessor("col_0", Expr(2_i)));
- auto* e10 = Const("e10", IndexAccessor("col_1", Expr(0_i)));
- auto* e11 = Const("e11", IndexAccessor("col_1", Expr(1_i)));
- auto* e12 = Const("e12", IndexAccessor("col_1", Expr(2_i)));
+ auto* col_0 = Const("col_0", IndexAccessor("a", 0_i));
+ auto* col_1 = Const("col_1", IndexAccessor("a", 1_i));
+ auto* e00 = Const("e00", IndexAccessor("col_0", 0_i));
+ auto* e01 = Const("e01", IndexAccessor("col_0", 1_i));
+ auto* e02 = Const("e02", IndexAccessor("col_0", 2_i));
+ auto* e10 = Const("e10", IndexAccessor("col_1", 0_i));
+ auto* e11 = Const("e11", IndexAccessor("col_1", 1_i));
+ auto* e12 = Const("e12", IndexAccessor("col_1", 2_i));
(void)col_0;
(void)col_1;
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 504e8ac..84932ed 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -34,6 +34,7 @@
#include "src/tint/ast/identifier.h"
#include "src/tint/ast/if_statement.h"
#include "src/tint/ast/increment_decrement_statement.h"
+#include "src/tint/ast/index_attribute.h"
#include "src/tint/ast/internal_attribute.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/invariant_attribute.h"
@@ -390,6 +391,10 @@
TraverseExpression(id->expr);
return true;
},
+ [&](const ast::IndexAttribute* index) {
+ TraverseExpression(index->expr);
+ return true;
+ },
[&](const ast::InterpolateAttribute* interpolate) {
TraverseExpression(interpolate->type);
TraverseExpression(interpolate->sampling);
diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc
index ee509a7..88bdc13 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -23,12 +23,12 @@
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/transform.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
using ::testing::ElementsAre;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
template <typename T>
class ResolverDependencyGraphTestWithParam : public ResolverTestWithParam<T> {
@@ -1732,7 +1732,7 @@
GlobalVar(Sym(), ty.array(T, V));
GlobalVar(Sym(), ty.vec3(T));
GlobalVar(Sym(), ty.mat3x2(T));
- GlobalVar(Sym(), ty.ptr(builtin::AddressSpace::kPrivate, T));
+ GlobalVar(Sym(), ty.ptr<private_>(T));
GlobalVar(Sym(), ty.sampled_texture(type::TextureDimension::k2d, T));
GlobalVar(Sym(), ty.depth_texture(type::TextureDimension::k2d));
GlobalVar(Sym(), ty.depth_multisampled_texture(type::TextureDimension::k2d));
diff --git a/src/tint/resolver/dual_source_blending_extension_test.cc b/src/tint/resolver/dual_source_blending_extension_test.cc
new file mode 100644
index 0000000..ebaf61c
--- /dev/null
+++ b/src/tint/resolver/dual_source_blending_extension_test.cc
@@ -0,0 +1,88 @@
+// 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/resolver/resolver.h"
+#include "src/tint/resolver/resolver_test_helper.h"
+
+#include "gmock/gmock.h"
+
+using namespace tint::number_suffixes; // NOLINT
+
+namespace tint::resolver {
+namespace {
+
+using DualSourceBlendingExtensionTest = ResolverTest;
+
+// Using the @index attribute without chromium_internal_dual_source_blending enabled should fail.
+TEST_F(DualSourceBlendingExtensionTest, UseIndexAttribWithoutExtensionError) {
+ Structure("Output", utils::Vector{
+ Member("a", ty.vec4<f32>(),
+ utils::Vector{Location(0_a), Index(Source{{12, 34}}, 0_a)}),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ "12:34 error: use of '@index' attribute requires enabling extension "
+ "'chromium_internal_dual_source_blending'");
+}
+
+TEST_F(DualSourceBlendingExtensionTest, IndexF32Error) {
+ Enable(builtin::Extension::kChromiumInternalDualSourceBlending);
+
+ Structure("Output", utils::Vector{
+ Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
+ utils::Vector{Location(0_a), Index(Source{{12, 34}}, 0_f)}),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: @location must be an i32 or u32 value");
+}
+
+TEST_F(DualSourceBlendingExtensionTest, IndexFloatValueError) {
+ Enable(builtin::Extension::kChromiumInternalDualSourceBlending);
+
+ Structure("Output", utils::Vector{
+ Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
+ utils::Vector{Location(0_a), Index(Source{{12, 34}}, 1.0_a)}),
+ });
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: @location must be an i32 or u32 value");
+}
+
+TEST_F(DualSourceBlendingExtensionTest, IndexNegativeValue) {
+ Enable(builtin::Extension::kChromiumInternalDualSourceBlending);
+
+ Structure("Output", utils::Vector{
+ Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
+ utils::Vector{Location(0_a), Index(Source{{12, 34}}, -1_a)}),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: @index value must be zero or one");
+}
+
+TEST_F(DualSourceBlendingExtensionTest, IndexValueAboveOne) {
+ Enable(builtin::Extension::kChromiumInternalDualSourceBlending);
+
+ Structure("Output", utils::Vector{
+ Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
+ utils::Vector{Location(0_a), Index(Source{{12, 34}}, 2_a)}),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: @index value must be zero or one");
+}
+
+} // namespace
+} // namespace tint::resolver
diff --git a/src/tint/resolver/entry_point_validation_test.cc b/src/tint/resolver/entry_point_validation_test.cc
index eb2d779..4da98db 100644
--- a/src/tint/resolver/entry_point_validation_test.cc
+++ b/src/tint/resolver/entry_point_validation_test.cc
@@ -22,27 +22,16 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
// Helpers and typedefs
template <typename T>
using DataType = builder::DataType<T>;
template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-template <typename T>
-using mat2x2 = builder::mat2x2<T>;
-template <typename T>
-using mat3x3 = builder::mat3x3<T>;
-template <typename T>
-using mat4x4 = builder::mat4x4<T>;
-template <typename T>
using alias = builder::alias<T>;
class ResolverEntryPointValidationTest : public TestHelper, public testing::Test {};
@@ -69,7 +58,7 @@
// fn main() -> @builtin(position) vec4<f32> { return vec4<f32>(); }
Func(Source{{12, 34}}, "main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
@@ -88,7 +77,7 @@
// }
Func(Source{{12, 34}}, "main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
@@ -105,7 +94,7 @@
// }
Func(Source{{12, 34}}, "main", utils::Empty, ty.vec4<f32>(),
utils::Vector{
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
@@ -793,7 +782,7 @@
Func(Source{{12, 34}}, "frag_main", utils::Empty, ty.array<f32, 2>(),
utils::Vector{
- Return(Call(ty.array<f32, 2>())),
+ Return(Call<array<f32, 2>>()),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
diff --git a/src/tint/resolver/evaluation_stage_test.cc b/src/tint/resolver/evaluation_stage_test.cc
index 2e148e5..c9c9e97 100644
--- a/src/tint/resolver/evaluation_stage_test.cc
+++ b/src/tint/resolver/evaluation_stage_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
#include "src/tint/resolver/resolver_test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverEvaluationStageTest = ResolverTest;
TEST_F(ResolverEvaluationStageTest, Literal_i32) {
@@ -41,7 +42,7 @@
}
TEST_F(ResolverEvaluationStageTest, Vector_Init) {
- auto* expr = vec3<f32>();
+ auto* expr = Call<vec3<f32>>();
WrapInFunction(expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -52,7 +53,7 @@
// const f = 1.f;
// vec2<f32>(f, f);
auto* f = Const("f", Expr(1_f));
- auto* expr = vec2<f32>(f, f);
+ auto* expr = Call<vec2<f32>>(f, f);
WrapInFunction(f, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -64,7 +65,7 @@
// var f = 1.f;
// vec2<f32>(f, f);
auto* f = Var("f", Expr(1_f));
- auto* expr = vec2<f32>(f, f);
+ auto* expr = Call<vec2<f32>>(f, f);
WrapInFunction(f, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -76,7 +77,7 @@
// const f = 1.f;
// vec2<u32>(vec2<f32>(f));
auto* f = Const("f", Expr(1_f));
- auto* expr = vec2<u32>(vec2<f32>(f));
+ auto* expr = Call<vec2<u32>>(Call<vec2<f32>>(f));
WrapInFunction(f, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -88,7 +89,7 @@
// var f = 1.f;
// vec2<u32>(vec2<f32>(f));
auto* f = Var("f", Expr(1_f));
- auto* expr = vec2<u32>(vec2<f32>(f));
+ auto* expr = Call<vec2<u32>>(Call<vec2<f32>>(f));
WrapInFunction(f, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -97,7 +98,7 @@
}
TEST_F(ResolverEvaluationStageTest, Matrix_Init) {
- auto* expr = mat2x2<f32>();
+ auto* expr = Call<mat2x2<f32>>();
WrapInFunction(expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -105,7 +106,7 @@
}
TEST_F(ResolverEvaluationStageTest, Array_Init) {
- auto* expr = array<f32, 3>();
+ auto* expr = Call<array<f32, 3>>();
WrapInFunction(expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -116,7 +117,7 @@
// const f = 1.f;
// array<f32, 2>(f, f);
auto* f = Const("f", Expr(1_f));
- auto* expr = Call(ty.array<f32, 2>(), f, f);
+ auto* expr = Call<array<f32, 2>>(f, f);
WrapInFunction(f, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -130,7 +131,7 @@
// array<f32, 2>(f1, f2);
auto* f1 = Const("f1", Expr(1_f));
auto* f2 = Override("f2", Expr(2_f));
- auto* expr = Call(ty.array<f32, 2>(), f1, f2);
+ auto* expr = Call<array<f32, 2>>(f1, f2);
WrapInFunction(f1, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -145,7 +146,7 @@
// array<f32, 2>(f1, f2);
auto* f1 = Override("f1", Expr(1_f));
auto* f2 = Var("f2", Expr(2_f));
- auto* expr = Call(ty.array<f32, 2>(), f1, f2);
+ auto* expr = Call<array<f32, 2>>(f1, f2);
WrapInFunction(f2, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -160,7 +161,7 @@
// array<f32, 2>(f1, f2);
auto* f1 = Const("f1", Expr(1_f));
auto* f2 = Var("f2", Expr(2_f));
- auto* expr = Call(ty.array<f32, 2>(), f1, f2);
+ auto* expr = Call<array<f32, 2>>(f1, f2);
WrapInFunction(f1, f2, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -173,7 +174,7 @@
// var f = 1.f;
// array<f32, 2>(f, f);
auto* f = Var("f", Expr(1_f));
- auto* expr = Call(ty.array<f32, 2>(), f, f);
+ auto* expr = Call<array<f32, 2>>(f, f);
WrapInFunction(f, expr);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -185,7 +186,7 @@
// const vec = vec4<f32>();
// const idx = 1_i;
// vec[idx]
- auto* vec = Const("vec", vec4<f32>());
+ auto* vec = Const("vec", Call<vec4<f32>>());
auto* idx = Const("idx", Expr(1_i));
auto* expr = IndexAccessor(vec, idx);
WrapInFunction(vec, idx, expr);
@@ -200,7 +201,7 @@
// var vec = vec4<f32>();
// const idx = 1_i;
// vec[idx]
- auto* vec = Var("vec", vec4<f32>());
+ auto* vec = Var("vec", Call<vec4<f32>>());
auto* idx = Const("idx", Expr(1_i));
auto* expr = IndexAccessor(vec, idx);
WrapInFunction(vec, idx, expr);
@@ -215,7 +216,7 @@
// const vec = vec4<f32>();
// override idx = 1_i;
// vec[idx]
- auto* vec = Const("vec", vec4<f32>());
+ auto* vec = Const("vec", Call<vec4<f32>>());
auto* idx = Override("idx", Expr(1_i));
auto* expr = IndexAccessor(vec, idx);
WrapInFunction(vec, expr);
@@ -230,7 +231,7 @@
// const vec = vec4<f32>();
// let idx = 1_i;
// vec[idx]
- auto* vec = Const("vec", vec4<f32>());
+ auto* vec = Const("vec", Call<vec4<f32>>());
auto* idx = Let("idx", Expr(1_i));
auto* expr = IndexAccessor(vec, idx);
WrapInFunction(vec, idx, expr);
@@ -244,7 +245,7 @@
TEST_F(ResolverEvaluationStageTest, Swizzle_Const) {
// const vec = S();
// vec.m
- auto* vec = Const("vec", vec4<f32>());
+ auto* vec = Const("vec", Call<vec4<f32>>());
auto* expr = MemberAccessor(vec, "xz");
WrapInFunction(vec, expr);
@@ -256,7 +257,7 @@
TEST_F(ResolverEvaluationStageTest, Swizzle_Runtime) {
// var vec = S();
// vec.m
- auto* vec = Var("vec", vec4<f32>());
+ auto* vec = Var("vec", Call<vec4<f32>>());
auto* expr = MemberAccessor(vec, "rg");
WrapInFunction(vec, expr);
diff --git a/src/tint/resolver/f16_extension_test.cc b/src/tint/resolver/f16_extension_test.cc
index 0868208..8e4ad02 100644
--- a/src/tint/resolver/f16_extension_test.cc
+++ b/src/tint/resolver/f16_extension_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverF16ExtensionTest = ResolverTest;
TEST_F(ResolverF16ExtensionTest, TypeUsedWithExtension) {
@@ -65,7 +66,7 @@
// var<private> v = vec2<f16>();
Enable(builtin::Extension::kF16);
- GlobalVar("v", vec2<f16>(), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec2<f16>>(), builtin::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
@@ -83,14 +84,15 @@
// var<private> v = vec2<f16>(vec2<f32>());
Enable(builtin::Extension::kF16);
- GlobalVar("v", vec2<f16>(vec2<f32>()), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec2<f16>>(Call<vec2<f32>>()), builtin::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverF16ExtensionTest, Vec2TypeConvUsedWithoutExtension) {
// var<private> v = vec2<f16>(vec2<f32>());
- GlobalVar("v", vec2(ty.f16(Source{{12, 34}}), vec2<f32>()), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call(ty.vec2(ty.f16(Source{{12, 34}})), Call<vec2<f32>>()),
+ builtin::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: f16 type used without 'f16' extension enabled");
diff --git a/src/tint/resolver/function_validation_test.cc b/src/tint/resolver/function_validation_test.cc
index b97e7f3..1ea121d 100644
--- a/src/tint/resolver/function_validation_test.cc
+++ b/src/tint/resolver/function_validation_test.cc
@@ -22,11 +22,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
class ResolverFunctionValidationTest : public TestHelper, public testing::Test {};
TEST_F(ResolverFunctionValidationTest, DuplicateParameterName) {
@@ -187,7 +188,7 @@
Func(Source{{1, 2}}, "func", utils::Empty, ty.vec4<f32>(),
utils::Vector{
Discard(Source{{12, 34}}),
- Return(Call(ty.vec4<f32>())),
+ Return(Call<vec4<f32>>()),
},
utils::Vector{Stage(ast::PipelineStage::kVertex)},
utils::Vector{Builtin(builtin::BuiltinValue::kPosition)});
@@ -926,7 +927,7 @@
}
TEST_F(ResolverFunctionValidationTest, ReturnIsConstructible_NonPlain) {
- auto ret_type = ty.ptr(Source{{12, 34}}, builtin::AddressSpace::kFunction, ty.i32());
+ auto ret_type = ty.ptr<function, i32>(Source{{12, 34}});
Func("f", utils::Empty, ret_type, utils::Empty);
EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/increment_decrement_validation_test.cc b/src/tint/resolver/increment_decrement_validation_test.cc
index c3a0c78..b0ce2e3 100644
--- a/src/tint/resolver/increment_decrement_validation_test.cc
+++ b/src/tint/resolver/increment_decrement_validation_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
#include "src/tint/resolver/resolver_test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverIncrementDecrementValidationTest = ResolverTest;
TEST_F(ResolverIncrementDecrementValidationTest, Increment_Signed) {
@@ -65,7 +66,7 @@
// let b : ptr<function,i32> = &a;
// *b++;
auto* var_a = Var("a", ty.i32(), builtin::AddressSpace::kFunction);
- auto* var_b = Let("b", ty.ptr<i32>(builtin::AddressSpace::kFunction), AddressOf(Expr("a")));
+ auto* var_b = Let("b", ty.ptr<function, i32>(), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b, Increment(Source{{12, 34}}, Deref("b")));
EXPECT_TRUE(r()->Resolve()) << r()->error();
diff --git a/src/tint/resolver/inferred_type_test.cc b/src/tint/resolver/inferred_type_test.cc
index 4545419..b6b5481 100644
--- a/src/tint/resolver/inferred_type_test.cc
+++ b/src/tint/resolver/inferred_type_test.cc
@@ -17,27 +17,16 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
// Helpers and typedefs
template <typename T>
using DataType = builder::DataType<T>;
template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-template <typename T>
-using mat2x2 = builder::mat2x2<T>;
-template <typename T>
-using mat3x3 = builder::mat3x3<T>;
-template <typename T>
-using mat4x4 = builder::mat4x4<T>;
-template <typename T>
using alias = builder::alias<T>;
struct ResolverInferredTypeTest : public resolver::TestHelper, public testing::Test {};
diff --git a/src/tint/resolver/intrinsic_table_test.cc b/src/tint/resolver/intrinsic_table_test.cc
index 1d5627c..7b658ad8 100644
--- a/src/tint/resolver/intrinsic_table_test.cc
+++ b/src/tint/resolver/intrinsic_table_test.cc
@@ -36,15 +36,16 @@
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
using Parameter = sem::Parameter;
using ParameterUsage = sem::ParameterUsage;
-using AFloatV = builder::vec<3, AFloat>;
-using AIntV = builder::vec<3, AInt>;
-using f32V = builder::vec<3, f32>;
-using i32V = builder::vec<3, i32>;
-using u32V = builder::vec<3, u32>;
+using AFloatV = vec3<AFloat>;
+using AIntV = vec3<AInt>;
+using f32V = vec3<f32>;
+using i32V = vec3<i32>;
+using u32V = vec3<u32>;
class IntrinsicTableTest : public testing::Test, public ProgramBuilder {
public:
diff --git a/src/tint/resolver/is_storeable_test.cc b/src/tint/resolver/is_storeable_test.cc
index 65c1ab9..b7fa0e8 100644
--- a/src/tint/resolver/is_storeable_test.cc
+++ b/src/tint/resolver/is_storeable_test.cc
@@ -18,6 +18,8 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/type/atomic.h"
+using namespace tint::builtin::fluent_types; // NOLINT
+
namespace tint::resolver {
namespace {
@@ -112,7 +114,7 @@
TEST_F(ResolverIsStorableTest, Struct_SomeMembersNonStorable) {
Structure("S", utils::Vector{
Member("a", ty.i32()),
- Member("b", ty.ptr<i32>(builtin::AddressSpace::kPrivate)),
+ Member("b", ty.ptr<private_, i32>()),
});
EXPECT_FALSE(r()->Resolve());
@@ -135,11 +137,10 @@
}
TEST_F(ResolverIsStorableTest, Struct_NestedNonStorable) {
- auto* non_storable =
- Structure("nonstorable", utils::Vector{
- Member("a", ty.i32()),
- Member("b", ty.ptr<i32>(builtin::AddressSpace::kPrivate)),
- });
+ auto* non_storable = Structure("nonstorable", utils::Vector{
+ Member("a", ty.i32()),
+ Member("b", ty.ptr<private_, i32>()),
+ });
Structure("S", utils::Vector{
Member("a", ty.i32()),
Member("b", ty.Of(non_storable)),
diff --git a/src/tint/resolver/load_test.cc b/src/tint/resolver/load_test.cc
index 2334227..48b9886 100644
--- a/src/tint/resolver/load_test.cc
+++ b/src/tint/resolver/load_test.cc
@@ -20,11 +20,12 @@
#include "src/tint/type/reference.h"
#include "src/tint/type/texture_dimension.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverLoadTest = ResolverTest;
TEST_F(ResolverLoadTest, VarInitializer) {
@@ -140,7 +141,7 @@
// var v = array<i32, 3>(1i, 2i, 3i)[ref];
auto* ident = Expr("ref");
WrapInFunction(Var("ref", Expr(1_i)), //
- IndexAccessor(array<i32, 3>(1_i, 2_i, 3_i), ident));
+ IndexAccessor(Call<array<i32, 3>>(1_i, 2_i, 3_i), ident));
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* load = Sem().Get<sem::Load>(ident);
@@ -154,7 +155,7 @@
// var ref = vec4(1);
// var v = ref.xyz;
auto* ident = Expr("ref");
- WrapInFunction(Var("ref", vec4<i32>(1_i)), //
+ WrapInFunction(Var("ref", Call<vec4<i32>>(1_i)), //
Var("v", MemberAccessor(ident, "xyz")));
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -230,7 +231,7 @@
},
ty.vec4<f32>(),
utils::Vector{
- Return(Call("textureSampleLevel", "tp", "sp", vec2<f32>(), 0_a)),
+ Return(Call("textureSampleLevel", "tp", "sp", Call<vec2<f32>>(), 0_a)),
});
auto* t_ident = Expr("t");
auto* s_ident = Expr("s");
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index cf67c93..7a45bf8 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -21,26 +21,27 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
-using AFloatV = builder::vec<3, AFloat>;
-using AFloatM = builder::mat<3, 2, AFloat>;
-using AFloatA = builder::array<3, AFloat>;
-using AIntV = builder::vec<3, AInt>;
-using AIntA = builder::array<3, AInt>;
-using f32V = builder::vec<3, f32>;
-using f16V = builder::vec<3, f16>;
-using i32V = builder::vec<3, i32>;
-using u32V = builder::vec<3, u32>;
-using f32M = builder::mat<3, 2, f32>;
-using f16M = builder::mat<3, 2, f16>;
-using f32A = builder::array<3, f32>;
-using f16A = builder::array<3, f16>;
-using i32A = builder::array<3, i32>;
-using u32A = builder::array<3, u32>;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
+using AFloatV = vec3<AFloat>;
+using AFloatM = mat3x2<AFloat>;
+using AFloatA = array<AFloat, 3>;
+using AIntV = vec3<AInt>;
+using AIntA = array<AInt, 3>;
+using f32V = vec3<f32>;
+using f16V = vec3<f16>;
+using i32V = vec3<i32>;
+using u32V = vec3<u32>;
+using f32M = mat3x2<f32>;
+using f16M = mat3x2<f16>;
+using f32A = array<f32, 3>;
+using f16A = array<f16, 3>;
+using i32A = array<i32, 3>;
+using u32A = array<u32, 3>;
constexpr double kTooBigF32 = static_cast<double>(3.5e+38);
constexpr double kTooBigF16 = static_cast<double>(6.6e+4);
@@ -1276,7 +1277,7 @@
TEST_F(MaterializeAbstractStructure, Modf_Vector_DefaultType) {
// var v = modf(vec2(1));
- auto* call = Call("modf", Call(ty.vec2<Infer>(), 1_a));
+ auto* call = Call("modf", Call<vec2<Infer>>(1_a));
WrapInFunction(Decl(Var("v", call)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(call);
@@ -1316,8 +1317,8 @@
// var v = modf(vec2(1_h)); // v is __modf_result_vec2_f16
// v = modf(vec2(1)); // __modf_result_vec2_f16 <- __modf_result_vec2_abstract
Enable(builtin::Extension::kF16);
- auto* call = Call("modf", Call(ty.vec2<Infer>(), 1_a));
- WrapInFunction(Decl(Var("v", Call("modf", Call(ty.vec2<Infer>(), 1_h)))), Assign("v", call));
+ auto* call = Call("modf", Call<vec2<Infer>>(1_a));
+ WrapInFunction(Decl(Var("v", Call("modf", Call<vec2<Infer>>(1_h)))), Assign("v", call));
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(call);
ASSERT_TRUE(sem->Is<sem::Materialize>());
@@ -1353,7 +1354,7 @@
TEST_F(MaterializeAbstractStructure, Frexp_Vector_DefaultType) {
// var v = frexp(vec2(1));
- auto* call = Call("frexp", Call(ty.vec2<Infer>(), 1_a));
+ auto* call = Call("frexp", Call<vec2<Infer>>(1_a));
WrapInFunction(Decl(Var("v", call)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(call);
@@ -1399,8 +1400,8 @@
// var v = frexp(vec2(1_h)); // v is __frexp_result_vec2_f16
// v = frexp(vec2(1)); // __frexp_result_vec2_f16 <- __frexp_result_vec2_abstract
Enable(builtin::Extension::kF16);
- auto* call = Call("frexp", Call(ty.vec2<Infer>(), 1_a));
- WrapInFunction(Decl(Var("v", Call("frexp", Call(ty.vec2<Infer>(), 1_h)))), Assign("v", call));
+ auto* call = Call("frexp", Call<vec2<Infer>>(1_a));
+ WrapInFunction(Decl(Var("v", Call("frexp", Call<vec2<Infer>>(1_h)))), Assign("v", call));
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(call);
ASSERT_TRUE(sem->Is<sem::Materialize>());
diff --git a/src/tint/resolver/ptr_ref_validation_test.cc b/src/tint/resolver/ptr_ref_validation_test.cc
index f6da233..2da5cf0 100644
--- a/src/tint/resolver/ptr_ref_validation_test.cc
+++ b/src/tint/resolver/ptr_ref_validation_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/type/reference.h"
#include "src/tint/type/texture_dimension.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
struct ResolverPtrRefValidationTest : public resolver::TestHelper, public testing::Test {};
TEST_F(ResolverPtrRefValidationTest, AddressOfLiteral) {
@@ -143,12 +144,11 @@
// }
auto* inner = Structure("Inner", utils::Vector{Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", utils::Vector{Member("inner", ty.Of(inner))});
- auto* storage = GlobalVar("s", ty.Of(buf), builtin::AddressSpace::kStorage,
- builtin::Access::kReadWrite, Binding(0_a), Group(0_a));
+ auto* var = GlobalVar("s", ty.Of(buf), builtin::AddressSpace::kStorage,
+ builtin::Access::kReadWrite, Binding(0_a), Group(0_a));
- auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 2_i);
- auto* ptr =
- Let(Source{{12, 34}}, "p", ty.ptr<i32>(builtin::AddressSpace::kStorage), AddressOf(expr));
+ auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(var, "inner"), "arr"), 2_i);
+ auto* ptr = Let(Source{{12, 34}}, "p", ty.ptr<storage, i32>(), AddressOf(expr));
WrapInFunction(ptr);
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 74a462a..51bf27c 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -3570,6 +3570,30 @@
return static_cast<uint32_t>(value);
}
+utils::Result<uint32_t> Resolver::IndexAttribute(const ast::IndexAttribute* attr) {
+ ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@index value"};
+ TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
+
+ auto* materialized = Materialize(ValueExpression(attr->expr));
+ if (!materialized) {
+ return utils::Failure;
+ }
+
+ if (!materialized->Type()->IsAnyOf<type::I32, type::U32>()) {
+ AddError("@location must be an i32 or u32 value", attr->source);
+ return utils::Failure;
+ }
+
+ auto const_value = materialized->ConstantValue();
+ auto value = const_value->ValueAs<AInt>();
+ if (value != 0 && value != 1) {
+ AddError("@index value must be zero or one", attr->source);
+ return utils::Failure;
+ }
+
+ return static_cast<uint32_t>(value);
+}
+
utils::Result<uint32_t> Resolver::BindingAttribute(const ast::BindingAttribute* attr) {
ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@binding"};
TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
@@ -4142,6 +4166,14 @@
attributes.location = value.Get();
return true;
},
+ [&](const ast::IndexAttribute* attr) {
+ auto value = IndexAttribute(attr);
+ if (!value) {
+ return false;
+ }
+ attributes.index = value.Get();
+ return true;
+ },
[&](const ast::BuiltinAttribute* attr) {
auto value = BuiltinAttribute(attr);
if (!value) {
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 5d13d25..46ac83f 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -320,6 +320,10 @@
/// @returns the location value on success.
utils::Result<uint32_t> LocationAttribute(const ast::LocationAttribute* attr);
+ /// Resolves the `@index` attribute @p attr
+ /// @returns the index value on success.
+ utils::Result<uint32_t> IndexAttribute(const ast::IndexAttribute* attr);
+
/// Resolves the `@binding` attribute @p attr
/// @returns the binding value on success.
utils::Result<uint32_t> BindingAttribute(const ast::BindingAttribute* attr);
diff --git a/src/tint/resolver/resolver_behavior_test.cc b/src/tint/resolver/resolver_behavior_test.cc
index bc4af42..378642b 100644
--- a/src/tint/resolver/resolver_behavior_test.cc
+++ b/src/tint/resolver/resolver_behavior_test.cc
@@ -22,11 +22,12 @@
#include "src/tint/sem/value_expression.h"
#include "src/tint/sem/while_statement.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
class ResolverBehaviorTest : public ResolverTest {
protected:
void SetUp() override {
@@ -82,7 +83,7 @@
Func("ArrayDiscardOrNext", utils::Empty, ty.array<i32, 4>(),
utils::Vector{
If(true, Block(Discard())),
- Return(array<i32, 4>()),
+ Return(Call<array<i32, 4>>()),
});
auto* stmt = Decl(Var("lhs", ty.i32(), IndexAccessor(Call("ArrayDiscardOrNext"), 1_i)));
diff --git a/src/tint/resolver/resolver_test.cc b/src/tint/resolver/resolver_test.cc
index eab9b86..c4d57aa 100644
--- a/src/tint/resolver/resolver_test.cc
+++ b/src/tint/resolver/resolver_test.cc
@@ -48,37 +48,18 @@
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/string_stream.h"
+namespace tint::resolver {
+namespace {
+
using ::testing::ElementsAre;
using ::testing::HasSubstr;
-using namespace tint::number_suffixes; // NOLINT
-
-namespace tint::resolver {
-namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
// Helpers and typedefs
template <typename T>
using DataType = builder::DataType<T>;
-template <int N, typename T>
-using vec = builder::vec<N, T>;
-template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-template <int N, int M, typename T>
-using mat = builder::mat<N, M, T>;
-template <typename T>
-using mat2x2 = builder::mat2x2<T>;
-template <typename T>
-using mat2x3 = builder::mat2x3<T>;
-template <typename T>
-using mat3x2 = builder::mat3x2<T>;
-template <typename T>
-using mat3x3 = builder::mat3x3<T>;
-template <typename T>
-using mat4x4 = builder::mat4x4<T>;
template <typename T, int ID = 0>
using alias = builder::alias<T, ID>;
template <typename T>
@@ -666,7 +647,7 @@
}
TEST_F(ResolverTest, Expr_Initializer_Type_Vec2) {
- auto* tc = vec2<f32>(1_f, 1_f);
+ auto* tc = Call<vec2<f32>>(1_f, 1_f);
WrapInFunction(tc);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -678,7 +659,7 @@
}
TEST_F(ResolverTest, Expr_Initializer_Type_Vec3) {
- auto* tc = vec3<f32>(1_f, 1_f, 1_f);
+ auto* tc = Call<vec3<f32>>(1_f, 1_f, 1_f);
WrapInFunction(tc);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -690,7 +671,7 @@
}
TEST_F(ResolverTest, Expr_Initializer_Type_Vec4) {
- auto* tc = vec4<f32>(1_f, 1_f, 1_f, 1_f);
+ auto* tc = Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f);
WrapInFunction(tc);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -756,7 +737,7 @@
// var a : array<bool, 10u> = 0;
// var idx : f32 = f32();
// var f : f32 = a[idx];
- auto* a = Var("a", ty.array<bool, 10>(), array<bool, 10>());
+ auto* a = Var("a", ty.array<bool, 10>(), Call<array<bool, 10>>());
auto* idx = Var("idx", ty.f32(), Call<f32>());
auto* f = Var("f", ty.f32(), IndexAccessor("a", Expr(Source{{12, 34}}, idx)));
Func("my_func", utils::Empty, ty.void_(),
@@ -803,7 +784,7 @@
auto* v = Expr("v");
auto* p = Expr("p");
auto* v_decl = Decl(Var("v", ty.f32()));
- auto* p_decl = Decl(Let("p", ty.ptr<f32>(builtin::AddressSpace::kFunction), AddressOf(v)));
+ auto* p_decl = Decl(Let("p", ty.ptr<function, f32>(), AddressOf(v)));
auto* assign = Assign(Deref(p), 1.23_f);
Func("my_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2138,7 +2119,7 @@
Binding(1_a));
GlobalVar("s", ty.sampler(type::SamplerKind::kSampler), Group(1_a), Binding(2_a));
- auto* call = Call("textureSample", "t", "s", vec2<f32>(1_f, 2_f));
+ auto* call = Call("textureSample", "t", "s", Call<vec2<f32>>(1_f, 2_f));
const ast::Function* f =
Func("test_function", utils::Empty, ty.void_(), utils::Vector{Assign(Phony(), call)},
utils::Vector{Stage(ast::PipelineStage::kFragment)});
@@ -2157,7 +2138,7 @@
Binding(1_a));
GlobalVar("s", ty.sampler(type::SamplerKind::kSampler), Group(1_a), Binding(2_a));
- auto* inner_call = Assign(Phony(), Call("textureSample", "t", "s", vec2<f32>(1_f, 2_f)));
+ auto* inner_call = Assign(Phony(), Call("textureSample", "t", "s", Call<vec2<f32>>(1_f, 2_f)));
const ast::Function* inner_func =
Func("inner_func", utils::Empty, ty.void_(), utils::Vector{inner_call});
auto* outer_call = CallStmt(Call("inner_func"));
@@ -2183,10 +2164,12 @@
Binding(1_a));
GlobalVar("s", ty.sampler(type::SamplerKind::kSampler), Group(1_a), Binding(2_a));
- auto* inner_call_1 = Assign(Phony(), Call("textureSample", "t", "s", vec2<f32>(1_f, 2_f)));
+ auto* inner_call_1 =
+ Assign(Phony(), Call("textureSample", "t", "s", Call<vec2<f32>>(1_f, 2_f)));
const ast::Function* inner_func_1 =
Func("inner_func_1", utils::Empty, ty.void_(), utils::Vector{inner_call_1});
- auto* inner_call_2 = Assign(Phony(), Call("textureSample", "t", "s", vec2<f32>(3_f, 4_f)));
+ auto* inner_call_2 =
+ Assign(Phony(), Call("textureSample", "t", "s", Call<vec2<f32>>(3_f, 4_f)));
const ast::Function* inner_func_2 =
Func("inner_func_2", utils::Empty, ty.void_(), utils::Vector{inner_call_2});
auto* outer_call_1 = CallStmt(Call("inner_func_1"));
@@ -2220,10 +2203,12 @@
Binding(2_a));
GlobalVar("s", ty.sampler(type::SamplerKind::kSampler), Group(1_a), Binding(3_a));
- auto* inner_call_1 = Assign(Phony(), Call("textureSample", "t1", "s", vec2<f32>(1_f, 2_f)));
+ auto* inner_call_1 =
+ Assign(Phony(), Call("textureSample", "t1", "s", Call<vec2<f32>>(1_f, 2_f)));
const ast::Function* inner_func_1 =
Func("inner_func_1", utils::Empty, ty.void_(), utils::Vector{inner_call_1});
- auto* inner_call_2 = Assign(Phony(), Call("textureSample", "t2", "s", vec2<f32>(3_f, 4_f)));
+ auto* inner_call_2 =
+ Assign(Phony(), Call("textureSample", "t2", "s", Call<vec2<f32>>(3_f, 4_f)));
const ast::Function* inner_func_2 =
Func("inner_func_2", utils::Empty, ty.void_(), utils::Vector{inner_call_2});
auto* outer_call_1 = CallStmt(Call("inner_func_1"));
@@ -2299,10 +2284,9 @@
Func("helper",
utils::Vector{
- Param("sl", ty.ptr(builtin::AddressSpace::kFunction,
- ty.sampler(type::SamplerKind::kSampler))),
- Param("tl", ty.ptr(builtin::AddressSpace::kFunction,
- ty.sampled_texture(type::TextureDimension::k2d, ty.f32()))),
+ Param("sl", ty.ptr<function>(ty.sampler(type::SamplerKind::kSampler))),
+ Param("tl",
+ ty.ptr<function>(ty.sampled_texture(type::TextureDimension::k2d, ty.f32()))),
},
ty.vec4<f32>(),
utils::Vector{
@@ -2537,7 +2521,7 @@
}
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfVector_Valid) {
- auto a = ty.array(ty.vec3<i32>(), 10_u);
+ auto a = ty.array<vec3<i32>, 10>();
size_t depth = 2; // Depth of array + vector
size_t iterations = kMaxNestDepthOfCompositeType - depth;
for (size_t i = 0; i < iterations; ++i) {
diff --git a/src/tint/resolver/resolver_test_helper.h b/src/tint/resolver/resolver_test_helper.h
index 706ba89..4f72b9c 100644
--- a/src/tint/resolver/resolver_test_helper.h
+++ b/src/tint/resolver/resolver_test_helper.h
@@ -130,51 +130,6 @@
namespace builder {
-template <uint32_t N, typename T>
-struct vec {};
-
-template <typename T>
-using vec2 = vec<2, T>;
-
-template <typename T>
-using vec3 = vec<3, T>;
-
-template <typename T>
-using vec4 = vec<4, T>;
-
-template <uint32_t N, uint32_t M, typename T>
-struct mat {};
-
-template <typename T>
-using mat2x2 = mat<2, 2, T>;
-
-template <typename T>
-using mat2x3 = mat<2, 3, T>;
-
-template <typename T>
-using mat2x4 = mat<2, 4, T>;
-
-template <typename T>
-using mat3x2 = mat<3, 2, T>;
-
-template <typename T>
-using mat3x3 = mat<3, 3, T>;
-
-template <typename T>
-using mat3x4 = mat<3, 4, T>;
-
-template <typename T>
-using mat4x2 = mat<4, 2, T>;
-
-template <typename T>
-using mat4x3 = mat<4, 3, T>;
-
-template <typename T>
-using mat4x4 = mat<4, 4, T>;
-
-template <uint32_t N, typename T>
-struct array {};
-
template <typename TO, int ID = 0>
struct alias {};
@@ -187,9 +142,6 @@
template <typename TO>
using alias3 = alias<TO, 3>;
-template <typename TO>
-struct ptr {};
-
/// A scalar value
using Scalar = std::variant<i32, u32, f32, f16, AInt, AFloat, bool>;
@@ -446,7 +398,7 @@
/// Helper for building vector types and expressions
template <uint32_t N, typename T>
-struct DataType<vec<N, T>> {
+struct DataType<builtin::fluent_types::vec<N, T>> {
/// The element type
using ElementType = T;
@@ -457,7 +409,7 @@
/// @return a new AST vector type
static inline ast::Type AST(ProgramBuilder& b) {
if (IsInferOrAbstract<T>) {
- return b.ty.vec<Infer, N>();
+ return b.ty.vec<builtin::fluent_types::Infer, N>();
} else {
return b.ty.vec(DataType<T>::AST(b), N);
}
@@ -498,7 +450,7 @@
/// Helper for building matrix types and expressions
template <uint32_t N, uint32_t M, typename T>
-struct DataType<mat<N, M, T>> {
+struct DataType<builtin::fluent_types::mat<N, M, T>> {
/// The element type
using ElementType = T;
@@ -509,7 +461,7 @@
/// @return a new AST matrix type
static inline ast::Type AST(ProgramBuilder& b) {
if (IsInferOrAbstract<T>) {
- return b.ty.mat<Infer, N, M>();
+ return b.ty.mat<builtin::fluent_types::Infer, N, M>();
} else {
return b.ty.mat(DataType<T>::AST(b), N, M);
}
@@ -535,13 +487,14 @@
utils::Vector<const ast::Expression*, N> r;
for (uint32_t i = 0; i < N; ++i) {
if (one_value) {
- r.Push(DataType<vec<M, T>>::Expr(b, utils::Vector<Scalar, 1>{args[0]}));
+ r.Push(DataType<builtin::fluent_types::vec<M, T>>::Expr(
+ b, utils::Vector<Scalar, 1>{args[0]}));
} else {
utils::Vector<Scalar, M> v;
for (size_t j = 0; j < M; ++j) {
v.Push(args[next++]);
}
- r.Push(DataType<vec<M, T>>::Expr(b, std::move(v)));
+ r.Push(DataType<builtin::fluent_types::vec<M, T>>::Expr(b, std::move(v)));
}
}
return r;
@@ -618,7 +571,8 @@
/// Helper for building pointer types and expressions
template <typename T>
-struct DataType<ptr<T>> {
+struct DataType<
+ builtin::fluent_types::ptr<builtin::AddressSpace::kPrivate, T, builtin::Access::kUndefined>> {
/// The element type
using ElementType = typename DataType<T>::ElementType;
@@ -628,9 +582,9 @@
/// @param b the ProgramBuilder
/// @return a new AST alias type
static inline ast::Type AST(ProgramBuilder& b) {
- return b.ty.ptr(builtin::AddressSpace::kPrivate, DataType<T>::AST(b),
- builtin::Access::kUndefined);
+ return b.ty.ptr<builtin::AddressSpace::kPrivate, T>();
}
+
/// @param b the ProgramBuilder
/// @return the semantic aliased type
static inline const type::Type* Sem(ProgramBuilder& b) {
@@ -659,8 +613,8 @@
};
/// Helper for building array types and expressions
-template <uint32_t N, typename T>
-struct DataType<array<N, T>> {
+template <typename T, uint32_t N>
+struct DataType<builtin::fluent_types::array<T, N>> {
/// The element type
using ElementType = typename DataType<T>::ElementType;
@@ -673,7 +627,7 @@
if (auto ast = DataType<T>::AST(b)) {
return b.ty.array(ast, u32(N));
}
- return b.ty.array<Infer>();
+ return b.ty.array<builtin::fluent_types::Infer>();
}
/// @param b the ProgramBuilder
/// @return the semantic array type
@@ -832,7 +786,7 @@
"Vector args must all be the same type");
constexpr size_t N = sizeof...(args);
utils::Vector<Scalar, sizeof...(args)> v{args...};
- return Value::Create<vec<N, FirstT>>(std::move(v));
+ return Value::Create<builtin::fluent_types::vec<N, FirstT>>(std::move(v));
}
/// Creates a Value of DataType<array<N, T>> from N scalar `args`
@@ -843,7 +797,7 @@
"Array args must all be the same type");
constexpr size_t N = sizeof...(args);
utils::Vector<Scalar, sizeof...(args)> v{args...};
- return Value::Create<array<N, FirstT>>(std::move(v));
+ return Value::Create<builtin::fluent_types::array<FirstT, N>>(std::move(v));
}
/// Creates a Value of DataType<mat<C,R,T> from C*R scalar `args`
@@ -855,7 +809,7 @@
m.Push(m_in[i][j]);
}
}
- return Value::Create<mat<C, R, T>>(std::move(m));
+ return Value::Create<builtin::fluent_types::mat<C, R, T>>(std::move(m));
}
/// Creates a Value of DataType<mat<2,R,T> from column vectors `c0` and `c1`
@@ -869,7 +823,7 @@
for (auto v : c1) {
m.Push(v);
}
- return Value::Create<mat<C, R, T>>(std::move(m));
+ return Value::Create<builtin::fluent_types::mat<C, R, T>>(std::move(m));
}
/// Creates a Value of DataType<mat<3,R,T> from column vectors `c0`, `c1`, and `c2`
@@ -886,7 +840,7 @@
for (auto v : c2) {
m.Push(v);
}
- return Value::Create<mat<C, R, T>>(std::move(m));
+ return Value::Create<builtin::fluent_types::mat<C, R, T>>(std::move(m));
}
/// Creates a Value of DataType<mat<4,R,T> from column vectors `c0`, `c1`, `c2`, and `c3`
@@ -906,7 +860,7 @@
for (auto v : c3) {
m.Push(v);
}
- return Value::Create<mat<C, R, T>>(std::move(m));
+ return Value::Create<builtin::fluent_types::mat<C, R, T>>(std::move(m));
}
} // namespace builder
} // namespace tint::resolver
diff --git a/src/tint/resolver/root_identifier_test.cc b/src/tint/resolver/root_identifier_test.cc
index 4ff43cb..f6d88f8 100644
--- a/src/tint/resolver/root_identifier_test.cc
+++ b/src/tint/resolver/root_identifier_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/type/texture_dimension.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
class ResolverRootIdentifierTest : public ResolverTest {};
TEST_F(ResolverRootIdentifierTest, GlobalPrivateVar) {
@@ -142,7 +143,7 @@
// {
// let b = a;
// }
- auto* param = Param("a", ty.ptr(builtin::AddressSpace::kFunction, ty.f32()));
+ auto* param = Param("a", ty.ptr<function, f32>());
auto* expr_param = Expr(param);
auto* let = Let("b", expr_param);
auto* expr_let = Expr("b");
diff --git a/src/tint/resolver/struct_pipeline_stage_use_test.cc b/src/tint/resolver/struct_pipeline_stage_use_test.cc
index b4857f0..70e6046 100644
--- a/src/tint/resolver/struct_pipeline_stage_use_test.cc
+++ b/src/tint/resolver/struct_pipeline_stage_use_test.cc
@@ -20,13 +20,13 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/sem/struct.h"
-using ::testing::UnorderedElementsAre;
-
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using ::testing::UnorderedElementsAre;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverPipelineStageUseTest = ResolverTest;
TEST_F(ResolverPipelineStageUseTest, UnusedStruct) {
@@ -68,7 +68,7 @@
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(0_a)})});
Func("main", utils::Vector{Param("param", ty.Of(s))}, ty.vec4<f32>(),
- utils::Vector{Return(Call(ty.vec4<f32>()))},
+ utils::Vector{Return(Call<vec4<f32>>())},
utils::Vector{Stage(ast::PipelineStage::kVertex)},
utils::Vector{Builtin(builtin::BuiltinValue::kPosition)});
diff --git a/src/tint/resolver/type_validation_test.cc b/src/tint/resolver/type_validation_test.cc
index de79f85..117b2ad 100644
--- a/src/tint/resolver/type_validation_test.cc
+++ b/src/tint/resolver/type_validation_test.cc
@@ -23,41 +23,16 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
// Helpers and typedefs
template <typename T>
using DataType = builder::DataType<T>;
template <typename T>
-using vec2 = builder::vec2<T>;
-template <typename T>
-using vec3 = builder::vec3<T>;
-template <typename T>
-using vec4 = builder::vec4<T>;
-template <typename T>
-using mat2x2 = builder::mat2x2<T>;
-template <typename T>
-using mat2x3 = builder::mat2x3<T>;
-template <typename T>
-using mat2x4 = builder::mat2x4<T>;
-template <typename T>
-using mat3x2 = builder::mat3x2<T>;
-template <typename T>
-using mat3x3 = builder::mat3x3<T>;
-template <typename T>
-using mat3x4 = builder::mat3x4<T>;
-template <typename T>
-using mat4x2 = builder::mat4x2<T>;
-template <typename T>
-using mat4x3 = builder::mat4x3<T>;
-template <typename T>
-using mat4x4 = builder::mat4x4<T>;
-template <int N, typename T>
-using array = builder::array<N, T>;
-template <typename T>
using alias = builder::alias<T>;
template <typename T>
using alias1 = builder::alias1<T>;
@@ -331,7 +306,7 @@
TEST_F(ResolverTypeValidationTest, ArraySize_IVecConst) {
// const size = vec2<i32>(100, 100);
// var<private> a : array<f32, size>;
- GlobalConst("size", Call(ty.vec2<i32>(), 100_i, 100_i));
+ GlobalConst("size", Call<vec2<i32>>(100_i, 100_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")),
builtin::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
@@ -881,7 +856,7 @@
}
TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableTypeWithStride) {
- auto ptr_ty = ty.ptr<u32>(Source{{12, 34}}, builtin::AddressSpace::kUniform);
+ auto ptr_ty = ty.ptr<uniform, u32>(Source{{12, 34}});
GlobalVar("arr", ty.array(ptr_ty, 4_i, utils::Vector{Stride(16)}),
builtin::AddressSpace::kPrivate);
@@ -1305,8 +1280,8 @@
ParamsFor<mat2x2<f16>>(3, 2),
ParamsFor<mat3x3<f16>>(3, 3),
ParamsFor<mat4x4<f16>>(3, 4),
- ParamsFor<array<2, f32>>(4, 2),
- ParamsFor<array<2, f16>>(4, 2)));
+ ParamsFor<array<f32, 2>>(4, 2),
+ ParamsFor<array<f16, 2>>(4, 2)));
} // namespace MatrixTests
namespace VectorTests {
@@ -1366,8 +1341,7 @@
builtin::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: vector element type must be 'bool', 'f32', 'f16', 'i32' "
- "or 'u32'");
+ "12:34 error: vector element type must be 'bool', 'f32', 'f16', 'i32' or 'u32'");
}
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
InvalidVectorElementTypes,
@@ -1377,7 +1351,7 @@
ParamsFor<mat2x2<f32>>(2),
ParamsFor<mat3x3<f16>>(2),
ParamsFor<mat4x4<f32>>(2),
- ParamsFor<array<2, f32>>(2)));
+ ParamsFor<array<f32, 2>>(2)));
} // namespace VectorTests
namespace BuiltinTypeAliasTests {
diff --git a/src/tint/resolver/uniformity_test.cc b/src/tint/resolver/uniformity_test.cc
index e890bcb..1cb9142 100644
--- a/src/tint/resolver/uniformity_test.cc
+++ b/src/tint/resolver/uniformity_test.cc
@@ -25,11 +25,12 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
class UniformityAnalysisTestBase {
protected:
/// Build and resolve a program from a ProgramBuilder object.
@@ -5301,8 +5302,7 @@
}
foo_body.Push(b.Decl(b.Let("rhs", rhs_init)));
for (int i = 0; i < 255; i++) {
- params.Push(
- b.Param("p" + std::to_string(i), ty.ptr(builtin::AddressSpace::kFunction, ty.i32())));
+ params.Push(b.Param("p" + std::to_string(i), ty.ptr<function, i32>()));
if (i > 0) {
foo_body.Push(b.Assign(b.Deref("p" + std::to_string(i)), "rhs"));
}
diff --git a/src/tint/resolver/validation_test.cc b/src/tint/resolver/validation_test.cc
index ca958ad..23fb56a 100644
--- a/src/tint/resolver/validation_test.cc
+++ b/src/tint/resolver/validation_test.cc
@@ -40,14 +40,14 @@
#include "src/tint/type/sampled_texture.h"
#include "src/tint/type/texture_dimension.h"
-using ::testing::ElementsAre;
-using ::testing::HasSubstr;
-
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using ::testing::ElementsAre;
+using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ResolverValidationTest = ResolverTest;
class FakeStmt final : public utils::Castable<FakeStmt, ast::Statement> {
@@ -380,7 +380,7 @@
// let x: f32 = (*p).z;
// return x;
// }
- auto* p = Param("p", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>()));
+ auto* p = Param("p", ty.ptr<function, vec4<f32>>());
auto* star_p = Deref(p);
auto* accessor_expr = MemberAccessor(star_p, "z");
auto* x = Var("x", ty.f32(), accessor_expr);
@@ -397,7 +397,7 @@
// let x: f32 = *p.z;
// return x;
// }
- auto* p = Param("p", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>()));
+ auto* p = Param("p", ty.ptr<function, vec4<f32>>());
auto* accessor_expr = MemberAccessor(p, Ident(Source{{12, 34}}, "z"));
auto* star_p = Deref(accessor_expr);
auto* x = Var("x", ty.f32(), star_p);
@@ -1234,8 +1234,8 @@
TEST_F(ResolverTest, Expr_Initializer_Cast_Pointer) {
auto* vf = Var("vf", ty.f32());
- auto* c = Call(Source{{12, 34}}, ty.ptr<i32>(builtin::AddressSpace::kFunction), ExprList(vf));
- auto* ip = Let("ip", ty.ptr<i32>(builtin::AddressSpace::kFunction), c);
+ auto* c = Call(Source{{12, 34}}, ty.ptr<function, i32>(), ExprList(vf));
+ auto* ip = Let("ip", ty.ptr<function, i32>(), c);
WrapInFunction(Decl(vf), Decl(ip));
EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index eb009c2..17b75e1 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -29,6 +29,7 @@
#include "src/tint/ast/for_loop_statement.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/if_statement.h"
+#include "src/tint/ast/index_attribute.h"
#include "src/tint/ast/internal_attribute.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/loop_statement.h"
@@ -1115,6 +1116,8 @@
is_input)) {
return false;
}
+ } else if (auto* index_attr = attr->As<ast::IndexAttribute>()) {
+ return IndexAttribute(index_attr);
} else if (auto* interpolate = attr->As<ast::InterpolateAttribute>()) {
if (decl->PipelineStage() == ast::PipelineStage::kCompute) {
is_invalid_compute_shader_attribute = true;
@@ -2113,6 +2116,7 @@
}
return true;
},
+ [&](const ast::IndexAttribute* index) { return IndexAttribute(index); },
[&](const ast::BuiltinAttribute* builtin_attr) {
if (!BuiltinAttribute(builtin_attr, member->Type(), stage,
/* is_input */ false)) {
@@ -2197,6 +2201,18 @@
return true;
}
+bool Validator::IndexAttribute(const ast::IndexAttribute* index_attr) const {
+ if (!enabled_extensions_.Contains(builtin::Extension::kChromiumInternalDualSourceBlending)) {
+ AddError(
+ "use of '@index' attribute requires enabling extension "
+ "'chromium_internal_dual_source_blending'",
+ index_attr->source);
+ return false;
+ }
+
+ return false;
+}
+
bool Validator::Return(const ast::ReturnStatement* ret,
const type::Type* func_type,
const type::Type* ret_type,
diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h
index 999bc49..19ceb5e 100644
--- a/src/tint/resolver/validator.h
+++ b/src/tint/resolver/validator.h
@@ -329,6 +329,11 @@
const Source& source,
const bool is_input = false) const;
+ /// Validates a index attribute
+ /// @param index_attr the index attribute to validate
+ /// @returns true on success, false otherwise.
+ bool IndexAttribute(const ast::IndexAttribute* index_attr) const;
+
/// Validates a loop statement
/// @param stmt the loop statement
/// @returns true on success, false otherwise.
diff --git a/src/tint/resolver/value_constructor_validation_test.cc b/src/tint/resolver/value_constructor_validation_test.cc
index 3b7ad64..4e41d25 100644
--- a/src/tint/resolver/value_constructor_validation_test.cc
+++ b/src/tint/resolver/value_constructor_validation_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/type/reference.h"
#include "src/tint/utils/string_stream.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ::testing::HasSubstr;
// Helpers and typedefs
@@ -34,14 +35,6 @@
using builder::CreatePtrs;
using builder::CreatePtrsFor;
using builder::DataType;
-using builder::mat2x2;
-using builder::mat2x3;
-using builder::mat3x2;
-using builder::mat3x3;
-using builder::mat4x4;
-using builder::vec2;
-using builder::vec3;
-using builder::vec4;
class ResolverValueConstructorValidationTest : public resolver::TestHelper, public testing::Test {};
@@ -478,7 +471,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, ConversionConstructorInvalid_InvalidConstructor) {
- auto* a = Var("a", ty.f32(), Call(Source{{12, 34}}, ty.f32(), Call(ty.array<f32, 4>())));
+ auto* a = Var("a", ty.f32(), Call(Source{{12, 34}}, ty.f32(), Call<array<f32, 4>>()));
WrapInFunction(a);
ASSERT_FALSE(r()->Resolve());
@@ -492,7 +485,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_ZeroValue_Pass) {
// array<u32, 10u>();
- auto* tc = array<u32, 10>();
+ auto* tc = Call<array<u32, 10>>();
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -508,7 +501,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_U32U32U32) {
// array<u32, 3u>(0u, 10u, 20u);
- auto* tc = array<u32, 3>(0_u, 10_u, 20_u);
+ auto* tc = Call<array<u32, 3>>(0_u, 10_u, 20_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -527,7 +520,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArray_U32U32U32) {
// array(0u, 10u, 20u);
- auto* tc = array<Infer>(Source{{12, 34}}, 0_u, 10_u, 20_u);
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 0_u, 10_u, 20_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -546,7 +539,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_U32AIU32) {
// array<u32, 3u>(0u, 10, 20u);
- auto* tc = array<u32, 3>(0_u, 10_a, 20_u);
+ auto* tc = Call<array<u32, 3>>(0_u, 10_a, 20_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -565,7 +558,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArray_U32AIU32) {
// array(0u, 10u, 20u);
- auto* tc = array<Infer>(Source{{12, 34}}, 0_u, 10_a, 20_u);
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 0_u, 10_a, 20_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -584,7 +577,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayU32_AIAIAI) {
// array<u32, 3u>(0, 10, 20);
- auto* tc = array<u32, 3>(0_a, 10_a, 20_a);
+ auto* tc = Call<array<u32, 3>>(0_a, 10_a, 20_a);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -603,7 +596,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArray_AIAIAI) {
// const c = array(0, 10, 20);
- auto* tc = array<Infer>(Source{{12, 34}}, 0_a, 10_a, 20_a);
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 0_a, 10_a, 20_a);
WrapInFunction(Decl(Const("C", tc)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -622,9 +615,9 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayU32_VecI32_VecAI) {
// array(vec2(10i), vec2(20));
- auto* tc = array<Infer>(Source{{12, 34}}, //
- Call(ty.vec<Infer>(2), 20_i), //
- Call(ty.vec<Infer>(2), 20_a));
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, //
+ Call<vec2<Infer>>(20_i), //
+ Call<vec2<Infer>>(20_a));
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -644,9 +637,9 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayU32_VecAI_VecF32) {
// array(vec2(20), vec2(10f));
- auto* tc = array<Infer>(Source{{12, 34}}, //
- Call(ty.vec<Infer>(2), 20_a), //
- Call(ty.vec<Infer>(2), 20_f));
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, //
+ Call<vec2<Infer>>(20_a), //
+ Call<vec2<Infer>>(20_f));
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -666,7 +659,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayArgumentTypeMismatch_U32F32) {
// array<u32, 3u>(0u, 1.0f, 20u);
- auto* tc = array<u32, 3>(0_u, Expr(Source{{12, 34}}, 1_f), 20_u);
+ auto* tc = Call<array<u32, 3>>(0_u, Expr(Source{{12, 34}}, 1_f), 20_u);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -675,7 +668,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_U32F32) {
// array(0u, 1.0f, 20u);
- auto* tc = array<Infer>(Source{{12, 34}}, 0_u, 1_f, 20_u);
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 0_u, 1_f, 20_u);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -687,7 +680,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayArgumentTypeMismatch_F32I32) {
// array<f32, 1u>(1i);
- auto* tc = array<f32, 1>(Expr(Source{{12, 34}}, 1_i));
+ auto* tc = Call<array<f32, 1>>(Expr(Source{{12, 34}}, 1_i));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -696,7 +689,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_F32I32) {
// array(1f, 1i);
- auto* tc = array<Infer>(Source{{12, 34}}, 1_f, 1_i);
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 1_f, 1_i);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -708,7 +701,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayArgumentTypeMismatch_U32I32) {
// array<u32, 1u>(1i, 0u, 0u, 0u, 0u, 0u);
- auto* tc = array<u32, 1>(Expr(Source{{12, 34}}, 1_i), 0_u, 0_u, 0_u, 0_u);
+ auto* tc = Call<array<u32, 1>>(Expr(Source{{12, 34}}, 1_i), 0_u, 0_u, 0_u, 0_u);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -717,7 +710,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_U32I32) {
// array(1i, 0u, 0u, 0u, 0u, 0u);
- auto* tc = array<Infer>(Source{{12, 34}}, 1_i, 0_u, 0_u, 0_u, 0_u);
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 1_i, 0_u, 0_u, 0_u, 0_u);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -729,7 +722,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayArgumentTypeMismatch_I32Vec2) {
// array<i32, 3u>(1i, vec2<i32>());
- auto* tc = array<i32, 3>(1_i, vec2<i32>(Source{{12, 34}}));
+ auto* tc = Call<array<i32, 3>>(1_i, Call<vec2<i32>>(Source{{12, 34}}));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -738,7 +731,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_I32Vec2) {
// array(1i, vec2<i32>());
- auto* tc = array<Infer>(Source{{12, 34}}, 1_i, vec2<i32>());
+ auto* tc = Call<array<Infer>>(Source{{12, 34}}, 1_i, Call<vec2<i32>>());
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -749,7 +742,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayArgumentTypeMismatch_Vec3i32_Vec3u32) {
// array<vec3<i32>, 2u>(vec3<u32>(), vec3<u32>());
- auto* t = array(ty.vec3<i32>(), 2_u, vec3<u32>(Source{{12, 34}}), vec3<u32>());
+ auto* t = Call<array<vec3<i32>, 2>>(Call<vec3<u32>>(Source{{12, 34}}), Call<vec3<u32>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -759,7 +752,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_Vec3i32_Vec3u32) {
// array(vec3<i32>(), vec3<u32>());
- auto* t = array<Infer>(Source{{12, 34}}, vec3<i32>(), vec3<u32>());
+ auto* t = Call<array<Infer>>(Source{{12, 34}}, Call<vec3<i32>>(), Call<vec3<u32>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -771,7 +764,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_Vec3i32_Vec3AF) {
// array(vec3<i32>(), vec3(1.0));
- auto* t = array<Infer>(Source{{12, 34}}, vec3<i32>(), Call("vec3", 1._a));
+ auto* t = Call<array<Infer>>(Source{{12, 34}}, Call<vec3<i32>>(), Call("vec3", 1._a));
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -783,7 +776,7 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayArgumentTypeMismatch_Vec3i32_Vec3bool) {
// array<vec3<i32>, 2u>(vec3<i32>(), vec3<bool>());
- auto* t = array(ty.vec3<i32>(), 2_u, vec3<i32>(), vec3<bool>());
+ auto* t = Call<array<vec3<i32>, 2>>(Call<vec3<i32>>(), Call<vec3<bool>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -793,7 +786,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayArgumentTypeMismatch_Vec3i32_Vec3bool) {
// array(vec3<i32>(), vec3<bool>());
- auto* t = array<Infer>(Source{{12, 34}}, vec3<i32>(), vec3<bool>());
+ auto* t = Call<array<Infer>>(Source{{12, 34}}, Call<vec3<i32>>(), Call<vec3<bool>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -805,7 +798,8 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayOfArray_SubElemSizeMismatch) {
// array<array<i32, 2u>, 2u>(array<i32, 3u>(), array<i32, 2u>());
- auto* t = array(Source{{12, 34}}, ty.array<i32, 2>(), 2_i, array<i32, 3>(), array<i32, 2>());
+ auto* t = Call<array<array<i32, 2>, 2>>(Source{{12, 34}}, Call<array<i32, 3>>(),
+ Call<array<i32, 2>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -815,7 +809,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayOfArray_SubElemSizeMismatch) {
// array<array<i32, 2u>, 2u>(array<i32, 3u>(), array<i32, 2u>());
- auto* t = array<Infer>(Source{{12, 34}}, array<i32, 3>(), array<i32, 2>());
+ auto* t = Call<array<Infer>>(Source{{12, 34}}, Call<array<i32, 3>>(), Call<array<i32, 2>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -827,7 +821,8 @@
TEST_F(ResolverValueConstructorValidationTest, ArrayOfArray_SubElemTypeMismatch) {
// array<array<i32, 2u>, 2u>(array<i32, 2u>(), array<u32, 2u>());
- auto* t = array(Source{{12, 34}}, ty.array<i32, 2>(), 2_i, array<i32, 2>(), array<u32, 2>());
+ auto* t = Call<array<array<i32, 2>, 2>>(Source{{12, 34}}, Call<array<i32, 2>>(),
+ Call<array<u32, 2>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -837,7 +832,7 @@
TEST_F(ResolverValueConstructorValidationTest, InferredArrayOfArray_SubElemTypeMismatch) {
// array<array<i32, 2u>, 2u>(array<i32, 2u>(), array<u32, 2u>());
- auto* t = array<Infer>(Source{{12, 34}}, array<i32, 2>(), array<u32, 2>());
+ auto* t = Call<array<Infer>>(Source{{12, 34}}, Call<array<i32, 2>>(), Call<array<u32, 2>>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
@@ -850,7 +845,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_TooFewElements) {
// array<i32, 4u>(1i, 2i, 3i);
SetSource(Source::Location({12, 34}));
- auto* tc = array<i32, 4>(Expr(1_i), Expr(2_i), Expr(3_i));
+ auto* tc = Call<array<i32, 4>>(Expr(1_i), Expr(2_i), Expr(3_i));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -861,7 +856,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_TooManyElements) {
// array<i32, 4u>(1i, 2i, 3i, 4i, 5i);
SetSource(Source::Location({12, 34}));
- auto* tc = array<i32, 4>(Expr(1_i), Expr(2_i), Expr(3_i), Expr(4_i), Expr(5_i));
+ auto* tc = Call<array<i32, 4>>(Expr(1_i), Expr(2_i), Expr(3_i), Expr(4_i), Expr(5_i));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -873,7 +868,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_Runtime) {
// array<i32>(1i);
- auto* tc = array<i32>(Source{{12, 34}}, Expr(1_i));
+ auto* tc = Call<array<i32>>(Source{{12, 34}}, Expr(1_i));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -882,7 +877,7 @@
TEST_F(ResolverValueConstructorValidationTest, Array_RuntimeZeroValue) {
// array<i32>();
- auto* tc = array<i32>(Source{{12, 34}});
+ auto* tc = Call<array<i32>>(Source{{12, 34}});
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -1048,7 +1043,7 @@
namespace VectorConstructor {
TEST_F(ResolverValueConstructorValidationTest, Vec2F32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, 1_i, 2_f));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, 1_i, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1058,7 +1053,7 @@
TEST_F(ResolverValueConstructorValidationTest, Vec2F16_Error_ScalarArgumentTypeMismatch) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec2<f16>(Source{{12, 34}}, 1_h, 2_f));
+ WrapInFunction(Call<vec2<f16>>(Source{{12, 34}}, 1_h, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1066,7 +1061,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2U32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec2<u32>(Source{{12, 34}}, 1_u, 2_i));
+ WrapInFunction(Call<vec2<u32>>(Source{{12, 34}}, 1_u, 2_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1074,7 +1069,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2I32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec2<i32>(Source{{12, 34}}, 1_u, 2_i));
+ WrapInFunction(Call<vec2<i32>>(Source{{12, 34}}, 1_u, 2_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1082,7 +1077,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2Bool_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec2<bool>(Source{{12, 34}}, true, 1_i));
+ WrapInFunction(Call<vec2<bool>>(Source{{12, 34}}, true, 1_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1090,7 +1085,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_Vec3ArgumentCardinalityTooLarge) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, vec3<f32>()));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, Call<vec3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1098,7 +1093,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_Vec4ArgumentCardinalityTooLarge) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, vec4<f32>()));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, Call<vec4<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1106,7 +1101,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_TooManyArgumentsScalar) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1114,7 +1109,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_TooManyArgumentsVector) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>()));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), Call<vec2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1123,7 +1118,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_TooManyArgumentsVectorAndScalar) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, vec2<f32>(), 1_f));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1131,7 +1126,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_InvalidArgumentType) {
- WrapInFunction(vec2<f32>(Source{{12, 34}}, mat2x2<f32>()));
+ WrapInFunction(Call<vec2<f32>>(Source{{12, 34}}, Call<mat2x2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1139,7 +1134,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Success_ZeroValue) {
- auto* tc = vec2<f32>();
+ auto* tc = Call<vec2<f32>>();
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1158,7 +1153,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2F32_Success_Scalar) {
- auto* tc = vec2<f32>(1_f, 1_f);
+ auto* tc = Call<vec2<f32>>(1_f, 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1181,7 +1176,7 @@
TEST_F(ResolverValueConstructorValidationTest, Vec2F16_Success_Scalar) {
Enable(builtin::Extension::kF16);
- auto* tc = vec2<f16>(1_h, 1_h);
+ auto* tc = Call<vec2<f16>>(1_h, 1_h);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1202,7 +1197,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2U32_Success_Scalar) {
- auto* tc = vec2<u32>(1_u, 1_u);
+ auto* tc = Call<vec2<u32>>(1_u, 1_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1223,7 +1218,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2I32_Success_Scalar) {
- auto* tc = vec2<i32>(1_i, 1_i);
+ auto* tc = Call<vec2<i32>>(1_i, 1_i);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1244,7 +1239,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2Bool_Success_Scalar) {
- auto* tc = vec2<bool>(true, false);
+ auto* tc = Call<vec2<bool>>(true, false);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1265,7 +1260,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Success_Identity) {
- auto* tc = vec2<f32>(vec2<f32>());
+ auto* tc = Call<vec2<f32>>(Call<vec2<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1285,7 +1280,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Success_Vec2TypeConversion) {
- auto* tc = vec2<f32>(vec2<i32>());
+ auto* tc = Call<vec2<f32>>(Call<vec2<i32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1305,7 +1300,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3F32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, 1_f, 2_f, 3_i));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, 1_f, 2_f, 3_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1315,7 +1310,7 @@
TEST_F(ResolverValueConstructorValidationTest, Vec3F16_Error_ScalarArgumentTypeMismatch) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(Source{{12, 34}}, 1_h, 2_h, 3_f));
+ WrapInFunction(Call<vec3<f16>>(Source{{12, 34}}, 1_h, 2_h, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1323,7 +1318,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3U32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec3<u32>(Source{{12, 34}}, 1_u, 2_i, 3_u));
+ WrapInFunction(Call<vec3<u32>>(Source{{12, 34}}, 1_u, 2_i, 3_u));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1331,7 +1326,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3I32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec3<i32>(Source{{12, 34}}, 1_i, 2_u, 3_i));
+ WrapInFunction(Call<vec3<i32>>(Source{{12, 34}}, 1_i, 2_u, 3_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1339,7 +1334,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3Bool_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec3<bool>(Source{{12, 34}}, false, 1_i, true));
+ WrapInFunction(Call<vec3<bool>>(Source{{12, 34}}, false, 1_i, true));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1347,7 +1342,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_Vec4ArgumentCardinalityTooLarge) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, vec4<f32>()));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, Call<vec4<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1355,7 +1350,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooFewArgumentsScalar) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, 1_f, 2_f));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, 1_f, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1363,7 +1358,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsScalar) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f, 4_f));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, 1_f, 2_f, 3_f, 4_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1372,7 +1367,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooFewArgumentsVec2) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, vec2<f32>()));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, Call<vec2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1380,7 +1375,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsVec2) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>()));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), Call<vec2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1389,7 +1384,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsVec2AndScalar) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, vec2<f32>(), 1_f, 1_f));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), 1_f, 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1398,7 +1393,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsVec3) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, vec3<f32>(), 1_f));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, Call<vec3<f32>>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1406,7 +1401,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_InvalidArgumentType) {
- WrapInFunction(vec3<f32>(Source{{12, 34}}, mat2x2<f32>()));
+ WrapInFunction(Call<vec3<f32>>(Source{{12, 34}}, Call<mat2x2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1414,7 +1409,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Success_ZeroValue) {
- auto* tc = vec3<f32>();
+ auto* tc = Call<vec3<f32>>();
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1433,7 +1428,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3F32_Success_Scalar) {
- auto* tc = vec3<f32>(1_f, 1_f, 1_f);
+ auto* tc = Call<vec3<f32>>(1_f, 1_f, 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1457,7 +1452,7 @@
TEST_F(ResolverValueConstructorValidationTest, Vec3F16_Success_Scalar) {
Enable(builtin::Extension::kF16);
- auto* tc = vec3<f16>(1_h, 1_h, 1_h);
+ auto* tc = Call<vec3<f16>>(1_h, 1_h, 1_h);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1479,7 +1474,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3U32_Success_Scalar) {
- auto* tc = vec3<u32>(1_u, 1_u, 1_u);
+ auto* tc = Call<vec3<u32>>(1_u, 1_u, 1_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1501,7 +1496,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3I32_Success_Scalar) {
- auto* tc = vec3<i32>(1_i, 1_i, 1_i);
+ auto* tc = Call<vec3<i32>>(1_i, 1_i, 1_i);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1523,7 +1518,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3Bool_Success_Scalar) {
- auto* tc = vec3<bool>(true, false, true);
+ auto* tc = Call<vec3<bool>>(true, false, true);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1545,7 +1540,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Success_Vec2AndScalar) {
- auto* tc = vec3<f32>(vec2<f32>(), 1_f);
+ auto* tc = Call<vec3<f32>>(Call<vec2<f32>>(), 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1566,7 +1561,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Success_ScalarAndVec2) {
- auto* tc = vec3<f32>(1_f, vec2<f32>());
+ auto* tc = Call<vec3<f32>>(1_f, Call<vec2<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1587,7 +1582,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Success_Identity) {
- auto* tc = vec3<f32>(vec3<f32>());
+ auto* tc = Call<vec3<f32>>(Call<vec3<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1607,7 +1602,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Success_Vec3TypeConversion) {
- auto* tc = vec3<f32>(vec3<i32>());
+ auto* tc = Call<vec3<f32>>(Call<vec3<i32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1627,7 +1622,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4F32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, 1_f, 1_f, 1_i, 1_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, 1_f, 1_f, 1_i, 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1638,7 +1633,7 @@
TEST_F(ResolverValueConstructorValidationTest, Vec4F16_Error_ScalarArgumentTypeMismatch) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec4<f16>(Source{{12, 34}}, 1_h, 1_h, 1_f, 1_h));
+ WrapInFunction(Call<vec4<f16>>(Source{{12, 34}}, 1_h, 1_h, 1_f, 1_h));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1647,7 +1642,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4U32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec4<u32>(Source{{12, 34}}, 1_u, 1_u, 1_i, 1_u));
+ WrapInFunction(Call<vec4<u32>>(Source{{12, 34}}, 1_u, 1_u, 1_i, 1_u));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1656,7 +1651,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4I32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec4<i32>(Source{{12, 34}}, 1_i, 1_i, 1_u, 1_i));
+ WrapInFunction(Call<vec4<i32>>(Source{{12, 34}}, 1_i, 1_i, 1_u, 1_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1665,7 +1660,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4Bool_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(vec4<bool>(Source{{12, 34}}, true, false, 1_i, true));
+ WrapInFunction(Call<vec4<bool>>(Source{{12, 34}}, true, false, 1_i, true));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1674,7 +1669,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooFewArgumentsScalar) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1682,7 +1677,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsScalar) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f, 4_f, 5_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, 1_f, 2_f, 3_f, 4_f, 5_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1691,7 +1686,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooFewArgumentsVec2AndScalar) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), 1_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1699,7 +1694,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2AndScalars) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), 1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1708,7 +1703,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2Vec2Scalar) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>(), 1_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), Call<vec2<f32>>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1717,7 +1712,8 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2Vec2Vec2) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>(), vec2<f32>()));
+ WrapInFunction(
+ Call<vec4<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), Call<vec2<f32>>(), Call<vec2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1727,7 +1723,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooFewArgumentsVec3) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>()));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1735,7 +1731,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndScalars) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>(), 1_f, 2_f));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec3<f32>>(), 1_f, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1744,7 +1740,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndVec2) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>(), vec2<f32>()));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec3<f32>>(), Call<vec2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1753,7 +1749,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2AndVec3) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), vec3<f32>()));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), Call<vec3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1762,7 +1758,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndVec3) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>(), vec3<f32>()));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<vec3<f32>>(), Call<vec3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1771,7 +1767,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_InvalidArgumentType) {
- WrapInFunction(vec4<f32>(Source{{12, 34}}, mat2x2<f32>()));
+ WrapInFunction(Call<vec4<f32>>(Source{{12, 34}}, Call<mat2x2<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1779,7 +1775,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_ZeroValue) {
- auto* tc = vec4<f32>();
+ auto* tc = Call<vec4<f32>>();
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1791,7 +1787,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4F32_Success_Scalar) {
- auto* tc = vec4<f32>(1_f, 1_f, 1_f, 1_f);
+ auto* tc = Call<vec4<f32>>(1_f, 1_f, 1_f, 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1805,7 +1801,7 @@
TEST_F(ResolverValueConstructorValidationTest, Vec4F16_Success_Scalar) {
Enable(builtin::Extension::kF16);
- auto* tc = vec4<f16>(1_h, 1_h, 1_h, 1_h);
+ auto* tc = Call<vec4<f16>>(1_h, 1_h, 1_h, 1_h);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1817,7 +1813,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4U32_Success_Scalar) {
- auto* tc = vec4<u32>(1_u, 1_u, 1_u, 1_u);
+ auto* tc = Call<vec4<u32>>(1_u, 1_u, 1_u, 1_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1829,7 +1825,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4I32_Success_Scalar) {
- auto* tc = vec4<i32>(1_i, 1_i, 1_i, 1_i);
+ auto* tc = Call<vec4<i32>>(1_i, 1_i, 1_i, 1_i);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1841,7 +1837,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4Bool_Success_Scalar) {
- auto* tc = vec4<bool>(true, false, true, false);
+ auto* tc = Call<vec4<bool>>(true, false, true, false);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1853,7 +1849,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_Vec2ScalarScalar) {
- auto* tc = vec4<f32>(vec2<f32>(), 1_f, 1_f);
+ auto* tc = Call<vec4<f32>>(Call<vec2<f32>>(), 1_f, 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1865,7 +1861,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_ScalarVec2Scalar) {
- auto* tc = vec4<f32>(1_f, vec2<f32>(), 1_f);
+ auto* tc = Call<vec4<f32>>(1_f, Call<vec2<f32>>(), 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1877,7 +1873,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_ScalarScalarVec2) {
- auto* tc = vec4<f32>(1_f, 1_f, vec2<f32>());
+ auto* tc = Call<vec4<f32>>(1_f, 1_f, Call<vec2<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1889,7 +1885,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_Vec2AndVec2) {
- auto* tc = vec4<f32>(vec2<f32>(), vec2<f32>());
+ auto* tc = Call<vec4<f32>>(Call<vec2<f32>>(), Call<vec2<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1901,7 +1897,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_Vec3AndScalar) {
- auto* tc = vec4<f32>(vec3<f32>(), 1_f);
+ auto* tc = Call<vec4<f32>>(Call<vec3<f32>>(), 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1913,7 +1909,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_ScalarAndVec3) {
- auto* tc = vec4<f32>(1_f, vec3<f32>());
+ auto* tc = Call<vec4<f32>>(1_f, Call<vec3<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1925,7 +1921,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_Identity) {
- auto* tc = vec4<f32>(vec4<f32>());
+ auto* tc = Call<vec4<f32>>(Call<vec4<f32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1937,7 +1933,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_Vec4TypeConversion) {
- auto* tc = vec4<f32>(vec4<i32>());
+ auto* tc = Call<vec4<f32>>(Call<vec4<i32>>());
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1949,9 +1945,9 @@
}
TEST_F(ResolverValueConstructorValidationTest, NestedVectorConstructors_InnerError) {
- WrapInFunction(vec4<f32>(vec4<f32>(1_f, 1_f, //
- vec3<f32>(Source{{12, 34}}, 1_f, 1_f)),
- 1_f));
+ WrapInFunction(Call<vec4<f32>>(Call<vec4<f32>>(1_f, 1_f, //
+ Call<vec3<f32>>(Source{{12, 34}}, 1_f, 1_f)),
+ 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -1959,7 +1955,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, NestedVectorConstructors_Success) {
- auto* tc = vec4<f32>(vec3<f32>(vec2<f32>(1_f, 1_f), 1_f), 1_f);
+ auto* tc = Call<vec4<f32>>(Call<vec3<f32>>(Call<vec2<f32>>(1_f, 1_f), 1_f), 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1974,7 +1970,7 @@
auto* alias = Alias("UnsignedInt", ty.u32());
GlobalVar("uint_var", ty.Of(alias), builtin::AddressSpace::kPrivate);
- auto* tc = vec2<f32>(Source{{12, 34}}, "uint_var");
+ auto* tc = Call<vec2<f32>>(Source{{12, 34}}, "uint_var");
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -1987,7 +1983,7 @@
GlobalVar("my_f32", ty.Of(f32_alias), builtin::AddressSpace::kPrivate);
GlobalVar("my_vec2", ty.Of(vec2_alias), builtin::AddressSpace::kPrivate);
- auto* tc = vec3<f32>("my_vec2", "my_f32");
+ auto* tc = Call<vec3<f32>>("my_vec2", "my_f32");
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -2020,7 +2016,7 @@
// vec3<u32>(vec<Float32>(), 1.0f)
auto vec_type = ty.vec(ty.Of(f32_alias), 2);
- WrapInFunction(vec3<u32>(Source{{12, 34}}, Call(vec_type), 1_f));
+ WrapInFunction(Call<vec3<u32>>(Source{{12, 34}}, Call(vec_type), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
@@ -2032,7 +2028,7 @@
// vec3<f32>(vec<Float32>(), 1.0f)
auto vec_type = ty.vec(ty.Of(f32_alias), 2);
- auto* tc = vec3<f32>(Call(Source{{12, 34}}, vec_type), 1_f);
+ auto* tc = Call<vec3<f32>>(Call(Source{{12, 34}}, vec_type), 1_f);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2041,11 +2037,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec2ElementTypeFromScalars) {
Enable(builtin::Extension::kF16);
- auto* vec2_bool = vec2<Infer>(true, false);
- auto* vec2_i32 = vec2<Infer>(1_i, 2_i);
- auto* vec2_u32 = vec2<Infer>(1_u, 2_u);
- auto* vec2_f32 = vec2<Infer>(1_f, 2_f);
- auto* vec2_f16 = vec2<Infer>(1_h, 2_h);
+ auto* vec2_bool = Call<vec2<Infer>>(true, false);
+ auto* vec2_i32 = Call<vec2<Infer>>(1_i, 2_i);
+ auto* vec2_u32 = Call<vec2<Infer>>(1_u, 2_u);
+ auto* vec2_f32 = Call<vec2<Infer>>(1_f, 2_f);
+ auto* vec2_f16 = Call<vec2<Infer>>(1_h, 2_h);
WrapInFunction(vec2_bool, vec2_i32, vec2_u32, vec2_f32, vec2_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2070,11 +2066,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec2ElementTypeFromVec2) {
Enable(builtin::Extension::kF16);
- auto* vec2_bool = vec2<Infer>(vec2<bool>(true, false));
- auto* vec2_i32 = vec2<Infer>(vec2<i32>(1_i, 2_i));
- auto* vec2_u32 = vec2<Infer>(vec2<u32>(1_u, 2_u));
- auto* vec2_f32 = vec2<Infer>(vec2<f32>(1_f, 2_f));
- auto* vec2_f16 = vec2<Infer>(vec2<f16>(1_h, 2_h));
+ auto* vec2_bool = Call<vec2<Infer>>(Call<vec2<bool>>(true, false));
+ auto* vec2_i32 = Call<vec2<Infer>>(Call<vec2<i32>>(1_i, 2_i));
+ auto* vec2_u32 = Call<vec2<Infer>>(Call<vec2<u32>>(1_u, 2_u));
+ auto* vec2_f32 = Call<vec2<Infer>>(Call<vec2<f32>>(1_f, 2_f));
+ auto* vec2_f16 = Call<vec2<Infer>>(Call<vec2<f16>>(1_h, 2_h));
WrapInFunction(vec2_bool, vec2_i32, vec2_u32, vec2_f32, vec2_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2099,11 +2095,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec3ElementTypeFromScalars) {
Enable(builtin::Extension::kF16);
- auto* vec3_bool = vec3<Infer>(Expr(true), Expr(false), Expr(true));
- auto* vec3_i32 = vec3<Infer>(Expr(1_i), Expr(2_i), Expr(3_i));
- auto* vec3_u32 = vec3<Infer>(Expr(1_u), Expr(2_u), Expr(3_u));
- auto* vec3_f32 = vec3<Infer>(Expr(1_f), Expr(2_f), Expr(3_f));
- auto* vec3_f16 = vec3<Infer>(Expr(1_h), Expr(2_h), Expr(3_h));
+ auto* vec3_bool = Call<vec3<Infer>>(true, false, true);
+ auto* vec3_i32 = Call<vec3<Infer>>(1_i, 2_i, 3_i);
+ auto* vec3_u32 = Call<vec3<Infer>>(1_u, 2_u, 3_u);
+ auto* vec3_f32 = Call<vec3<Infer>>(1_f, 2_f, 3_f);
+ auto* vec3_f16 = Call<vec3<Infer>>(1_h, 2_h, 3_h);
WrapInFunction(vec3_bool, vec3_i32, vec3_u32, vec3_f32, vec3_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2128,11 +2124,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec3ElementTypeFromVec3) {
Enable(builtin::Extension::kF16);
- auto* vec3_bool = vec3<Infer>(vec3<bool>(true, false, true));
- auto* vec3_i32 = vec3<Infer>(vec3<i32>(1_i, 2_i, 3_i));
- auto* vec3_u32 = vec3<Infer>(vec3<u32>(1_u, 2_u, 3_u));
- auto* vec3_f32 = vec3<Infer>(vec3<f32>(1_f, 2_f, 3_f));
- auto* vec3_f16 = vec3<Infer>(vec3<f16>(1_h, 2_h, 3_h));
+ auto* vec3_bool = Call<vec3<Infer>>(Call<vec3<bool>>(true, false, true));
+ auto* vec3_i32 = Call<vec3<Infer>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
+ auto* vec3_u32 = Call<vec3<Infer>>(Call<vec3<u32>>(1_u, 2_u, 3_u));
+ auto* vec3_f32 = Call<vec3<Infer>>(Call<vec3<f32>>(1_f, 2_f, 3_f));
+ auto* vec3_f16 = Call<vec3<Infer>>(Call<vec3<f16>>(1_h, 2_h, 3_h));
WrapInFunction(vec3_bool, vec3_i32, vec3_u32, vec3_f32, vec3_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2157,11 +2153,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec3ElementTypeFromScalarAndVec2) {
Enable(builtin::Extension::kF16);
- auto* vec3_bool = vec3<Infer>(Expr(true), vec2<bool>(false, true));
- auto* vec3_i32 = vec3<Infer>(Expr(1_i), vec2<i32>(2_i, 3_i));
- auto* vec3_u32 = vec3<Infer>(Expr(1_u), vec2<u32>(2_u, 3_u));
- auto* vec3_f32 = vec3<Infer>(Expr(1_f), vec2<f32>(2_f, 3_f));
- auto* vec3_f16 = vec3<Infer>(Expr(1_h), vec2<f16>(2_h, 3_h));
+ auto* vec3_bool = Call<vec3<Infer>>(true, Call<vec2<bool>>(false, true));
+ auto* vec3_i32 = Call<vec3<Infer>>(1_i, Call<vec2<i32>>(2_i, 3_i));
+ auto* vec3_u32 = Call<vec3<Infer>>(1_u, Call<vec2<u32>>(2_u, 3_u));
+ auto* vec3_f32 = Call<vec3<Infer>>(1_f, Call<vec2<f32>>(2_f, 3_f));
+ auto* vec3_f16 = Call<vec3<Infer>>(1_h, Call<vec2<f16>>(2_h, 3_h));
WrapInFunction(vec3_bool, vec3_i32, vec3_u32, vec3_f32, vec3_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2186,11 +2182,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec4ElementTypeFromScalars) {
Enable(builtin::Extension::kF16);
- auto* vec4_bool = vec4<Infer>(Expr(true), Expr(false), Expr(true), Expr(false));
- auto* vec4_i32 = vec4<Infer>(Expr(1_i), Expr(2_i), Expr(3_i), Expr(4_i));
- auto* vec4_u32 = vec4<Infer>(Expr(1_u), Expr(2_u), Expr(3_u), Expr(4_u));
- auto* vec4_f32 = vec4<Infer>(Expr(1_f), Expr(2_f), Expr(3_f), Expr(4_f));
- auto* vec4_f16 = vec4<Infer>(Expr(1_h), Expr(2_h), Expr(3_h), Expr(4_h));
+ auto* vec4_bool = Call<vec4<Infer>>(true, false, true, false);
+ auto* vec4_i32 = Call<vec4<Infer>>(1_i, 2_i, 3_i, 4_i);
+ auto* vec4_u32 = Call<vec4<Infer>>(1_u, 2_u, 3_u, 4_u);
+ auto* vec4_f32 = Call<vec4<Infer>>(1_f, 2_f, 3_f, 4_f);
+ auto* vec4_f16 = Call<vec4<Infer>>(1_h, 2_h, 3_h, 4_h);
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32, vec4_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2215,11 +2211,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec4ElementTypeFromVec4) {
Enable(builtin::Extension::kF16);
- auto* vec4_bool = vec4<Infer>(vec4<bool>(true, false, true, false));
- auto* vec4_i32 = vec4<Infer>(vec4<i32>(1_i, 2_i, 3_i, 4_i));
- auto* vec4_u32 = vec4<Infer>(vec4<u32>(1_u, 2_u, 3_u, 4_u));
- auto* vec4_f32 = vec4<Infer>(vec4<f32>(1_f, 2_f, 3_f, 4_f));
- auto* vec4_f16 = vec4<Infer>(vec4<f16>(1_h, 2_h, 3_h, 4_h));
+ auto* vec4_bool = Call<vec4<Infer>>(Call<vec4<bool>>(true, false, true, false));
+ auto* vec4_i32 = Call<vec4<Infer>>(Call<vec4<i32>>(1_i, 2_i, 3_i, 4_i));
+ auto* vec4_u32 = Call<vec4<Infer>>(Call<vec4<u32>>(1_u, 2_u, 3_u, 4_u));
+ auto* vec4_f32 = Call<vec4<Infer>>(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f));
+ auto* vec4_f16 = Call<vec4<Infer>>(Call<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32, vec4_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2244,11 +2240,11 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec4ElementTypeFromScalarAndVec3) {
Enable(builtin::Extension::kF16);
- auto* vec4_bool = vec4<Infer>(Expr(true), vec3<bool>(false, true, false));
- auto* vec4_i32 = vec4<Infer>(Expr(1_i), vec3<i32>(2_i, 3_i, 4_i));
- auto* vec4_u32 = vec4<Infer>(Expr(1_u), vec3<u32>(2_u, 3_u, 4_u));
- auto* vec4_f32 = vec4<Infer>(Expr(1_f), vec3<f32>(2_f, 3_f, 4_f));
- auto* vec4_f16 = vec4<Infer>(Expr(1_h), vec3<f16>(2_h, 3_h, 4_h));
+ auto* vec4_bool = Call<vec4<Infer>>(true, Call<vec3<bool>>(false, true, false));
+ auto* vec4_i32 = Call<vec4<Infer>>(1_i, Call<vec3<i32>>(2_i, 3_i, 4_i));
+ auto* vec4_u32 = Call<vec4<Infer>>(1_u, Call<vec3<u32>>(2_u, 3_u, 4_u));
+ auto* vec4_f32 = Call<vec4<Infer>>(1_f, Call<vec3<f32>>(2_f, 3_f, 4_f));
+ auto* vec4_f16 = Call<vec4<Infer>>(1_h, Call<vec3<f16>>(2_h, 3_h, 4_h));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32, vec4_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2273,11 +2269,12 @@
TEST_F(ResolverValueConstructorValidationTest, InferVec4ElementTypeFromVec2AndVec2) {
Enable(builtin::Extension::kF16);
- auto* vec4_bool = vec4<Infer>(vec2<bool>(true, false), vec2<bool>(true, false));
- auto* vec4_i32 = vec4<Infer>(vec2<i32>(1_i, 2_i), vec2<i32>(3_i, 4_i));
- auto* vec4_u32 = vec4<Infer>(vec2<u32>(1_u, 2_u), vec2<u32>(3_u, 4_u));
- auto* vec4_f32 = vec4<Infer>(vec2<f32>(1_f, 2_f), vec2<f32>(3_f, 4_f));
- auto* vec4_f16 = vec4<Infer>(vec2<f16>(1_h, 2_h), vec2<f16>(3_h, 4_h));
+ auto* vec4_bool =
+ Call<vec4<Infer>>(Call<vec2<bool>>(true, false), Call<vec2<bool>>(true, false));
+ auto* vec4_i32 = Call<vec4<Infer>>(Call<vec2<i32>>(1_i, 2_i), Call<vec2<i32>>(3_i, 4_i));
+ auto* vec4_u32 = Call<vec4<Infer>>(Call<vec2<u32>>(1_u, 2_u), Call<vec2<u32>>(3_u, 4_u));
+ auto* vec4_f32 = Call<vec4<Infer>>(Call<vec2<f32>>(1_f, 2_f), Call<vec2<f32>>(3_f, 4_f));
+ auto* vec4_f16 = Call<vec4<Infer>>(Call<vec2<f16>>(1_h, 2_h), Call<vec2<f16>>(3_h, 4_h));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32, vec4_f16);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2300,9 +2297,9 @@
}
TEST_F(ResolverValueConstructorValidationTest, InferVecNoArgs) {
- auto* v2 = vec2<Infer>();
- auto* v3 = vec3<Infer>();
- auto* v4 = vec4<Infer>();
+ auto* v2 = Call<vec2<Infer>>();
+ auto* v3 = Call<vec3<Infer>>();
+ auto* v4 = Call<vec4<Infer>>();
GlobalConst("v2", v2);
GlobalConst("v3", v3);
@@ -2409,8 +2406,8 @@
DataType<T>::Name,
DataType<T>::AST,
DataType<T>::ExprFromDouble,
- DataType<tint::resolver::builder::vec<R, T>>::AST,
- DataType<tint::resolver::builder::mat<C, R, T>>::AST,
+ DataType<vec<R, T>>::AST,
+ DataType<mat<C, R, T>>::AST,
};
}
@@ -2776,7 +2773,7 @@
TEST_F(ResolverValueConstructorValidationTest, MatrixConstructor_ArgumentTypeAlias_Error) {
auto* alias = Alias("VectorUnsigned2", ty.vec2<u32>());
- auto* tc = Call(Source{{12, 34}}, ty.mat2x2<f32>(), Call(ty.Of(alias)), vec2<f32>());
+ auto* tc = Call(Source{{12, 34}}, ty.mat2x2<f32>(), Call(ty.Of(alias)), Call<vec2<f32>>());
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
@@ -2973,12 +2970,6 @@
namespace StructConstructor {
using builder::CreatePtrs;
using builder::CreatePtrsFor;
-using builder::mat2x2;
-using builder::mat3x3;
-using builder::mat4x4;
-using builder::vec2;
-using builder::vec3;
-using builder::vec4;
constexpr CreatePtrs all_types[] = {
CreatePtrsFor<bool>(), //
@@ -3170,7 +3161,7 @@
}
TEST_F(ResolverValueConstructorValidationTest, BuilinTypeConstructorAsStatement) {
- WrapInFunction(CallStmt(vec2<f32>(Source{{12, 34}}, 1_f, 2_f)));
+ WrapInFunction(CallStmt(Call<vec2<f32>>(Source{{12, 34}}, 1_f, 2_f)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: value constructor evaluated but not used");
diff --git a/src/tint/resolver/variable_test.cc b/src/tint/resolver/variable_test.cc
index 7095cfe..2054885 100644
--- a/src/tint/resolver/variable_test.cc
+++ b/src/tint/resolver/variable_test.cc
@@ -21,7 +21,8 @@
namespace tint::resolver {
namespace {
-using namespace tint::number_suffixes; // NOLINT
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
struct ResolverVariableTest : public resolver::TestHelper, public testing::Test {};
@@ -421,7 +422,7 @@
auto* b = Let("b", ty.bool_(), b_c);
auto* s = Let("s", ty.Of(S), s_c);
auto* a = Let("a", ty.Of(A), a_c);
- auto* p = Let("p", ty.ptr<i32>(builtin::AddressSpace::kFunction), p_c);
+ auto* p = Let("p", ty.ptr<function, i32>(), p_c);
Func("F", utils::Empty, ty.void_(),
utils::Vector{
@@ -898,10 +899,10 @@
auto* c_i32 = Const("a", ty.i32(), Expr(0_i));
auto* c_u32 = Const("b", ty.u32(), Expr(0_u));
auto* c_f32 = Const("c", ty.f32(), Expr(0_f));
- auto* c_vi32 = Const("d", ty.vec3<i32>(), vec3<i32>());
- auto* c_vu32 = Const("e", ty.vec3<u32>(), vec3<u32>());
- auto* c_vf32 = Const("f", ty.vec3<f32>(), vec3<f32>());
- auto* c_mf32 = Const("g", ty.mat3x3<f32>(), mat3x3<f32>());
+ auto* c_vi32 = Const("d", ty.vec3<i32>(), Call<vec3<i32>>());
+ auto* c_vu32 = Const("e", ty.vec3<u32>(), Call<vec3<u32>>());
+ auto* c_vf32 = Const("f", ty.vec3<f32>(), Call<vec3<f32>>());
+ auto* c_mf32 = Const("g", ty.mat3x3<f32>(), Call<mat3x3<f32>>());
auto* c_s = Const("h", ty("S"), Call("S"));
WrapInFunction(c_i32, c_u32, c_f32, c_vi32, c_vu32, c_vf32, c_mf32, c_s);
@@ -944,16 +945,16 @@
auto* c_f32 = Const("c", Expr(0_f));
auto* c_ai = Const("d", Expr(0_a));
auto* c_af = Const("e", Expr(0._a));
- auto* c_vi32 = Const("f", vec3<i32>());
- auto* c_vu32 = Const("g", vec3<u32>());
- auto* c_vf32 = Const("h", vec3<f32>());
- auto* c_vai = Const("i", Call(ty.vec<Infer>(3), Expr(0_a)));
- auto* c_vaf = Const("j", Call(ty.vec<Infer>(3), Expr(0._a)));
- auto* c_mf32 = Const("k", mat3x3<f32>());
- auto* c_maf32 =
- Const("l", Call(ty.mat3x3<Infer>(), //
- Call(ty.vec<Infer>(3), Expr(0._a)), Call(ty.vec<Infer>(3), Expr(0._a)),
- Call(ty.vec<Infer>(3), Expr(0._a))));
+ auto* c_vi32 = Const("f", Call<vec3<i32>>());
+ auto* c_vu32 = Const("g", Call<vec3<u32>>());
+ auto* c_vf32 = Const("h", Call<vec3<f32>>());
+ auto* c_vai = Const("i", Call<vec3<Infer>>(0_a));
+ auto* c_vaf = Const("j", Call<vec3<Infer>>(0._a));
+ auto* c_mf32 = Const("k", Call<mat3x3<f32>>());
+ auto* c_maf32 = Const("l", Call<mat3x3<Infer>>( //
+ Call<vec3<Infer>>(0._a), //
+ Call<vec3<Infer>>(0._a), //
+ Call<vec3<Infer>>(0._a)));
auto* c_s = Const("m", Call("S"));
WrapInFunction(c_i32, c_u32, c_f32, c_ai, c_af, c_vi32, c_vu32, c_vf32, c_vai, c_vaf, c_mf32,
@@ -1082,10 +1083,10 @@
auto* c_i32 = GlobalConst("a", ty.i32(), Expr(0_i));
auto* c_u32 = GlobalConst("b", ty.u32(), Expr(0_u));
auto* c_f32 = GlobalConst("c", ty.f32(), Expr(0_f));
- auto* c_vi32 = GlobalConst("d", ty.vec3<i32>(), vec3<i32>());
- auto* c_vu32 = GlobalConst("e", ty.vec3<u32>(), vec3<u32>());
- auto* c_vf32 = GlobalConst("f", ty.vec3<f32>(), vec3<f32>());
- auto* c_mf32 = GlobalConst("g", ty.mat3x3<f32>(), mat3x3<f32>());
+ auto* c_vi32 = GlobalConst("d", ty.vec3<i32>(), Call<vec3<i32>>());
+ auto* c_vu32 = GlobalConst("e", ty.vec3<u32>(), Call<vec3<u32>>());
+ auto* c_vf32 = GlobalConst("f", ty.vec3<f32>(), Call<vec3<f32>>());
+ auto* c_mf32 = GlobalConst("g", ty.mat3x3<f32>(), Call<mat3x3<f32>>());
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -1120,16 +1121,16 @@
auto* c_f32 = GlobalConst("c", Expr(0_f));
auto* c_ai = GlobalConst("d", Expr(0_a));
auto* c_af = GlobalConst("e", Expr(0._a));
- auto* c_vi32 = GlobalConst("f", vec3<i32>());
- auto* c_vu32 = GlobalConst("g", vec3<u32>());
- auto* c_vf32 = GlobalConst("h", vec3<f32>());
- auto* c_vai = GlobalConst("i", Call(ty.vec<Infer>(3), Expr(0_a)));
- auto* c_vaf = GlobalConst("j", Call(ty.vec<Infer>(3), Expr(0._a)));
- auto* c_mf32 = GlobalConst("k", mat3x3<f32>());
- auto* c_maf32 = GlobalConst(
- "l", Call(ty.mat3x3<Infer>(), //
- Call(ty.vec<Infer>(3), Expr(0._a)), Call(ty.vec<Infer>(3), Expr(0._a)),
- Call(ty.vec<Infer>(3), Expr(0._a))));
+ auto* c_vi32 = GlobalConst("f", Call<vec3<i32>>());
+ auto* c_vu32 = GlobalConst("g", Call<vec3<u32>>());
+ auto* c_vf32 = GlobalConst("h", Call<vec3<f32>>());
+ auto* c_vai = GlobalConst("i", Call<vec3<Infer>>(0_a));
+ auto* c_vaf = GlobalConst("j", Call<vec3<Infer>>(0._a));
+ auto* c_mf32 = GlobalConst("k", Call<mat3x3<f32>>());
+ auto* c_maf32 = GlobalConst("l", Call<mat3x3<Infer>>( //
+ Call<vec3<Infer>>(0._a), //
+ Call<vec3<Infer>>(0._a), //
+ Call<vec3<Infer>>(0._a)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
diff --git a/src/tint/resolver/variable_validation_test.cc b/src/tint/resolver/variable_validation_test.cc
index 9656574..44cc973 100644
--- a/src/tint/resolver/variable_validation_test.cc
+++ b/src/tint/resolver/variable_validation_test.cc
@@ -17,11 +17,12 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/type/texture_dimension.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::resolver {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
struct ResolverVariableValidationTest : public resolver::TestHelper, public testing::Test {};
TEST_F(ResolverVariableValidationTest, VarNoInitializerNoType) {
@@ -132,8 +133,8 @@
// var i : i32;
// var p : pointer<function, i32> = &v;
auto* i = Var("i", ty.i32());
- auto* p = Var("a", ty.ptr<i32>(Source{{56, 78}}, builtin::AddressSpace::kFunction),
- builtin::AddressSpace::kUndefined, AddressOf(Source{{12, 34}}, "i"));
+ auto* p = Var("a", ty.ptr<function, i32>(Source{{56, 78}}), builtin::AddressSpace::kUndefined,
+ AddressOf(Source{{12, 34}}, "i"));
WrapInFunction(i, p);
EXPECT_FALSE(r()->Resolve());
@@ -162,7 +163,7 @@
TEST_F(ResolverVariableValidationTest, OverrideInferedTypeNotScalar) {
// override o = vec3(1.0f);
- Override(Source{{56, 78}}, "o", vec3<f32>(1.0_f));
+ Override(Source{{56, 78}}, "o", Call<vec3<f32>>(1.0_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "56:78 error: vec3<f32> cannot be used as the type of a 'override'");
@@ -314,13 +315,11 @@
auto* buf = Structure("S", utils::Vector{
Member("inner", ty.Of(inner)),
});
- auto* storage =
+ auto* var =
GlobalVar("s", ty.Of(buf), builtin::AddressSpace::kStorage, Binding(0_a), Group(0_a));
- auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 2_i);
- auto* ptr = Let(Source{{12, 34}}, "p",
- ty.ptr<i32>(builtin::AddressSpace::kStorage, builtin::Access::kReadWrite),
- AddressOf(expr));
+ auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(var, "inner"), "arr"), 2_i);
+ auto* ptr = Let(Source{{12, 34}}, "p", ty.ptr<storage, i32, read_write>(), AddressOf(expr));
WrapInFunction(ptr);
@@ -390,7 +389,7 @@
TEST_F(ResolverVariableValidationTest, VectorConstNoType) {
// const a vec3 = vec3<f32>();
- WrapInFunction(Const("a", ty.vec3<Infer>(Source{{12, 34}}), vec3<f32>()));
+ WrapInFunction(Const("a", ty.vec3<Infer>(Source{{12, 34}}), Call<vec3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'vec3'");
@@ -398,7 +397,7 @@
TEST_F(ResolverVariableValidationTest, VectorLetNoType) {
// let a : vec3 = vec3<f32>();
- WrapInFunction(Let("a", ty.vec3<Infer>(Source{{12, 34}}), vec3<f32>()));
+ WrapInFunction(Let("a", ty.vec3<Infer>(Source{{12, 34}}), Call<vec3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'vec3'");
@@ -414,7 +413,7 @@
TEST_F(ResolverVariableValidationTest, MatrixConstNoType) {
// const a : mat3x3 = mat3x3<f32>();
- WrapInFunction(Const("a", ty.mat3x3<Infer>(Source{{12, 34}}), mat3x3<f32>()));
+ WrapInFunction(Const("a", ty.mat3x3<Infer>(Source{{12, 34}}), Call<mat3x3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'mat3x3'");
@@ -422,7 +421,7 @@
TEST_F(ResolverVariableValidationTest, MatrixLetNoType) {
// let a : mat3x3 = mat3x3<f32>();
- WrapInFunction(Let("a", ty.mat3x3<Infer>(Source{{12, 34}}), mat3x3<f32>()));
+ WrapInFunction(Let("a", ty.mat3x3<Infer>(Source{{12, 34}}), Call<mat3x3<f32>>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'mat3x3'");
diff --git a/src/tint/sem/statement.h b/src/tint/sem/statement.h
index 87214a2..1d9b6cb 100644
--- a/src/tint/sem/statement.h
+++ b/src/tint/sem/statement.h
@@ -88,7 +88,7 @@
/// pointer to that template argument type, otherwise a CompoundStatement
/// pointer is returned.
template <typename... TYPES>
- const detail::FindFirstParentReturnType<TYPES...>* FindFirstParent() const;
+ const sem::detail::FindFirstParentReturnType<TYPES...>* FindFirstParent() const;
/// @return the closest enclosing block for this statement
const BlockStatement* Block() const;
@@ -181,8 +181,8 @@
}
template <typename... TYPES>
-const detail::FindFirstParentReturnType<TYPES...>* Statement::FindFirstParent() const {
- using ReturnType = detail::FindFirstParentReturnType<TYPES...>;
+const sem::detail::FindFirstParentReturnType<TYPES...>* Statement::FindFirstParent() const {
+ using ReturnType = sem::detail::FindFirstParentReturnType<TYPES...>;
if (sizeof...(TYPES) == 1) {
if (auto* p = As<ReturnType>()) {
return p;
diff --git a/src/tint/switch.h b/src/tint/switch.h
index df5bd95..4073bb8 100644
--- a/src/tint/switch.h
+++ b/src/tint/switch.h
@@ -110,8 +110,8 @@
template <typename... CASE_RETURN_TYPES>
struct SwitchReturnTypeImpl</*IS_CASTABLE*/ true, utils::detail::Infer, CASE_RETURN_TYPES...> {
private:
- using InferredType = utils::CastableCommonBase<
- detail::NullptrToIgnore<std::remove_pointer_t<CASE_RETURN_TYPES>>...>;
+ using InferredType =
+ utils::CastableCommonBase<NullptrToIgnore<std::remove_pointer_t<CASE_RETURN_TYPES>>...>;
public:
/// `const T*` or `T*`, where T is the common base type for all the castable case types.
@@ -166,8 +166,9 @@
typename T = utils::CastableBase,
typename... CASES>
inline auto Switch(T* object, CASES&&... cases) {
- using ReturnType = detail::SwitchReturnType<RETURN_TYPE, utils::traits::ReturnType<CASES>...>;
- static constexpr int kDefaultIndex = detail::IndexOfDefaultCase<std::tuple<CASES...>>();
+ using ReturnType =
+ tint::detail::SwitchReturnType<RETURN_TYPE, utils::traits::ReturnType<CASES>...>;
+ static constexpr int kDefaultIndex = tint::detail::IndexOfDefaultCase<std::tuple<CASES...>>();
static constexpr bool kHasDefaultCase = kDefaultIndex >= 0;
static constexpr bool kHasReturnType = !std::is_same_v<ReturnType, void>;
@@ -202,8 +203,8 @@
struct alignas(alignof(ReturnTypeOrU8)) ReturnStorage {
uint8_t data[sizeof(ReturnTypeOrU8)];
};
- ReturnStorage storage;
- auto* result = utils::Bitcast<ReturnTypeOrU8*>(&storage);
+ ReturnStorage return_storage;
+ auto* result = utils::Bitcast<ReturnTypeOrU8*>(&return_storage);
const utils::TypeInfo& type_info = object->TypeInfo();
@@ -217,7 +218,7 @@
// `result` pointer.
auto try_case = [&](auto&& case_fn) {
using CaseFunc = std::decay_t<decltype(case_fn)>;
- using CaseType = detail::SwitchCaseType<CaseFunc>;
+ using CaseType = tint::detail::SwitchCaseType<CaseFunc>;
bool success = false;
if constexpr (std::is_same_v<CaseType, Default>) {
if constexpr (kHasReturnType) {
diff --git a/src/tint/transform/manager_test.cc b/src/tint/transform/manager_test.cc
index a41fa87..c1083b2 100644
--- a/src/tint/transform/manager_test.cc
+++ b/src/tint/transform/manager_test.cc
@@ -51,7 +51,7 @@
void Run(ir::Module* mod, const DataMap&, DataMap&) const override {
ir::Builder builder(*mod);
auto* func = builder.Function("ir_func", mod->Types().Get<type::Void>());
- func->StartTarget()->SetInstructions(utils::Vector{builder.Return(func)});
+ func->StartTarget()->Append(builder.Return(func));
mod->functions.Push(func);
}
};
@@ -68,7 +68,7 @@
ir::Module mod;
ir::Builder builder(mod);
auto* func = builder.Function("main", mod.Types().Get<type::Void>());
- func->StartTarget()->SetInstructions(utils::Vector{builder.Return(func)});
+ func->StartTarget()->Append(builder.Return(func));
builder.ir.functions.Push(func);
return mod;
}
diff --git a/src/tint/type/manager.cc b/src/tint/type/manager.cc
index f5f382b..89a0c0a 100644
--- a/src/tint/type/manager.cc
+++ b/src/tint/type/manager.cc
@@ -14,6 +14,8 @@
#include "src/tint/type/manager.h"
+#include <algorithm>
+
#include "src/tint/type/abstract_float.h"
#include "src/tint/type/abstract_int.h"
#include "src/tint/type/array.h"
@@ -158,8 +160,24 @@
const type::Pointer* Manager::ptr(builtin::AddressSpace address_space,
const type::Type* subtype,
- builtin::Access access) {
+ builtin::Access access /* = builtin::Access::kReadWrite */) {
return Get<type::Pointer>(address_space, subtype, access);
}
+const type::Struct* Manager::Struct(Symbol name, utils::VectorRef<StructMemberDesc> md) {
+ utils::Vector<const type::StructMember*, 4> members;
+ uint32_t current_size = 0u;
+ uint32_t max_align = 0u;
+ for (const auto& m : md) {
+ uint32_t index = static_cast<uint32_t>(members.Length());
+ uint32_t offset = utils::RoundUp(m.type->Align(), current_size);
+ members.Push(Get<type::StructMember>(m.name, m.type, index, offset, m.type->Align(),
+ m.type->Size(), std::move(m.attributes)));
+ current_size = offset + m.type->Size();
+ max_align = std::max(max_align, m.type->Align());
+ }
+ return Get<type::Struct>(name, members, max_align, utils::RoundUp(max_align, current_size),
+ current_size);
+}
+
} // namespace tint::type
diff --git a/src/tint/type/manager.h b/src/tint/type/manager.h
index a9bdbeb..99ffda3 100644
--- a/src/tint/type/manager.h
+++ b/src/tint/type/manager.h
@@ -19,7 +19,10 @@
#include "src/tint/builtin/access.h"
#include "src/tint/builtin/address_space.h"
-#include "src/tint/number.h"
+#include "src/tint/builtin/fluent_types.h"
+#include "src/tint/builtin/number.h"
+#include "src/tint/symbol.h"
+#include "src/tint/type/struct.h"
#include "src/tint/type/type.h"
#include "src/tint/type/unique_node.h"
#include "src/tint/utils/hash.h"
@@ -43,9 +46,6 @@
namespace tint::type {
-template <typename T>
-struct CppToType;
-
/// The type manager holds all the pointers to the known types.
class Manager final {
public:
@@ -92,10 +92,31 @@
/// the same pointer is returned.
template <typename T, typename... ARGS>
auto* Get(ARGS&&... args) {
- using N = ToType<T>;
- if constexpr (utils::traits::IsTypeOrDerived<N, Type>) {
- return types_.Get<N>(std::forward<ARGS>(args)...);
- } else if constexpr (utils::traits::IsTypeOrDerived<N, UniqueNode>) {
+ if constexpr (std::is_same_v<T, tint::AInt>) {
+ return Get<type::AbstractInt>(std::forward<ARGS>(args)...);
+ } else if constexpr (std::is_same_v<T, tint::AFloat>) {
+ return Get<type::AbstractFloat>(std::forward<ARGS>(args)...);
+ } else if constexpr (std::is_same_v<T, tint::i32>) {
+ return Get<type::I32>(std::forward<ARGS>(args)...);
+ } else if constexpr (std::is_same_v<T, tint::u32>) {
+ return Get<type::U32>(std::forward<ARGS>(args)...);
+ } else if constexpr (std::is_same_v<T, tint::f32>) {
+ return Get<type::F32>(std::forward<ARGS>(args)...);
+ } else if constexpr (std::is_same_v<T, tint::f16>) {
+ return Get<type::F16>(std::forward<ARGS>(args)...);
+ } else if constexpr (std::is_same_v<T, bool>) {
+ return Get<type::Bool>(std::forward<ARGS>(args)...);
+ } else if constexpr (builtin::fluent_types::IsVector<T>) {
+ return vec<typename T::type, T::width>(std::forward<ARGS>(args)...);
+ } else if constexpr (builtin::fluent_types::IsMatrix<T>) {
+ return mat<T::columns, T::rows, typename T::type>(std::forward<ARGS>(args)...);
+ } else if constexpr (builtin::fluent_types::IsPointer<T>) {
+ return ptr<T::address, typename T::type, T::access>(std::forward<ARGS>(args)...);
+ } else if constexpr (builtin::fluent_types::IsArray<T>) {
+ return array<typename T::type, T::length>(std::forward<ARGS>(args)...);
+ } else if constexpr (utils::traits::IsTypeOrDerived<T, Type>) {
+ return types_.Get<T>(std::forward<ARGS>(args)...);
+ } else if constexpr (utils::traits::IsTypeOrDerived<T, UniqueNode>) {
return unique_nodes_.Get<T>(std::forward<ARGS>(args)...);
} else {
return nodes_.Create<T>(std::forward<ARGS>(args)...);
@@ -158,6 +179,7 @@
/// @returns the vector type
template <typename T, size_t N>
const type::Vector* vec() {
+ TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
static_assert(N >= 2 && N <= 4);
switch (N) {
case 2:
@@ -167,6 +189,8 @@
case 4:
return vec4<T>();
}
+ return nullptr; // unreachable
+ TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
}
/// @tparam T the element type
@@ -295,6 +319,24 @@
return mat4x4(Get<T>());
}
+ /// @param columns the number of columns of the matrix
+ /// @param rows the number of rows of the matrix
+ /// @tparam T the element type
+ /// @returns a matrix with the given number of columns and rows
+ template <typename T>
+ const type::Matrix* mat(uint32_t columns, uint32_t rows) {
+ return mat(Get<T>(), columns, rows);
+ }
+
+ /// @tparam C the number of columns in the matrix
+ /// @tparam R the number of rows in the matrix
+ /// @tparam T the element type
+ /// @returns a matrix with the given number of columns and rows
+ template <uint32_t C, uint32_t R, typename T>
+ const type::Matrix* mat() {
+ return mat(Get<T>(), C, R);
+ }
+
/// @param elem_ty the array element type
/// @param count the array element count
/// @param stride the optional array element stride
@@ -325,7 +367,7 @@
/// @returns the pointer type
const type::Pointer* ptr(builtin::AddressSpace address_space,
const type::Type* subtype,
- builtin::Access access);
+ builtin::Access access = builtin::Access::kReadWrite);
/// @tparam SPACE the address space
/// @tparam T the storage type
@@ -338,6 +380,39 @@
return ptr(SPACE, Get<T>(), ACCESS);
}
+ /// @param subtype the pointer subtype
+ /// @tparam SPACE the address space
+ /// @tparam ACCESS the access mode
+ /// @returns the pointer type with the templated address space, storage type and access.
+ template <builtin::AddressSpace SPACE, builtin::Access ACCESS = builtin::Access::kReadWrite>
+ const type::Pointer* ptr(const type::Type* subtype) {
+ return ptr(SPACE, subtype, ACCESS);
+ }
+
+ /// A structure member descriptor.
+ struct StructMemberDesc {
+ /// The name of the struct member.
+ Symbol name;
+ /// The type of the struct member.
+ const type::Type* type = nullptr;
+ /// The optional struct member attributes.
+ type::StructMemberAttributes attributes = {};
+ };
+
+ /// Create a new structure declaration.
+ /// @param name the name of the structure
+ /// @param members the list of structure member descriptors
+ /// @returns the structure type
+ const type::Struct* Struct(Symbol name, utils::VectorRef<StructMemberDesc> members);
+
+ /// Create a new structure declaration.
+ /// @param name the name of the structure
+ /// @param members the list of structure member descriptors
+ /// @returns the structure type
+ const type::Struct* Struct(Symbol name, std::initializer_list<StructMemberDesc> members) {
+ return Struct(name, utils::Vector<StructMemberDesc, 4>(members));
+ }
+
/// @returns an iterator to the beginning of the types
TypeIterator begin() const { return types_.begin(); }
/// @returns an iterator to the end of the types
@@ -362,46 +437,6 @@
utils::BlockAllocator<Node> nodes_;
};
-//! @cond Doxygen_Suppress
-// Various template specializations for Manager::ToTypeImpl.
-template <>
-struct Manager::ToTypeImpl<AInt> {
- using type = type::AbstractInt;
-};
-template <>
-struct Manager::ToTypeImpl<AFloat> {
- using type = type::AbstractFloat;
-};
-template <>
-struct Manager::ToTypeImpl<i32> {
- using type = type::I32;
-};
-template <>
-struct Manager::ToTypeImpl<u32> {
- using type = type::U32;
-};
-template <>
-struct Manager::ToTypeImpl<f32> {
- using type = type::F32;
-};
-template <>
-struct Manager::ToTypeImpl<f16> {
- using type = type::F16;
-};
-template <>
-struct Manager::ToTypeImpl<bool> {
- using type = type::Bool;
-};
-template <typename T>
-struct Manager::ToTypeImpl<const T> {
- using type = const Manager::ToType<T>;
-};
-template <typename T>
-struct Manager::ToTypeImpl<T*> {
- using type = Manager::ToType<T>*;
-};
-//! @endcond
-
} // namespace tint::type
#endif // SRC_TINT_TYPE_MANAGER_H_
diff --git a/src/tint/type/struct.h b/src/tint/type/struct.h
index 720beca..907485c 100644
--- a/src/tint/type/struct.h
+++ b/src/tint/type/struct.h
@@ -185,6 +185,8 @@
struct StructMemberAttributes {
/// The value of a `@location` attribute
std::optional<uint32_t> location;
+ /// The value of a `@index` attribute
+ std::optional<uint32_t> index;
/// The value of a `@builtin` attribute
std::optional<builtin::BuiltinValue> builtin;
/// The values of a `@interpolate` attribute
diff --git a/src/tint/utils/castable.cc b/src/tint/utils/castable.cc
index b7756b3..484014f 100644
--- a/src/tint/utils/castable.cc
+++ b/src/tint/utils/castable.cc
@@ -19,7 +19,7 @@
/// The unique TypeInfo for the CastableBase type
/// @return doxygen-thinks-this-static-field-is-a-function :(
template <>
-const TypeInfo detail::TypeInfoOf<CastableBase>::info{
+const TypeInfo utils::detail::TypeInfoOf<CastableBase>::info{
nullptr,
"CastableBase",
tint::utils::TypeInfo::HashCodeOf<CastableBase>(),
diff --git a/src/tint/utils/castable.h b/src/tint/utils/castable.h
index f402c1c..176b107 100644
--- a/src/tint/utils/castable.h
+++ b/src/tint/utils/castable.h
@@ -176,7 +176,7 @@
/// @returns the static TypeInfo for the type T
template <typename T>
static const TypeInfo& Of() {
- return detail::TypeInfoOf<std::remove_cv_t<T>>::info;
+ return utils::detail::TypeInfoOf<std::remove_cv_t<T>>::info;
}
/// @returns a compile-time hashcode for the type `T`.
@@ -281,7 +281,7 @@
/// @returns true if `obj` is a valid pointer, and is of, or derives from the class `TO`
/// @param obj the object to test from
/// @see CastFlags
-template <typename TO, int FLAGS = 0, typename FROM = detail::Infer>
+template <typename TO, int FLAGS = 0, typename FROM = utils::detail::Infer>
inline bool Is(FROM* obj) {
if (obj == nullptr) {
return false;
@@ -295,7 +295,10 @@
/// @param pred predicate function with signature `bool(const TYPE*)` called iff object is of, or
/// derives from the class `TYPE`.
/// @see CastFlags
-template <typename TYPE, int FLAGS = 0, typename OBJ = detail::Infer, typename Pred = detail::Infer>
+template <typename TYPE,
+ int FLAGS = 0,
+ typename OBJ = utils::detail::Infer,
+ typename Pred = utils::detail::Infer>
inline bool Is(OBJ* obj, Pred&& pred) {
return Is<TYPE, FLAGS, OBJ>(obj) && pred(static_cast<std::add_const_t<TYPE>*>(obj));
}
@@ -315,7 +318,7 @@
/// `TO`.
/// @param obj the object to cast from
/// @see CastFlags
-template <typename TO, int FLAGS = 0, typename FROM = detail::Infer>
+template <typename TO, int FLAGS = 0, typename FROM = utils::detail::Infer>
inline TO* As(FROM* obj) {
auto* as_castable = static_cast<CastableBase*>(obj);
return Is<TO, FLAGS>(obj) ? static_cast<TO*>(as_castable) : nullptr;
@@ -325,7 +328,7 @@
/// `TO`.
/// @param obj the object to cast from
/// @see CastFlags
-template <typename TO, int FLAGS = 0, typename FROM = detail::Infer>
+template <typename TO, int FLAGS = 0, typename FROM = utils::detail::Infer>
inline const TO* As(const FROM* obj) {
auto* as_castable = static_cast<const CastableBase*>(obj);
return Is<TO, FLAGS>(obj) ? static_cast<const TO*>(as_castable) : nullptr;
@@ -361,7 +364,7 @@
/// returns true
/// @param pred predicate function with signature `bool(const TO*)` called iff object is of, or
/// derives from the class `TO`.
- template <typename TO, int FLAGS = 0, typename Pred = detail::Infer>
+ template <typename TO, int FLAGS = 0, typename Pred = utils::detail::Infer>
inline bool Is(Pred&& pred) const {
return tint::utils::Is<TO, FLAGS>(this, std::forward<Pred>(pred));
}
@@ -445,7 +448,7 @@
/// pred(const TO*) returns true
/// @param pred predicate function with signature `bool(const TO*)` called iff
/// object is of, or derives from the class `TO`.
- template <int FLAGS = 0, typename Pred = detail::Infer>
+ template <int FLAGS = 0, typename Pred = utils::detail::Infer>
inline bool Is(Pred&& pred) const {
using TO = typename std::remove_pointer<utils::traits::ParameterType<Pred, 0>>::type;
return tint::utils::Is<TO, FLAGS>(static_cast<const CLASS*>(this),
@@ -534,7 +537,7 @@
/// Resolves to the common most derived type that each of the types in `TYPES` derives from.
template <typename... TYPES>
-using CastableCommonBase = detail::CastableCommonBase<TYPES...>;
+using CastableCommonBase = utils::detail::CastableCommonBase<TYPES...>;
} // namespace tint::utils
diff --git a/src/tint/utils/hash.h b/src/tint/utils/hash.h
index fe1614e..f02c777 100644
--- a/src/tint/utils/hash.h
+++ b/src/tint/utils/hash.h
@@ -209,7 +209,7 @@
/// The returned hash is dependent on the order of the arguments.
template <typename... ARGS>
size_t HashCombine(size_t hash, const ARGS&... values) {
- constexpr size_t offset = detail::HashCombineOffset<sizeof(size_t)>::value();
+ constexpr size_t offset = utils::detail::HashCombineOffset<sizeof(size_t)>::value();
((hash ^= Hash(values) + (offset ^ (hash >> 2))), ...);
return hash;
}
diff --git a/src/tint/utils/hashset.h b/src/tint/utils/hashset.h
index 2d427a1..5339565 100644
--- a/src/tint/utils/hashset.h
+++ b/src/tint/utils/hashset.h
@@ -35,6 +35,17 @@
using PutMode = typename Base::PutMode;
public:
+ using Base::Base;
+
+ /// Constructor with initializer list of items
+ /// @param items the items to place into the set
+ Hashset(std::initializer_list<KEY> items) {
+ this->Reserve(items.size());
+ for (auto item : items) {
+ this->Add(item);
+ }
+ }
+
/// Adds a value to the set, if the set does not already contain an entry equal to `value`.
/// @param value the value to add to the set.
/// @returns true if the value was added, false if there was an existing value in the set.
@@ -55,6 +66,30 @@
}
return out;
}
+
+ /// @returns true if the predicate function returns true for any of the elements of the set
+ /// @param pred a function-like with the signature `bool(T)`
+ template <typename PREDICATE>
+ bool Any(PREDICATE&& pred) const {
+ for (const auto& it : *this) {
+ if (pred(it)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// @returns false if the predicate function returns false for any of the elements of the set
+ /// @param pred a function-like with the signature `bool(T)`
+ template <typename PREDICATE>
+ bool All(PREDICATE&& pred) const {
+ for (const auto& it : *this) {
+ if (!pred(it)) {
+ return false;
+ }
+ }
+ return true;
+ }
};
} // namespace tint::utils
diff --git a/src/tint/utils/hashset_test.cc b/src/tint/utils/hashset_test.cc
index c541fb5..31a025a 100644
--- a/src/tint/utils/hashset_test.cc
+++ b/src/tint/utils/hashset_test.cc
@@ -21,6 +21,7 @@
#include <unordered_set>
#include "gmock/gmock.h"
+#include "src/tint/utils/predicates.h"
namespace tint::utils {
namespace {
@@ -38,6 +39,16 @@
EXPECT_EQ(set.Count(), 0u);
}
+TEST(Hashset, InitializerConstructor) {
+ Hashset<int, 8> set{1, 5, 7};
+ EXPECT_EQ(set.Count(), 3u);
+ EXPECT_TRUE(set.Contains(1u));
+ EXPECT_FALSE(set.Contains(3u));
+ EXPECT_TRUE(set.Contains(5u));
+ EXPECT_TRUE(set.Contains(7u));
+ EXPECT_FALSE(set.Contains(9u));
+}
+
TEST(Hashset, AddRemove) {
Hashset<std::string, 8> set;
EXPECT_TRUE(set.Add("hello"));
@@ -140,5 +151,31 @@
}
}
+TEST(HashsetTest, Any) {
+ Hashset<int, 8> set{1, 7, 5, 9};
+ EXPECT_TRUE(set.Any(Eq(1)));
+ EXPECT_FALSE(set.Any(Eq(2)));
+ EXPECT_FALSE(set.Any(Eq(3)));
+ EXPECT_FALSE(set.Any(Eq(4)));
+ EXPECT_TRUE(set.Any(Eq(5)));
+ EXPECT_FALSE(set.Any(Eq(6)));
+ EXPECT_TRUE(set.Any(Eq(7)));
+ EXPECT_FALSE(set.Any(Eq(8)));
+ EXPECT_TRUE(set.Any(Eq(9)));
+}
+
+TEST(HashsetTest, All) {
+ Hashset<int, 8> set{1, 7, 5, 9};
+ EXPECT_FALSE(set.All(Ne(1)));
+ EXPECT_TRUE(set.All(Ne(2)));
+ EXPECT_TRUE(set.All(Ne(3)));
+ EXPECT_TRUE(set.All(Ne(4)));
+ EXPECT_FALSE(set.All(Ne(5)));
+ EXPECT_TRUE(set.All(Ne(6)));
+ EXPECT_FALSE(set.All(Ne(7)));
+ EXPECT_TRUE(set.All(Ne(8)));
+ EXPECT_FALSE(set.All(Ne(9)));
+}
+
} // namespace
} // namespace tint::utils
diff --git a/src/tint/utils/slice.h b/src/tint/utils/slice.h
index ca25949..49483ec 100644
--- a/src/tint/utils/slice.h
+++ b/src/tint/utils/slice.h
@@ -94,7 +94,8 @@
/// * `FROM` and `TO` are pointers to CastableBase (or derived), and the pointee type of `TO` is of
/// the same type as, or is an ancestor of the pointee type of `FROM`.
template <ReinterpretMode MODE, typename TO, typename FROM>
-static constexpr bool CanReinterpretSlice = detail::CanReinterpretSlice<MODE, TO, FROM>::value;
+static constexpr bool CanReinterpretSlice =
+ utils::detail::CanReinterpretSlice<MODE, TO, FROM>::value;
/// A slice represents a contigious array of elements of type T.
template <typename T>
diff --git a/src/tint/utils/traits.h b/src/tint/utils/traits.h
index 711ea36..f37b073 100644
--- a/src/tint/utils/traits.h
+++ b/src/tint/utils/traits.h
@@ -148,14 +148,14 @@
/// `[OFFSET..OFFSET+COUNT)`
template <std::size_t OFFSET, std::size_t COUNT, typename TUPLE>
constexpr auto Slice(TUPLE&& t) {
- return detail::Swizzle<TUPLE>(std::forward<TUPLE>(t), Range<OFFSET, COUNT>());
+ return traits::detail::Swizzle<TUPLE>(std::forward<TUPLE>(t), Range<OFFSET, COUNT>());
}
/// Resolves to the slice of the tuple `t` with the tuple elements
/// `[OFFSET..OFFSET+COUNT)`
template <std::size_t OFFSET, std::size_t COUNT, typename TUPLE>
using SliceTuple =
- std::remove_pointer_t<decltype(detail::SwizzlePtrTy<TUPLE>(Range<OFFSET, COUNT>()))>;
+ std::remove_pointer_t<decltype(traits::detail::SwizzlePtrTy<TUPLE>(Range<OFFSET, COUNT>()))>;
namespace detail {
/// Base template for IsTypeIn
@@ -171,7 +171,7 @@
/// Works for std::variant, std::tuple, std::pair, or any typename template where all parameters are
/// types.
template <typename T, typename TypeContainer>
-static constexpr bool IsTypeIn = detail::IsTypeIn<T, TypeContainer>::value;
+static constexpr bool IsTypeIn = traits::detail::IsTypeIn<T, TypeContainer>::value;
/// Evaluates to the decayed pointer element type, or the decayed type T if T is not a pointer.
template <typename T>
@@ -207,7 +207,7 @@
/// Evaluates to `char*` or `const char*` if `T` is `char[N]` or `const char[N]`, respectively,
/// otherwise T.
template <typename T>
-using CharArrayToCharPtr = typename detail::CharArrayToCharPtrImpl<T>::type;
+using CharArrayToCharPtr = typename traits::detail::CharArrayToCharPtrImpl<T>::type;
} // namespace tint::utils::traits
diff --git a/src/tint/utils/vector.h b/src/tint/utils/vector.h
index 8b8fc0f..78cddbd 100644
--- a/src/tint/utils/vector.h
+++ b/src/tint/utils/vector.h
@@ -571,7 +571,7 @@
/// Helper for determining the Vector element type (`T`) from the vector's constuctor arguments
template <typename... Ts>
using VectorCommonType =
- typename detail::VectorCommonType<IsCastable<std::remove_pointer_t<Ts>...>, Ts...>::type;
+ typename utils::detail::VectorCommonType<IsCastable<std::remove_pointer_t<Ts>...>, Ts...>::type;
/// Deduction guide for Vector
template <typename... Ts>
@@ -792,7 +792,7 @@
/// True if T is a Vector<T, N> or VectorRef<T>
template <typename T>
-static constexpr bool IsVectorLike = detail::IsVectorLike<T>::value;
+static constexpr bool IsVectorLike = utils::detail::IsVectorLike<T>::value;
} // namespace tint::utils
diff --git a/src/tint/writer/append_vector_test.cc b/src/tint/writer/append_vector_test.cc
index ff58ba3..b9e7857 100644
--- a/src/tint/writer/append_vector_test.cc
+++ b/src/tint/writer/append_vector_test.cc
@@ -20,11 +20,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
class AppendVectorTest : public ::testing::Test, public ProgramBuilder {};
// AppendVector(vec2<i32>(1, 2), 3) -> vec3<i32>(1, 2, 3)
@@ -32,7 +33,7 @@
auto* scalar_1 = Expr(1_i);
auto* scalar_2 = Expr(2_i);
auto* scalar_3 = Expr(3_i);
- auto* vec_12 = vec2<i32>(scalar_1, scalar_2);
+ auto* vec_12 = Call<vec2<i32>>(scalar_1, scalar_2);
WrapInFunction(vec_12, scalar_3);
resolver::Resolver resolver(this);
@@ -73,7 +74,7 @@
auto* scalar_1 = Expr(1_i);
auto* scalar_2 = Expr(2_i);
auto* scalar_3 = Expr(3_u);
- auto* vec_12 = vec2<i32>(scalar_1, scalar_2);
+ auto* vec_12 = Call<vec2<i32>>(scalar_1, scalar_2);
WrapInFunction(vec_12, scalar_3);
resolver::Resolver resolver(this);
@@ -120,8 +121,8 @@
auto* scalar_1 = Expr(1_u);
auto* scalar_2 = Expr(2_u);
auto* scalar_3 = Expr(3_u);
- auto* uvec_12 = vec2<u32>(scalar_1, scalar_2);
- auto* vec_12 = vec2<i32>(uvec_12);
+ auto* uvec_12 = Call<vec2<u32>>(scalar_1, scalar_2);
+ auto* vec_12 = Call<vec2<i32>>(uvec_12);
WrapInFunction(vec_12, scalar_3);
resolver::Resolver resolver(this);
@@ -170,7 +171,7 @@
auto* scalar_1 = Expr(1_i);
auto* scalar_2 = Expr(2_i);
auto* scalar_3 = Expr(3_f);
- auto* vec_12 = vec2<i32>(scalar_1, scalar_2);
+ auto* vec_12 = Call<vec2<i32>>(scalar_1, scalar_2);
WrapInFunction(vec_12, scalar_3);
resolver::Resolver resolver(this);
@@ -216,7 +217,7 @@
auto* scalar_2 = Expr(2_i);
auto* scalar_3 = Expr(3_i);
auto* scalar_4 = Expr(4_i);
- auto* vec_123 = vec3<i32>(scalar_1, scalar_2, scalar_3);
+ auto* vec_123 = Call<vec3<i32>>(scalar_1, scalar_2, scalar_3);
WrapInFunction(vec_123, scalar_4);
resolver::Resolver resolver(this);
@@ -298,7 +299,7 @@
auto* scalar_1 = Expr(1_i);
auto* scalar_2 = Expr(2_i);
auto* scalar_3 = Expr("scalar_3");
- auto* vec_12 = vec2<i32>(scalar_1, scalar_2);
+ auto* vec_12 = Call<vec2<i32>>(scalar_1, scalar_2);
WrapInFunction(vec_12, scalar_3);
resolver::Resolver resolver(this);
@@ -455,7 +456,7 @@
// AppendVector(vec3<i32>(), 4) -> vec3<bool>(0, 0, 0, 4)
TEST_F(AppendVectorTest, ZeroVec3i32_i32) {
auto* scalar = Expr(4_i);
- auto* vec000 = vec3<i32>();
+ auto* vec000 = Call<vec3<i32>>();
WrapInFunction(vec000, scalar);
resolver::Resolver resolver(this);
diff --git a/src/tint/writer/glsl/generator_impl_binary_test.cc b/src/tint/writer/glsl/generator_impl_binary_test.cc
index 9be3fa4..7ca2b09 100644
--- a/src/tint/writer/glsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/glsl/generator_impl_binary_test.cc
@@ -19,11 +19,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslGeneratorImplTest_Binary = TestHelper;
struct BinaryData {
@@ -160,7 +161,7 @@
BinaryData{"(left % right)", ast::BinaryOp::kModulo}));
TEST_F(GlslGeneratorImplTest_Binary, Multiply_VectorScalar_f32) {
- GlobalVar("a", vec3<f32>(1_f, 1_f, 1_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("a", Call<vec3<f32>>(1_f, 1_f, 1_f), builtin::AddressSpace::kPrivate);
auto* lhs = Expr("a");
auto* rhs = Expr(1_f);
@@ -179,7 +180,7 @@
TEST_F(GlslGeneratorImplTest_Binary, Multiply_VectorScalar_f16) {
Enable(builtin::Extension::kF16);
- GlobalVar("a", vec3<f16>(1_h, 1_h, 1_h), builtin::AddressSpace::kPrivate);
+ GlobalVar("a", Call<vec3<f16>>(1_h, 1_h, 1_h), builtin::AddressSpace::kPrivate);
auto* lhs = Expr("a");
auto* rhs = Expr(1_h);
@@ -196,7 +197,7 @@
}
TEST_F(GlslGeneratorImplTest_Binary, Multiply_ScalarVector_f32) {
- GlobalVar("a", vec3<f32>(1_f, 1_f, 1_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("a", Call<vec3<f32>>(1_f, 1_f, 1_f), builtin::AddressSpace::kPrivate);
auto* lhs = Expr(1_f);
auto* rhs = Expr("a");
@@ -215,7 +216,7 @@
TEST_F(GlslGeneratorImplTest_Binary, Multiply_ScalarVector_f16) {
Enable(builtin::Extension::kF16);
- GlobalVar("a", vec3<f16>(1_h, 1_h, 1_h), builtin::AddressSpace::kPrivate);
+ GlobalVar("a", Call<vec3<f16>>(1_h, 1_h, 1_h), builtin::AddressSpace::kPrivate);
auto* lhs = Expr(1_h);
auto* rhs = Expr("a");
@@ -302,7 +303,7 @@
TEST_F(GlslGeneratorImplTest_Binary, Multiply_MatrixVector_f32) {
GlobalVar("mat", ty.mat3x3<f32>(), builtin::AddressSpace::kPrivate);
auto* lhs = Expr("mat");
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
WrapInFunction(expr);
@@ -320,7 +321,7 @@
GlobalVar("mat", ty.mat3x3<f16>(), builtin::AddressSpace::kPrivate);
auto* lhs = Expr("mat");
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
WrapInFunction(expr);
@@ -335,7 +336,7 @@
TEST_F(GlslGeneratorImplTest_Binary, Multiply_VectorMatrix_f32) {
GlobalVar("mat", ty.mat3x3<f32>(), builtin::AddressSpace::kPrivate);
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* rhs = Expr("mat");
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -353,7 +354,7 @@
Enable(builtin::Extension::kF16);
GlobalVar("mat", ty.mat3x3<f16>(), builtin::AddressSpace::kPrivate);
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* rhs = Expr("mat");
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
diff --git a/src/tint/writer/glsl/generator_impl_builtin_test.cc b/src/tint/writer/glsl/generator_impl_builtin_test.cc
index e7d1a61..78765ef 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_test.cc
@@ -19,13 +19,13 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/glsl/test_helper.h"
-using ::testing::HasSubstr;
-
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslGeneratorImplTest_Builtin = TestHelper;
enum class CallParamType {
@@ -371,9 +371,9 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, Select_Vector) {
- GlobalVar("a", vec2<i32>(1_i, 2_i), builtin::AddressSpace::kPrivate);
- GlobalVar("b", vec2<i32>(3_i, 4_i), builtin::AddressSpace::kPrivate);
- auto* call = Call("select", "a", "b", vec2<bool>(true, false));
+ GlobalVar("a", Call<vec2<i32>>(1_i, 2_i), builtin::AddressSpace::kPrivate);
+ GlobalVar("b", Call<vec2<i32>>(3_i, 4_i), builtin::AddressSpace::kPrivate);
+ auto* call = Call("select", "a", "b", Call<vec2<bool>>(true, false));
WrapInFunction(Decl(Var("r", call)));
GeneratorImpl& gen = Build();
@@ -495,7 +495,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("f", vec3<f32>(1.5_f, 2.5_f, 3.5_f))), //
+ WrapInFunction(Decl(Let("f", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f))), //
Decl(Let("v", Call("modf", "f"))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -532,7 +532,7 @@
TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Modf_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("f", vec3<f16>(1.5_h, 2.5_h, 3.5_h))), //
+ WrapInFunction(Decl(Let("f", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h))), //
Decl(Let("v", Call("modf", "f"))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -625,7 +625,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, Const_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("modf", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))));
+ WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f)))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -654,7 +654,7 @@
TEST_F(GlslGeneratorImplTest_Builtin, Const_Modf_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("v", Call("modf", vec3<f16>(1.5_h, 2.5_h, 3.5_h)))));
+ WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h)))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -755,7 +755,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f32) {
- WrapInFunction(Var("f", Expr(vec3<f32>())), //
+ WrapInFunction(Var("f", Call<vec3<f32>>()), //
Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -792,7 +792,7 @@
TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Var("f", Expr(vec3<f16>())), //
+ WrapInFunction(Var("f", Call<vec3<f16>>()), //
Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -885,7 +885,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("frexp", vec3<f32>()))));
+ WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f32>>()))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -914,7 +914,7 @@
TEST_F(GlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("v", Call("frexp", vec3<f16>()))));
+ WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f16>>()))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -1576,7 +1576,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, QuantizeToF16_Vec2) {
- GlobalVar("v", vec2<f32>(2_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec2<f32>>(2_f), builtin::AddressSpace::kPrivate);
WrapInFunction(Call("quantizeToF16", "v"));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -1604,7 +1604,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, QuantizeToF16_Vec3) {
- GlobalVar("v", vec3<f32>(2_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec3<f32>>(2_f), builtin::AddressSpace::kPrivate);
WrapInFunction(Call("quantizeToF16", "v"));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -1634,7 +1634,7 @@
}
TEST_F(GlslGeneratorImplTest_Builtin, QuantizeToF16_Vec4) {
- GlobalVar("v", vec4<f32>(2_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec4<f32>>(2_f), builtin::AddressSpace::kPrivate);
WrapInFunction(Call("quantizeToF16", "v"));
GeneratorImpl& gen = SanitizeAndBuild();
diff --git a/src/tint/writer/glsl/generator_impl_cast_test.cc b/src/tint/writer/glsl/generator_impl_cast_test.cc
index 4773a4b..870e46e 100644
--- a/src/tint/writer/glsl/generator_impl_cast_test.cc
+++ b/src/tint/writer/glsl/generator_impl_cast_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslGeneratorImplTest_Cast = TestHelper;
TEST_F(GlslGeneratorImplTest_Cast, EmitExpression_Cast_Scalar) {
@@ -37,7 +38,7 @@
}
TEST_F(GlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) {
- auto* cast = vec3<f32>(vec3<i32>(1_i, 2_i, 3_i));
+ auto* cast = Call<vec3<f32>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
WrapInFunction(cast);
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/glsl/generator_impl_constructor_test.cc b/src/tint/writer/glsl/generator_impl_constructor_test.cc
index 2983382..8a18dc7 100644
--- a/src/tint/writer/glsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/glsl/generator_impl_constructor_test.cc
@@ -15,12 +15,12 @@
#include "gmock/gmock.h"
#include "src/tint/writer/glsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using GlslGeneratorImplTest_Constructor = TestHelper;
@@ -121,7 +121,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_F32) {
- WrapInFunction(vec3<f32>(1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec3<f32>>(1_f, 2_f, 3_f));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -132,7 +132,7 @@
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(1_h, 2_h, 3_h));
+ WrapInFunction(Call<vec3<f16>>(1_h, 2_h, 3_h));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -141,7 +141,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_Empty_F32) {
- WrapInFunction(vec3<f32>());
+ WrapInFunction(Call<vec3<f32>>());
GeneratorImpl& gen = Build();
gen.Generate();
@@ -152,7 +152,7 @@
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_Empty_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>());
+ WrapInFunction(Call<vec3<f16>>());
GeneratorImpl& gen = Build();
gen.Generate();
@@ -161,7 +161,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
- WrapInFunction(vec3<f32>(2_f));
+ WrapInFunction(Call<vec3<f32>>(2_f));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -172,7 +172,7 @@
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(2_h));
+ WrapInFunction(Call<vec3<f16>>(2_h));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -182,7 +182,7 @@
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
auto* var = Var("v", Expr(2_f));
- auto* cast = vec3<f32>(var);
+ auto* cast = Call<vec3<f32>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -196,7 +196,7 @@
Enable(builtin::Extension::kF16);
auto* var = Var("v", Expr(2_h));
- auto* cast = vec3<f16>(var);
+ auto* cast = Call<vec3<f16>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -207,7 +207,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Bool) {
- WrapInFunction(vec3<bool>(true));
+ WrapInFunction(Call<vec3<bool>>(true));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -216,7 +216,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Int) {
- WrapInFunction(vec3<i32>(2_i));
+ WrapInFunction(Call<vec3<i32>>(2_i));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -225,7 +225,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_UInt) {
- WrapInFunction(vec3<u32>(2_u));
+ WrapInFunction(Call<vec3<u32>>(2_u));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -234,7 +234,8 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_F32) {
- WrapInFunction(mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(3_f, 4_f, 5_f)));
+ WrapInFunction(
+ Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(3_f, 4_f, 5_f)));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -245,7 +246,8 @@
TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>(vec3<f16>(1_h, 2_h, 3_h), vec3<f16>(3_h, 4_h, 5_h)));
+ WrapInFunction(
+ Call<mat2x3<f16>>(Call<vec3<f16>>(1_h, 2_h, 3_h), Call<vec3<f16>>(3_h, 4_h, 5_h)));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -262,14 +264,14 @@
// vec4<f32>(vec4<f32>(42.0f, 21.0f, 6.0f, -5.0f)),
// );
auto* vector_literal =
- vec4<f32>(Expr(f32(2.0)), Expr(f32(3.0)), Expr(f32(4.0)), Expr(f32(8.0)));
- auto* vector_zero_init = vec4<f32>();
- auto* vector_single_scalar_init = vec4<f32>(Expr(f32(7.0)));
- auto* vector_identical_init =
- vec4<f32>(vec4<f32>(Expr(f32(42.0)), Expr(f32(21.0)), Expr(f32(6.0)), Expr(f32(-5.0))));
+ Call<vec4<f32>>(Expr(f32(2.0)), Expr(f32(3.0)), Expr(f32(4.0)), Expr(f32(8.0)));
+ auto* vector_zero_init = Call<vec4<f32>>();
+ auto* vector_single_scalar_init = Call<vec4<f32>>(Expr(f32(7.0)));
+ auto* vector_identical_init = Call<vec4<f32>>(
+ Call<vec4<f32>>(Expr(f32(42.0)), Expr(f32(21.0)), Expr(f32(6.0)), Expr(f32(-5.0))));
- auto* ctor = mat4x4<f32>(vector_literal, vector_zero_init, vector_single_scalar_init,
- vector_identical_init);
+ auto* ctor = Call<mat4x4<f32>>(vector_literal, vector_zero_init, vector_single_scalar_init,
+ vector_identical_init);
WrapInFunction(ctor);
@@ -290,14 +292,14 @@
Enable(builtin::Extension::kF16);
auto* vector_literal =
- vec4<f16>(Expr(f16(2.0)), Expr(f16(3.0)), Expr(f16(4.0)), Expr(f16(8.0)));
- auto* vector_zero_init = vec4<f16>();
- auto* vector_single_scalar_init = vec4<f16>(Expr(f16(7.0)));
- auto* vector_identical_init =
- vec4<f16>(vec4<f16>(Expr(f16(42.0)), Expr(f16(21.0)), Expr(f16(6.0)), Expr(f16(-5.0))));
+ Call<vec4<f16>>(Expr(f16(2.0)), Expr(f16(3.0)), Expr(f16(4.0)), Expr(f16(8.0)));
+ auto* vector_zero_init = Call<vec4<f16>>();
+ auto* vector_single_scalar_init = Call<vec4<f16>>(Expr(f16(7.0)));
+ auto* vector_identical_init = Call<vec4<f16>>(
+ Call<vec4<f16>>(Expr(f16(42.0)), Expr(f16(21.0)), Expr(f16(6.0)), Expr(f16(-5.0))));
- auto* ctor = mat4x4<f16>(vector_literal, vector_zero_init, vector_single_scalar_init,
- vector_identical_init);
+ auto* ctor = Call<mat4x4<f16>>(vector_literal, vector_zero_init, vector_single_scalar_init,
+ vector_identical_init);
WrapInFunction(ctor);
@@ -310,7 +312,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_Empty_F32) {
- WrapInFunction(mat2x3<f32>());
+ WrapInFunction(Call<mat2x3<f32>>());
GeneratorImpl& gen = Build();
gen.Generate();
@@ -321,7 +323,7 @@
TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_Empty_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>());
+ WrapInFunction(Call<mat2x3<f16>>());
GeneratorImpl& gen = Build();
gen.Generate();
@@ -336,8 +338,8 @@
// var m_2: mat4x4<f32> = mat4x4<f32>(m_1);
// }
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), mat4x4<f32>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), mat4x4<f32>(m_1));
+ auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>());
+ auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>(m_1));
WrapInFunction(m_1, m_2);
@@ -355,8 +357,8 @@
Enable(builtin::Extension::kF16);
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), mat4x4<f16>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), mat4x4<f16>(m_1));
+ auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>());
+ auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>(m_1));
WrapInFunction(m_1, m_2);
@@ -367,8 +369,9 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Array) {
- WrapInFunction(Call(ty.array(ty.vec3<f32>(), 3_u), vec3<f32>(1_f, 2_f, 3_f),
- vec3<f32>(4_f, 5_f, 6_f), vec3<f32>(7_f, 8_f, 9_f)));
+ WrapInFunction(Call<array<vec3<f32>, 3>>(Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(4_f, 5_f, 6_f),
+ Call<vec3<f32>>(7_f, 8_f, 9_f)));
GeneratorImpl& gen = Build();
gen.Generate();
@@ -379,7 +382,7 @@
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Array_Empty) {
- WrapInFunction(Call(ty.array(ty.vec3<f32>(), 3_u)));
+ WrapInFunction(Call<array<vec3<f32>, 3>>());
GeneratorImpl& gen = Build();
gen.Generate();
@@ -394,7 +397,7 @@
Member("c", ty.vec3<i32>()),
});
- WrapInFunction(Call(ty.Of(str), 1_i, 2_f, vec3<i32>(3_i, 4_i, 5_i)));
+ WrapInFunction(Call(ty.Of(str), 1_i, 2_f, Call<vec3<i32>>(3_i, 4_i, 5_i)));
GeneratorImpl& gen = SanitizeAndBuild();
gen.Generate();
diff --git a/src/tint/writer/glsl/generator_impl_function_test.cc b/src/tint/writer/glsl/generator_impl_function_test.cc
index 34375f7..43f8773 100644
--- a/src/tint/writer/glsl/generator_impl_function_test.cc
+++ b/src/tint/writer/glsl/generator_impl_function_test.cc
@@ -20,11 +20,12 @@
using ::testing::HasSubstr;
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslGeneratorImplTest_Function = TestHelper;
TEST_F(GlslGeneratorImplTest_Function, Emit_Function) {
@@ -110,7 +111,7 @@
// fn f(foo : ptr<function, f32>) -> f32 {
// return *foo;
// }
- Func("f", utils::Vector{Param("foo", ty.ptr<f32>(builtin::AddressSpace::kFunction))}, ty.f32(),
+ Func("f", utils::Vector{Param("foo", ty.ptr<function, f32>())}, ty.f32(),
utils::Vector{Return(Deref("foo"))});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -207,7 +208,7 @@
// @location(2) col2 : f32;
// };
// fn vert_main() -> Interface {
- // return Interface(vec4<f32>(), 0.4, 0.6);
+ // return Interface(vec4<f32>(), 0.5, 0.25);
// }
// fn frag_main(inputs : Interface) {
// const r = inputs.col1;
@@ -223,8 +224,7 @@
});
Func("vert_main", utils::Empty, ty.Of(interface_struct),
- utils::Vector{Return(
- Call(ty.Of(interface_struct), Call(ty.vec4<f32>()), Expr(0.5_f), Expr(0.25_f)))},
+ utils::Vector{Return(Call(ty.Of(interface_struct), Call<vec4<f32>>(), 0.5_f, 0.25_f))},
utils::Vector{Stage(ast::PipelineStage::kVertex)});
Func("frag_main", utils::Vector{Param("inputs", ty.Of(interface_struct))}, ty.void_(),
@@ -301,7 +301,7 @@
Func("foo", utils::Vector{Param("x", ty.f32())}, ty.Of(vertex_output_struct),
{Return(Call(ty.Of(vertex_output_struct),
- Call(ty.vec4<f32>(), "x", "x", "x", Expr(1_f))))},
+ Call<vec4<f32>>( "x", "x", "x", 1_f)))},
{});
Func("vert_main1", utils::Empty, ty.Of(vertex_output_struct),
@@ -845,7 +845,7 @@
TEST_F(GlslGeneratorImplTest_Function, Emit_Function_WithArrayReturn) {
Func("my_func", utils::Empty, ty.array<f32, 5>(),
utils::Vector{
- Return(Call(ty.array<f32, 5>())),
+ Return(Call<array<f32, 5>>()),
});
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/glsl/generator_impl_import_test.cc b/src/tint/writer/glsl/generator_impl_import_test.cc
index 6f772ea..0f27e4b 100644
--- a/src/tint/writer/glsl/generator_impl_import_test.cc
+++ b/src/tint/writer/glsl/generator_impl_import_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslGeneratorImplTest_Import = TestHelper;
struct GlslImportData {
@@ -95,7 +96,7 @@
TEST_P(GlslImportData_SingleVectorParamTest, FloatVector) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(0.1_f, 0.2_f, 0.3_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(0.1_f, 0.2_f, 0.3_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -162,7 +163,7 @@
TEST_P(GlslImportData_DualParam_VectorTest, Float) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -227,8 +228,8 @@
TEST_P(GlslImportData_TripleParam_VectorTest, Float) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f),
- vec3<f32>(7_f, 8_f, 9_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f),
+ Call<vec3<f32>>(7_f, 8_f, 9_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/glsl/generator_impl_member_accessor_test.cc b/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
index 041e72c..7f252b1 100644
--- a/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
@@ -17,12 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using create_type_func_ptr = ast::Type (*)(const ProgramBuilder::TypesBuilder& ty);
@@ -275,7 +275,7 @@
});
SetupFunction(utils::Vector{
- Assign(MemberAccessor("data", "b"), Call(ty.mat2x3<f32>())),
+ Assign(MemberAccessor("data", "b"), Call<mat2x3<f32>>()),
});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -769,7 +769,7 @@
SetupFunction(utils::Vector{
Assign(MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"),
- vec3<f32>(1_f, 2_f, 3_f)),
+ Call<vec3<f32>>(1_f, 2_f, 3_f)),
});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -868,7 +868,7 @@
}
TEST_F(GlslGeneratorImplTest_MemberAccessor, Swizzle_xyz) {
- auto* var = Var("my_vec", ty.vec4<f32>(), vec4<f32>(1_f, 2_f, 3_f, 4_f));
+ auto* var = Var("my_vec", ty.vec4<f32>(), Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f));
auto* expr = MemberAccessor("my_vec", "xyz");
WrapInFunction(var, expr);
@@ -879,7 +879,7 @@
}
TEST_F(GlslGeneratorImplTest_MemberAccessor, Swizzle_gbr) {
- auto* var = Var("my_vec", ty.vec4<f32>(), vec4<f32>(1_f, 2_f, 3_f, 4_f));
+ auto* var = Var("my_vec", ty.vec4<f32>(), Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f));
auto* expr = MemberAccessor("my_vec", "gbr");
WrapInFunction(var, expr);
diff --git a/src/tint/writer/glsl/generator_impl_module_constant_test.cc b/src/tint/writer/glsl/generator_impl_module_constant_test.cc
index 8de0dd0..9a80721 100644
--- a/src/tint/writer/glsl/generator_impl_module_constant_test.cc
+++ b/src/tint/writer/glsl/generator_impl_module_constant_test.cc
@@ -17,15 +17,16 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslGeneratorImplTest_ModuleConstant = TestHelper;
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalLet) {
- auto* var = Let("pos", ty.array<f32, 3>(), array<f32, 3>(1_f, 2_f, 3_f));
+ auto* var = Let("pos", ty.array<f32, 3>(), Call<array<f32, 3>>(1_f, 2_f, 3_f));
WrapInFunction(Decl(var));
GeneratorImpl& gen = Build();
@@ -152,7 +153,7 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_AInt) {
- auto* var = GlobalConst("G", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* var = GlobalConst("G", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -171,7 +172,7 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_AFloat) {
- auto* var = GlobalConst("G", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* var = GlobalConst("G", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -190,7 +191,7 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_f32) {
- auto* var = GlobalConst("G", vec3<f32>(1_f, 2_f, 3_f));
+ auto* var = GlobalConst("G", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -211,7 +212,7 @@
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* var = GlobalConst("G", vec3<f16>(1_h, 2_h, 3_h));
+ auto* var = GlobalConst("G", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -231,7 +232,7 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_AFloat) {
- auto* var = GlobalConst("G", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* var = GlobalConst("G", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -250,7 +251,7 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_f32) {
- auto* var = GlobalConst("G", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* var = GlobalConst("G", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -271,7 +272,7 @@
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* var = GlobalConst("G", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* var = GlobalConst("G", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -291,7 +292,7 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_arr_f32) {
- auto* var = GlobalConst("G", Call(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
+ auto* var = GlobalConst("G", Call<array<f32, 3>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
@@ -310,10 +311,10 @@
}
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_arr_vec2_bool) {
- auto* var = GlobalConst("G", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* var = GlobalConst("G", Call<array<vec2<bool>, 3>>( //
+ Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", Expr(var))),
diff --git a/src/tint/writer/glsl/generator_impl_sanitizer_test.cc b/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
index fdd216f..ca60d36 100644
--- a/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
+++ b/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
@@ -19,11 +19,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using GlslSanitizerTest = TestHelper;
TEST_F(GlslSanitizerTest, Call_ArrayLength) {
@@ -149,7 +150,7 @@
}
TEST_F(GlslSanitizerTest, PromoteArrayInitializerToConstVar) {
- auto* array_init = array<i32, 4>(1_i, 2_i, 3_i, 4_i);
+ auto* array_init = Call<array<i32, 4>>(1_i, 2_i, 3_i, 4_i);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -189,7 +190,7 @@
Member("c", ty.i32()),
});
auto* runtime_value = Var("runtime_value", Expr(3_f));
- auto* struct_init = Call(ty.Of(str), 1_i, vec3<f32>(2_f, runtime_value, 4_f), 4_i);
+ auto* struct_init = Call(ty.Of(str), 1_i, Call<vec3<f32>>(2_f, runtime_value, 4_f), 4_i);
auto* struct_access = MemberAccessor(struct_init, "b");
auto* pos = Var("pos", ty.vec3<f32>(), struct_access);
@@ -235,7 +236,7 @@
// let p : ptr<function, i32> = &v;
// let x : i32 = *p;
auto* v = Var("v", ty.i32());
- auto* p = Let("p", ty.ptr<i32>(builtin::AddressSpace::kFunction), AddressOf(v));
+ auto* p = Let("p", ty.ptr<function, i32>(), AddressOf(v));
auto* x = Var("x", ty.i32(), Deref(p));
Func("main", utils::Empty, ty.void_(),
@@ -276,12 +277,9 @@
// let vp : ptr<function, vec4<f32>> = &(*mp)[2i];
// let v : vec4<f32> = *vp;
auto* a = Var("a", ty.array(ty.mat4x4<f32>(), 4_u));
- auto* ap = Let("ap", ty.ptr(builtin::AddressSpace::kFunction, ty.array(ty.mat4x4<f32>(), 4_u)),
- AddressOf(a));
- auto* mp = Let("mp", ty.ptr(builtin::AddressSpace::kFunction, ty.mat4x4<f32>()),
- AddressOf(IndexAccessor(Deref(ap), 3_i)));
- auto* vp = Let("vp", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>()),
- AddressOf(IndexAccessor(Deref(mp), 2_i)));
+ auto* ap = Let("ap", ty.ptr<function, array<mat4x4<f32>, 4>>(), AddressOf(a));
+ auto* mp = Let("mp", ty.ptr<function, mat4x4<f32>>(), AddressOf(IndexAccessor(Deref(ap), 3_i)));
+ auto* vp = Let("vp", ty.ptr<function, vec4<f32>>(), AddressOf(IndexAccessor(Deref(mp), 2_i)));
auto* v = Var("v", ty.vec4<f32>(), Deref(vp));
Func("main", utils::Empty, ty.void_(),
diff --git a/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc b/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc
index 821b0e9..8ebe654 100644
--- a/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc
+++ b/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/tint/number.h"
+#include "src/tint/builtin/number.h"
#include "src/tint/writer/glsl/test_helper.h"
#include "gmock/gmock.h"
diff --git a/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc
index 80a1fa0..d4171c5 100644
--- a/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc
@@ -17,12 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::glsl {
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using GlslGeneratorImplTest_VariableDecl = TestHelper;
@@ -186,7 +186,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_AInt) {
- auto* C = Const("C", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* C = Const("C", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -206,7 +206,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_AFloat) {
- auto* C = Const("C", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* C = Const("C", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -226,7 +226,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_f32) {
- auto* C = Const("C", vec3<f32>(1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -248,7 +248,7 @@
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", vec3<f16>(1_h, 2_h, 3_h));
+ auto* C = Const("C", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -269,7 +269,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_AFloat) {
- auto* C = Const("C", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* C = Const("C", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -289,7 +289,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_f32) {
- auto* C = Const("C", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* C = Const("C", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -311,7 +311,7 @@
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* C = Const("C", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -332,7 +332,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_arr_f32) {
- auto* C = Const("C", Call(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<array<f32, 3>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -352,7 +352,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_arr_f32_zero) {
- auto* C = Const("C", Call(ty.array<f32, 2>()));
+ auto* C = Const("C", Call<array<f32, 2>>());
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -372,7 +372,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_arr_arr_f32_zero) {
- auto* C = Const("C", Call(ty.array(ty.array<f32, 2>(), 3_i)));
+ auto* C = Const("C", Call<array<array<f32, 2>, 3>>());
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -418,10 +418,10 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_arr_vec2_bool) {
- auto* C = Const("C", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* C = Const("C", Call<array<vec2<bool>, 3>>( //
+ Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -466,7 +466,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_f32) {
- auto* var = Var("a", ty.vec3<f32>(), vec3<f32>());
+ auto* var = Var("a", ty.vec3<f32>(), Call<vec3<f32>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -481,7 +481,7 @@
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_f16) {
Enable(builtin::Extension::kF16);
- auto* var = Var("a", ty.vec3<f16>(), vec3<f16>());
+ auto* var = Var("a", ty.vec3<f16>(), Call<vec3<f16>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -494,7 +494,7 @@
}
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat_f32) {
- auto* var = Var("a", ty.mat2x3<f32>(), mat2x3<f32>());
+ auto* var = Var("a", ty.mat2x3<f32>(), Call<mat2x3<f32>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -510,7 +510,7 @@
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat_f16) {
Enable(builtin::Extension::kF16);
- auto* var = Var("a", ty.mat2x3<f16>(), mat2x3<f16>());
+ auto* var = Var("a", ty.mat2x3<f16>(), Call<mat2x3<f16>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index def946a..1267bea 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -194,9 +194,16 @@
manager.Add<ast::transform::Robustness>();
ast::transform::Robustness::Config config = {};
+
config.bindings_ignored = std::unordered_set<sem::BindingPoint>(
options.binding_points_ignored_in_robustness_transform.cbegin(),
options.binding_points_ignored_in_robustness_transform.cend());
+
+ // Direct3D guarantees to return zero for any resource that is accessed out of bounds, and
+ // according to the description of the assembly store_uav_typed, out of bounds addressing
+ // means nothing gets written to memory.
+ config.texture_action = ast::transform::Robustness::Action::kIgnore;
+
data.Add<ast::transform::Robustness::Config>(config);
}
diff --git a/src/tint/writer/hlsl/generator_impl_binary_test.cc b/src/tint/writer/hlsl/generator_impl_binary_test.cc
index 61a4ee1..5269dca 100644
--- a/src/tint/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_binary_test.cc
@@ -17,11 +17,12 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslGeneratorImplTest_Binary = TestHelper;
struct BinaryData {
@@ -176,7 +177,7 @@
BinaryData::Types::Float}));
TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorScalar_f32) {
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* rhs = Expr(1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -193,7 +194,7 @@
TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorScalar_f16) {
Enable(builtin::Extension::kF16);
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* rhs = Expr(1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -209,7 +210,7 @@
TEST_F(HlslGeneratorImplTest_Binary, Multiply_ScalarVector_f32) {
auto* lhs = Expr(1_f);
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -226,7 +227,7 @@
Enable(builtin::Extension::kF16);
auto* lhs = Expr(1_h);
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -306,7 +307,7 @@
TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixVector_f32) {
GlobalVar("mat", ty.mat3x3<f32>(), builtin::AddressSpace::kPrivate);
auto* lhs = Expr("mat");
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
WrapInFunction(expr);
@@ -323,7 +324,7 @@
GlobalVar("mat", ty.mat3x3<f16>(), builtin::AddressSpace::kPrivate);
auto* lhs = Expr("mat");
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
WrapInFunction(expr);
@@ -337,7 +338,7 @@
TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorMatrix_f32) {
GlobalVar("mat", ty.mat3x3<f32>(), builtin::AddressSpace::kPrivate);
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* rhs = Expr("mat");
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -354,7 +355,7 @@
Enable(builtin::Extension::kF16);
GlobalVar("mat", ty.mat3x3<f16>(), builtin::AddressSpace::kPrivate);
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* rhs = Expr("mat");
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
index 92406a6..16dfcea 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
@@ -19,13 +19,13 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using ::testing::HasSubstr;
-
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslGeneratorImplTest_Builtin = TestHelper;
enum class CallParamType {
@@ -368,9 +368,9 @@
}
TEST_F(HlslGeneratorImplTest_Builtin, Select_Vector) {
- GlobalVar("a", vec2<i32>(1_i, 2_i), builtin::AddressSpace::kPrivate);
- GlobalVar("b", vec2<i32>(3_i, 4_i), builtin::AddressSpace::kPrivate);
- auto* call = Call("select", "a", "b", vec2<bool>(true, false));
+ GlobalVar("a", Call<vec2<i32>>(1_i, 2_i), builtin::AddressSpace::kPrivate);
+ GlobalVar("b", Call<vec2<i32>>(3_i, 4_i), builtin::AddressSpace::kPrivate);
+ auto* call = Call("select", "a", "b", Call<vec2<bool>>(true, false));
WrapInFunction(Decl(Var("r", call)));
GeneratorImpl& gen = Build();
@@ -435,7 +435,7 @@
}
TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("f", vec3<f32>(1.5_f, 2.5_f, 3.5_f))), //
+ WrapInFunction(Decl(Let("f", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f))), //
Decl(Let("v", Call("modf", "f"))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -463,7 +463,7 @@
TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Modf_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("f", vec3<f16>(1.5_h, 2.5_h, 3.5_h))), //
+ WrapInFunction(Decl(Let("f", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h))), //
Decl(Let("v", Call("modf", "f"))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -527,7 +527,7 @@
}
TEST_F(HlslGeneratorImplTest_Builtin, Const_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("modf", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))));
+ WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f)))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -547,7 +547,7 @@
TEST_F(HlslGeneratorImplTest_Builtin, Const_Modf_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("v", Call("modf", vec3<f16>(1.5_h, 2.5_h, 3.5_h)))));
+ WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h)))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -568,10 +568,10 @@
WrapInFunction(
// Declare a variable with the result of a modf call.
// This is required to infer the 'var' type.
- Decl(Var("v", Call("modf", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))),
+ Decl(Var("v", Call("modf", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f)))),
// Now assign 'v' again with another modf call.
// This requires generating a temporary variable for the struct initializer.
- Assign("v", Call("modf", vec3<f32>(4.5_a, 5.5_a, 6.5_a))));
+ Assign("v", Call("modf", Call<vec3<f32>>(4.5_a, 5.5_a, 6.5_a))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -647,7 +647,7 @@
}
TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f32) {
- WrapInFunction(Var("f", Expr(vec3<f32>())), //
+ WrapInFunction(Var("f", Call<vec3<f32>>()), //
Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -676,7 +676,7 @@
TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Var("f", Expr(vec3<f16>())), //
+ WrapInFunction(Var("f", Call<vec3<f16>>()), //
Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -741,7 +741,7 @@
}
TEST_F(HlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("frexp", vec3<f32>()))));
+ WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f32>>()))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -761,7 +761,7 @@
TEST_F(HlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("v", Call("frexp", vec3<f16>()))));
+ WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f16>>()))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -782,10 +782,10 @@
WrapInFunction(
// Declare a variable with the result of a frexp call.
// This is required to infer the 'var' type.
- Decl(Var("v", Call("frexp", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))),
+ Decl(Var("v", Call("frexp", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f)))),
// Now assign 'v' again with another frexp call.
// This requires generating a temporary variable for the struct initializer.
- Assign("v", Call("frexp", vec3<f32>(4.5_a, 5.5_a, 6.5_a))));
+ Assign("v", Call("frexp", Call<vec3<f32>>(4.5_a, 5.5_a, 6.5_a))));
GeneratorImpl& gen = SanitizeAndBuild();
diff --git a/src/tint/writer/hlsl/generator_impl_cast_test.cc b/src/tint/writer/hlsl/generator_impl_cast_test.cc
index 73bc170..6484974 100644
--- a/src/tint/writer/hlsl/generator_impl_cast_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_cast_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslGeneratorImplTest_Cast = TestHelper;
TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Scalar) {
@@ -34,7 +35,7 @@
}
TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) {
- auto* cast = vec3<f32>(vec3<i32>(1_i, 2_i, 3_i));
+ auto* cast = Call<vec3<f32>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
WrapInFunction(cast);
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/hlsl/generator_impl_constructor_test.cc b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
index f9c41ea..bdb05ba 100644
--- a/src/tint/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
@@ -15,12 +15,12 @@
#include "gmock/gmock.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using HlslGeneratorImplTest_Constructor = TestHelper;
@@ -121,7 +121,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_F32) {
- WrapInFunction(vec3<f32>(1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec3<f32>>(1_f, 2_f, 3_f));
GeneratorImpl& gen = Build();
@@ -132,7 +132,7 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(1_h, 2_h, 3_h));
+ WrapInFunction(Call<vec3<f16>>(1_h, 2_h, 3_h));
GeneratorImpl& gen = Build();
@@ -143,7 +143,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_Empty_F32) {
- WrapInFunction(vec3<f32>());
+ WrapInFunction(Call<vec3<f32>>());
GeneratorImpl& gen = Build();
@@ -154,7 +154,7 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_Empty_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>());
+ WrapInFunction(Call<vec3<f16>>());
GeneratorImpl& gen = Build();
@@ -163,7 +163,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
- WrapInFunction(vec3<f32>(2_f));
+ WrapInFunction(Call<vec3<f32>>(2_f));
GeneratorImpl& gen = Build();
@@ -174,7 +174,7 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(2_h));
+ WrapInFunction(Call<vec3<f16>>(2_h));
GeneratorImpl& gen = Build();
@@ -184,7 +184,7 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
auto* var = Var("v", Expr(2_f));
- auto* cast = vec3<f32>(var);
+ auto* cast = Call<vec3<f32>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -198,7 +198,7 @@
Enable(builtin::Extension::kF16);
auto* var = Var("v", Expr(2_h));
- auto* cast = vec3<f16>(var);
+ auto* cast = Call<vec3<f16>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -209,7 +209,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Bool_Literal) {
- WrapInFunction(vec3<bool>(true));
+ WrapInFunction(Call<vec3<bool>>(true));
GeneratorImpl& gen = Build();
@@ -219,7 +219,7 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Bool_Var) {
auto* var = Var("v", Expr(true));
- auto* cast = vec3<bool>(var);
+ auto* cast = Call<vec3<bool>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -230,7 +230,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Int) {
- WrapInFunction(vec3<i32>(2_i));
+ WrapInFunction(Call<vec3<i32>>(2_i));
GeneratorImpl& gen = Build();
@@ -239,7 +239,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_UInt) {
- WrapInFunction(vec3<u32>(2_u));
+ WrapInFunction(Call<vec3<u32>>(2_u));
GeneratorImpl& gen = Build();
@@ -248,7 +248,8 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_F32) {
- WrapInFunction(mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(3_f, 4_f, 5_f)));
+ WrapInFunction(
+ Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(3_f, 4_f, 5_f)));
GeneratorImpl& gen = Build();
@@ -261,7 +262,8 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>(vec3<f16>(1_h, 2_h, 3_h), vec3<f16>(3_h, 4_h, 5_h)));
+ WrapInFunction(
+ Call<mat2x3<f16>>(Call<vec3<f16>>(1_h, 2_h, 3_h), Call<vec3<f16>>(3_h, 4_h, 5_h)));
GeneratorImpl& gen = Build();
@@ -280,15 +282,14 @@
// vec4<f32>(7.0f),
// vec4<f32>(vec4<f32>(42.0f, 21.0f, 6.0f, -5.0f)),
// );
- auto* vector_literal =
- vec4<f32>(Expr(f32(2.0)), Expr(f32(3.0)), Expr(f32(4.0)), Expr(f32(8.0)));
- auto* vector_zero_init = vec4<f32>();
- auto* vector_single_scalar_init = vec4<f32>(Expr(f32(7.0)));
+ auto* vector_literal = Call<vec4<f32>>(f32(2.0), f32(3.0), f32(4.0), f32(8.0));
+ auto* vector_zero_init = Call<vec4<f32>>();
+ auto* vector_single_scalar_init = Call<vec4<f32>>(f32(7.0));
auto* vector_identical_init =
- vec4<f32>(vec4<f32>(Expr(f32(42.0)), Expr(f32(21.0)), Expr(f32(6.0)), Expr(f32(-5.0))));
+ Call<vec4<f32>>(Call<vec4<f32>>(f32(42.0), f32(21.0), f32(6.0), f32(-5.0)));
- auto* constructor = mat4x4<f32>(vector_literal, vector_zero_init, vector_single_scalar_init,
- vector_identical_init);
+ auto* constructor = Call<mat4x4<f32>>(vector_literal, vector_zero_init,
+ vector_single_scalar_init, vector_identical_init);
WrapInFunction(constructor);
@@ -309,15 +310,14 @@
// );
Enable(builtin::Extension::kF16);
- auto* vector_literal =
- vec4<f16>(Expr(f16(2.0)), Expr(f16(3.0)), Expr(f16(4.0)), Expr(f16(8.0)));
- auto* vector_zero_init = vec4<f16>();
- auto* vector_single_scalar_init = vec4<f16>(Expr(f16(7.0)));
+ auto* vector_literal = Call<vec4<f16>>(f16(2.0), f16(3.0), f16(4.0), f16(8.0));
+ auto* vector_zero_init = Call<vec4<f16>>();
+ auto* vector_single_scalar_init = Call<vec4<f16>>(f16(7.0));
auto* vector_identical_init =
- vec4<f16>(vec4<f16>(Expr(f16(42.0)), Expr(f16(21.0)), Expr(f16(6.0)), Expr(f16(-5.0))));
+ Call<vec4<f16>>(Call<vec4<f16>>(f16(42.0), f16(21.0), f16(6.0), f16(-5.0)));
- auto* constructor = mat4x4<f16>(vector_literal, vector_zero_init, vector_single_scalar_init,
- vector_identical_init);
+ auto* constructor = Call<mat4x4<f16>>(vector_literal, vector_zero_init,
+ vector_single_scalar_init, vector_identical_init);
WrapInFunction(constructor);
@@ -334,7 +334,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_Empty_F32) {
- WrapInFunction(mat2x3<f32>());
+ WrapInFunction(Call<mat2x3<f32>>());
GeneratorImpl& gen = Build();
@@ -346,7 +346,7 @@
TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_Empty_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>());
+ WrapInFunction(Call<mat2x3<f16>>());
GeneratorImpl& gen = Build();
@@ -362,8 +362,8 @@
// var m_2: mat4x4<f32> = mat4x4<f32>(m_1);
// }
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), mat4x4<f32>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), mat4x4<f32>(m_1));
+ auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>());
+ auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>(m_1));
WrapInFunction(m_1, m_2);
@@ -382,8 +382,8 @@
Enable(builtin::Extension::kF16);
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), mat4x4<f16>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), mat4x4<f16>(m_1));
+ auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>());
+ auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>(m_1));
WrapInFunction(m_1, m_2);
@@ -396,8 +396,9 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Array) {
- WrapInFunction(Call(ty.array(ty.vec3<f32>(), 3_u), vec3<f32>(1_f, 2_f, 3_f),
- vec3<f32>(4_f, 5_f, 6_f), vec3<f32>(7_f, 8_f, 9_f)));
+ WrapInFunction(Call<array<vec3<f32>, 3>>(Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(4_f, 5_f, 6_f),
+ Call<vec3<f32>>(7_f, 8_f, 9_f)));
GeneratorImpl& gen = Build();
@@ -409,7 +410,7 @@
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Array_Empty) {
- WrapInFunction(Call(ty.array(ty.vec3<f32>(), 3_u)));
+ WrapInFunction(Call<array<vec3<f32>, 3>>());
GeneratorImpl& gen = Build();
@@ -424,7 +425,7 @@
Member("c", ty.vec3<i32>()),
});
- WrapInFunction(Call(ty.Of(str), 1_i, 2_f, vec3<i32>(3_i, 4_i, 5_i)));
+ WrapInFunction(Call(ty.Of(str), 1_i, 2_f, Call<vec3<i32>>(3_i, 4_i, 5_i)));
GeneratorImpl& gen = SanitizeAndBuild();
diff --git a/src/tint/writer/hlsl/generator_impl_function_test.cc b/src/tint/writer/hlsl/generator_impl_function_test.cc
index 37d94c3..a374924 100644
--- a/src/tint/writer/hlsl/generator_impl_function_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_function_test.cc
@@ -20,11 +20,12 @@
using ::testing::HasSubstr;
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslGeneratorImplTest_Function = TestHelper;
TEST_F(HlslGeneratorImplTest_Function, Emit_Function) {
@@ -101,7 +102,7 @@
// fn f(foo : ptr<function, f32>) -> f32 {
// return *foo;
// }
- Func("f", utils::Vector{Param("foo", ty.ptr<f32>(builtin::AddressSpace::kFunction))}, ty.f32(),
+ Func("f", utils::Vector{Param("foo", ty.ptr<function, f32>())}, ty.f32(),
utils::Vector{Return(Deref("foo"))});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -216,7 +217,7 @@
Func("vert_main", utils::Empty, ty.Of(interface_struct),
utils::Vector{
- Return(Call(ty.Of(interface_struct), Call(ty.vec4<f32>()), Expr(0.5_f), Expr(0.25_f))),
+ Return(Call(ty.Of(interface_struct), Call<vec4<f32>>(), 0.5_f, 0.25_f)),
},
utils::Vector{Stage(ast::PipelineStage::kVertex)});
@@ -296,8 +297,7 @@
Func("foo", utils::Vector{Param("x", ty.f32())}, ty.Of(vertex_output_struct),
utils::Vector{
- Return(
- Call(ty.Of(vertex_output_struct), Call(ty.vec4<f32>(), "x", "x", "x", Expr(1_f)))),
+ Return(Call(ty.Of(vertex_output_struct), Call<vec4<f32>>("x", "x", "x", 1_f))),
},
utils::Empty);
@@ -752,7 +752,7 @@
TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayReturn) {
Func("my_func", utils::Empty, ty.array<f32, 5>(),
utils::Vector{
- Return(Call(ty.array<f32, 5>())),
+ Return(Call<array<f32, 5>>()),
});
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/hlsl/generator_impl_import_test.cc b/src/tint/writer/hlsl/generator_impl_import_test.cc
index 67af40d..1b78943 100644
--- a/src/tint/writer/hlsl/generator_impl_import_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_import_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslGeneratorImplTest_Import = TestHelper;
struct HlslImportData {
@@ -89,7 +90,7 @@
TEST_P(HlslImportData_SingleVectorParamTest, FloatVector) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(0.1_f, 0.2_f, 0.3_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(0.1_f, 0.2_f, 0.3_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -152,7 +153,7 @@
TEST_P(HlslImportData_DualParam_VectorTest, Float) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -215,8 +216,8 @@
TEST_P(HlslImportData_TripleParam_VectorTest, Float) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f),
- vec3<f32>(7_f, 8_f, 9_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f),
+ Call<vec3<f32>>(7_f, 8_f, 9_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -279,7 +280,7 @@
}
TEST_F(HlslGeneratorImplTest_Import, HlslImportData_QuantizeToF16_Vector) {
- GlobalVar("v", vec3<f32>(2_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec3<f32>>(2_f), builtin::AddressSpace::kPrivate);
auto* expr = Call("quantizeToF16", "v");
WrapInFunction(expr);
diff --git a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
index 389b8f2..6232315 100644
--- a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -18,11 +18,12 @@
using ::testing::HasSubstr;
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using create_type_func_ptr = ast::Type (*)(const ProgramBuilder::TypesBuilder& ty);
inline ast::Type ty_i32(const ProgramBuilder::TypesBuilder& ty) {
@@ -1133,7 +1134,7 @@
});
SetupFunction(utils::Vector{
- Assign(MemberAccessor("data", "b"), Call(ty.mat2x3<f32>())),
+ Assign(MemberAccessor("data", "b"), Call<mat2x3<f32>>()),
});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -1330,7 +1331,7 @@
SetupUniformBuffer(utils::Vector{
Member("z", ty.f32()),
- Member("a", ty.array(ty.vec4(ty.i32()), 5_i)),
+ Member("a", ty.array<vec4<i32>, 5>()),
});
SetupFunction(utils::Vector{
@@ -1505,7 +1506,7 @@
SetupUniformBuffer(utils::Vector{
Member("z", ty.f32()),
- Member("a", ty.array(ty.vec4(ty.i32()), 5_i)),
+ Member("a", ty.array<vec4<i32>, 5>()),
});
SetupFunction(utils::Vector{
@@ -1922,7 +1923,7 @@
SetupFunction(utils::Vector{
Assign(MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"),
- vec3<f32>(1_f, 2_f, 3_f)),
+ Call<vec3<f32>>(1_f, 2_f, 3_f)),
});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -1981,7 +1982,7 @@
}
TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_xyz) {
- auto* var = Var("my_vec", ty.vec4<f32>(), vec4<f32>(1_f, 2_f, 3_f, 4_f));
+ auto* var = Var("my_vec", ty.vec4<f32>(), Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f));
auto* expr = MemberAccessor("my_vec", "xyz");
WrapInFunction(var, expr);
@@ -1991,7 +1992,7 @@
}
TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_gbr) {
- auto* var = Var("my_vec", ty.vec4<f32>(), vec4<f32>(1_f, 2_f, 3_f, 4_f));
+ auto* var = Var("my_vec", ty.vec4<f32>(), Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f));
auto* expr = MemberAccessor("my_vec", "gbr");
WrapInFunction(var, expr);
diff --git a/src/tint/writer/hlsl/generator_impl_module_constant_test.cc b/src/tint/writer/hlsl/generator_impl_module_constant_test.cc
index e7805a7..c4e4e01 100644
--- a/src/tint/writer/hlsl/generator_impl_module_constant_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_module_constant_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/ast/id_attribute.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslGeneratorImplTest_ModuleConstant = TestHelper;
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_AInt) {
@@ -109,7 +110,7 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_AInt) {
- auto* var = GlobalConst("G", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* var = GlobalConst("G", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -123,7 +124,7 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_AFloat) {
- auto* var = GlobalConst("G", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* var = GlobalConst("G", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -137,7 +138,7 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_f32) {
- auto* var = GlobalConst("G", vec3<f32>(1_f, 2_f, 3_f));
+ auto* var = GlobalConst("G", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -153,7 +154,7 @@
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* var = GlobalConst("G", vec3<f16>(1_h, 2_h, 3_h));
+ auto* var = GlobalConst("G", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -167,7 +168,7 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_AFloat) {
- auto* var = GlobalConst("G", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* var = GlobalConst("G", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -181,7 +182,7 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_f32) {
- auto* var = GlobalConst("G", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* var = GlobalConst("G", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -197,7 +198,7 @@
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* var = GlobalConst("G", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* var = GlobalConst("G", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -211,7 +212,7 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_arr_f32) {
- auto* var = GlobalConst("G", Call(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
+ auto* var = GlobalConst("G", Call<array<f32, 3>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -225,10 +226,10 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_arr_vec2_bool) {
- auto* var = GlobalConst("G", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* var = GlobalConst("G", Call<array<vec2<bool>, 3>>( //
+ Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc b/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc
index b1fef10..0d5ed73 100644
--- a/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc
@@ -17,11 +17,12 @@
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using HlslSanitizerTest = TestHelper;
TEST_F(HlslSanitizerTest, Call_ArrayLength) {
@@ -170,7 +171,7 @@
}
TEST_F(HlslSanitizerTest, PromoteArrayInitializerToConstVar) {
- auto* array_init = array<i32, 4>(1_i, 2_i, 3_i, 4_i);
+ auto* array_init = Call<array<i32, 4>>(1_i, 2_i, 3_i, 4_i);
Func("main", utils::Empty, ty.void_(),
utils::Vector{
@@ -203,7 +204,7 @@
Member("b", ty.vec3<f32>()),
Member("c", ty.i32()),
});
- auto* struct_init = Call(ty.Of(str), 1_i, vec3<f32>(2_f, runtime_value, 4_f), 4_i);
+ auto* struct_init = Call(ty.Of(str), 1_i, Call<vec3<f32>>(2_f, runtime_value, 4_f), 4_i);
auto* struct_access = MemberAccessor(struct_init, "b");
auto* pos = Var("pos", ty.vec3<f32>(), struct_access);
@@ -242,7 +243,7 @@
// let p : ptr<function, i32> = &v;
// let x : i32 = *p;
auto* v = Var("v", ty.i32());
- auto* p = Let("p", ty.ptr<i32>(builtin::AddressSpace::kFunction), AddressOf(v));
+ auto* p = Let("p", ty.ptr<function, i32>(), AddressOf(v));
auto* x = Var("x", ty.i32(), Deref(p));
Func("main", utils::Empty, ty.void_(),
@@ -276,12 +277,9 @@
// let vp : ptr<function, vec4<f32>> = &(*mp)[2i];
// let v : vec4<f32> = *vp;
auto* a = Var("a", ty.array(ty.mat4x4<f32>(), 4_u));
- auto* ap = Let("ap", ty.ptr(builtin::AddressSpace::kFunction, ty.array(ty.mat4x4<f32>(), 4_u)),
- AddressOf(a));
- auto* mp = Let("mp", ty.ptr(builtin::AddressSpace::kFunction, ty.mat4x4<f32>()),
- AddressOf(IndexAccessor(Deref(ap), 3_i)));
- auto* vp = Let("vp", ty.ptr(builtin::AddressSpace::kFunction, ty.vec4<f32>()),
- AddressOf(IndexAccessor(Deref(mp), 2_i)));
+ auto* ap = Let("ap", ty.ptr<function, array<mat4x4<f32>, 4>>(), AddressOf(a));
+ auto* mp = Let("mp", ty.ptr<function, mat4x4<f32>>(), AddressOf(IndexAccessor(Deref(ap), 3_i)));
+ auto* vp = Let("vp", ty.ptr<function, vec4<f32>>(), AddressOf(IndexAccessor(Deref(mp), 2_i)));
auto* v = Var("v", ty.vec4<f32>(), Deref(vp));
Func("main", utils::Empty, ty.void_(),
diff --git a/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
index f50ab58..f53eee2 100644
--- a/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
@@ -16,11 +16,12 @@
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/writer/hlsl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::hlsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using ::testing::HasSubstr;
using HlslGeneratorImplTest_VariableDecl = TestHelper;
@@ -175,7 +176,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_AInt) {
- auto* C = Const("C", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* C = Const("C", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -193,7 +194,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_AFloat) {
- auto* C = Const("C", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* C = Const("C", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -211,7 +212,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_f32) {
- auto* C = Const("C", vec3<f32>(1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -231,7 +232,7 @@
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", vec3<f16>(1_h, 2_h, 3_h));
+ auto* C = Const("C", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -249,7 +250,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_AFloat) {
- auto* C = Const("C", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* C = Const("C", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -267,7 +268,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_f32) {
- auto* C = Const("C", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* C = Const("C", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -287,7 +288,7 @@
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* C = Const("C", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -323,10 +324,10 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_arr_vec2_bool) {
- auto* C = Const("C", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* C = Const("C", Call<array<vec2<bool>, 3>>( //
+ Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -370,7 +371,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_F32) {
- auto* var = Var("a", ty.vec3<f32>(), vec3<f32>());
+ auto* var = Var("a", ty.vec3<f32>(), Call<vec3<f32>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -385,7 +386,7 @@
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_F16) {
Enable(builtin::Extension::kF16);
- auto* var = Var("a", ty.vec3<f16>(), vec3<f16>());
+ auto* var = Var("a", ty.vec3<f16>(), Call<vec3<f16>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -398,7 +399,7 @@
}
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat_F32) {
- auto* var = Var("a", ty.mat2x3<f32>(), mat2x3<f32>());
+ auto* var = Var("a", ty.mat2x3<f32>(), Call<mat2x3<f32>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -414,7 +415,7 @@
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat_F16) {
Enable(builtin::Extension::kF16);
- auto* var = Var("a", ty.mat2x3<f16>(), mat2x3<f16>());
+ auto* var = Var("a", ty.mat2x3<f16>(), Call<mat2x3<f16>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
diff --git a/src/tint/writer/msl/generator_impl_builtin_test.cc b/src/tint/writer/msl/generator_impl_builtin_test.cc
index 5a38ba2..bb117b1 100644
--- a/src/tint/writer/msl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_test.cc
@@ -17,11 +17,12 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using MslGeneratorImplTest = TestHelper;
enum class CallParamType {
@@ -473,7 +474,7 @@
}
TEST_F(MslGeneratorImplTest, Runtime_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("f", vec3<f32>(1.5_f, 2.5_f, 3.5_f))), //
+ WrapInFunction(Decl(Let("f", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f))), //
Decl(Let("v", Call("modf", "f"))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -505,7 +506,7 @@
TEST_F(MslGeneratorImplTest, Runtime_Modf_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("f", vec3<f16>(1.5_h, 2.5_h, 3.5_h))), //
+ WrapInFunction(Decl(Let("f", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h))), //
Decl(Let("v", Call("modf", "f"))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -581,7 +582,7 @@
}
TEST_F(MslGeneratorImplTest, Const_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("modf", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))));
+ WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f)))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -605,7 +606,7 @@
TEST_F(MslGeneratorImplTest, Const_Modf_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("v", Call("modf", vec3<f16>(1.5_h, 2.5_h, 3.5_h)))));
+ WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h)))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -689,7 +690,7 @@
}
TEST_F(MslGeneratorImplTest, Runtime_Frexp_Vector_f32) {
- WrapInFunction(Var("f", Expr(vec3<f32>())), //
+ WrapInFunction(Var("f", Call<vec3<f32>>()), //
Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -721,7 +722,7 @@
TEST_F(MslGeneratorImplTest, Runtime_Frexp_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Var("f", Expr(vec3<f16>())), //
+ WrapInFunction(Var("f", Call<vec3<f16>>()), //
Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -797,7 +798,7 @@
}
TEST_F(MslGeneratorImplTest, Const_Frexp_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("frexp", vec3<f32>()))));
+ WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f32>>()))));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -821,7 +822,7 @@
TEST_F(MslGeneratorImplTest, Const_Frexp_Vector_f16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(Decl(Let("v", Call("frexp", vec3<f16>()))));
+ WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f16>>()))));
GeneratorImpl& gen = SanitizeAndBuild();
diff --git a/src/tint/writer/msl/generator_impl_cast_test.cc b/src/tint/writer/msl/generator_impl_cast_test.cc
index 78d6c58..3895559 100644
--- a/src/tint/writer/msl/generator_impl_cast_test.cc
+++ b/src/tint/writer/msl/generator_impl_cast_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Scalar) {
@@ -34,7 +35,7 @@
}
TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Vector) {
- auto* cast = vec3<f32>(vec3<i32>(1_i, 2_i, 3_i));
+ auto* cast = Call<vec3<f32>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
WrapInFunction(cast);
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/msl/generator_impl_constructor_test.cc b/src/tint/writer/msl/generator_impl_constructor_test.cc
index b3a333e..64c2629 100644
--- a/src/tint/writer/msl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/msl/generator_impl_constructor_test.cc
@@ -15,12 +15,12 @@
#include "gmock/gmock.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using MslGeneratorImplTest_Constructor = TestHelper;
@@ -121,7 +121,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_F32) {
- WrapInFunction(vec3<f32>(1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec3<f32>>(1_f, 2_f, 3_f));
GeneratorImpl& gen = Build();
@@ -132,7 +132,7 @@
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(1_h, 2_h, 3_h));
+ WrapInFunction(Call<vec3<f16>>(1_h, 2_h, 3_h));
GeneratorImpl& gen = Build();
@@ -141,7 +141,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_Empty_F32) {
- WrapInFunction(vec3<f32>());
+ WrapInFunction(Call<vec3<f32>>());
GeneratorImpl& gen = Build();
@@ -152,7 +152,7 @@
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_Empty_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>());
+ WrapInFunction(Call<vec3<f16>>());
GeneratorImpl& gen = Build();
@@ -161,7 +161,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
- WrapInFunction(vec3<f32>(2_f));
+ WrapInFunction(Call<vec3<f32>>(2_f));
GeneratorImpl& gen = Build();
@@ -172,7 +172,7 @@
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(2_h));
+ WrapInFunction(Call<vec3<f16>>(2_h));
GeneratorImpl& gen = Build();
@@ -182,7 +182,7 @@
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
auto* var = Var("v", Expr(2_f));
- auto* cast = vec3<f32>(var);
+ auto* cast = Call<vec3<f32>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -196,7 +196,7 @@
Enable(builtin::Extension::kF16);
auto* var = Var("v", Expr(2_h));
- auto* cast = vec3<f16>(var);
+ auto* cast = Call<vec3<f16>>(var);
WrapInFunction(var, cast);
GeneratorImpl& gen = Build();
@@ -207,7 +207,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Bool) {
- WrapInFunction(vec3<bool>(true));
+ WrapInFunction(Call<vec3<bool>>(true));
GeneratorImpl& gen = Build();
@@ -216,7 +216,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Int) {
- WrapInFunction(vec3<i32>(2_i));
+ WrapInFunction(Call<vec3<i32>>(2_i));
GeneratorImpl& gen = Build();
@@ -225,7 +225,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_UInt) {
- WrapInFunction(vec3<u32>(2_u));
+ WrapInFunction(Call<vec3<u32>>(2_u));
GeneratorImpl& gen = Build();
@@ -234,7 +234,8 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Mat_F32) {
- WrapInFunction(mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(3_f, 4_f, 5_f)));
+ WrapInFunction(
+ Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(3_f, 4_f, 5_f)));
GeneratorImpl& gen = Build();
@@ -247,7 +248,8 @@
TEST_F(MslGeneratorImplTest_Constructor, Type_Mat_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>(vec3<f16>(1_h, 2_h, 3_h), vec3<f16>(3_h, 4_h, 5_h)));
+ WrapInFunction(
+ Call<mat2x3<f16>>(Call<vec3<f16>>(1_h, 2_h, 3_h), Call<vec3<f16>>(3_h, 4_h, 5_h)));
GeneratorImpl& gen = Build();
@@ -264,15 +266,14 @@
// vec4<f32>(7.0f),
// vec4<f32>(vec4<f32>(42.0f, 21.0f, 6.0f, -5.0f)),
// );
- auto* vector_literal =
- vec4<f32>(Expr(f32(2.0)), Expr(f32(3.0)), Expr(f32(4.0)), Expr(f32(8.0)));
- auto* vector_zero_init = vec4<f32>();
- auto* vector_single_scalar_init = vec4<f32>(Expr(f32(7.0)));
+ auto* vector_literal = Call<vec4<f32>>(f32(2.0), f32(3.0), f32(4.0), f32(8.0));
+ auto* vector_zero_init = Call<vec4<f32>>();
+ auto* vector_single_scalar_init = Call<vec4<f32>>(f32(7.0));
auto* vector_identical_init =
- vec4<f32>(vec4<f32>(Expr(f32(42.0)), Expr(f32(21.0)), Expr(f32(6.0)), Expr(f32(-5.0))));
+ Call<vec4<f32>>(Call<vec4<f32>>(f32(42.0), f32(21.0), f32(6.0), f32(-5.0)));
- auto* constructor = mat4x4<f32>(vector_literal, vector_zero_init, vector_single_scalar_init,
- vector_identical_init);
+ auto* constructor = Call<mat4x4<f32>>(vector_literal, vector_zero_init,
+ vector_single_scalar_init, vector_identical_init);
WrapInFunction(constructor);
@@ -293,15 +294,14 @@
// );
Enable(builtin::Extension::kF16);
- auto* vector_literal =
- vec4<f16>(Expr(f16(2.0)), Expr(f16(3.0)), Expr(f16(4.0)), Expr(f16(8.0)));
- auto* vector_zero_init = vec4<f16>();
- auto* vector_single_scalar_init = vec4<f16>(Expr(f16(7.0)));
+ auto* vector_literal = Call<vec4<f16>>(f16(2.0), f16(3.0), f16(4.0), f16(8.0));
+ auto* vector_zero_init = Call<vec4<f16>>();
+ auto* vector_single_scalar_init = Call<vec4<f16>>(f16(7.0));
auto* vector_identical_init =
- vec4<f16>(vec4<f16>(Expr(f16(42.0)), Expr(f16(21.0)), Expr(f16(6.0)), Expr(f16(-5.0))));
+ Call<vec4<f16>>(Call<vec4<f16>>(f16(42.0), f16(21.0), f16(6.0), f16(-5.0)));
- auto* constructor = mat4x4<f16>(vector_literal, vector_zero_init, vector_single_scalar_init,
- vector_identical_init);
+ auto* constructor = Call<mat4x4<f16>>(vector_literal, vector_zero_init,
+ vector_single_scalar_init, vector_identical_init);
WrapInFunction(constructor);
@@ -314,7 +314,7 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Mat_Empty_F32) {
- WrapInFunction(mat2x3<f32>());
+ WrapInFunction(Call<mat2x3<f32>>());
GeneratorImpl& gen = Build();
@@ -327,7 +327,7 @@
TEST_F(MslGeneratorImplTest_Constructor, Type_Mat_Empty_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>());
+ WrapInFunction(Call<mat2x3<f16>>());
GeneratorImpl& gen = Build();
@@ -343,8 +343,8 @@
// var m_2: mat4x4<f32> = mat4x4<f32>(m_1);
// }
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), mat4x4<f32>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), mat4x4<f32>(m_1));
+ auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>());
+ auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>(m_1));
WrapInFunction(m_1, m_2);
@@ -363,8 +363,8 @@
Enable(builtin::Extension::kF16);
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), mat4x4<f16>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), mat4x4<f16>(m_1));
+ auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>());
+ auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>(m_1));
WrapInFunction(m_1, m_2);
@@ -376,8 +376,9 @@
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Array) {
- WrapInFunction(Call(ty.array(ty.vec3<f32>(), 3_u), vec3<f32>(1_f, 2_f, 3_f),
- vec3<f32>(4_f, 5_f, 6_f), vec3<f32>(7_f, 8_f, 9_f)));
+ WrapInFunction(Call<array<vec3<f32>, 3>>(Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(4_f, 5_f, 6_f),
+ Call<vec3<f32>>(7_f, 8_f, 9_f)));
GeneratorImpl& gen = Build();
@@ -393,7 +394,7 @@
Member("c", ty.vec3<i32>()),
});
- WrapInFunction(Call(ty.Of(str), 1_i, 2_f, vec3<i32>(3_i, 4_i, 5_i)));
+ WrapInFunction(Call(ty.Of(str), 1_i, 2_f, Call<vec3<i32>>(3_i, 4_i, 5_i)));
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/msl/generator_impl_function_test.cc b/src/tint/writer/msl/generator_impl_function_test.cc
index b828574..c8020f5 100644
--- a/src/tint/writer/msl/generator_impl_function_test.cc
+++ b/src/tint/writer/msl/generator_impl_function_test.cc
@@ -16,11 +16,12 @@
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, Emit_Function) {
@@ -194,7 +195,7 @@
});
Func("vert_main", utils::Empty, ty.Of(interface_struct),
- utils::Vector{Return(Call(ty.Of(interface_struct), 0.5_f, 0.25_f, vec4<f32>()))},
+ utils::Vector{Return(Call(ty.Of(interface_struct), 0.5_f, 0.25_f, Call<vec4<f32>>()))},
utils::Vector{Stage(ast::PipelineStage::kVertex)});
Func("frag_main", utils::Vector{Param("colors", ty.Of(interface_struct))}, ty.void_(),
@@ -276,8 +277,7 @@
Func("foo", utils::Vector{Param("x", ty.f32())}, ty.Of(vertex_output_struct),
utils::Vector{
- Return(
- Call(ty.Of(vertex_output_struct), Call(ty.vec4<f32>(), "x", "x", "x", Expr(1_f)))),
+ Return(Call(ty.Of(vertex_output_struct), Call<vec4<f32>>("x", "x", "x", 1_f))),
});
Func("vert_main1", utils::Empty, ty.Of(vertex_output_struct),
utils::Vector{Return(Expr(Call("foo", Expr(0.5_f))))},
diff --git a/src/tint/writer/msl/generator_impl_import_test.cc b/src/tint/writer/msl/generator_impl_import_test.cc
index d221665..8b4a877 100644
--- a/src/tint/writer/msl/generator_impl_import_test.cc
+++ b/src/tint/writer/msl/generator_impl_import_test.cc
@@ -16,11 +16,12 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using MslGeneratorImplTest = TestHelper;
struct MslImportData {
@@ -134,7 +135,7 @@
TEST_P(MslImportData_DualParam_VectorTest, Float) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -196,8 +197,8 @@
TEST_P(MslImportData_TripleParam_VectorTest, Float) {
auto param = GetParam();
- auto* expr = Call(param.name, vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f),
- vec3<f32>(7_f, 8_f, 9_f));
+ auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f),
+ Call<vec3<f32>>(7_f, 8_f, 9_f));
WrapInFunction(expr);
GeneratorImpl& gen = Build();
@@ -262,7 +263,7 @@
}
TEST_F(MslGeneratorImplTest, MslImportData_QuantizeToF16_Vector) {
- GlobalVar("v", vec3<f32>(2_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec3<f32>>(2_f), builtin::AddressSpace::kPrivate);
auto* expr = Call("quantizeToF16", "v");
WrapInFunction(expr);
diff --git a/src/tint/writer/msl/generator_impl_module_constant_test.cc b/src/tint/writer/msl/generator_impl_module_constant_test.cc
index 4d977b0..4f99b31 100644
--- a/src/tint/writer/msl/generator_impl_module_constant_test.cc
+++ b/src/tint/writer/msl/generator_impl_module_constant_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/ast/id_attribute.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_AInt) {
@@ -133,7 +134,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_vec3_AInt) {
- auto* var = GlobalConst("G", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* var = GlobalConst("G", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -151,7 +152,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_vec3_AFloat) {
- auto* var = GlobalConst("G", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* var = GlobalConst("G", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -169,7 +170,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_vec3_f32) {
- auto* var = GlobalConst("G", vec3<f32>(1_f, 2_f, 3_f));
+ auto* var = GlobalConst("G", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -189,7 +190,7 @@
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* var = GlobalConst("G", vec3<f16>(1_h, 2_h, 3_h));
+ auto* var = GlobalConst("G", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -207,7 +208,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_mat2x3_AFloat) {
- auto* var = GlobalConst("G", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* var = GlobalConst("G", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -225,7 +226,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_mat2x3_f32) {
- auto* var = GlobalConst("G", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* var = GlobalConst("G", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -245,7 +246,7 @@
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* var = GlobalConst("G", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* var = GlobalConst("G", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
@@ -294,10 +295,9 @@
}
TEST_F(MslGeneratorImplTest, Emit_GlobalConst_arr_vec2_bool) {
- auto* var = GlobalConst("G", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* var = GlobalConst("G", Call<array<vec2<bool>, 3>>(Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(Let("l", Expr(var)))});
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/msl/generator_impl_type_test.cc b/src/tint/writer/msl/generator_impl_type_test.cc
index 52d02ee..05109c0 100644
--- a/src/tint/writer/msl/generator_impl_type_test.cc
+++ b/src/tint/writer/msl/generator_impl_type_test.cc
@@ -26,13 +26,13 @@
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h"
-using ::testing::HasSubstr;
-
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
+using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
void FormatMSLField(utils::StringStream& out,
const char* addr,
const char* type,
@@ -562,7 +562,7 @@
TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayVec3DefaultStride) {
// array: size(64), align(16)
- auto array = ty.array(ty.vec3<f32>(), 4_u);
+ auto array = ty.array<vec3<f32>, 4>();
auto* s = Structure("S", utils::Vector{
Member("a", ty.i32()),
diff --git a/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
index 3660be5..be9fe72 100644
--- a/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -16,12 +16,12 @@
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/writer/msl/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::msl {
namespace {
using ::testing::HasSubstr;
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
using MslGeneratorImplTest = TestHelper;
@@ -175,7 +175,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_AInt) {
- auto* C = Const("C", vec3<Infer>(1_a, 2_a, 3_a));
+ auto* C = Const("C", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -193,7 +193,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_AFloat) {
- auto* C = Const("C", vec3<Infer>(1._a, 2._a, 3._a));
+ auto* C = Const("C", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -211,7 +211,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_f32) {
- auto* C = Const("C", vec3<f32>(1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -231,7 +231,7 @@
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", vec3<f16>(1_h, 2_h, 3_h));
+ auto* C = Const("C", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -249,7 +249,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_mat2x3_AFloat) {
- auto* C = Const("C", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* C = Const("C", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -267,7 +267,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_mat2x3_f32) {
- auto* C = Const("C", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* C = Const("C", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -287,7 +287,7 @@
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* C = Const("C", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -305,7 +305,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_arr_f32) {
- auto* C = Const("C", array<f32, 3>(1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<array<f32, 3>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -336,10 +336,10 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_arr_vec2_bool) {
- auto* C = Const("C", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* C = Const("C", Call<array<vec2<bool>, 3>>( //
+ Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(), utils::Vector{Decl(C), Decl(Let("l", Expr(C)))});
GeneratorImpl& gen = Build();
@@ -460,7 +460,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroVec_f32) {
- auto* var = Var("a", ty.vec3<f32>(), vec3<f32>());
+ auto* var = Var("a", ty.vec3<f32>(), Call<vec3<f32>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -475,7 +475,7 @@
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroVec_f16) {
Enable(builtin::Extension::kF16);
- auto* var = Var("a", ty.vec3<f16>(), vec3<f16>());
+ auto* var = Var("a", ty.vec3<f16>(), Call<vec3<f16>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -488,7 +488,7 @@
}
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroMat_f32) {
- auto* var = Var("a", ty.mat2x3<f32>(), mat2x3<f32>());
+ auto* var = Var("a", ty.mat2x3<f32>(), Call<mat2x3<f32>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
@@ -504,7 +504,7 @@
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroMat_f16) {
Enable(builtin::Extension::kF16);
- auto* var = Var("a", ty.mat2x3<f16>(), mat2x3<f16>());
+ auto* var = Var("a", ty.mat2x3<f16>(), Call<mat2x3<f16>>());
auto* stmt = Decl(var);
WrapInFunction(stmt);
diff --git a/src/tint/writer/spirv/builder_accessor_expression_test.cc b/src/tint/writer/spirv/builder_accessor_expression_test.cc
index d93b414..f42da66 100644
--- a/src/tint/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_accessor_expression_test.cc
@@ -15,18 +15,19 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, Let_IndexAccessor_Vector) {
// let ary = vec3<i32>(1, 2, 3);
// var x = ary[1i];
- auto* ary = Let("ary", vec3<i32>(1_i, 2_i, 3_i));
+ auto* ary = Let("ary", Call<vec3<i32>>(1_i, 2_i, 3_i));
auto* x = Var("x", IndexAccessor(ary, 1_i));
WrapInFunction(ary, x);
@@ -61,7 +62,7 @@
// const ary = vec3<i32>(1, 2, 3);
// var x = ary[1i];
- auto* ary = Const("ary", vec3<i32>(1_i, 2_i, 3_i));
+ auto* ary = Const("ary", Call<vec3<i32>>(1_i, 2_i, 3_i));
auto* x = Var("x", IndexAccessor(ary, 1_i));
WrapInFunction(ary, x);
@@ -169,7 +170,7 @@
// let ary : vec3<i32>(1, 2, 3);
// var x = ary[1i + 1i];
- auto* ary = Let("ary", vec3<i32>(1_i, 2_i, 3_i));
+ auto* ary = Let("ary", Call<vec3<i32>>(1_i, 2_i, 3_i));
auto* x = Var("x", IndexAccessor(ary, Add(1_i, 1_i)));
WrapInFunction(ary, x);
@@ -286,8 +287,8 @@
// let ary = array<vec3<f32>, 2u>(vec3<f32>(1.0f, 2.0f, 3.0f), vec3<f32>(4.0f, 5.0f, 6.0f));
// var x = ary[1i][2i];
- auto* ary = Let("ary", array(ty.vec3<f32>(), 2_u, vec3<f32>(1._f, 2._f, 3._f),
- vec3<f32>(4._f, 5._f, 6._f)));
+ auto* ary = Let("ary", Call<array<vec3<f32>, 2>>(Call<vec3<f32>>(1._f, 2._f, 3._f),
+ Call<vec3<f32>>(4._f, 5._f, 6._f)));
auto* x = Var("x", IndexAccessor(IndexAccessor(ary, 1_i), 2_i));
WrapInFunction(ary, x);
@@ -334,8 +335,8 @@
// const ary = array<vec3<f32>, 2u>(vec3<f32>(1.0f, 2.0f, 3.0f), vec3<f32>(4.0f, 5.0f, 6.0f));
// var x = ary[1i][2i];
- auto* ary = Const("ary", array(ty.vec3<f32>(), 2_u, vec3<f32>(1._f, 2._f, 3._f),
- vec3<f32>(4._f, 5._f, 6._f)));
+ auto* ary = Const("ary", Call<array<vec3<f32>, 2>>(Call<vec3<f32>>(1._f, 2._f, 3._f),
+ Call<vec3<f32>>(4._f, 5._f, 6._f)));
auto* x = Var("x", IndexAccessor(IndexAccessor(ary, 1_i), 2_i));
WrapInFunction(ary, x);
@@ -365,7 +366,7 @@
// var ary : array<vec3<f32>, 4u>;
// var x = ary[1i][2i];
- auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* ary = Var("ary", ty.array<vec3<f32>, 4>());
auto* x = Var("x", IndexAccessor(IndexAccessor(ary, 1_i), 2_i));
WrapInFunction(ary, x);
@@ -407,7 +408,7 @@
// var one = 1i;
// var x = ary[one][2i];
- auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* ary = Var("ary", ty.array<vec3<f32>, 4>());
auto* one = Var("one", Expr(3_i));
auto* x = Var("x", IndexAccessor(IndexAccessor(ary, one), 2_i));
WrapInFunction(ary, one, x);
@@ -453,8 +454,8 @@
// let ary = array<vec3<f32>, 2u>(vec3<f32>(1.0f, 2.0f, 3.0f), vec3<f32>(4.0f, 5.0f, 6.0f));
// var x = a[1i].xy;
- auto* ary = Let("ary", array(ty.vec3<f32>(), 2_u, vec3<f32>(1._f, 2._f, 3._f),
- vec3<f32>(4._f, 5._f, 6._f)));
+ auto* ary = Let("ary", Call<array<vec3<f32>, 2>>(Call<vec3<f32>>(1._f, 2._f, 3._f),
+ Call<vec3<f32>>(4._f, 5._f, 6._f)));
auto* x = Var("x", MemberAccessor(IndexAccessor("ary", 1_i), "xy"));
WrapInFunction(ary, x);
@@ -501,7 +502,7 @@
// var ary : array<vec3<f32>, 4u>;
// var x = ary[1i].xy;
- auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* ary = Var("ary", ty.array<vec3<f32>, 4>());
auto* x = Var("x", MemberAccessor(IndexAccessor("ary", 1_i), "xy"));
WrapInFunction(ary, x);
@@ -545,7 +546,7 @@
// var one = 1i;
// var x = ary[one].xy;
- auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* ary = Var("ary", ty.array<vec3<f32>, 4>());
auto* one = Var("one", Expr(1_i));
auto* x = Var("x", MemberAccessor(IndexAccessor("ary", one), "xy"));
WrapInFunction(ary, one, x);
@@ -596,9 +597,10 @@
// array<f32, 2>(0.5, -0.5));
// var x = pos[1u][0u];
- auto* pos = Let("pos", ty.array(ty.vec2<f32>(), 3_u),
- Call(ty.array(ty.vec2<f32>(), 3_u), vec2<f32>(0_f, 0.5_f),
- vec2<f32>(-0.5_f, -0.5_f), vec2<f32>(0.5_f, -0.5_f)));
+ auto* pos =
+ Let("pos", ty.array<vec2<f32>, 3>(),
+ Call<array<vec2<f32>, 3>>(Call<vec2<f32>>(0_f, 0.5_f), Call<vec2<f32>>(-0.5_f, -0.5_f),
+ Call<vec2<f32>>(0.5_f, -0.5_f)));
auto* x = Var("x", IndexAccessor(IndexAccessor(pos, 1_u), 0_u));
WrapInFunction(pos, x);
@@ -644,9 +646,10 @@
// array<f32, 2>(0.5, -0.5));
// var x = pos[1u][0u];
- auto* pos = Const("pos", ty.array(ty.vec2<f32>(), 3_u),
- Call(ty.array(ty.vec2<f32>(), 3_u), vec2<f32>(0_f, 0.5_f),
- vec2<f32>(-0.5_f, -0.5_f), vec2<f32>(0.5_f, -0.5_f)));
+ auto* pos = Const(
+ "pos", ty.array<vec2<f32>, 3>(),
+ Call<array<vec2<f32>, 3>>(Call<vec2<f32>>(0_f, 0.5_f), Call<vec2<f32>>(-0.5_f, -0.5_f),
+ Call<vec2<f32>>(0.5_f, -0.5_f)));
auto* x = Var("x", IndexAccessor(IndexAccessor(pos, 1_u), 0_u));
WrapInFunction(pos, x);
@@ -676,7 +679,7 @@
// var pos : array<vec3<f32>, 3u>;
// var x = pos[1u][2u];
- auto* pos = Var("pos", ty.array(ty.vec3<f32>(), 3_a));
+ auto* pos = Var("pos", ty.array<vec3<f32>, 3>());
auto* x = Var("x", IndexAccessor(IndexAccessor(pos, 1_u), 2_u));
WrapInFunction(pos, x);
@@ -762,9 +765,10 @@
// let a : mat2x2<f32>(vec2<f32>(1., 2.), vec2<f32>(3., 4.));
// var x = a[1i]
- auto* a =
- Let("a", ty.mat2x2<f32>(),
- Call(ty.mat2x2<f32>(), Call(ty.vec2<f32>(), 1_f, 2_f), Call(ty.vec2<f32>(), 3_f, 4_f)));
+ auto* a = Let("a", ty.mat2x2<f32>(),
+ Call<mat2x2<f32>>( //
+ Call<vec2<f32>>(1_f, 2_f), //
+ Call<vec2<f32>>(3_f, 4_f)));
auto* x = Var("x", IndexAccessor("a", 1_i));
WrapInFunction(a, x);
@@ -805,9 +809,10 @@
// const a : mat2x2<f32>(vec2<f32>(1., 2.), vec2<f32>(3., 4.));
// var x = a[1i]
- auto* a = Const(
- "a", ty.mat2x2<f32>(),
- Call(ty.mat2x2<f32>(), Call(ty.vec2<f32>(), 1_f, 2_f), Call(ty.vec2<f32>(), 3_f, 4_f)));
+ auto* a = Const("a", ty.mat2x2<f32>(),
+ Call<mat2x2<f32>>( //
+ Call<vec2<f32>>(1_f, 2_f), //
+ Call<vec2<f32>>(3_f, 4_f)));
auto* x = Var("x", IndexAccessor("a", 1_i));
WrapInFunction(a, x);
diff --git a/src/tint/writer/spirv/builder_assign_test.cc b/src/tint/writer/spirv/builder_assign_test.cc
index e37563a..d6d9d35 100644
--- a/src/tint/writer/spirv/builder_assign_test.cc
+++ b/src/tint/writer/spirv/builder_assign_test.cc
@@ -17,11 +17,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, Assign_Var) {
@@ -75,7 +76,7 @@
TEST_F(BuilderTest, Assign_Var_ZeroInitializer) {
auto* v = GlobalVar("var", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
- auto* val = vec3<f32>();
+ auto* val = Call<vec3<f32>>();
auto* assign = Assign("var", val);
WrapInFunction(assign);
@@ -102,7 +103,7 @@
}
TEST_F(BuilderTest, Assign_Var_Complex_InitializerNestedVector) {
- auto* init = vec3<f32>(vec2<f32>(1_f, 2_f), 3_f);
+ auto* init = Call<vec3<f32>>(Call<vec2<f32>>(1_f, 2_f), 3_f);
auto* v = GlobalVar("var", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
@@ -135,7 +136,7 @@
}
TEST_F(BuilderTest, Assign_Var_Complex_Initializer) {
- auto* init = vec3<f32>(1_f, 2_f, 3_f);
+ auto* init = Call<vec3<f32>>(1_f, 2_f, 3_f);
auto* v = GlobalVar("var", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
@@ -214,7 +215,7 @@
TEST_F(BuilderTest, Assign_Vector) {
auto* v = GlobalVar("var", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
- auto* val = vec3<f32>(1_f, 1_f, 3_f);
+ auto* val = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* assign = Assign("var", val);
WrapInFunction(assign);
diff --git a/src/tint/writer/spirv/builder_binary_expression_test.cc b/src/tint/writer/spirv/builder_binary_expression_test.cc
index 36bd427..70dc106 100644
--- a/src/tint/writer/spirv/builder_binary_expression_test.cc
+++ b/src/tint/writer/spirv/builder_binary_expression_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
struct BinaryData {
@@ -66,8 +67,8 @@
return;
}
- auto* lhs = vec3<i32>(1_i, 1_i, 1_i);
- auto* rhs = vec3<i32>(1_i, 1_i, 1_i);
+ auto* lhs = Call<vec3<i32>>(1_i, 1_i, 1_i);
+ auto* rhs = Call<vec3<i32>>(1_i, 1_i, 1_i);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -159,8 +160,8 @@
return;
}
- auto* lhs = vec3<u32>(1_u, 1_u, 1_u);
- auto* rhs = vec3<u32>(1_u, 1_u, 1_u);
+ auto* lhs = Call<vec3<u32>>(1_u, 1_u, 1_u);
+ auto* rhs = Call<vec3<u32>>(1_u, 1_u, 1_u);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -220,8 +221,8 @@
TEST_P(BinaryArithF32Test, Vector) {
auto param = GetParam();
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -279,8 +280,8 @@
auto param = GetParam();
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -334,8 +335,8 @@
TEST_P(BinaryOperatorBoolTest, Vector) {
auto param = GetParam();
- auto* lhs = vec3<bool>(false, true, false);
- auto* rhs = vec3<bool>(true, false, true);
+ auto* lhs = Call<vec3<bool>>(false, true, false);
+ auto* rhs = Call<vec3<bool>>(true, false, true);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -391,8 +392,8 @@
TEST_P(BinaryCompareUnsignedIntegerTest, Vector) {
auto param = GetParam();
- auto* lhs = vec3<u32>(1_u, 1_u, 1_u);
- auto* rhs = vec3<u32>(1_u, 1_u, 1_u);
+ auto* lhs = Call<vec3<u32>>(1_u, 1_u, 1_u);
+ auto* rhs = Call<vec3<u32>>(1_u, 1_u, 1_u);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -451,8 +452,8 @@
TEST_P(BinaryCompareSignedIntegerTest, Vector) {
auto param = GetParam();
- auto* lhs = vec3<i32>(1_i, 1_i, 1_i);
- auto* rhs = vec3<i32>(1_i, 1_i, 1_i);
+ auto* lhs = Call<vec3<i32>>(1_i, 1_i, 1_i);
+ auto* rhs = Call<vec3<i32>>(1_i, 1_i, 1_i);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -511,8 +512,8 @@
TEST_P(BinaryCompareF32Test, Vector) {
auto param = GetParam();
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -575,8 +576,8 @@
auto param = GetParam();
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(param.op, lhs, rhs);
@@ -608,7 +609,7 @@
BinaryData{ast::BinaryOp::kNotEqual, "OpFOrdNotEqual"}));
TEST_F(BuilderTest, Binary_Multiply_VectorScalar_F32) {
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* rhs = Expr(1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -633,7 +634,7 @@
TEST_F(BuilderTest, Binary_Multiply_VectorScalar_F16) {
Enable(builtin::Extension::kF16);
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* rhs = Expr(1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -657,7 +658,7 @@
TEST_F(BuilderTest, Binary_Multiply_ScalarVector_F32) {
auto* lhs = Expr(1_f);
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -682,7 +683,7 @@
Enable(builtin::Extension::kF16);
auto* lhs = Expr(1_h);
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, rhs);
@@ -813,7 +814,7 @@
TEST_F(BuilderTest, Binary_Multiply_MatrixVector_F32) {
auto* var = Var("mat", ty.mat3x3<f32>());
- auto* rhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* rhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr("mat"), rhs);
WrapInFunction(var, expr);
@@ -843,7 +844,7 @@
Enable(builtin::Extension::kF16);
auto* var = Var("mat", ty.mat3x3<f16>());
- auto* rhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* rhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr("mat"), rhs);
WrapInFunction(var, expr);
@@ -871,7 +872,7 @@
TEST_F(BuilderTest, Binary_Multiply_VectorMatrix_F32) {
auto* var = Var("mat", ty.mat3x3<f32>());
- auto* lhs = vec3<f32>(1_f, 1_f, 1_f);
+ auto* lhs = Call<vec3<f32>>(1_f, 1_f, 1_f);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, Expr("mat"));
WrapInFunction(var, expr);
@@ -901,7 +902,7 @@
Enable(builtin::Extension::kF16);
auto* var = Var("mat", ty.mat3x3<f16>());
- auto* lhs = vec3<f16>(1_h, 1_h, 1_h);
+ auto* lhs = Call<vec3<f16>>(1_h, 1_h, 1_h);
auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, lhs, Expr("mat"));
@@ -1252,19 +1253,23 @@
auto name = builder->Symbols().New();
switch (type) {
case Type::f32:
- builder->GlobalVar(name, builder->ty.vec3<f32>(), builder->vec3<f32>(1_f, 1_f, 1_f),
+ builder->GlobalVar(name, builder->ty.vec3<f32>(),
+ builder->Call<vec3<f32>>(1_f, 1_f, 1_f),
builtin::AddressSpace::kPrivate);
break;
case Type::f16:
- builder->GlobalVar(name, builder->ty.vec3<f16>(), builder->vec3<f16>(1_h, 1_h, 1_h),
+ builder->GlobalVar(name, builder->ty.vec3<f16>(),
+ builder->Call<vec3<f16>>(1_h, 1_h, 1_h),
builtin::AddressSpace::kPrivate);
break;
case Type::i32:
- builder->GlobalVar(name, builder->ty.vec3<i32>(), builder->vec3<i32>(1_i, 1_i, 1_i),
+ builder->GlobalVar(name, builder->ty.vec3<i32>(),
+ builder->Call<vec3<i32>>(1_i, 1_i, 1_i),
builtin::AddressSpace::kPrivate);
break;
case Type::u32:
- builder->GlobalVar(name, builder->ty.vec3<u32>(), builder->vec3<u32>(1_u, 1_u, 1_u),
+ builder->GlobalVar(name, builder->ty.vec3<u32>(),
+ builder->Call<vec3<u32>>(1_u, 1_u, 1_u),
builtin::AddressSpace::kPrivate);
break;
}
@@ -1581,11 +1586,11 @@
auto name = builder->Symbols().New();
switch (type) {
case Type::f32:
- builder->GlobalVar(name, builder->ty.mat3x4<f32>(), builder->mat3x4<f32>(),
+ builder->GlobalVar(name, builder->ty.mat3x4<f32>(), builder->Call<mat3x4<f32>>(),
builtin::AddressSpace::kPrivate);
break;
case Type::f16:
- builder->GlobalVar(name, builder->ty.mat3x4<f16>(), builder->mat3x4<f16>(),
+ builder->GlobalVar(name, builder->ty.mat3x4<f16>(), builder->Call<mat3x4<f16>>(),
builtin::AddressSpace::kPrivate);
break;
}
@@ -1595,11 +1600,11 @@
auto name = builder->Symbols().New();
switch (type) {
case Type::f32:
- builder->GlobalVar(name, builder->ty.mat4x3<f32>(), builder->mat4x3<f32>(),
+ builder->GlobalVar(name, builder->ty.mat4x3<f32>(), builder->Call<mat4x3<f32>>(),
builtin::AddressSpace::kPrivate);
break;
case Type::f16:
- builder->GlobalVar(name, builder->ty.mat4x3<f16>(), builder->mat4x3<f16>(),
+ builder->GlobalVar(name, builder->ty.mat4x3<f16>(), builder->Call<mat4x3<f16>>(),
builtin::AddressSpace::kPrivate);
}
return builder->Expr(name);
diff --git a/src/tint/writer/spirv/builder_builtin_test.cc b/src/tint/writer/spirv/builder_builtin_test.cc
index ba33a443..dd76407 100644
--- a/src/tint/writer/spirv/builder_builtin_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_test.cc
@@ -20,11 +20,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuiltinBuilderTest = TestHelper;
template <typename T>
@@ -47,8 +48,10 @@
auto* tex = GlobalVar("texture", t, Binding(0_a), Group(0_a));
auto* sampler = GlobalVar("sampler", s, Binding(1_a), Group(0_a));
- auto* expr1 = Call("textureSampleCompare", "texture", "sampler", vec2<f32>(1_f, 2_f), 2_f);
- auto* expr2 = Call("textureSampleCompare", "texture", "sampler", vec2<f32>(1_f, 2_f), 2_f);
+ auto* expr1 =
+ Call("textureSampleCompare", "texture", "sampler", Call<vec2<f32>>(1_f, 2_f), 2_f);
+ auto* expr2 =
+ Call("textureSampleCompare", "texture", "sampler", Call<vec2<f32>>(1_f, 2_f), 2_f);
Func("f1", utils::Empty, ty.void_(),
utils::Vector{
@@ -561,7 +564,7 @@
auto param = GetParam();
// Use a variable to prevent the function being evaluated as constant.
- auto* vec = Var("a", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("a", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call(param.name, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -605,7 +608,7 @@
auto param = GetParam();
// Use a variable to prevent the function being evaluated as constant.
- auto* vec = Var("a", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("a", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call(param.name, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -743,7 +746,7 @@
}
TEST_F(BuiltinBuilderTest, Call_Length_Vector_f32) {
- auto* vec = Var("a", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("a", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call("length", vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -782,7 +785,7 @@
TEST_F(BuiltinBuilderTest, Call_Length_Vector_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("a", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("a", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call("length", vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -819,7 +822,7 @@
}
TEST_F(BuiltinBuilderTest, Call_Normalize_f32) {
- auto* vec = Var("a", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("a", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call("normalize", vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -858,7 +861,7 @@
TEST_F(BuiltinBuilderTest, Call_Normalize_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("a", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("a", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call("normalize", vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -977,7 +980,7 @@
TEST_P(Builtin_Builder_DualParam_Float_Test, Call_Vector_f32) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call(param.name, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1020,7 +1023,7 @@
Enable(builtin::Extension::kF16);
auto param = GetParam();
- auto* vec = Var("vec", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call(param.name, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1068,7 +1071,7 @@
BuiltinData{"step", "Step"}));
TEST_F(BuiltinBuilderTest, Call_Reflect_Vector_f32) {
- auto* vec = Var("vec", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call("reflect", vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1108,7 +1111,7 @@
TEST_F(BuiltinBuilderTest, Call_Reflect_Vector_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("vec", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call("reflect", vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1220,7 +1223,7 @@
}
TEST_F(BuiltinBuilderTest, Call_Distance_Vector_f32) {
- auto* vec = Var("vec", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call("distance", vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1260,7 +1263,7 @@
TEST_F(BuiltinBuilderTest, Call_Distance_Vector_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("vec", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call("distance", vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1298,7 +1301,7 @@
}
TEST_F(BuiltinBuilderTest, Call_Cross_f32) {
- auto* vec = Var("vec", vec3<f32>(1_f, 1_f, 1_f));
+ auto* vec = Var("vec", Call<vec3<f32>>(1_f, 1_f, 1_f));
auto* expr = Call("cross", vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1338,7 +1341,7 @@
TEST_F(BuiltinBuilderTest, Call_Cross_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("vec", vec3<f16>(1_h, 1_h, 1_h));
+ auto* vec = Var("vec", Call<vec3<f16>>(1_h, 1_h, 1_h));
auto* expr = Call("cross", vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1460,7 +1463,7 @@
TEST_P(Builtin_Builder_ThreeParam_Float_Test, Call_Vector_f32) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call(param.name, vec, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1504,7 +1507,7 @@
Enable(builtin::Extension::kF16);
auto param = GetParam();
- auto* vec = Var("vec", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call(param.name, vec, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1553,7 +1556,7 @@
BuiltinData{"smoothstep", "SmoothStep"}));
TEST_F(BuiltinBuilderTest, Call_FaceForward_Vector_f32) {
- auto* vec = Var("vec", vec2<f32>(1_f, 1_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 1_f));
auto* expr = Call("faceForward", vec, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1594,7 +1597,7 @@
TEST_F(BuiltinBuilderTest, Call_FaceForward_Vector_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("vec", vec2<f16>(1_h, 1_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 1_h));
auto* expr = Call("faceForward", vec, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1633,7 +1636,7 @@
}
TEST_F(BuiltinBuilderTest, Runtime_Call_Modf_f32) {
- auto* vec = Var("vec", vec2<f32>(1_f, 2_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 2_f));
auto* expr = Call("modf", vec);
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1687,7 +1690,7 @@
TEST_F(BuiltinBuilderTest, Runtime_Call_Modf_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("vec", vec2<f16>(1_h, 2_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 2_h));
auto* expr = Call("modf", vec);
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1743,7 +1746,7 @@
}
TEST_F(BuiltinBuilderTest, Const_Call_Modf_f32) {
- auto* expr = Call("modf", vec2<f32>(1_f, 2_f));
+ auto* expr = Call("modf", Call<vec2<f32>>(1_f, 2_f));
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", expr)),
@@ -1789,7 +1792,7 @@
TEST_F(BuiltinBuilderTest, Const_Call_Modf_f16) {
Enable(builtin::Extension::kF16);
- auto* expr = Call("modf", vec2<f16>(1_h, 2_h));
+ auto* expr = Call("modf", Call<vec2<f16>>(1_h, 2_h));
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("l", expr)),
@@ -1837,7 +1840,7 @@
}
TEST_F(BuiltinBuilderTest, Runtime_Call_Frexp_f32) {
- auto* vec = Var("vec", vec2<f32>(1_f, 2_f));
+ auto* vec = Var("vec", Call<vec2<f32>>(1_f, 2_f));
auto* expr = Call("frexp", vec);
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1893,7 +1896,7 @@
TEST_F(BuiltinBuilderTest, Runtime_Call_Frexp_f16) {
Enable(builtin::Extension::kF16);
- auto* vec = Var("vec", vec2<f16>(1_h, 2_h));
+ auto* vec = Var("vec", Call<vec2<f16>>(1_h, 2_h));
auto* expr = Call("frexp", vec);
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -1953,7 +1956,7 @@
TEST_F(BuiltinBuilderTest, Const_Call_Frexp_f32) {
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
- Decl(Let("l", Call("frexp", vec2<f32>(1_f, 2_f)))),
+ Decl(Let("l", Call("frexp", Call<vec2<f32>>(1_f, 2_f)))),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -2001,7 +2004,7 @@
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
- Decl(Let("l", Call("frexp", vec2<f16>(1_h, 2_h)))),
+ Decl(Let("l", Call("frexp", Call<vec2<f16>>(1_h, 2_h)))),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -2088,7 +2091,7 @@
}
TEST_F(BuiltinBuilderTest, Call_QuantizeToF16_Vector) {
- GlobalVar("v", vec3<f32>(2_f), builtin::AddressSpace::kPrivate);
+ GlobalVar("v", Call<vec3<f32>>(2_f), builtin::AddressSpace::kPrivate);
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2320,7 +2323,7 @@
TEST_P(Builtin_Builder_SingleParam_Sint_Test, Call_Vector) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<i32>(1_i, 1_i));
+ auto* vec = Var("vec", Call<vec2<i32>>(1_i, 1_i));
auto* expr = Call(param.name, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2397,7 +2400,7 @@
}
TEST_F(Builtin_Builder_Abs_Uint_Test, Call_Vector) {
- auto* scalar = Var("scalar", vec2<u32>(1_u, 1_u));
+ auto* scalar = Var("scalar", Call<vec2<u32>>(1_u, 1_u));
auto* expr = Call("abs", scalar);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2473,7 +2476,7 @@
TEST_P(Builtin_Builder_DualParam_SInt_Test, Call_Vector) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<i32>(1_i, 1_i));
+ auto* vec = Var("vec", Call<vec2<i32>>(1_i, 1_i));
auto* expr = Call(param.name, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2557,7 +2560,7 @@
TEST_P(Builtin_Builder_DualParam_UInt_Test, Call_Vector) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<u32>(1_u, 1_u));
+ auto* vec = Var("vec", Call<vec2<u32>>(1_u, 1_u));
auto* expr = Call(param.name, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2642,7 +2645,7 @@
TEST_P(Builtin_Builder_ThreeParam_Sint_Test, Call_Vector) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<i32>(1_i, 1_i));
+ auto* vec = Var("vec", Call<vec2<i32>>(1_i, 1_i));
auto* expr = Call(param.name, vec, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -2728,7 +2731,7 @@
TEST_P(Builtin_Builder_ThreeParam_Uint_Test, Call_Vector) {
auto param = GetParam();
- auto* vec = Var("vec", vec2<u32>(1_u, 1_u));
+ auto* vec = Var("vec", Call<vec2<u32>>(1_u, 1_u));
auto* expr = Call(param.name, vec, vec, vec);
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
@@ -3945,7 +3948,8 @@
auto param = GetParam();
bool pack4 = param.name == "pack4x8snorm" || param.name == "pack4x8unorm";
- auto* call = pack4 ? Call(param.name, vec4<f32>("one")) : Call(param.name, vec2<f32>("one"));
+ auto* call =
+ pack4 ? Call(param.name, Call<vec4<f32>>("one")) : Call(param.name, Call<vec2<f32>>("one"));
auto* func = Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
Decl(Let("one", Expr(1_f))),
diff --git a/src/tint/writer/spirv/builder_constructor_expression_test.cc b/src/tint/writer/spirv/builder_constructor_expression_test.cc
index 7416bc2..b1eb366 100644
--- a/src/tint/writer/spirv/builder_constructor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_constructor_expression_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using SpvBuilderConstructorTest = TestHelper;
TEST_F(SpvBuilderConstructorTest, Const) {
@@ -37,7 +38,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type) {
- auto* t = vec3<f32>(1_f, 1_f, 3_f);
+ auto* t = Call<vec3<f32>>(1_f, 1_f, 3_f);
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -54,7 +55,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_WithCasts) {
- auto* t = vec2<f32>(Call<f32>(1_i), Call<f32>(1_i));
+ auto* t = Call<vec2<f32>>(Call<f32>(1_i), Call<f32>(1_i));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -94,7 +95,7 @@
TEST_F(SpvBuilderConstructorTest, Type_IdentifierExpression_Param) {
auto* var = Var("ident", ty.f32());
- auto* t = vec2<f32>(1_f, "ident");
+ auto* t = Call<vec2<f32>>(1_f, "ident");
WrapInFunction(var, t);
spirv::Builder& b = Build();
@@ -122,7 +123,7 @@
}
TEST_F(SpvBuilderConstructorTest, Vector_Bitcast_Params) {
- auto* var = Var("v", vec3<f32>(1_f, 2_f, 3_f));
+ auto* var = Var("v", Call<vec3<f32>>(1_f, 2_f, 3_f));
auto* cast = Bitcast(ty.vec3<u32>(), var);
WrapInFunction(var, cast);
@@ -230,7 +231,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_Bool_Literal) {
- auto* cast = vec2<bool>(true);
+ auto* cast = Call<vec2<bool>>(true);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -248,7 +249,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_Bool_Var) {
auto* var = Var("v", Expr(true));
- auto* cast = vec2<bool>(var);
+ auto* cast = Call<vec2<bool>>(var);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -271,7 +272,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_Literal) {
- auto* cast = vec2<f32>(2_f);
+ auto* cast = Call<vec2<f32>>(2_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -290,7 +291,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F16_Literal) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(2_h);
+ auto* cast = Call<vec2<f16>>(2_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -308,7 +309,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32) {
auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
- auto* cast = vec2<f32>("x", "x");
+ auto* cast = Call<vec2<f32>>("x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -335,7 +336,7 @@
Enable(builtin::Extension::kF16);
auto* var = Decl(Var("x", ty.f16(), Expr(2_h)));
- auto* cast = vec2<f16>("x", "x");
+ auto* cast = Call<vec2<f16>>("x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -359,7 +360,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32_Const) {
- auto* cast = vec2<f32>(1_f, 2_f);
+ auto* cast = Call<vec2<f32>>(1_f, 2_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -379,7 +380,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F16_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(1_h, 2_h);
+ auto* cast = Call<vec2<f16>>(1_h, 2_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -397,8 +398,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec2_F32_With_Vec2) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
- auto* cast = vec2<f32>("x");
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(1_f, 2_f)));
+ auto* cast = Call<vec2<f32>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -424,8 +425,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec2_F16_With_Vec2) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(1_h, 2_h)));
- auto* cast = vec2<f16>("x");
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(1_h, 2_h)));
+ auto* cast = Call<vec2<f16>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -449,7 +450,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec2_F32_With_Vec2_Const) {
- auto* cast = vec2<f32>(vec2<f32>(1_f, 2_f));
+ auto* cast = Call<vec2<f32>>(Call<vec2<f32>>(1_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -469,7 +470,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec2_F16_With_Vec2_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(vec2<f16>(1_h, 2_h));
+ auto* cast = Call<vec2<f16>>(Call<vec2<f16>>(1_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -488,7 +489,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32) {
auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
- auto* cast = vec3<f32>("x", "x", "x");
+ auto* cast = Call<vec3<f32>>("x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -516,7 +517,7 @@
Enable(builtin::Extension::kF16);
auto* var = Decl(Var("x", ty.f16(), Expr(2_h)));
- auto* cast = vec3<f16>("x", "x", "x");
+ auto* cast = Call<vec3<f16>>("x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -541,7 +542,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Const) {
- auto* cast = vec3<f32>(1_f, 2_f, 3_f);
+ auto* cast = Call<vec3<f32>>(1_f, 2_f, 3_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -562,7 +563,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(1_h, 2_h, 3_h);
+ auto* cast = Call<vec3<f16>>(1_h, 2_h, 3_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -582,7 +583,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Bool) {
auto* var = Decl(Var("x", ty.bool_(), Expr(true)));
- auto* cast = vec3<bool>("x", "x", "x");
+ auto* cast = Call<vec3<bool>>("x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -607,7 +608,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Bool_Const) {
- auto* cast = vec3<bool>(true, false, true);
+ auto* cast = Call<vec3<bool>>(true, false, true);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -626,7 +627,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_F32_F32) {
auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
- auto* cast = vec3<f32>("x", "x", "x");
+ auto* cast = Call<vec3<f32>>("x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -654,7 +655,7 @@
Enable(builtin::Extension::kF16);
auto* var = Decl(Var("x", ty.f16(), Expr(2_h)));
- auto* cast = vec3<f16>("x", "x", "x");
+ auto* cast = Call<vec3<f16>>("x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -679,7 +680,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_F32_F32_Const) {
- auto* cast = vec3<f32>(1_f, 2_f, 3_f);
+ auto* cast = Call<vec3<f32>>(1_f, 2_f, 3_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -700,7 +701,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F16_F16_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(1_h, 2_h, 3_h);
+ auto* cast = Call<vec3<f16>>(1_h, 2_h, 3_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -719,8 +720,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Vec2) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(2_f, 3_f)));
- auto* cast = vec3<f32>(1_f, "x");
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(2_f, 3_f)));
+ auto* cast = Call<vec3<f32>>(1_f, "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -751,8 +752,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F16_Vec2) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(2_h, 3_h)));
- auto* cast = vec3<f16>(1_h, "x");
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(2_h, 3_h)));
+ auto* cast = Call<vec3<f16>>(1_h, "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -781,7 +782,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_Vec2_Const) {
- auto* cast = vec3<f32>(1_f, vec2<f32>(2_f, 3_f));
+ auto* cast = Call<vec3<f32>>(1_f, Call<vec2<f32>>(2_f, 3_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -802,7 +803,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F16_Vec2_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(1_h, vec2<f16>(2_h, 3_h));
+ auto* cast = Call<vec3<f16>>(1_h, Call<vec2<f16>>(2_h, 3_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -821,8 +822,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F32) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
- auto* cast = vec3<f32>("x", 3_f);
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(1_f, 2_f)));
+ auto* cast = Call<vec3<f32>>("x", 3_f);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -853,8 +854,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F16) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(1_h, 2_h)));
- auto* cast = vec3<f16>("x", 3_h);
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(1_h, 2_h)));
+ auto* cast = Call<vec3<f16>>("x", 3_h);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -883,7 +884,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F32_Const) {
- auto* cast = vec3<f32>(vec2<f32>(1_f, 2_f), 3_f);
+ auto* cast = Call<vec3<f32>>(Call<vec2<f32>>(1_f, 2_f), 3_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -904,7 +905,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec2<f16>(1_h, 2_h), 3_h);
+ auto* cast = Call<vec3<f16>>(Call<vec2<f16>>(1_h, 2_h), 3_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -923,8 +924,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_F32_With_Vec3) {
- auto* var = Decl(Var("x", ty.vec3<f32>(), vec3<f32>(1_f, 2_f, 3_f)));
- auto* cast = vec3<f32>("x");
+ auto* var = Decl(Var("x", ty.vec3<f32>(), Call<vec3<f32>>(1_f, 2_f, 3_f)));
+ auto* cast = Call<vec3<f32>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -951,8 +952,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_F16_With_Vec3) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec3<f16>(), vec3<f16>(1_h, 2_h, 3_h)));
- auto* cast = vec3<f16>("x");
+ auto* var = Decl(Var("x", ty.vec3<f16>(), Call<vec3<f16>>(1_h, 2_h, 3_h)));
+ auto* cast = Call<vec3<f16>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -977,7 +978,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec3_F32_With_Vec3_Const) {
- auto* cast = vec3<f32>(vec3<f32>(1_f, 2_f, 3_f));
+ auto* cast = Call<vec3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -998,7 +999,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec3_F16_With_Vec3_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec3<f16>(1_h, 2_h, 3_h));
+ auto* cast = Call<vec3<f16>>(Call<vec3<f16>>(1_h, 2_h, 3_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1018,7 +1019,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Bool) {
auto* var = Decl(Var("x", ty.bool_(), Expr(true)));
- auto* cast = vec4<bool>("x");
+ auto* cast = Call<vec4<bool>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1041,7 +1042,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Bool_Const) {
- auto* cast = vec4<bool>(true);
+ auto* cast = Call<vec4<bool>>(true);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1059,7 +1060,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32) {
auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
- auto* cast = vec4<f32>("x");
+ auto* cast = Call<vec4<f32>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1085,7 +1086,7 @@
Enable(builtin::Extension::kF16);
auto* var = Decl(Var("x", ty.f16(), Expr(2_h)));
- auto* cast = vec4<f16>("x");
+ auto* cast = Call<vec4<f16>>("x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1108,7 +1109,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Const) {
- auto* cast = vec4<f32>(2_f);
+ auto* cast = Call<vec4<f32>>(2_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1127,7 +1128,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h);
+ auto* cast = Call<vec4<f16>>(2_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1145,7 +1146,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_F32_F32) {
auto* var = Decl(Var("x", ty.f32(), Expr(2_f)));
- auto* cast = vec4<f32>("x", "x", "x", "x");
+ auto* cast = Call<vec4<f32>>("x", "x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1174,7 +1175,7 @@
Enable(builtin::Extension::kF16);
auto* var = Decl(Var("x", ty.f16(), Expr(2_h)));
- auto* cast = vec4<f16>("x", "x", "x", "x");
+ auto* cast = Call<vec4<f16>>("x", "x", "x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1200,7 +1201,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_F32_F32_Const) {
- auto* cast = vec4<f32>(1_f, 2_f, 3_f, 4_f);
+ auto* cast = Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1222,7 +1223,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_F16_F16_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(1_h, 2_h, 3_h, 4_h);
+ auto* cast = Call<vec4<f16>>(1_h, 2_h, 3_h, 4_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1242,8 +1243,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_Vec2) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
- auto* cast = vec4<f32>(1_f, 2_f, "x");
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(1_f, 2_f)));
+ auto* cast = Call<vec4<f32>>(1_f, 2_f, "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1273,8 +1274,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_F16_Vec2) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(1_h, 2_h)));
- auto* cast = vec4<f16>(1_h, 2_h, "x");
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(1_h, 2_h)));
+ auto* cast = Call<vec4<f16>>(1_h, 2_h, "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1302,7 +1303,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_Vec2_Const) {
- auto* cast = vec4<f32>(1_f, 2_f, vec2<f32>(3_f, 4_f));
+ auto* cast = Call<vec4<f32>>(1_f, 2_f, Call<vec2<f32>>(3_f, 4_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1324,7 +1325,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_F16_Vec2_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(1_h, 2_h, vec2<f16>(3_h, 4_h));
+ auto* cast = Call<vec4<f16>>(1_h, 2_h, Call<vec2<f16>>(3_h, 4_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1344,8 +1345,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec2_F32) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(2_f, 3_f)));
- auto* cast = vec4<f32>(1_f, "x", 4_f);
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(2_f, 3_f)));
+ auto* cast = Call<vec4<f32>>(1_f, "x", 4_f);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1377,8 +1378,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_Vec2_F16) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(2_h, 3_h)));
- auto* cast = vec4<f16>(1_h, "x", 4_h);
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(2_h, 3_h)));
+ auto* cast = Call<vec4<f16>>(1_h, "x", 4_h);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1408,7 +1409,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec2_F32_Const) {
- auto* cast = vec4<f32>(1_f, vec2<f32>(2_f, 3_f), 4_f);
+ auto* cast = Call<vec4<f32>>(1_f, Call<vec2<f32>>(2_f, 3_f), 4_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1430,7 +1431,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_Vec2_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(1_h, vec2<f16>(2_h, 3_h), 4_h);
+ auto* cast = Call<vec4<f16>>(1_h, Call<vec2<f16>>(2_h, 3_h), 4_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1450,8 +1451,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F32_F32) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
- auto* cast = vec4<f32>("x", 3_f, 4_f);
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(1_f, 2_f)));
+ auto* cast = Call<vec4<f32>>("x", 3_f, 4_f);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1483,8 +1484,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F16_F16) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(1_h, 2_h)));
- auto* cast = vec4<f16>("x", 3_h, 4_h);
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(1_h, 2_h)));
+ auto* cast = Call<vec4<f16>>("x", 3_h, 4_h);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1514,7 +1515,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F32_F32_Const) {
- auto* cast = vec4<f32>(vec2<f32>(1_f, 2_f), 3_f, 4_f);
+ auto* cast = Call<vec4<f32>>(Call<vec2<f32>>(1_f, 2_f), 3_f, 4_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1536,7 +1537,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec2_F16_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec2<f16>(1_h, 2_h), 3_h, 4_h);
+ auto* cast = Call<vec4<f16>>(Call<vec2<f16>>(1_h, 2_h), 3_h, 4_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1556,8 +1557,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_F32_With_Vec2_Vec2) {
- auto* var = Decl(Var("x", ty.vec2<f32>(), vec2<f32>(1_f, 2_f)));
- auto* cast = vec4<f32>("x", "x");
+ auto* var = Decl(Var("x", ty.vec2<f32>(), Call<vec2<f32>>(1_f, 2_f)));
+ auto* cast = Call<vec4<f32>>("x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1590,8 +1591,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_F16_With_Vec2_Vec2) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec2<f16>(), vec2<f16>(1_h, 2_h)));
- auto* cast = vec4<f16>("x", "x");
+ auto* var = Decl(Var("x", ty.vec2<f16>(), Call<vec2<f16>>(1_h, 2_h)));
+ auto* cast = Call<vec4<f16>>("x", "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1622,7 +1623,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_F32_With_Vec2_Vec2_Const) {
- auto* cast = vec4<f32>(vec2<f32>(1_f, 2_f), vec2<f32>(1_f, 2_f));
+ auto* cast = Call<vec4<f32>>(Call<vec2<f32>>(1_f, 2_f), Call<vec2<f32>>(1_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1642,7 +1643,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_F16_With_Vec2_Vec2_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec2<f16>(1_h, 2_h), vec2<f16>(1_h, 2_h));
+ auto* cast = Call<vec4<f16>>(Call<vec2<f16>>(1_h, 2_h), Call<vec2<f16>>(1_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1660,8 +1661,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec3) {
- auto* var = Decl(Var("x", ty.vec3<f32>(), vec3<f32>(2_f, 2_f, 2_f)));
- auto* cast = vec4<f32>(2_f, "x");
+ auto* var = Decl(Var("x", ty.vec3<f32>(), Call<vec3<f32>>(2_f, 2_f, 2_f)));
+ auto* cast = Call<vec4<f32>>(2_f, "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1691,8 +1692,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_Vec3) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec3<f16>(), vec3<f16>(2_h, 2_h, 2_h)));
- auto* cast = vec4<f16>(2_h, "x");
+ auto* var = Decl(Var("x", ty.vec3<f16>(), Call<vec3<f16>>(2_h, 2_h, 2_h)));
+ auto* cast = Call<vec4<f16>>(2_h, "x");
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1720,7 +1721,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_Vec3_Const) {
- auto* cast = vec4<f32>(2_f, vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(2_f, Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1739,7 +1740,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F16_Vec3_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h, vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(2_h, Call<vec3<f16>>(2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1756,8 +1757,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F32) {
- auto* var = Decl(Var("x", ty.vec3<f32>(), vec3<f32>(2_f, 2_f, 2_f)));
- auto* cast = vec4<f32>("x", 2_f);
+ auto* var = Decl(Var("x", ty.vec3<f32>(), Call<vec3<f32>>(2_f, 2_f, 2_f)));
+ auto* cast = Call<vec4<f32>>("x", 2_f);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1787,8 +1788,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F16) {
Enable(builtin::Extension::kF16);
- auto* var = Decl(Var("x", ty.vec3<f16>(), vec3<f16>(2_h, 2_h, 2_h)));
- auto* cast = vec4<f16>("x", 2_h);
+ auto* var = Decl(Var("x", ty.vec3<f16>(), Call<vec3<f16>>(2_h, 2_h, 2_h)));
+ auto* cast = Call<vec4<f16>>("x", 2_h);
WrapInFunction(var, cast);
spirv::Builder& b = Build();
@@ -1816,7 +1817,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F32_Const) {
- auto* cast = vec4<f32>(vec3<f32>(2_f, 2_f, 2_f), 2_f);
+ auto* cast = Call<vec4<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f), 2_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1835,7 +1836,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F16_Const) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec3<f16>(2_h, 2_h, 2_h), 2_h);
+ auto* cast = Call<vec4<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h), 2_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1852,8 +1853,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Vec4_F32_With_Vec4) {
- auto* value = vec4<f32>(2_f, 2_f, 2_f, 2_f);
- auto* cast = vec4<f32>(value);
+ auto* value = Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f);
+ auto* cast = Call<vec4<f32>>(value);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -1872,8 +1873,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Vec4_F16_With_Vec4) {
Enable(builtin::Extension::kF16);
- auto* value = vec4<f16>(2_h, 2_h, 2_h, 2_h);
- auto* cast = vec4<f16>(value);
+ auto* value = Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h);
+ auto* cast = Call<vec4<f16>>(value);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -2050,7 +2051,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec2_With_F32) {
- auto* cast = vec2<f32>(2_f);
+ auto* cast = Call<vec2<f32>>(2_f);
GlobalConst("g", ty.vec2<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2075,7 +2076,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec2_With_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(2_h);
+ auto* cast = Call<vec2<f16>>(2_h);
GlobalConst("g", ty.vec2<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2098,7 +2099,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec2_With_F32) {
- auto* cast = vec2<f32>(2_f);
+ auto* cast = Call<vec2<f32>>(2_f);
auto* g = GlobalVar("g", ty.vec2<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2116,7 +2117,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec2_With_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(2_h);
+ auto* cast = Call<vec2<f16>>(2_h);
auto* g = GlobalVar("g", ty.vec2<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2132,7 +2133,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec2_F32_With_Vec2) {
- auto* cast = vec2<f32>(vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec2<f32>>(Call<vec2<f32>>(2_f, 2_f));
GlobalConst("g", ty.vec2<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2157,7 +2158,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec2_F16_With_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec2<f16>>(Call<vec2<f16>>(2_h, 2_h));
GlobalConst("g", ty.vec2<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2180,7 +2181,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec2_F32_With_Vec2) {
- auto* cast = vec2<f32>(vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec2<f32>>(Call<vec2<f32>>(2_f, 2_f));
GlobalVar("a", ty.vec2<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = SanitizeAndBuild();
@@ -2202,7 +2203,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec2_F16_With_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec2<f16>(vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec2<f16>>(Call<vec2<f16>>(2_h, 2_h));
GlobalVar("a", ty.vec2<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = SanitizeAndBuild();
@@ -2222,7 +2223,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_F32_With_Vec3) {
- auto* cast = vec3<f32>(vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<vec3<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f));
GlobalConst("g", ty.vec3<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2247,7 +2248,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_F16_With_Vec3) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<vec3<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h));
GlobalConst("g", ty.vec3<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2270,7 +2271,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_F32_With_Vec3) {
- auto* cast = vec3<f32>(vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<vec3<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f));
GlobalVar("a", ty.vec3<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = SanitizeAndBuild();
@@ -2292,7 +2293,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_F16_With_Vec3) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<vec3<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h));
GlobalVar("a", ty.vec3<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = SanitizeAndBuild();
@@ -2312,7 +2313,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_F32_With_Vec4) {
- auto* cast = vec4<f32>(vec4<f32>(2_f, 2_f, 2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f));
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2337,7 +2338,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_F16_With_Vec4) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec4<f16>(2_h, 2_h, 2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h));
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2360,7 +2361,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_F32_With_Vec4) {
- auto* cast = vec4<f32>(vec4<f32>(2_f, 2_f, 2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f));
GlobalVar("a", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = SanitizeAndBuild();
@@ -2382,7 +2383,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_F16_With_Vec4) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec4<f16>(2_h, 2_h, 2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h));
GlobalVar("a", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = SanitizeAndBuild();
@@ -2402,7 +2403,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_With_F32) {
- auto* cast = vec3<f32>(2_f);
+ auto* cast = Call<vec3<f32>>(2_f);
GlobalConst("g", ty.vec3<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2427,7 +2428,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_With_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(2_h);
+ auto* cast = Call<vec3<f16>>(2_h);
GlobalConst("g", ty.vec3<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2450,7 +2451,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_With_F32) {
- auto* cast = vec3<f32>(2_f);
+ auto* cast = Call<vec3<f32>>(2_f);
auto* g = GlobalVar("g", ty.vec3<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2468,7 +2469,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_With_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(2_h);
+ auto* cast = Call<vec3<f16>>(2_h);
auto* g = GlobalVar("g", ty.vec3<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2484,7 +2485,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_With_F32_Vec2) {
- auto* cast = vec3<f32>(2_f, vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec3<f32>>(2_f, Call<vec2<f32>>(2_f, 2_f));
GlobalConst("g", ty.vec3<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2509,7 +2510,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_With_F16_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(2_h, vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec3<f16>>(2_h, Call<vec2<f16>>(2_h, 2_h));
GlobalConst("g", ty.vec3<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2532,7 +2533,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_With_F32_Vec2) {
- auto* cast = vec3<f32>(2_f, vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec3<f32>>(2_f, Call<vec2<f32>>(2_f, 2_f));
auto* g = GlobalVar("g", ty.vec3<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2550,7 +2551,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_With_F16_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(2_h, vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec3<f16>>(2_h, Call<vec2<f16>>(2_h, 2_h));
auto* g = GlobalVar("g", ty.vec3<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2566,7 +2567,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_With_Vec2_F32) {
- auto* cast = vec3<f32>(vec2<f32>(2_f, 2_f), 2_f);
+ auto* cast = Call<vec3<f32>>(Call<vec2<f32>>(2_f, 2_f), 2_f);
GlobalConst("g", ty.vec3<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2591,7 +2592,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec3_With_Vec2_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec2<f16>(2_h, 2_h), 2_h);
+ auto* cast = Call<vec3<f16>>(Call<vec2<f16>>(2_h, 2_h), 2_h);
GlobalConst("g", ty.vec3<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2614,7 +2615,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_With_Vec2_F32) {
- auto* cast = vec3<f32>(vec2<f32>(2_f, 2_f), 2_f);
+ auto* cast = Call<vec3<f32>>(Call<vec2<f32>>(2_f, 2_f), 2_f);
auto* g = GlobalVar("g", ty.vec3<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2632,7 +2633,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec3_With_Vec2_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec2<f16>(2_h, 2_h), 2_h);
+ auto* cast = Call<vec3<f16>>(Call<vec2<f16>>(2_h, 2_h), 2_h);
auto* g = GlobalVar("g", ty.vec3<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2648,7 +2649,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F32) {
- auto* cast = vec4<f32>(2_f);
+ auto* cast = Call<vec4<f32>>(2_f);
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2673,7 +2674,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h);
+ auto* cast = Call<vec4<f16>>(2_h);
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2696,7 +2697,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F32) {
- auto* cast = vec4<f32>(2_f);
+ auto* cast = Call<vec4<f32>>(2_f);
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2714,7 +2715,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h);
+ auto* cast = Call<vec4<f16>>(2_h);
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2730,7 +2731,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F32_F32_Vec2) {
- auto* cast = vec4<f32>(2_f, 2_f, vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(2_f, 2_f, Call<vec2<f32>>(2_f, 2_f));
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2755,7 +2756,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F16_F16_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h, 2_h, vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(2_h, 2_h, Call<vec2<f16>>(2_h, 2_h));
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2778,7 +2779,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F32_F32_Vec2) {
- auto* cast = vec4<f32>(2_f, 2_f, vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(2_f, 2_f, Call<vec2<f32>>(2_f, 2_f));
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2796,7 +2797,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F16_F16_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h, 2_h, vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(2_h, 2_h, Call<vec2<f16>>(2_h, 2_h));
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2812,7 +2813,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F32_Vec2_F32) {
- auto* cast = vec4<f32>(2_f, vec2<f32>(2_f, 2_f), 2_f);
+ auto* cast = Call<vec4<f32>>(2_f, Call<vec2<f32>>(2_f, 2_f), 2_f);
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2837,7 +2838,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F16_Vec2_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h, vec2<f16>(2_h, 2_h), 2_h);
+ auto* cast = Call<vec4<f16>>(2_h, Call<vec2<f16>>(2_h, 2_h), 2_h);
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2860,7 +2861,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F32_Vec2_F32) {
- auto* cast = vec4<f32>(2_f, vec2<f32>(2_f, 2_f), 2_f);
+ auto* cast = Call<vec4<f32>>(2_f, Call<vec2<f32>>(2_f, 2_f), 2_f);
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2878,7 +2879,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F16_Vec2_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h, vec2<f16>(2_h, 2_h), 2_h);
+ auto* cast = Call<vec4<f16>>(2_h, Call<vec2<f16>>(2_h, 2_h), 2_h);
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2894,7 +2895,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_Vec2_F32_F32) {
- auto* cast = vec4<f32>(vec2<f32>(2_f, 2_f), 2_f, 2_f);
+ auto* cast = Call<vec4<f32>>(Call<vec2<f32>>(2_f, 2_f), 2_f, 2_f);
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2919,7 +2920,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_Vec2_F16_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec2<f16>(2_h, 2_h), 2_h, 2_h);
+ auto* cast = Call<vec4<f16>>(Call<vec2<f16>>(2_h, 2_h), 2_h, 2_h);
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -2942,7 +2943,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_Vec2_F32_F32) {
- auto* cast = vec4<f32>(vec2<f32>(2_f, 2_f), 2_f, 2_f);
+ auto* cast = Call<vec4<f32>>(Call<vec2<f32>>(2_f, 2_f), 2_f, 2_f);
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2960,7 +2961,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_Vec2_F16_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec2<f16>(2_h, 2_h), 2_h, 2_h);
+ auto* cast = Call<vec4<f16>>(Call<vec2<f16>>(2_h, 2_h), 2_h, 2_h);
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -2976,7 +2977,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_F32_With_Vec2_Vec2) {
- auto* cast = vec4<f32>(vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(Call<vec2<f32>>(2_f, 2_f), Call<vec2<f32>>(2_f, 2_f));
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -3001,7 +3002,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_F16_With_Vec2_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(Call<vec2<f16>>(2_h, 2_h), Call<vec2<f16>>(2_h, 2_h));
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -3024,7 +3025,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_F32_With_Vec2_Vec2) {
- auto* cast = vec4<f32>(vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(Call<vec2<f32>>(2_f, 2_f), Call<vec2<f32>>(2_f, 2_f));
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -3042,7 +3043,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_F16_With_Vec2_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(Call<vec2<f16>>(2_h, 2_h), Call<vec2<f16>>(2_h, 2_h));
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -3058,7 +3059,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_F32_Vec3) {
- auto* cast = vec4<f32>(2_f, vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(2_f, Call<vec3<f32>>(2_f, 2_f, 2_f));
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -3081,7 +3082,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F32_Vec3) {
- auto* cast = vec4<f32>(2_f, vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<vec4<f32>>(2_f, Call<vec3<f32>>(2_f, 2_f, 2_f));
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -3099,7 +3100,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_F16_Vec3) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(2_h, vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<vec4<f16>>(2_h, Call<vec3<f16>>(2_h, 2_h, 2_h));
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -3115,7 +3116,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_Vec3_F32) {
- auto* cast = vec4<f32>(vec3<f32>(2_f, 2_f, 2_f), 2_f);
+ auto* cast = Call<vec4<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f), 2_f);
GlobalConst("g", ty.vec4<f32>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -3140,7 +3141,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalConst_Vec4_With_Vec3_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec3<f16>(2_h, 2_h, 2_h), 2_h);
+ auto* cast = Call<vec4<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h), 2_h);
GlobalConst("g", ty.vec4<f16>(), cast);
WrapInFunction(Decl(Var("l", Expr("g"))));
@@ -3163,7 +3164,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_Vec3_F32) {
- auto* cast = vec4<f32>(vec3<f32>(2_f, 2_f, 2_f), 2_f);
+ auto* cast = Call<vec4<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f), 2_f);
auto* g = GlobalVar("g", ty.vec4<f32>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -3181,7 +3182,7 @@
TEST_F(SpvBuilderConstructorTest, Type_GlobalVar_Vec4_With_Vec3_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = vec4<f16>(vec3<f16>(2_h, 2_h, 2_h), 2_h);
+ auto* cast = Call<vec4<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h), 2_h);
auto* g = GlobalVar("g", ty.vec4<f16>(), builtin::AddressSpace::kPrivate, cast);
spirv::Builder& b = Build();
@@ -3197,7 +3198,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat2x2_F32_With_Vec2_Vec2) {
- auto* cast = mat2x2<f32>(vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f));
+ auto* cast = Call<mat2x2<f32>>(Call<vec2<f32>>(2_f, 2_f), Call<vec2<f32>>(2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3217,7 +3218,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat2x2_F16_With_Vec2_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = mat2x2<f16>(vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h));
+ auto* cast = Call<mat2x2<f16>>(Call<vec2<f16>>(2_h, 2_h), Call<vec2<f16>>(2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3235,7 +3236,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat3x2_F32_With_Vec2_Vec2_Vec2) {
- auto* cast = mat3x2<f32>(vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f));
+ auto* cast = Call<mat3x2<f32>>(Call<vec2<f32>>(2_f, 2_f), Call<vec2<f32>>(2_f, 2_f),
+ Call<vec2<f32>>(2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3255,7 +3257,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat3x2_F16_With_Vec2_Vec2_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = mat3x2<f16>(vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h));
+ auto* cast = Call<mat3x2<f16>>(Call<vec2<f16>>(2_h, 2_h), Call<vec2<f16>>(2_h, 2_h),
+ Call<vec2<f16>>(2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3273,8 +3276,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat4x2_F32_With_Vec2_Vec2_Vec2_Vec2) {
- auto* cast = mat4x2<f32>(vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f), vec2<f32>(2_f, 2_f),
- vec2<f32>(2_f, 2_f));
+ auto* cast = Call<mat4x2<f32>>(Call<vec2<f32>>(2_f, 2_f), Call<vec2<f32>>(2_f, 2_f),
+ Call<vec2<f32>>(2_f, 2_f), Call<vec2<f32>>(2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3294,8 +3297,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat4x2_F16_With_Vec2_Vec2_Vec2_Vec2) {
Enable(builtin::Extension::kF16);
- auto* cast = mat4x2<f16>(vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h), vec2<f16>(2_h, 2_h),
- vec2<f16>(2_h, 2_h));
+ auto* cast = Call<mat4x2<f16>>(Call<vec2<f16>>(2_h, 2_h), Call<vec2<f16>>(2_h, 2_h),
+ Call<vec2<f16>>(2_h, 2_h), Call<vec2<f16>>(2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3313,7 +3316,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat2x3_F32_With_Vec3_Vec3) {
- auto* cast = mat2x3<f32>(vec3<f32>(2_f, 2_f, 2_f), vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<mat2x3<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f), Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3333,7 +3336,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat2x3_F16_With_Vec3_Vec3) {
Enable(builtin::Extension::kF16);
- auto* cast = mat2x3<f16>(vec3<f16>(2_h, 2_h, 2_h), vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<mat2x3<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h), Call<vec3<f16>>(2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3351,8 +3354,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat3x3_F32_With_Vec3_Vec3_Vec3) {
- auto* cast =
- mat3x3<f32>(vec3<f32>(2_f, 2_f, 2_f), vec3<f32>(2_f, 2_f, 2_f), vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<mat3x3<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f), Call<vec3<f32>>(2_f, 2_f, 2_f),
+ Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3372,8 +3375,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat3x3_F16_With_Vec3_Vec3_Vec3) {
Enable(builtin::Extension::kF16);
- auto* cast =
- mat3x3<f16>(vec3<f16>(2_h, 2_h, 2_h), vec3<f16>(2_h, 2_h, 2_h), vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<mat3x3<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h), Call<vec3<f16>>(2_h, 2_h, 2_h),
+ Call<vec3<f16>>(2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3391,8 +3394,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat4x3_F32_With_Vec3_Vec3_Vec3_Vec3) {
- auto* cast = mat4x3<f32>(vec3<f32>(2_f, 2_f, 2_f), vec3<f32>(2_f, 2_f, 2_f),
- vec3<f32>(2_f, 2_f, 2_f), vec3<f32>(2_f, 2_f, 2_f));
+ auto* cast = Call<mat4x3<f32>>(Call<vec3<f32>>(2_f, 2_f, 2_f), Call<vec3<f32>>(2_f, 2_f, 2_f),
+ Call<vec3<f32>>(2_f, 2_f, 2_f), Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3412,8 +3415,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat4x3_F16_With_Vec3_Vec3_Vec3_Vec3) {
Enable(builtin::Extension::kF16);
- auto* cast = mat4x3<f16>(vec3<f16>(2_h, 2_h, 2_h), vec3<f16>(2_h, 2_h, 2_h),
- vec3<f16>(2_h, 2_h, 2_h), vec3<f16>(2_h, 2_h, 2_h));
+ auto* cast = Call<mat4x3<f16>>(Call<vec3<f16>>(2_h, 2_h, 2_h), Call<vec3<f16>>(2_h, 2_h, 2_h),
+ Call<vec3<f16>>(2_h, 2_h, 2_h), Call<vec3<f16>>(2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3431,7 +3434,8 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat2x4_F32_With_Vec4_Vec4) {
- auto* cast = mat2x4<f32>(vec4<f32>(2_f, 2_f, 2_f, 2_f), vec4<f32>(2_f, 2_f, 2_f, 2_f));
+ auto* cast =
+ Call<mat2x4<f32>>(Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f), Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3451,7 +3455,8 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat2x4_F16_With_Vec4_Vec4) {
Enable(builtin::Extension::kF16);
- auto* cast = mat2x4<f16>(vec4<f16>(2_h, 2_h, 2_h, 2_h), vec4<f16>(2_h, 2_h, 2_h, 2_h));
+ auto* cast =
+ Call<mat2x4<f16>>(Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h), Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3469,8 +3474,9 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat3x4_F32_With_Vec4_Vec4_Vec4) {
- auto* cast = mat3x4<f32>(vec4<f32>(2_f, 2_f, 2_f, 2_f), vec4<f32>(2_f, 2_f, 2_f, 2_f),
- vec4<f32>(2_f, 2_f, 2_f, 2_f));
+ auto* cast =
+ Call<mat3x4<f32>>(Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f), Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f),
+ Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3490,8 +3496,9 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat3x4_F16_With_Vec4_Vec4_Vec4) {
Enable(builtin::Extension::kF16);
- auto* cast = mat3x4<f16>(vec4<f16>(2_h, 2_h, 2_h, 2_h), vec4<f16>(2_h, 2_h, 2_h, 2_h),
- vec4<f16>(2_h, 2_h, 2_h, 2_h));
+ auto* cast =
+ Call<mat3x4<f16>>(Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h), Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h),
+ Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3509,8 +3516,9 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Mat4x4_F32_With_Vec4_Vec4_Vec4_Vec4) {
- auto* cast = mat4x4<f32>(vec4<f32>(2_f, 2_f, 2_f, 2_f), vec4<f32>(2_f, 2_f, 2_f, 2_f),
- vec4<f32>(2_f, 2_f, 2_f, 2_f), vec4<f32>(2_f, 2_f, 2_f, 2_f));
+ auto* cast =
+ Call<mat4x4<f32>>(Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f), Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f),
+ Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f), Call<vec4<f32>>(2_f, 2_f, 2_f, 2_f));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3530,8 +3538,9 @@
TEST_F(SpvBuilderConstructorTest, Type_Mat4x4_F16_With_Vec4_Vec4_Vec4_Vec4) {
Enable(builtin::Extension::kF16);
- auto* cast = mat4x4<f16>(vec4<f16>(2_h, 2_h, 2_h, 2_h), vec4<f16>(2_h, 2_h, 2_h, 2_h),
- vec4<f16>(2_h, 2_h, 2_h, 2_h), vec4<f16>(2_h, 2_h, 2_h, 2_h));
+ auto* cast =
+ Call<mat4x4<f16>>(Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h), Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h),
+ Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h), Call<vec4<f16>>(2_h, 2_h, 2_h, 2_h));
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3549,7 +3558,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Array_5_F32) {
- auto* cast = array<f32, 5>(2_f, 2_f, 2_f, 2_f, 2_f);
+ auto* cast = Call<array<f32, 5>>(2_f, 2_f, 2_f, 2_f, 2_f);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3569,7 +3578,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Array_5_F16) {
Enable(builtin::Extension::kF16);
- auto* cast = array<f16, 5>(2_h, 2_h, 2_h, 2_h, 2_h);
+ auto* cast = Call<array<f16, 5>>(2_h, 2_h, 2_h, 2_h, 2_h);
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -3587,9 +3596,9 @@
}
TEST_F(SpvBuilderConstructorTest, Type_Array_2_Vec3_F32) {
- auto* first = vec3<f32>(1_f, 2_f, 3_f);
- auto* second = vec3<f32>(1_f, 2_f, 3_f);
- auto* t = Call(ty.array(ty.vec3<f32>(), 2_u), first, second);
+ auto* first = Call<vec3<f32>>(1_f, 2_f, 3_f);
+ auto* second = Call<vec3<f32>>(1_f, 2_f, 3_f);
+ auto* t = Call(ty.array<vec3<f32>, 2>(), first, second);
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -3611,9 +3620,9 @@
TEST_F(SpvBuilderConstructorTest, Type_Array_2_Vec3_F16) {
Enable(builtin::Extension::kF16);
- auto* first = vec3<f16>(1_h, 2_h, 3_h);
- auto* second = vec3<f16>(1_h, 2_h, 3_h);
- auto* t = Call(ty.array(ty.vec3<f16>(), 2_u), first, second);
+ auto* first = Call<vec3<f16>>(1_h, 2_h, 3_h);
+ auto* second = Call<vec3<f16>>(1_h, 2_h, 3_h);
+ auto* t = Call(ty.array<vec3<f16>, 2>(), first, second);
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -3633,8 +3642,8 @@
}
TEST_F(SpvBuilderConstructorTest, CommonInitializer_TwoVectors) {
- auto* v1 = vec3<f32>(2_f, 2_f, 2_f);
- auto* v2 = vec3<f32>(2_f, 2_f, 2_f);
+ auto* v1 = Call<vec3<f32>>(2_f, 2_f, 2_f);
+ auto* v2 = Call<vec3<f32>>(2_f, 2_f, 2_f);
WrapInFunction(WrapInStatement(v1), WrapInStatement(v2));
spirv::Builder& b = Build();
@@ -3651,8 +3660,8 @@
}
TEST_F(SpvBuilderConstructorTest, CommonInitializer_TwoArrays) {
- auto* a1 = array<f32, 3>(2_f, 2_f, 2_f);
- auto* a2 = array<f32, 3>(2_f, 2_f, 2_f);
+ auto* a1 = Call<array<f32, 3>>(2_f, 2_f, 2_f);
+ auto* a2 = Call<array<f32, 3>>(2_f, 2_f, 2_f);
WrapInFunction(WrapInStatement(a1), WrapInStatement(a2));
spirv::Builder& b = Build();
@@ -3674,8 +3683,8 @@
// Test that initializers of different types with the same values produce
// different OpConstantComposite instructions.
// crbug.com/tint/777
- auto* a1 = array<f32, 2>(1_f, 2_f);
- auto* a2 = vec2<f32>(1_f, 2_f);
+ auto* a1 = Call<array<f32, 2>>(1_f, 2_f);
+ auto* a2 = Call<vec2<f32>>(1_f, 2_f);
WrapInFunction(WrapInStatement(a1), WrapInStatement(a2));
spirv::Builder& b = Build();
@@ -3701,7 +3710,7 @@
Member("b", ty.vec3<f32>()),
});
- auto* t = Call(ty.Of(s), 2_f, vec3<f32>(2_f, 2_f, 2_f));
+ auto* t = Call(ty.Of(s), 2_f, Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -3808,7 +3817,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Vector) {
- auto* t = vec2<i32>();
+ auto* t = Call<vec2<i32>>();
WrapInFunction(t);
@@ -3826,7 +3835,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Matrix_F32) {
- auto* t = mat4x2<f32>();
+ auto* t = Call<mat4x2<f32>>();
WrapInFunction(t);
@@ -3847,7 +3856,7 @@
TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Matrix_F16) {
Enable(builtin::Extension::kF16);
- auto* t = mat4x2<f16>();
+ auto* t = Call<mat4x2<f16>>();
WrapInFunction(t);
@@ -3866,7 +3875,7 @@
}
TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Array) {
- auto* t = array<i32, 2>();
+ auto* t = Call<array<i32, 2>>();
WrapInFunction(t);
@@ -4206,7 +4215,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Convert_Vectors_U32_to_I32) {
auto* var = GlobalVar("i", ty.vec3<u32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<i32>("i");
+ auto* cast = Call<vec3<i32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4232,7 +4241,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Convert_Vectors_F32_to_I32) {
auto* var = GlobalVar("i", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<i32>("i");
+ auto* cast = Call<vec3<i32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4260,7 +4269,7 @@
auto* var = GlobalVar("i", ty.vec3<f16>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<i32>("i");
+ auto* cast = Call<vec3<i32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4286,7 +4295,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Convert_Vectors_I32_to_U32) {
auto* var = GlobalVar("i", ty.vec3<i32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<u32>("i");
+ auto* cast = Call<vec3<u32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4312,7 +4321,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Convert_Vectors_F32_to_U32) {
auto* var = GlobalVar("i", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<u32>("i");
+ auto* cast = Call<vec3<u32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4340,7 +4349,7 @@
auto* var = GlobalVar("i", ty.vec3<f16>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<u32>("i");
+ auto* cast = Call<vec3<u32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4366,7 +4375,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Convert_Vectors_I32_to_F32) {
auto* var = GlobalVar("i", ty.vec3<i32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<f32>("i");
+ auto* cast = Call<vec3<f32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4392,7 +4401,7 @@
TEST_F(SpvBuilderConstructorTest, Type_Convert_Vectors_U32_to_F32) {
auto* var = GlobalVar("i", ty.vec3<u32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<f32>("i");
+ auto* cast = Call<vec3<f32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4420,7 +4429,7 @@
auto* var = GlobalVar("i", ty.vec3<f16>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<f32>("i");
+ auto* cast = Call<vec3<f32>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4448,7 +4457,7 @@
auto* var = GlobalVar("i", ty.vec3<i32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<f16>("i");
+ auto* cast = Call<vec3<f16>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4476,7 +4485,7 @@
auto* var = GlobalVar("i", ty.vec3<u32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<f16>("i");
+ auto* cast = Call<vec3<f16>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4504,7 +4513,7 @@
auto* var = GlobalVar("i", ty.vec3<f32>(), builtin::AddressSpace::kPrivate);
- auto* cast = vec3<f16>("i");
+ auto* cast = Call<vec3<f16>>("i");
WrapInFunction(cast);
spirv::Builder& b = Build();
@@ -4529,7 +4538,7 @@
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_GlobalVectorWithAllConstInitializers) {
// vec3<f32>(1.0, 2.0, 3.0) -> true
- auto* t = vec3<f32>(1_f, 2_f, 3_f);
+ auto* t = Call<vec3<f32>>(1_f, 2_f, 3_f);
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4541,8 +4550,8 @@
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_GlobalArrayWithAllConstInitializers) {
// array<vec3<f32>, 2u>(vec3<f32>(1.0, 2.0, 3.0), vec3<f32>(1.0, 2.0, 3.0))
// -> true
- auto* t =
- Call(ty.array(ty.vec3<f32>(), 2_u), vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(1_f, 2_f, 3_f));
+ auto* t = Call(ty.array<vec3<f32>, 2>(), Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(1_f, 2_f, 3_f));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4554,7 +4563,7 @@
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_GlobalVectorWithMatchingTypeInitializers) {
// vec2<f32>(f32(1.0), f32(2.0)) -> false
- auto* t = vec2<f32>(Call<f32>(1_f), Call<f32>(2_f));
+ auto* t = Call<vec2<f32>>(Call<f32>(1_f), Call<f32>(2_f));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4566,7 +4575,7 @@
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_GlobalWithTypeConversionInitializer) {
// vec2<f32>(f32(1), f32(2)) -> false
- auto* t = vec2<f32>(Call<f32>(1_i), Call<f32>(2_i));
+ auto* t = Call<vec2<f32>>(Call<f32>(1_i), Call<f32>(2_i));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4578,7 +4587,7 @@
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_VectorWithAllConstInitializers) {
// vec3<f32>(1.0, 2.0, 3.0) -> true
- auto* t = vec3<f32>(1_f, 2_f, 3_f);
+ auto* t = Call<vec3<f32>>(1_f, 2_f, 3_f);
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4594,7 +4603,7 @@
GlobalVar("b", ty.f32(), builtin::AddressSpace::kPrivate);
GlobalVar("c", ty.f32(), builtin::AddressSpace::kPrivate);
- auto* t = vec3<f32>("a", "b", "c");
+ auto* t = Call<vec3<f32>>("a", "b", "c");
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4607,10 +4616,10 @@
// array<vec3<f32>, 2u>(vec3<f32>(1.0, 2.0, 3.0), vec3<f32>(1.0, 2.0, 3.0))
// -> true
- auto* first = vec3<f32>(1_f, 2_f, 3_f);
- auto* second = vec3<f32>(1_f, 2_f, 3_f);
+ auto* first = Call<vec3<f32>>(1_f, 2_f, 3_f);
+ auto* second = Call<vec3<f32>>(1_f, 2_f, 3_f);
- auto* t = Call(ty.array(ty.vec3<f32>(), 2_u), first, second);
+ auto* t = Call(ty.array<vec3<f32>, 2>(), first, second);
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4622,7 +4631,7 @@
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_VectorWithTypeConversionConstInitializers) {
// vec2<f32>(f32(1), f32(2)) -> false
- auto* t = vec2<f32>(Call<f32>(1_i), Call<f32>(2_i));
+ auto* t = Call<vec2<f32>>(Call<f32>(1_i), Call<f32>(2_i));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4632,7 +4641,7 @@
}
TEST_F(SpvBuilderConstructorTest, IsConstructorConst_BitCastScalars) {
- auto* t = vec2<u32>(Call<u32>(1_i), Call<u32>(1_i));
+ auto* t = Call<vec2<u32>>(Call<u32>(1_i), Call<u32>(1_i));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4647,7 +4656,7 @@
Member("b", ty.vec3<f32>()),
});
- auto* t = Call(ty.Of(s), 2_f, vec3<f32>(2_f, 2_f, 2_f));
+ auto* t = Call(ty.Of(s), 2_f, Call<vec3<f32>>(2_f, 2_f, 2_f));
WrapInFunction(t);
spirv::Builder& b = Build();
@@ -4680,8 +4689,8 @@
// }
// let y = vec3<f32>(1.0, 2.0, 3.0); // Reuses the ID 'x'
- WrapInFunction(If(true, Block(Decl(Let("x", vec3<f32>(1_f, 2_f, 3_f))))),
- Decl(Let("y", vec3<f32>(1_f, 2_f, 3_f))));
+ WrapInFunction(If(true, Block(Decl(Let("x", Call<vec3<f32>>(1_f, 2_f, 3_f))))),
+ Decl(Let("y", Call<vec3<f32>>(1_f, 2_f, 3_f))));
spirv::Builder& b = SanitizeAndBuild();
ASSERT_TRUE(b.Build());
@@ -4725,8 +4734,8 @@
// let y = vec3<f32>(one, 2.0, 3.0); // Mustn't reuse the ID 'x'
WrapInFunction(Decl(Var("one", Expr(1_f))),
- If(true, Block(Decl(Let("x", vec3<f32>("one", 2_f, 3_f))))),
- Decl(Let("y", vec3<f32>("one", 2_f, 3_f))));
+ If(true, Block(Decl(Let("x", Call<vec3<f32>>("one", 2_f, 3_f))))),
+ Decl(Let("y", Call<vec3<f32>>("one", 2_f, 3_f))));
spirv::Builder& b = SanitizeAndBuild();
ASSERT_TRUE(b.Build());
diff --git a/src/tint/writer/spirv/builder_entry_point_test.cc b/src/tint/writer/spirv/builder_entry_point_test.cc
index 0e057a3..46ffb2d 100644
--- a/src/tint/writer/spirv/builder_entry_point_test.cc
+++ b/src/tint/writer/spirv/builder_entry_point_test.cc
@@ -29,11 +29,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, EntryPoint_Parameters) {
@@ -215,7 +216,7 @@
Member("pos", ty.vec4<f32>(), utils::Vector{Builtin(builtin::BuiltinValue::kPosition)}),
});
- auto* vert_retval = Call(ty.Of(interface), 42_f, vec4<f32>());
+ auto* vert_retval = Call(ty.Of(interface), 42_f, Call<vec4<f32>>());
Func("vert_main", utils::Empty, ty.Of(interface), utils::Vector{Return(vert_retval)},
utils::Vector{
Stage(ast::PipelineStage::kVertex),
diff --git a/src/tint/writer/spirv/builder_function_attribute_test.cc b/src/tint/writer/spirv/builder_function_attribute_test.cc
index c47429b..2bdcc44 100644
--- a/src/tint/writer/spirv/builder_function_attribute_test.cc
+++ b/src/tint/writer/spirv/builder_function_attribute_test.cc
@@ -19,11 +19,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, Attribute_Stage) {
@@ -61,7 +62,7 @@
if (params.stage == ast::PipelineStage::kVertex) {
ret_type = ty.vec4<f32>();
ret_type_attrs.Push(Builtin(builtin::BuiltinValue::kPosition));
- body.Push(Return(Call(ty.vec4<f32>())));
+ body.Push(Return(Call<vec4<f32>>()));
}
utils::Vector<const ast::Attribute*, 2> deco_list{Stage(params.stage)};
diff --git a/src/tint/writer/spirv/builder_function_variable_test.cc b/src/tint/writer/spirv/builder_function_variable_test.cc
index 9f77d4e..d85a761 100644
--- a/src/tint/writer/spirv/builder_function_variable_test.cc
+++ b/src/tint/writer/spirv/builder_function_variable_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, FunctionVar_NoAddressSpace) {
@@ -44,7 +45,7 @@
}
TEST_F(BuilderTest, FunctionVar_WithConstantInitializer) {
- auto* init = vec3<f32>(1_f, 1_f, 3_f);
+ auto* init = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* v = Var("var", ty.vec3<f32>(), builtin::AddressSpace::kFunction, init);
WrapInFunction(v);
@@ -74,7 +75,7 @@
TEST_F(BuilderTest, FunctionVar_WithNonConstantInitializer) {
auto* a = Let("a", Expr(3_f));
- auto* init = vec2<f32>(1_f, Add(Expr("a"), 3_f));
+ auto* init = Call<vec2<f32>>(1_f, Add(Expr("a"), 3_f));
auto* v = Var("var", ty.vec2<f32>(), init);
WrapInFunction(a, v);
@@ -207,7 +208,7 @@
}
TEST_F(BuilderTest, FunctionVar_Let) {
- auto* init = vec3<f32>(1_f, 1_f, 3_f);
+ auto* init = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* v = Let("var", ty.vec3<f32>(), init);
@@ -227,7 +228,7 @@
}
TEST_F(BuilderTest, FunctionVar_Const) {
- auto* init = vec3<f32>(1_f, 1_f, 3_f);
+ auto* init = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* v = Const("var", ty.vec3<f32>(), init);
diff --git a/src/tint/writer/spirv/builder_global_variable_test.cc b/src/tint/writer/spirv/builder_global_variable_test.cc
index 671bacc..0640ec7 100644
--- a/src/tint/writer/spirv/builder_global_variable_test.cc
+++ b/src/tint/writer/spirv/builder_global_variable_test.cc
@@ -18,11 +18,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, GlobalVar_WithAddressSpace) {
@@ -41,7 +42,7 @@
}
TEST_F(BuilderTest, GlobalVar_WithInitializer) {
- auto* init = vec3<f32>(1_f, 1_f, 3_f);
+ auto* init = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* v = GlobalVar("var", ty.vec3<f32>(), builtin::AddressSpace::kPrivate, init);
@@ -91,7 +92,7 @@
// const c = vec3<f32>(1f, 2f, 3f);
// var v = c;
- auto* c = GlobalConst("c", vec3<f32>(1_f, 2_f, 3_f));
+ auto* c = GlobalConst("c", Call<vec3<f32>>(1_f, 2_f, 3_f));
GlobalVar("v", builtin::AddressSpace::kPrivate, Expr(c));
spirv::Builder& b = SanitizeAndBuild();
@@ -121,7 +122,7 @@
// var v = c;
Enable(builtin::Extension::kF16);
- auto* c = GlobalConst("c", vec3<f16>(1_h, 2_h, 3_h));
+ auto* c = GlobalConst("c", Call<vec3<f16>>(1_h, 2_h, 3_h));
GlobalVar("v", builtin::AddressSpace::kPrivate, Expr(c));
spirv::Builder& b = SanitizeAndBuild();
@@ -150,7 +151,7 @@
// const c = vec3(1, 2, 3);
// var v = c;
- auto* c = GlobalConst("c", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* c = GlobalConst("c", Call<vec3<Infer>>(1_a, 2_a, 3_a));
GlobalVar("v", builtin::AddressSpace::kPrivate, Expr(c));
spirv::Builder& b = SanitizeAndBuild();
@@ -179,7 +180,7 @@
// const c = vec3(1.0, 2.0, 3.0);
// var v = c;
- auto* c = GlobalConst("c", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* c = GlobalConst("c", Call<vec3<Infer>>(1._a, 2._a, 3._a));
GlobalVar("v", builtin::AddressSpace::kPrivate, Expr(c));
spirv::Builder& b = SanitizeAndBuild();
@@ -208,7 +209,7 @@
// const c = vec3<f32>(vec2<f32>(1f, 2f), 3f));
// var v = c;
- auto* c = GlobalConst("c", vec3<f32>(vec2<f32>(1_f, 2_f), 3_f));
+ auto* c = GlobalConst("c", Call<vec3<f32>>(Call<vec2<f32>>(1_f, 2_f), 3_f));
GlobalVar("v", builtin::AddressSpace::kPrivate, Expr(c));
spirv::Builder& b = SanitizeAndBuild();
diff --git a/src/tint/writer/spirv/builder_ident_expression_test.cc b/src/tint/writer/spirv/builder_ident_expression_test.cc
index 5ab7c19..1278cfc 100644
--- a/src/tint/writer/spirv/builder_ident_expression_test.cc
+++ b/src/tint/writer/spirv/builder_ident_expression_test.cc
@@ -16,11 +16,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, IdentifierExpression_GlobalConst) {
@@ -28,7 +29,7 @@
{
ProgramBuilder pb;
- auto* init = pb.vec3<f32>(1_f, 1_f, 3_f);
+ auto* init = pb.Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* v = pb.GlobalConst("c", pb.ty.vec3<f32>(), init);
@@ -66,7 +67,7 @@
}
TEST_F(BuilderTest, IdentifierExpression_FunctionConst) {
- auto* init = vec3<f32>(1_f, 1_f, 3_f);
+ auto* init = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* v = Let("var", ty.vec3<f32>(), init);
diff --git a/src/tint/writer/spirv/builder_return_test.cc b/src/tint/writer/spirv/builder_return_test.cc
index 13a65d6..041092f 100644
--- a/src/tint/writer/spirv/builder_return_test.cc
+++ b/src/tint/writer/spirv/builder_return_test.cc
@@ -15,11 +15,12 @@
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using BuilderTest = TestHelper;
TEST_F(BuilderTest, Return) {
@@ -37,7 +38,7 @@
}
TEST_F(BuilderTest, Return_WithValue) {
- auto* val = vec3<f32>(1_f, 1_f, 3_f);
+ auto* val = Call<vec3<f32>>(1_f, 1_f, 3_f);
auto* ret = Return(val);
Func("test", utils::Empty, ty.vec3<f32>(), utils::Vector{ret}, utils::Empty);
diff --git a/src/tint/writer/spirv/generator.h b/src/tint/writer/spirv/generator.h
index 0200426..3319c05 100644
--- a/src/tint/writer/spirv/generator.h
+++ b/src/tint/writer/spirv/generator.h
@@ -60,6 +60,10 @@
/// VK_KHR_zero_initialize_workgroup_memory is enabled.
bool use_zero_initialize_workgroup_memory_extension = false;
+ /// Set to `true` to skip robustness transform on textures when VK_EXT_robustness is enabled and
+ /// robustImageAccess == VK_TRUE.
+ bool disable_image_robustness = false;
+
#if TINT_BUILD_IR
/// Set to `true` to generate SPIR-V via the Tint IR instead of from the AST.
bool use_tint_ir = false;
@@ -70,7 +74,8 @@
emit_vertex_point_size,
disable_workgroup_init,
external_texture_options,
- use_zero_initialize_workgroup_memory_extension);
+ use_zero_initialize_workgroup_memory_extension,
+ disable_image_robustness);
};
/// The result produced when generating SPIR-V.
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index 1b22710..b5e5a5c 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -82,6 +82,12 @@
// Robustness must come after PromoteSideEffectsToDecl
// Robustness must come before BuiltinPolyfill and CanonicalizeEntryPointIO
manager.Add<ast::transform::Robustness>();
+
+ ast::transform::Robustness::Config config = {};
+ if (options.disable_image_robustness) {
+ config.texture_action = ast::transform::Robustness::Action::kIgnore;
+ }
+ data.Add<ast::transform::Robustness::Config>(config);
}
// BindingRemapper must come before MultiplanarExternalTexture. Note, this is flipped to the
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.cc b/src/tint/writer/spirv/ir/generator_impl_ir.cc
index ad1b180..1a821da 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.cc
@@ -25,6 +25,7 @@
#include "src/tint/ir/block_param.h"
#include "src/tint/ir/break_if.h"
#include "src/tint/ir/builtin_call.h"
+#include "src/tint/ir/construct.h"
#include "src/tint/ir/continue.h"
#include "src/tint/ir/exit_if.h"
#include "src/tint/ir/exit_loop.h"
@@ -40,7 +41,9 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/transform/add_empty_entry_point.h"
#include "src/tint/ir/transform/block_decorated_structs.h"
+#include "src/tint/ir/transform/merge_return.h"
#include "src/tint/ir/transform/var_for_dynamic_index.h"
+#include "src/tint/ir/unreachable.h"
#include "src/tint/ir/user_call.h"
#include "src/tint/ir/validate.h"
#include "src/tint/ir/var.h"
@@ -58,6 +61,7 @@
#include "src/tint/type/u32.h"
#include "src/tint/type/vector.h"
#include "src/tint/type/void.h"
+#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/writer/spirv/generator.h"
#include "src/tint/writer/spirv/module.h"
@@ -71,6 +75,7 @@
manager.Add<ir::transform::AddEmptyEntryPoint>();
manager.Add<ir::transform::BlockDecoratedStructs>();
+ manager.Add<ir::transform::MergeReturn>();
manager.Add<ir::transform::VarForDynamicIndex>();
transform::DataMap outputs;
@@ -222,6 +227,10 @@
module_.PushType(spv::Op::OpTypeFloat, {id, 32u});
},
[&](const type::F16*) {
+ module_.PushCapability(SpvCapabilityFloat16);
+ module_.PushCapability(SpvCapabilityUniformAndStorageBuffer16BitAccess);
+ module_.PushCapability(SpvCapabilityStorageBuffer16BitAccess);
+ module_.PushCapability(SpvCapabilityStorageInputOutput16);
module_.PushType(spv::Op::OpTypeFloat, {id, 16u});
},
[&](const type::Vector* vec) {
@@ -256,6 +265,10 @@
});
}
+uint32_t GeneratorImplIr::Value(ir::Instruction* inst) {
+ return Value(inst->Result());
+}
+
uint32_t GeneratorImplIr::Value(ir::Value* value) {
return Switch(
value, //
@@ -458,6 +471,7 @@
[&](ir::Access* a) { EmitAccess(a); }, //
[&](ir::Binary* b) { EmitBinary(b); }, //
[&](ir::BuiltinCall* b) { EmitBuiltinCall(b); }, //
+ [&](ir::Construct* c) { EmitConstruct(c); }, //
[&](ir::Load* l) { EmitLoad(l); }, //
[&](ir::Loop* l) { EmitLoop(l); }, //
[&](ir::Switch* sw) { EmitSwitch(sw); }, //
@@ -471,6 +485,11 @@
<< "unimplemented instruction: " << inst->TypeInfo().name;
});
}
+
+ if (block->IsEmpty()) {
+ // If the last emitted instruction is not a branch, then this should be unreachable.
+ current_function_.push_inst(spv::Op::OpUnreachable, {});
+ }
}
void GeneratorImplIr::EmitBranch(ir::Branch* b) {
@@ -491,48 +510,47 @@
current_function_.push_inst(spv::Op::OpBranchConditional,
{
Value(breakif->Condition()),
- Label(breakif->Loop()->Merge()),
+ loop_merge_label_,
Label(breakif->Loop()->Body()),
});
},
[&](ir::Continue* cont) {
current_function_.push_inst(spv::Op::OpBranch, {Label(cont->Loop()->Continuing())});
},
- [&](ir::ExitIf* if_) {
- current_function_.push_inst(spv::Op::OpBranch, {Label(if_->If()->Merge())});
- },
- [&](ir::ExitLoop* loop) {
- current_function_.push_inst(spv::Op::OpBranch, {Label(loop->Loop()->Merge())});
- },
- [&](ir::ExitSwitch* swtch) {
- current_function_.push_inst(spv::Op::OpBranch, {Label(swtch->Switch()->Merge())});
+ [&](ir::ExitIf*) { current_function_.push_inst(spv::Op::OpBranch, {if_merge_label_}); },
+ [&](ir::ExitLoop*) { current_function_.push_inst(spv::Op::OpBranch, {loop_merge_label_}); },
+ [&](ir::ExitSwitch*) {
+ current_function_.push_inst(spv::Op::OpBranch, {switch_merge_label_});
},
[&](ir::NextIteration* loop) {
current_function_.push_inst(spv::Op::OpBranch, {Label(loop->Loop()->Body())});
},
+ [&](ir::Unreachable*) { current_function_.push_inst(spv::Op::OpUnreachable, {}); },
+
[&](Default) {
TINT_ICE(Writer, diagnostics_) << "unimplemented branch: " << b->TypeInfo().name;
});
}
void GeneratorImplIr::EmitIf(ir::If* i) {
- auto* merge_block = i->Merge();
auto* true_block = i->True();
auto* false_block = i->False();
// Generate labels for the blocks. We emit the true or false block if it:
// 1. contains instructions other then the branch, or
- // 2. branches somewhere other then the Merge(), or
- // 3. the merge has input parameters
+ // 2. branches somewhere instead of exiting the loop (e.g. return or break), or
+ // 3. the if returns a value
// Otherwise we skip them and branch straight to the merge block.
- uint32_t merge_label = Label(merge_block);
+ uint32_t merge_label = module_.NextId();
+ TINT_SCOPED_ASSIGNMENT(if_merge_label_, merge_label);
+
uint32_t true_label = merge_label;
uint32_t false_label = merge_label;
- if (true_block->Length() > 1 || !merge_block->Params().IsEmpty() ||
+ if (true_block->Length() > 1 || i->HasResults() ||
(true_block->HasBranchTarget() && !true_block->Branch()->Is<ir::ExitIf>())) {
true_label = Label(true_block);
}
- if (false_block->Length() > 1 || !merge_block->Params().IsEmpty() ||
+ if (false_block->Length() > 1 || i->HasResults() ||
(false_block->HasBranchTarget() && !false_block->Branch()->Is<ir::ExitIf>())) {
false_label = Label(false_block);
}
@@ -551,15 +569,19 @@
EmitBlock(false_block);
}
- // Emit the merge block.
- EmitBlock(merge_block);
+ current_function_.push_inst(spv::Op::OpLabel, {merge_label});
+
+ // Emit the OpPhis for the ExitIfs
+ EmitExitPhis(i);
}
void GeneratorImplIr::EmitAccess(ir::Access* access) {
- auto id = Value(access);
- OperandList operands = {Type(access->Type()), id, Value(access->Object())};
+ auto* ty = access->Result()->Type();
- if (access->Type()->Is<type::Pointer>()) {
+ auto id = Value(access);
+ OperandList operands = {Type(ty), id, Value(access->Object())};
+
+ if (ty->Is<type::Pointer>()) {
// Use OpAccessChain for accesses into pointer types.
for (auto* idx : access->Indices()) {
operands.push_back(Value(idx));
@@ -593,7 +615,7 @@
}
// Now emit the OpVectorExtractDynamic instruction.
- operands = {Type(access->Type()), id, vec_id, Value(idx)};
+ operands = {Type(ty), id, vec_id, Value(idx)};
current_function_.push_inst(spv::Op::OpVectorExtractDynamic, std::move(operands));
return;
}
@@ -603,17 +625,18 @@
void GeneratorImplIr::EmitBinary(ir::Binary* binary) {
auto id = Value(binary);
+ auto* ty = binary->Result()->Type();
auto* lhs_ty = binary->LHS()->Type();
// Determine the opcode.
spv::Op op = spv::Op::Max;
switch (binary->Kind()) {
case ir::Binary::Kind::kAdd: {
- op = binary->Type()->is_integer_scalar_or_vector() ? spv::Op::OpIAdd : spv::Op::OpFAdd;
+ op = ty->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;
+ op = ty->is_integer_scalar_or_vector() ? spv::Op::OpISub : spv::Op::OpFSub;
break;
}
@@ -698,17 +721,16 @@
}
// Emit the instruction.
- current_function_.push_inst(
- op, {Type(binary->Type()), id, Value(binary->LHS()), Value(binary->RHS())});
+ current_function_.push_inst(op, {Type(ty), id, Value(binary->LHS()), Value(binary->RHS())});
}
void GeneratorImplIr::EmitBuiltinCall(ir::BuiltinCall* builtin) {
- auto* result_ty = builtin->Type();
+ auto* result_ty = builtin->Result()->Type();
if (builtin->Func() == builtin::Function::kAbs &&
result_ty->is_unsigned_integer_scalar_or_vector()) {
// abs() is a no-op for unsigned integers.
- values_.Add(builtin, Value(builtin->Args()[0]));
+ values_.Add(builtin->Result(), Value(builtin->Args()[0]));
return;
}
@@ -771,9 +793,17 @@
current_function_.push_inst(op, operands);
}
+void GeneratorImplIr::EmitConstruct(ir::Construct* construct) {
+ OperandList operands = {Type(construct->Result()->Type()), Value(construct)};
+ for (auto* arg : construct->Args()) {
+ operands.push_back(Value(arg));
+ }
+ current_function_.push_inst(spv::Op::OpCompositeConstruct, std::move(operands));
+}
+
void GeneratorImplIr::EmitLoad(ir::Load* load) {
current_function_.push_inst(spv::Op::OpLoad,
- {Type(load->Type()), Value(load), Value(load->From())});
+ {Type(load->Result()->Type()), Value(load), Value(load->From())});
}
void GeneratorImplIr::EmitLoop(ir::Loop* loop) {
@@ -781,7 +811,9 @@
auto header_label = Label(loop->Body()); // Back-edge needs to branch to the loop header
auto body_label = module_.NextId();
auto continuing_label = Label(loop->Continuing());
- auto merge_label = Label(loop->Merge());
+
+ uint32_t merge_label = module_.NextId();
+ TINT_SCOPED_ASSIGNMENT(loop_merge_label_, merge_label);
if (init_label != 0) {
// Emit the loop initializer.
@@ -814,7 +846,10 @@
}
// Emit the loop merge block.
- EmitBlock(loop->Merge());
+ current_function_.push_inst(spv::Op::OpLabel, {merge_label});
+
+ // Emit the OpPhis for the ExitLoops
+ EmitExitPhis(loop);
}
void GeneratorImplIr::EmitSwitch(ir::Switch* swtch) {
@@ -823,7 +858,7 @@
for (auto& c : swtch->Cases()) {
for (auto& sel : c.selectors) {
if (sel.IsDefault()) {
- default_label = Label(c.Start());
+ default_label = Label(c.Block());
}
}
}
@@ -832,7 +867,7 @@
// Build the operands to the OpSwitch instruction.
OperandList switch_operands = {Value(swtch->Condition()), default_label};
for (auto& c : swtch->Cases()) {
- auto label = Label(c.Start());
+ auto label = Label(c.Block());
for (auto& sel : c.selectors) {
if (sel.IsDefault()) {
continue;
@@ -842,18 +877,24 @@
}
}
+ uint32_t merge_label = module_.NextId();
+ TINT_SCOPED_ASSIGNMENT(switch_merge_label_, merge_label);
+
// Emit the OpSelectionMerge and OpSwitch instructions.
current_function_.push_inst(spv::Op::OpSelectionMerge,
- {Label(swtch->Merge()), U32Operand(SpvSelectionControlMaskNone)});
+ {merge_label, U32Operand(SpvSelectionControlMaskNone)});
current_function_.push_inst(spv::Op::OpSwitch, switch_operands);
// Emit the cases.
for (auto& c : swtch->Cases()) {
- EmitBlock(c.Start());
+ EmitBlock(c.Block());
}
// Emit the switch merge block.
- EmitBlock(swtch->Merge());
+ current_function_.push_inst(spv::Op::OpLabel, {merge_label});
+
+ // Emit the OpPhis for the ExitSwitches
+ EmitExitPhis(swtch);
}
void GeneratorImplIr::EmitStore(ir::Store* store) {
@@ -862,7 +903,7 @@
void GeneratorImplIr::EmitUserCall(ir::UserCall* call) {
auto id = Value(call);
- OperandList operands = {Type(call->Type()), id, Value(call->Func())};
+ OperandList operands = {Type(call->Result()->Type()), id, Value(call->Func())};
for (auto* arg : call->Args()) {
operands.push_back(Value(arg));
}
@@ -871,7 +912,7 @@
void GeneratorImplIr::EmitVar(ir::Var* var) {
auto id = Value(var);
- auto* ptr = var->Type();
+ auto* ptr = var->Result()->Type()->As<type::Pointer>();
auto ty = Type(ptr);
switch (ptr->AddressSpace()) {
@@ -928,4 +969,32 @@
}
}
+void GeneratorImplIr::EmitExitPhis(ir::ControlInstruction* inst) {
+ struct Branch {
+ uint32_t label = 0;
+ ir::Value* value = nullptr;
+ bool operator<(const Branch& other) const { return label < other.label; }
+ };
+
+ auto results = inst->Results();
+ for (size_t index = 0; index < results.Length(); index++) {
+ auto* result = results[index];
+ auto* ty = result->Type();
+
+ utils::Vector<Branch, 8> branches;
+ branches.Reserve(inst->Exits().Count());
+ for (auto& exit : inst->Exits()) {
+ branches.Push(Branch{Label(exit->Block()), exit->Args()[index]});
+ }
+ branches.Sort(); // Sort the branches by label to ensure deterministic output
+
+ OperandList ops{Type(ty), Value(result)};
+ for (auto& branch : branches) {
+ ops.push_back(Value(branch.value));
+ ops.push_back(branch.label);
+ }
+ current_function_.push_inst(spv::Op::OpPhi, std::move(ops));
+ }
+}
+
} // namespace tint::writer::spirv
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.h b/src/tint/writer/spirv/ir/generator_impl_ir.h
index dccb23a..1a2ec8e 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.h
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.h
@@ -35,6 +35,11 @@
class BlockParam;
class Branch;
class BuiltinCall;
+class Construct;
+class ControlInstruction;
+class ExitIf;
+class ExitLoop;
+class ExitSwitch;
class Function;
class If;
class Load;
@@ -95,6 +100,11 @@
/// @returns the result ID of the value
uint32_t Value(ir::Value* value);
+ /// Get the result ID of the instruction result `value`, emitting its instruction if necessary.
+ /// @param inst the instruction to get the ID for
+ /// @returns the result ID of the instruction
+ uint32_t Value(ir::Instruction* inst);
+
/// Get the ID of the label for `block`.
/// @param block the block to get the label ID for
/// @returns the ID of the block's label
@@ -146,6 +156,10 @@
/// @param call the builtin call instruction to emit
void EmitBuiltinCall(ir::BuiltinCall* call);
+ /// Emit a construct instruction.
+ /// @param construct the construct instruction to emit
+ void EmitConstruct(ir::Construct* construct);
+
/// Emit a load instruction.
/// @param load the load instruction to emit
void EmitLoad(ir::Load* load);
@@ -174,6 +188,10 @@
/// @param b the branch instruction to emit
void EmitBranch(ir::Branch* b);
+ /// Emit the OpPhis for the given flow control instruction.
+ /// @param inst the flow control instruction
+ void EmitExitPhis(ir::ControlInstruction* inst);
+
private:
/// Get the result ID of the constant `constant`, emitting its instruction if necessary.
/// @param constant the constant to get the ID for
@@ -234,6 +252,15 @@
/// The current function that is being emitted.
Function current_function_;
+ /// The merge block for the current if statement
+ uint32_t if_merge_label_ = 0;
+
+ /// The merge block for the current loop statement
+ uint32_t loop_merge_label_ = 0;
+
+ /// The merge block for the current switch statement
+ uint32_t switch_merge_label_ = 0;
+
bool zero_init_workgroup_memory_ = false;
};
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
index 4318147..1f33350 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
@@ -14,24 +14,22 @@
#include "src/tint/writer/spirv/ir/test_helper_ir.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
-class SpvGeneratorImplTest_Access : public SpvGeneratorImplTest {
- protected:
- const type::Pointer* ptr(const type::Type* elem) {
- return ty.ptr(builtin::AddressSpace::kFunction, elem, builtin::Access::kReadWrite);
- }
-};
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
+using SpvGeneratorImplTest_Access = SpvGeneratorImplTest;
TEST_F(SpvGeneratorImplTest_Access, Array_Value_ConstantIndex) {
auto* arr_val = b.FunctionParam(ty.array(ty.i32(), 4));
- auto* access = b.Access(ty.i32(), arr_val, 1_u);
auto* func = b.Function("foo", ty.void_());
func->SetParams({arr_val});
- func->StartTarget()->SetInstructions({access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ sb.Access(ty.i32(), arr_val, 1_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -54,10 +52,12 @@
}
TEST_F(SpvGeneratorImplTest_Access, Array_Pointer_ConstantIndex) {
- auto* arr_var = b.Var(ptr(ty.array(ty.i32(), 4)));
- auto* access = b.Access(ptr(ty.i32()), arr_var, 1_u);
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({arr_var, access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* arr_var = sb.Var(ty.ptr<function, array<i32, 4>>());
+ sb.Access(ty.ptr<function, i32>(), arr_var, 1_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -83,13 +83,14 @@
}
TEST_F(SpvGeneratorImplTest_Access, Array_Pointer_DynamicIndex) {
- auto* arr_var = b.Var(ptr(ty.array(ty.i32(), 4)));
- auto* idx_var = b.Var(ptr(ty.i32()));
- auto* idx = b.Load(idx_var);
- auto* access = b.Access(ptr(ty.i32()), arr_var, idx);
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{idx_var, idx, arr_var, access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* idx_var = sb.Var(ty.ptr<function, i32>());
+ auto* idx = sb.Load(idx_var);
+ auto* arr_var = sb.Var(ty.ptr<function, array<i32, 4>>());
+ sb.Access(ty.ptr<function, i32>(), arr_var, idx);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -117,11 +118,13 @@
TEST_F(SpvGeneratorImplTest_Access, Matrix_Value_ConstantIndex) {
auto* mat_val = b.FunctionParam(ty.mat2x2(ty.f32()));
- auto* access_vec = b.Access(ty.vec2(ty.f32()), mat_val, 1_u);
- auto* access_el = b.Access(ty.f32(), mat_val, 1_u, 0_u);
auto* func = b.Function("foo", ty.void_());
func->SetParams({mat_val});
- func->StartTarget()->SetInstructions({access_vec, access_el, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ sb.Access(ty.vec2(ty.f32()), mat_val, 1_u);
+ sb.Access(ty.f32(), mat_val, 1_u, 0_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -143,11 +146,13 @@
}
TEST_F(SpvGeneratorImplTest_Access, Matrix_Pointer_ConstantIndex) {
- auto* mat_var = b.Var(ptr(ty.mat2x2(ty.f32())));
- auto* access_vec = b.Access(ptr(ty.vec2(ty.f32())), mat_var, 1_u);
- auto* access_el = b.Access(ptr(ty.f32()), mat_var, 1_u, 0_u);
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({access_vec, access_el, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* mat_var = sb.Var(ty.ptr<function, mat2x2<f32>>());
+ sb.Access(ty.ptr<function, vec2<f32>>(), mat_var, 1_u);
+ sb.Access(ty.ptr<function, f32>(), mat_var, 1_u, 0_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -155,31 +160,35 @@
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
%2 = OpTypeVoid
%3 = OpTypeFunction %2
-%8 = OpTypeFloat 32
-%7 = OpTypeVector %8 2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 2
+%7 = OpTypeMatrix %8 2
%6 = OpTypePointer Function %7
-%11 = OpTypeInt 32 0
-%10 = OpConstant %11 1
-%13 = OpTypePointer Function %8
-%14 = OpConstant %11 0
+%11 = OpTypePointer Function %8
+%13 = OpTypeInt 32 0
+%12 = OpConstant %13 1
+%15 = OpTypePointer Function %9
+%16 = OpConstant %13 0
%1 = OpFunction %2 None %3
%4 = OpLabel
-%5 = OpAccessChain %6 %9 %10
-%12 = OpAccessChain %13 %9 %10 %14
+%5 = OpVariable %6 Function
+%10 = OpAccessChain %11 %5 %12
+%14 = OpAccessChain %15 %5 %12 %16
OpReturn
OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest_Access, Matrix_Pointer_DynamicIndex) {
- auto* mat_var = b.Var(ptr(ty.mat2x2(ty.f32())));
- auto* idx_var = b.Var(ptr(ty.i32()));
- auto* idx = b.Load(idx_var);
- auto* access_vec = b.Access(ptr(ty.vec2(ty.f32())), mat_var, idx);
- auto* access_el = b.Access(ptr(ty.f32()), mat_var, idx, idx);
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{idx_var, idx, mat_var, access_vec, access_el, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* idx_var = sb.Var(ty.ptr<function, i32>());
+ auto* idx = sb.Load(idx_var);
+ auto* mat_var = sb.Var(ty.ptr<function, mat2x2<f32>>());
+ sb.Access(ty.ptr<function, vec2<f32>>(), mat_var, idx);
+ sb.Access(ty.ptr<function, f32>(), mat_var, idx, idx);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -208,11 +217,13 @@
}
TEST_F(SpvGeneratorImplTest_Access, Vector_Value_ConstantIndex) {
- auto* vec_val = b.FunctionParam(ty.vec4(ty.i32()));
- auto* access = b.Access(ty.i32(), vec_val, 1_u);
auto* func = b.Function("foo", ty.void_());
+ auto* vec_val = b.FunctionParam(ty.vec4(ty.i32()));
func->SetParams({vec_val});
- func->StartTarget()->SetInstructions({access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ sb.Access(ty.i32(), vec_val, 1_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -232,13 +243,15 @@
}
TEST_F(SpvGeneratorImplTest_Access, Vector_Value_DynamicIndex) {
- auto* vec_val = b.FunctionParam(ty.vec4(ty.i32()));
- auto* idx_var = b.Var(ptr(ty.i32()));
- auto* idx = b.Load(idx_var);
- auto* access = b.Access(ty.i32(), vec_val, idx);
auto* func = b.Function("foo", ty.void_());
+ auto* vec_val = b.FunctionParam(ty.vec4(ty.i32()));
func->SetParams({vec_val});
- func->StartTarget()->SetInstructions({idx_var, idx, access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* idx_var = sb.Var(ty.ptr<function, i32>());
+ auto* idx = sb.Load(idx_var);
+ sb.Access(ty.i32(), vec_val, idx);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -261,10 +274,12 @@
}
TEST_F(SpvGeneratorImplTest_Access, Vector_Pointer_ConstantIndex) {
- auto* vec_var = b.Var(ptr(ty.vec4(ty.i32())));
- auto* access = b.Access(ptr(ty.i32()), vec_var, 1_u);
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({vec_var, access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* vec_var = sb.Var(ty.ptr<function, vec4<i32>>());
+ sb.Access(ty.ptr<function, i32>(), vec_var, 1_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -288,13 +303,14 @@
}
TEST_F(SpvGeneratorImplTest_Access, Vector_Pointer_DynamicIndex) {
- auto* vec_var = b.Var(ptr(ty.vec4(ty.i32())));
- auto* idx_var = b.Var(ptr(ty.i32()));
- auto* idx = b.Load(idx_var);
- auto* access = b.Access(ptr(ty.i32()), vec_var, idx);
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{idx_var, idx, vec_var, access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* idx_var = sb.Var(ty.ptr<function, i32>());
+ auto* idx = sb.Load(idx_var);
+ auto* vec_var = sb.Var(ty.ptr<function, vec4<i32>>());
+ sb.Access(ty.ptr<function, i32>(), vec_var, idx);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -319,12 +335,14 @@
TEST_F(SpvGeneratorImplTest_Access, NestedVector_Value_DynamicIndex) {
auto* val = b.FunctionParam(ty.array(ty.array(ty.vec4(ty.i32()), 4), 4));
- auto* idx_var = b.Var(ptr(ty.i32()));
- auto* idx = b.Load(idx_var);
- auto* access = b.Access(ty.i32(), val, 1_u, 2_u, idx);
auto* func = b.Function("foo", ty.void_());
func->SetParams({val});
- func->StartTarget()->SetInstructions({idx_var, idx, access, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* idx_var = sb.Var(ty.ptr<function, i32>());
+ auto* idx = sb.Load(idx_var);
+ sb.Access(ty.i32(), val, 1_u, 2_u, idx);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -354,21 +372,19 @@
}
TEST_F(SpvGeneratorImplTest_Access, Struct_Value_ConstantIndex) {
- auto* str = ty.Get<type::Struct>(
- mod.symbols.Register("MyStruct"),
- utils::Vector{
- ty.Get<type::StructMember>(mod.symbols.Register("a"), ty.f32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.Register("b"), ty.vec4(ty.i32()), 1u, 16u, 16u,
- 16u, type::StructMemberAttributes{}),
- },
- 16u, 32u, 32u);
+ auto* str =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.Register("a"), ty.f32()},
+ {mod.symbols.Register("b"), ty.vec4<i32>()},
+ });
auto* str_val = b.FunctionParam(str);
- auto* access_vec = b.Access(ty.i32(), str_val, 1_u);
- auto* access_el = b.Access(ty.i32(), str_val, 1_u, 2_u);
auto* func = b.Function("foo", ty.void_());
func->SetParams({str_val});
- func->StartTarget()->SetInstructions({access_vec, access_el, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ sb.Access(ty.i32(), str_val, 1_u);
+ sb.Access(ty.i32(), str_val, 1_u, 2_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -396,21 +412,18 @@
}
TEST_F(SpvGeneratorImplTest_Access, Struct_Pointer_ConstantIndex) {
- auto* str = ty.Get<type::Struct>(
- mod.symbols.Register("MyStruct"),
- utils::Vector{
- ty.Get<type::StructMember>(mod.symbols.Register("a"), ty.f32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.Register("b"), ty.vec4(ty.i32()), 1u, 16u, 16u,
- 16u, type::StructMemberAttributes{}),
- },
- 16u, 32u, 32u);
- auto* str_var = b.Var(ptr(str));
- auto* access_vec = b.Access(ptr(ty.i32()), str_var, 1_u);
- auto* access_el = b.Access(ptr(ty.i32()), str_var, 1_u, 2_u);
+ auto* str =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.Register("a"), ty.f32()},
+ {mod.symbols.Register("b"), ty.vec4<i32>()},
+ });
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{str_var, access_vec, access_el, b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* str_var = sb.Var(ty.ptr(function, str, read_write));
+ sb.Access(ty.ptr<function, i32>(), str_var, 1_u);
+ sb.Access(ty.ptr<function, i32>(), str_var, 1_u, 2_u);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
index 6ca13f7..37b702c 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
@@ -37,10 +37,10 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{b.Binary(params.kind, MakeScalarType(params.type),
- MakeScalarValue(params.type), MakeScalarValue(params.type)),
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Binary(params.kind, MakeScalarType(params.type), MakeScalarValue(params.type),
+ MakeScalarValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -51,11 +51,10 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{b.Binary(params.kind, MakeVectorType(params.type),
- MakeVectorValue(params.type), MakeVectorValue(params.type)),
-
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Binary(params.kind, MakeVectorType(params.type), MakeVectorValue(params.type),
+ MakeVectorValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -88,10 +87,10 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{b.Binary(params.kind, MakeScalarType(params.type),
- MakeScalarValue(params.type), MakeScalarValue(params.type)),
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Binary(params.kind, MakeScalarType(params.type), MakeScalarValue(params.type),
+ MakeScalarValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -102,11 +101,10 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{b.Binary(params.kind, MakeVectorType(params.type),
- MakeVectorValue(params.type), MakeVectorValue(params.type)),
-
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Binary(params.kind, MakeVectorType(params.type), MakeVectorValue(params.type),
+ MakeVectorValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -131,25 +129,24 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{b.Binary(params.kind, ty.bool_(), MakeScalarValue(params.type),
- MakeScalarValue(params.type)),
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Binary(params.kind, ty.bool_(), MakeScalarValue(params.type), MakeScalarValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
}
+
TEST_P(Comparison, Vector) {
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- utils::Vector{b.Binary(params.kind, ty.vec2(ty.bool_()), MakeVectorValue(params.type),
- MakeVectorValue(params.type)),
-
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Binary(params.kind, ty.vec2(ty.bool_()), MakeVectorValue(params.type),
+ MakeVectorValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -204,8 +201,11 @@
TEST_F(SpvGeneratorImplTest, Binary_Chain) {
auto* func = b.Function("foo", ty.void_());
- auto* a = b.Subtract(ty.i32(), 1_i, 2_i);
- func->StartTarget()->SetInstructions({a, b.Add(ty.i32(), a, a), b.Return(func)});
+
+ auto sb = b.With(func->StartTarget());
+ auto* a = sb.Subtract(ty.i32(), 1_i, 2_i);
+ sb.Add(ty.i32(), a, a);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc
index 44d0505..ae45e1c 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc
@@ -38,10 +38,9 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({
- b.Call(MakeScalarType(params.type), params.function, MakeScalarValue(params.type)),
- b.Return(func),
- });
+ auto sb = b.With(func->StartTarget());
+ sb.Call(MakeScalarType(params.type), params.function, MakeScalarValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -52,10 +51,9 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({
- b.Call(MakeVectorType(params.type), params.function, MakeVectorValue(params.type)),
- b.Return(func),
- });
+ auto sb = b.With(func->StartTarget());
+ sb.Call(MakeVectorType(params.type), params.function, MakeVectorValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -69,12 +67,10 @@
// Test that abs of an unsigned value just folds away.
TEST_F(SpvGeneratorImplTest, Builtin_Abs_u32) {
- auto* result = b.Call(MakeScalarType(kU32), builtin::Function::kAbs, MakeScalarValue(kU32));
auto* func = b.Function("foo", MakeScalarType(kU32));
- func->StartTarget()->SetInstructions({
- result,
- b.Return(func, result),
- });
+ auto sb = b.With(func->StartTarget());
+ auto* result = sb.Call(MakeScalarType(kU32), builtin::Function::kAbs, MakeScalarValue(kU32));
+ sb.Return(func, result);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -91,12 +87,10 @@
}
TEST_F(SpvGeneratorImplTest, Builtin_Abs_vec2u) {
- auto* result = b.Call(MakeVectorType(kU32), builtin::Function::kAbs, MakeVectorValue(kU32));
auto* func = b.Function("foo", MakeVectorType(kU32));
- func->StartTarget()->SetInstructions({
- result,
- b.Return(func, result),
- });
+ auto sb = b.With(func->StartTarget());
+ auto* result = sb.Call(MakeVectorType(kU32), builtin::Function::kAbs, MakeVectorValue(kU32));
+ sb.Return(func, result);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -121,11 +115,10 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({
- b.Call(MakeScalarType(params.type), params.function, MakeScalarValue(params.type),
- MakeScalarValue(params.type)),
- b.Return(func),
- });
+ auto sb = b.With(func->StartTarget());
+ sb.Call(MakeScalarType(params.type), params.function, MakeScalarValue(params.type),
+ MakeScalarValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -136,12 +129,10 @@
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({
- b.Call(MakeVectorType(params.type), params.function, MakeVectorValue(params.type),
- MakeVectorValue(params.type)),
-
- b.Return(func),
- });
+ auto sb = b.With(func->StartTarget());
+ sb.Call(MakeVectorType(params.type), params.function, MakeVectorValue(params.type),
+ MakeVectorValue(params.type));
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc
new file mode 100644
index 0000000..732c6ff
--- /dev/null
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc
@@ -0,0 +1,165 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/spirv/ir/test_helper_ir.h"
+
+namespace tint::writer::spirv {
+namespace {
+
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
+TEST_F(SpvGeneratorImplTest, Construct_Vector) {
+ auto* func = b.Function("foo", ty.vec4<i32>());
+ func->SetParams({
+ b.FunctionParam(ty.i32()),
+ b.FunctionParam(ty.i32()),
+ b.FunctionParam(ty.i32()),
+ b.FunctionParam(ty.i32()),
+ });
+
+ auto sb = b.With(func->StartTarget());
+ sb.Return(func, sb.Construct(ty.vec4<i32>(), func->Params()));
+
+ ASSERT_TRUE(IRIsValid()) << Error();
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%3 = OpTypeInt 32 1
+%2 = OpTypeVector %3 4
+%8 = OpTypeFunction %2 %3 %3 %3 %3
+%1 = OpFunction %2 None %8
+%4 = OpFunctionParameter %3
+%5 = OpFunctionParameter %3
+%6 = OpFunctionParameter %3
+%7 = OpFunctionParameter %3
+%9 = OpLabel
+%10 = OpCompositeConstruct %2 %4 %5 %6 %7
+OpReturnValue %10
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Construct_Matrix) {
+ auto* func = b.Function("foo", ty.mat3x4<f32>());
+ func->SetParams({
+ b.FunctionParam(ty.vec4<f32>()),
+ b.FunctionParam(ty.vec4<f32>()),
+ b.FunctionParam(ty.vec4<f32>()),
+ });
+
+ auto sb = b.With(func->StartTarget());
+ sb.Return(func, sb.Construct(ty.mat3x4<f32>(), func->Params()));
+
+ ASSERT_TRUE(IRIsValid()) << Error();
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%4 = OpTypeFloat 32
+%3 = OpTypeVector %4 4
+%2 = OpTypeMatrix %3 3
+%8 = OpTypeFunction %2 %3 %3 %3
+%1 = OpFunction %2 None %8
+%5 = OpFunctionParameter %3
+%6 = OpFunctionParameter %3
+%7 = OpFunctionParameter %3
+%9 = OpLabel
+%10 = OpCompositeConstruct %2 %5 %6 %7
+OpReturnValue %10
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Construct_Array) {
+ auto* func = b.Function("foo", ty.array<f32, 4>());
+ func->SetParams({
+ b.FunctionParam(ty.f32()),
+ b.FunctionParam(ty.f32()),
+ b.FunctionParam(ty.f32()),
+ b.FunctionParam(ty.f32()),
+ });
+
+ auto sb = b.With(func->StartTarget());
+ sb.Return(func, sb.Construct(ty.array<f32, 4>(), func->Params()));
+
+ ASSERT_TRUE(IRIsValid()) << Error();
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+OpDecorate %2 ArrayStride 4
+%3 = OpTypeFloat 32
+%5 = OpTypeInt 32 0
+%4 = OpConstant %5 4
+%2 = OpTypeArray %3 %4
+%10 = OpTypeFunction %2 %3 %3 %3 %3
+%1 = OpFunction %2 None %10
+%6 = OpFunctionParameter %3
+%7 = OpFunctionParameter %3
+%8 = OpFunctionParameter %3
+%9 = OpFunctionParameter %3
+%11 = OpLabel
+%12 = OpCompositeConstruct %2 %6 %7 %8 %9
+OpReturnValue %12
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Construct_Struct) {
+ auto* str =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.Register("a"), ty.i32()},
+ {mod.symbols.Register("b"), ty.u32()},
+ {mod.symbols.Register("c"), ty.vec4<f32>()},
+ });
+
+ auto* func = b.Function("foo", str);
+ func->SetParams({
+ b.FunctionParam(ty.i32()),
+ b.FunctionParam(ty.u32()),
+ b.FunctionParam(ty.vec4<f32>()),
+ });
+
+ auto sb = b.With(func->StartTarget());
+ sb.Return(func, sb.Construct(str, func->Params()));
+
+ ASSERT_TRUE(IRIsValid()) << Error();
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+OpMemberName %2 0 "a"
+OpMemberName %2 1 "b"
+OpMemberName %2 2 "c"
+OpName %2 "MyStruct"
+OpMemberDecorate %2 0 Offset 0
+OpMemberDecorate %2 1 Offset 4
+OpMemberDecorate %2 2 Offset 16
+%3 = OpTypeInt 32 1
+%4 = OpTypeInt 32 0
+%6 = OpTypeFloat 32
+%5 = OpTypeVector %6 4
+%2 = OpTypeStruct %3 %4 %5
+%10 = OpTypeFunction %2 %3 %4 %5
+%1 = OpFunction %2 None %10
+%7 = OpFunctionParameter %3
+%8 = OpFunctionParameter %4
+%9 = OpFunctionParameter %5
+%11 = OpLabel
+%12 = OpCompositeConstruct %2 %7 %8 %9
+OpReturnValue %12
+OpFunctionEnd
+)");
+}
+
+} // namespace
+} // namespace tint::writer::spirv
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc
index 9c67418..81f1091 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc
@@ -19,7 +19,7 @@
TEST_F(SpvGeneratorImplTest, Function_Empty) {
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({b.Return(func)});
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -37,7 +37,7 @@
// Test that we do not emit the same function type more than once.
TEST_F(SpvGeneratorImplTest, Function_DeduplicateType) {
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions({b.Return(func)});
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -52,7 +52,7 @@
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Compute) {
auto* func =
b.Function("main", ty.void_(), ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
- func->StartTarget()->SetInstructions({b.Return(func)});
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -71,7 +71,7 @@
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Fragment) {
auto* func = b.Function("main", ty.void_(), ir::Function::PipelineStage::kFragment);
- func->StartTarget()->SetInstructions({b.Return(func)});
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -90,7 +90,7 @@
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Vertex) {
auto* func = b.Function("main", ty.void_(), ir::Function::PipelineStage::kVertex);
- func->StartTarget()->SetInstructions({b.Return(func)});
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -108,13 +108,13 @@
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Multiple) {
auto* f1 = b.Function("main1", ty.void_(), ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
- f1->StartTarget()->SetInstructions({b.Return(f1)});
+ f1->StartTarget()->Append(b.Return(f1));
auto* f2 = b.Function("main2", ty.void_(), ir::Function::PipelineStage::kCompute, {{8, 2, 16}});
- f2->StartTarget()->SetInstructions({b.Return(f2)});
+ f2->StartTarget()->Append(b.Return(f2));
auto* f3 = b.Function("main3", ty.void_(), ir::Function::PipelineStage::kFragment);
- f3->StartTarget()->SetInstructions({b.Return(f3)});
+ f3->StartTarget()->Append(b.Return(f3));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -149,7 +149,7 @@
TEST_F(SpvGeneratorImplTest, Function_ReturnValue) {
auto* func = b.Function("foo", ty.i32());
- func->StartTarget()->SetInstructions({b.Return(func, i32(42))});
+ func->StartTarget()->Append(b.Return(func, i32(42)));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -169,13 +169,15 @@
auto* i32 = ty.i32();
auto* x = b.FunctionParam(i32);
auto* y = b.FunctionParam(i32);
- auto* result = b.Add(i32, x, y);
auto* func = b.Function("foo", i32);
func->SetParams({x, y});
- func->StartTarget()->SetInstructions({result, b.Return(func, result)});
mod.SetName(x, "x");
mod.SetName(y, "y");
+ auto sb = b.With(func->StartTarget());
+ auto* result = sb.Add(i32, x, y);
+ sb.Return(func, result);
+
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
@@ -198,14 +200,21 @@
auto* i32_ty = ty.i32();
auto* x = b.FunctionParam(i32_ty);
auto* y = b.FunctionParam(i32_ty);
- auto* result = b.Add(i32_ty, x, y);
auto* foo = b.Function("foo", i32_ty);
foo->SetParams({x, y});
- foo->StartTarget()->SetInstructions({result, b.Return(foo, result)});
+
+ {
+ auto sb = b.With(foo->StartTarget());
+ auto* result = sb.Add(i32_ty, x, y);
+ sb.Return(foo, result);
+ }
auto* bar = b.Function("bar", ty.void_());
- bar->StartTarget()->SetInstructions(
- utils::Vector{b.Call(i32_ty, foo, i32(2), i32(3)), b.Return(bar)});
+ {
+ auto sb = b.With(bar->StartTarget());
+ sb.Call(i32_ty, foo, i32(2), i32(3));
+ sb.Return(bar);
+ }
ASSERT_TRUE(IRIsValid()) << Error();
@@ -236,11 +245,12 @@
TEST_F(SpvGeneratorImplTest, Function_Call_Void) {
auto* foo = b.Function("foo", ty.void_());
- foo->StartTarget()->SetInstructions({b.Return(foo)});
+ foo->StartTarget()->Append(b.Return(foo));
auto* bar = b.Function("bar", ty.void_());
- bar->StartTarget()->SetInstructions(
- utils::Vector{b.Call(ty.void_(), foo, utils::Empty), b.Return(bar)});
+ auto sb = b.With(bar->StartTarget());
+ sb.Call(ty.void_(), foo, utils::Empty);
+ sb.Return(bar);
ASSERT_TRUE(IRIsValid()) << Error();
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc
index 6534a56..62afeda 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc
@@ -23,11 +23,10 @@
auto* func = b.Function("foo", ty.void_());
auto* i = b.If(true);
- i->True()->SetInstructions({b.ExitIf(i)});
- i->False()->SetInstructions({b.ExitIf(i)});
- i->Merge()->SetInstructions({b.Return(func)});
-
- func->StartTarget()->SetInstructions({i});
+ i->True()->Append(b.ExitIf(i));
+ i->False()->Append(b.ExitIf(i));
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -51,13 +50,14 @@
auto* func = b.Function("foo", ty.void_());
auto* i = b.If(true);
- i->False()->SetInstructions({b.ExitIf(i)});
- i->Merge()->SetInstructions({b.Return(func)});
+ i->False()->Append(b.ExitIf(i));
- auto* true_block = i->True();
- true_block->SetInstructions({b.Add(ty.i32(), 1_i, 1_i), b.ExitIf(i)});
+ auto tb = b.With(i->True());
+ tb.Add(ty.i32(), 1_i, 1_i);
+ tb.ExitIf(i);
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -86,13 +86,14 @@
auto* func = b.Function("foo", ty.void_());
auto* i = b.If(true);
- i->True()->SetInstructions({b.ExitIf(i)});
- i->Merge()->SetInstructions({b.Return(func)});
+ i->True()->Append(b.ExitIf(i));
- auto* false_block = i->False();
- false_block->SetInstructions({b.Add(ty.i32(), 1_i, 1_i), b.ExitIf(i)});
+ auto fb = b.With(i->False());
+ fb.Add(ty.i32(), 1_i, 1_i);
+ fb.ExitIf(i);
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -121,10 +122,11 @@
auto* func = b.Function("foo", ty.void_());
auto* i = b.If(true);
- i->True()->SetInstructions({b.Return(func)});
- i->False()->SetInstructions({b.Return(func)});
+ i->True()->Append(b.Return(func));
+ i->False()->Append(b.Return(func));
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Unreachable());
ASSERT_TRUE(IRIsValid()) << Error();
@@ -149,29 +151,26 @@
}
TEST_F(SpvGeneratorImplTest, If_Phi_SingleValue) {
- auto* func = b.Function("foo", ty.void_());
-
- auto* merge_param = b.BlockParam(b.ir.Types().i32());
+ auto* func = b.Function("foo", ty.i32());
auto* i = b.If(true);
- i->True()->SetInstructions({b.ExitIf(i, 10_i)});
- i->False()->SetInstructions({b.ExitIf(i, 20_i)});
- i->Merge()->SetParams({merge_param});
- i->Merge()->SetInstructions({b.Return(func, merge_param)});
+ i->SetResults(b.InstructionResult(ty.i32()));
+ i->True()->Append(b.ExitIf(i, 10_i));
+ i->False()->Append(b.ExitIf(i, 20_i));
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func, i));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
%3 = OpTypeFunction %2
%9 = OpTypeBool
%8 = OpConstantTrue %9
-%10 = OpTypeInt 32 1
-%12 = OpConstant %10 10
-%13 = OpConstant %10 20
+%11 = OpConstant %2 10
+%12 = OpConstant %2 20
%1 = OpFunction %2 None %3
%4 = OpLabel
OpSelectionMerge %5 None
@@ -181,36 +180,33 @@
%7 = OpLabel
OpBranch %5
%5 = OpLabel
-%11 = OpPhi %10 %12 %6 %13 %7
-OpReturnValue %11
+%10 = OpPhi %2 %11 %6 %12 %7
+OpReturnValue %10
OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_SingleValue_TrueReturn) {
- auto* func = b.Function("foo", ty.void_());
-
- auto* merge_param = b.BlockParam(b.ir.Types().i32());
+ auto* func = b.Function("foo", ty.i32());
auto* i = b.If(true);
- i->True()->SetInstructions({b.Return(func, 42_i)});
- i->False()->SetInstructions({b.ExitIf(i, 20_i)});
- i->Merge()->SetParams({merge_param});
- i->Merge()->SetInstructions({b.Return(func, merge_param)});
+ i->SetResults(b.InstructionResult(ty.i32()));
+ i->True()->Append(b.Return(func, 42_i));
+ i->False()->Append(b.ExitIf(i, 20_i));
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func, i));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
%3 = OpTypeFunction %2
%9 = OpTypeBool
%8 = OpConstantTrue %9
-%11 = OpTypeInt 32 1
-%10 = OpConstant %11 42
-%13 = OpConstant %11 20
+%10 = OpConstant %2 42
+%12 = OpConstant %2 20
%1 = OpFunction %2 None %3
%4 = OpLabel
OpSelectionMerge %5 None
@@ -220,36 +216,33 @@
%7 = OpLabel
OpBranch %5
%5 = OpLabel
-%12 = OpPhi %11 %13 %7
-OpReturnValue %12
+%11 = OpPhi %2 %12 %7
+OpReturnValue %11
OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_SingleValue_FalseReturn) {
- auto* func = b.Function("foo", ty.void_());
-
- auto* merge_param = b.BlockParam(b.ir.Types().i32());
+ auto* func = b.Function("foo", ty.i32());
auto* i = b.If(true);
- i->True()->SetInstructions({b.ExitIf(i, 10_i)});
- i->False()->SetInstructions({b.Return(func, 42_i)});
- i->Merge()->SetParams({merge_param});
- i->Merge()->SetInstructions({b.Return(func, merge_param)});
+ i->SetResults(b.InstructionResult(ty.i32()));
+ i->True()->Append(b.ExitIf(i, 10_i));
+ i->False()->Append(b.Return(func, 42_i));
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func, i));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
%3 = OpTypeFunction %2
%9 = OpTypeBool
%8 = OpConstantTrue %9
-%11 = OpTypeInt 32 1
-%10 = OpConstant %11 42
-%13 = OpConstant %11 10
+%10 = OpConstant %2 42
+%12 = OpConstant %2 10
%1 = OpFunction %2 None %3
%4 = OpLabel
OpSelectionMerge %5 None
@@ -259,38 +252,34 @@
%7 = OpLabel
OpReturnValue %10
%5 = OpLabel
-%12 = OpPhi %11 %13 %6
-OpReturnValue %12
+%11 = OpPhi %2 %12 %6
+OpReturnValue %11
OpFunctionEnd
)");
}
-TEST_F(SpvGeneratorImplTest, If_Phi_MultipleValue) {
- auto* func = b.Function("foo", ty.void_());
-
- auto* merge_param_0 = b.BlockParam(b.ir.Types().i32());
- auto* merge_param_1 = b.BlockParam(b.ir.Types().bool_());
+TEST_F(SpvGeneratorImplTest, If_Phi_MultipleValue_0) {
+ auto* func = b.Function("foo", ty.i32());
auto* i = b.If(true);
- i->True()->SetInstructions({b.ExitIf(i, 10_i, true)});
- i->False()->SetInstructions({b.ExitIf(i, 20_i, false)});
- i->Merge()->SetParams({merge_param_0, merge_param_1});
- i->Merge()->SetInstructions({b.Return(func, merge_param_0)});
+ i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ i->True()->Append(b.ExitIf(i, 10_i, true));
+ i->False()->Append(b.ExitIf(i, 20_i, false));
- func->StartTarget()->SetInstructions({i});
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func, i->Result(0)));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
%3 = OpTypeFunction %2
%9 = OpTypeBool
%8 = OpConstantTrue %9
-%10 = OpTypeInt 32 1
-%12 = OpConstant %10 10
-%13 = OpConstant %10 20
-%15 = OpConstantFalse %9
+%11 = OpConstant %2 10
+%12 = OpConstant %2 20
+%14 = OpConstantFalse %9
%1 = OpFunction %2 None %3
%4 = OpLabel
OpSelectionMerge %5 None
@@ -300,9 +289,45 @@
%7 = OpLabel
OpBranch %5
%5 = OpLabel
-%11 = OpPhi %10 %12 %6 %13 %7
-%14 = OpPhi %9 %8 %6 %15 %7
-OpReturnValue %11
+%10 = OpPhi %2 %11 %6 %12 %7
+%13 = OpPhi %9 %8 %6 %14 %7
+OpReturnValue %10
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, If_Phi_MultipleValue_1) {
+ auto* func = b.Function("foo", ty.bool_());
+
+ auto* i = b.If(true);
+ i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ i->True()->Append(b.ExitIf(i, 10_i, true));
+ i->False()->Append(b.ExitIf(i, 20_i, false));
+
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func, i->Result(1)));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeBool
+%3 = OpTypeFunction %2
+%8 = OpConstantTrue %2
+%9 = OpTypeInt 32 1
+%11 = OpConstant %9 10
+%12 = OpConstant %9 20
+%14 = OpConstantFalse %2
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+OpSelectionMerge %5 None
+OpBranchConditional %8 %6 %7
+%6 = OpLabel
+OpBranch %5
+%7 = OpLabel
+OpBranch %5
+%5 = OpLabel
+%10 = OpPhi %9 %11 %6 %12 %7
+%13 = OpPhi %2 %8 %6 %14 %7
+OpReturnValue %13
OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
index c1e3f00..88a25e1 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
@@ -26,9 +26,9 @@
loop->Body()->Append(b.Continue(loop));
loop->Continuing()->Append(b.BreakIf(true, loop));
- loop->Merge()->Append(b.Return(func));
func->StartTarget()->Append(loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -61,9 +61,9 @@
auto* loop = b.Loop();
loop->Body()->Append(b.ExitLoop(loop));
- loop->Merge()->Append(b.Return(func));
func->StartTarget()->Append(loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -95,13 +95,13 @@
auto* cond_break = b.If(true);
cond_break->True()->Append(b.ExitLoop(loop));
cond_break->False()->Append(b.ExitIf(cond_break));
- cond_break->Merge()->Append(b.Continue(loop));
loop->Body()->Append(cond_break);
+ loop->Body()->Append(b.Continue(loop));
loop->Continuing()->Append(b.NextIteration(loop));
- loop->Merge()->Append(b.Return(func));
func->StartTarget()->Append(loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -140,13 +140,13 @@
auto* cond_break = b.If(true);
cond_break->True()->Append(b.Continue(loop));
cond_break->False()->Append(b.ExitIf(cond_break));
- cond_break->Merge()->Append(b.ExitLoop(loop));
loop->Body()->Append(cond_break);
+ loop->Body()->Append(b.ExitLoop(loop));
loop->Continuing()->Append(b.NextIteration(loop));
- loop->Merge()->Append(b.Return(func));
func->StartTarget()->Append(loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -183,10 +183,10 @@
auto* func = b.Function("foo", ty.void_());
auto* loop = b.Loop();
-
loop->Body()->Append(b.Return(func));
func->StartTarget()->Append(loop);
+ func->StartTarget()->Append(b.Unreachable());
ASSERT_TRUE(IRIsValid()) << Error();
@@ -215,13 +215,13 @@
auto* loop = b.Loop();
- auto* result = b.Equal(ty.i32(), 1_i, 2_i);
+ auto* result = loop->Body()->Append(b.Equal(ty.i32(), 1_i, 2_i));
+ loop->Body()->Append(b.Continue(loop, result));
- loop->Body()->Append(result);
loop->Continuing()->Append(b.BreakIf(result, loop));
- loop->Merge()->Append(b.Return(func));
func->StartTarget()->Append(loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -240,6 +240,7 @@
OpBranch %6
%6 = OpLabel
%9 = OpIEqual %10 %11 %12
+OpBranch %7
%7 = OpLabel
OpBranchConditional %9 %8 %5
%8 = OpLabel
@@ -256,13 +257,13 @@
inner_loop->Body()->Append(b.ExitLoop(inner_loop));
inner_loop->Continuing()->Append(b.NextIteration(inner_loop));
- inner_loop->Merge()->Append(b.Continue(outer_loop));
outer_loop->Body()->Append(inner_loop);
+ outer_loop->Body()->Append(b.Continue(outer_loop));
outer_loop->Continuing()->Append(b.BreakIf(true, outer_loop));
- outer_loop->Merge()->Append(b.Return(func));
func->StartTarget()->Append(outer_loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -305,13 +306,13 @@
inner_loop->Body()->Append(b.Continue(inner_loop));
inner_loop->Continuing()->Append(b.BreakIf(true, inner_loop));
- inner_loop->Merge()->Append(b.BreakIf(true, outer_loop));
outer_loop->Body()->Append(b.Continue(outer_loop));
outer_loop->Continuing()->Append(inner_loop);
- outer_loop->Merge()->Append(b.Return(func));
+ outer_loop->Continuing()->Append(b.BreakIf(true, outer_loop));
func->StartTarget()->Append(outer_loop);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -349,22 +350,31 @@
TEST_F(SpvGeneratorImplTest, Loop_Phi_SingleValue) {
auto* func = b.Function("foo", ty.void_());
- auto* l = b.Loop();
- func->StartTarget()->Append(l);
+ auto fb = b.With(func->StartTarget());
+ auto* l = fb.Loop();
- l->Initializer()->Append(b.NextIteration(l, 1_i));
+ {
+ auto ib = b.With(l->Initializer());
+ ib.NextIteration(l, 1_i, false);
+ }
- auto* loop_param = b.BlockParam(b.ir.Types().i32());
+ auto* loop_param = b.BlockParam(ty.i32());
l->Body()->SetParams({loop_param});
- auto* inc = b.Add(b.ir.Types().i32(), loop_param, 1_i);
- l->Body()->Append(inc);
- l->Body()->Append(b.Continue(l, inc));
+ {
+ auto lb = b.With(l->Body());
+ auto* inc = lb.Add(ty.i32(), loop_param, 1_i);
+ lb.Continue(l, inc);
+ }
- auto* cont_param = b.BlockParam(b.ir.Types().i32());
+ auto* cont_param = b.BlockParam(ty.i32());
l->Continuing()->SetParams({cont_param});
- auto* cmp = b.GreaterThan(b.ir.Types().bool_(), cont_param, 5_i);
- l->Continuing()->Append(cmp);
- l->Continuing()->Append(b.BreakIf(cmp, l, cont_param));
+ {
+ auto cb = b.With(l->Continuing());
+ auto* cmp = cb.GreaterThan(ty.bool_(), cont_param, 5_i);
+ cb.BreakIf(cmp, l, cont_param);
+ }
+
+ fb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -393,7 +403,7 @@
%15 = OpSGreaterThan %16 %13 %17
OpBranchConditional %15 %9 %6
%9 = OpLabel
-OpUnreachable
+OpReturn
OpFunctionEnd
)");
}
@@ -401,26 +411,34 @@
TEST_F(SpvGeneratorImplTest, Loop_Phi_MultipleValue) {
auto* func = b.Function("foo", ty.void_());
- auto* l = b.Loop();
- func->StartTarget()->Append(l);
+ auto fb = b.With(func->StartTarget());
+ auto* l = fb.Loop();
- l->Initializer()->Append(b.NextIteration(l, 1_i, false));
+ {
+ auto ib = b.With(l->Initializer());
+ ib.NextIteration(l, 1_i, false);
+ }
- auto* loop_param_a = b.BlockParam(b.ir.Types().i32());
- auto* loop_param_b = b.BlockParam(b.ir.Types().bool_());
+ auto* loop_param_a = b.BlockParam(ty.i32());
+ auto* loop_param_b = b.BlockParam(ty.bool_());
l->Body()->SetParams({loop_param_a, loop_param_b});
- auto* inc = b.Add(b.ir.Types().i32(), loop_param_a, 1_i);
- l->Body()->Append(inc);
- l->Body()->Append(b.Continue(l, inc, loop_param_b));
+ {
+ auto lb = b.With(l->Body());
+ auto* inc = lb.Add(ty.i32(), loop_param_a, 1_i);
+ lb.Continue(l, inc, loop_param_b);
+ }
- auto* cont_param_a = b.BlockParam(b.ir.Types().i32());
- auto* cont_param_b = b.BlockParam(b.ir.Types().bool_());
+ auto* cont_param_a = b.BlockParam(ty.i32());
+ auto* cont_param_b = b.BlockParam(ty.bool_());
l->Continuing()->SetParams({cont_param_a, cont_param_b});
- auto* cmp = b.GreaterThan(b.ir.Types().bool_(), cont_param_a, 5_i);
- l->Continuing()->Append(cmp);
- auto* not_b = b.Not(b.ir.Types().bool_(), cont_param_b);
- l->Continuing()->Append(not_b);
- l->Continuing()->Append(b.BreakIf(cmp, l, cont_param_a, not_b));
+ {
+ auto cb = b.With(l->Continuing());
+ auto* cmp = cb.GreaterThan(ty.bool_(), cont_param_a, 5_i);
+ auto* not_b = cb.Not(ty.bool_(), cont_param_b);
+ cb.BreakIf(cmp, l, cont_param_a, not_b);
+ }
+
+ fb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -453,7 +471,7 @@
%17 = OpLogicalEqual %14 %19 %16
OpBranchConditional %20 %9 %6
%9 = OpLabel
-OpUnreachable
+OpReturn
OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
index 215aad8..c0f32cf 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
@@ -27,9 +27,8 @@
auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
def_case->Append(b.ExitSwitch(swtch));
- swtch->Merge()->Append(b.Return(func));
-
func->StartTarget()->Append(swtch);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -65,9 +64,8 @@
auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
def_case->Append(b.ExitSwitch(swtch));
- swtch->Merge()->Append(b.Return(func));
-
func->StartTarget()->Append(swtch);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -110,9 +108,8 @@
ir::Switch::CaseSelector()});
def_case->Append(b.ExitSwitch(swtch));
- swtch->Merge()->Append(b.Return(func));
-
func->StartTarget()->Append(swtch);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -153,6 +150,7 @@
def_case->Append(b.Return(func));
func->StartTarget()->Append(swtch);
+ func->StartTarget()->Append(b.Unreachable());
ASSERT_TRUE(IRIsValid()) << Error();
@@ -186,17 +184,16 @@
auto* cond_break = b.If(true);
cond_break->True()->Append(b.ExitSwitch(swtch));
cond_break->False()->Append(b.ExitIf(cond_break));
- cond_break->Merge()->Append(b.Return(func));
auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
case_a->Append(cond_break);
+ case_a->Append(b.Return(func));
auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
def_case->Append(b.ExitSwitch(swtch));
- swtch->Merge()->Append(b.Return(func));
-
func->StartTarget()->Append(swtch);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -228,11 +225,10 @@
}
TEST_F(SpvGeneratorImplTest, Switch_Phi_SingleValue) {
- auto* func = b.Function("foo", ty.void_());
-
- auto* merge_param = b.BlockParam(b.ir.Types().i32());
+ auto* func = b.Function("foo", ty.i32());
auto* s = b.Switch(42_i);
+ s->SetResults(b.InstructionResult(ty.i32()));
auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
ir::Switch::CaseSelector{nullptr}});
case_a->Append(b.ExitSwitch(s, 10_i));
@@ -240,40 +236,38 @@
auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
case_b->Append(b.ExitSwitch(s, 20_i));
- s->Merge()->SetParams({merge_param});
- s->Merge()->Append(b.Return(func));
-
- func->StartTarget()->SetInstructions({s});
+ func->StartTarget()->Append(s);
+ func->StartTarget()->Append(b.Return(func, s));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%11 = OpConstant %7 10
-%12 = OpConstant %7 20
+%6 = OpConstant %2 42
+%10 = OpConstant %2 10
+%11 = OpConstant %2 20
%1 = OpFunction %2 None %3
%4 = OpLabel
-OpSelectionMerge %9 None
-OpSwitch %6 %5 1 %5 2 %8
+OpSelectionMerge %8 None
+OpSwitch %6 %5 1 %5 2 %7
%5 = OpLabel
-OpBranch %9
+OpBranch %8
+%7 = OpLabel
+OpBranch %8
%8 = OpLabel
-OpBranch %9
-%9 = OpLabel
-%10 = OpPhi %7 %11 %5 %12 %8
-OpReturn
+%9 = OpPhi %2 %10 %5 %11 %7
+OpReturnValue %9
OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_Phi_SingleValue_CaseReturn) {
- auto* func = b.Function("foo", ty.void_());
+ auto* func = b.Function("foo", ty.i32());
auto* s = b.Switch(42_i);
+ s->SetResults(b.InstructionResult(ty.i32()));
auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
ir::Switch::CaseSelector{nullptr}});
case_a->Append(b.Return(func, 10_i));
@@ -281,43 +275,38 @@
auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
case_b->Append(b.ExitSwitch(s, 20_i));
- s->Merge()->SetParams({b.BlockParam(b.ir.Types().i32())});
- s->Merge()->Append(b.Return(func));
-
- func->StartTarget()->SetInstructions({s});
+ func->StartTarget()->Append(s);
+ func->StartTarget()->Append(b.Return(func, s));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%10 = OpConstant %7 10
-%12 = OpConstant %7 20
+%6 = OpConstant %2 42
+%9 = OpConstant %2 10
+%11 = OpConstant %2 20
%1 = OpFunction %2 None %3
%4 = OpLabel
-OpSelectionMerge %9 None
-OpSwitch %6 %5 1 %5 2 %8
+OpSelectionMerge %8 None
+OpSwitch %6 %5 1 %5 2 %7
%5 = OpLabel
-OpReturnValue %10
+OpReturnValue %9
+%7 = OpLabel
+OpBranch %8
%8 = OpLabel
-OpBranch %9
-%9 = OpLabel
-%11 = OpPhi %7 %12 %8
-OpReturn
+%10 = OpPhi %2 %11 %7
+OpReturnValue %10
OpFunctionEnd
)");
}
-TEST_F(SpvGeneratorImplTest, Switch_Phi_MultipleValue) {
- auto* func = b.Function("foo", ty.void_());
-
- auto* merge_param_0 = b.BlockParam(b.ir.Types().i32());
- auto* merge_param_1 = b.BlockParam(b.ir.Types().bool_());
+TEST_F(SpvGeneratorImplTest, Switch_Phi_MultipleValue_0) {
+ auto* func = b.Function("foo", ty.i32());
auto* s = b.Switch(42_i);
+ s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
ir::Switch::CaseSelector{nullptr}});
case_a->Append(b.ExitSwitch(s, 10_i, true));
@@ -325,24 +314,62 @@
auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
case_b->Append(b.ExitSwitch(s, 20_i, false));
- s->Merge()->SetParams({merge_param_0, merge_param_1});
- s->Merge()->Append(b.Return(func, merge_param_0));
-
- func->StartTarget()->SetInstructions({s});
+ func->StartTarget()->Append(s);
+ func->StartTarget()->Append(b.Return(func, s->Result(0)));
ASSERT_TRUE(IRIsValid()) << Error();
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypeFunction %2
+%6 = OpConstant %2 42
+%10 = OpConstant %2 10
+%11 = OpConstant %2 20
+%12 = OpTypeBool
+%14 = OpConstantTrue %12
+%15 = OpConstantFalse %12
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+OpSelectionMerge %8 None
+OpSwitch %6 %5 1 %5 2 %7
+%5 = OpLabel
+OpBranch %8
+%7 = OpLabel
+OpBranch %8
+%8 = OpLabel
+%9 = OpPhi %2 %10 %5 %11 %7
+%13 = OpPhi %12 %14 %5 %15 %7
+OpReturnValue %9
+OpFunctionEnd
+)");
+}
+
+TEST_F(SpvGeneratorImplTest, Switch_Phi_MultipleValue_1) {
+ auto* func = b.Function("foo", ty.bool_());
+
+ auto* s = b.Switch(b.Constant(42_i));
+ s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
+ ir::Switch::CaseSelector{nullptr}});
+ case_a->Append(b.ExitSwitch(s, 10_i, true));
+
+ auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ case_b->Append(b.ExitSwitch(s, 20_i, false));
+
+ func->StartTarget()->Append(s);
+ func->StartTarget()->Append(b.Return(func, s->Result(1)));
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeBool
%3 = OpTypeFunction %2
%7 = OpTypeInt 32 1
%6 = OpConstant %7 42
%11 = OpConstant %7 10
%12 = OpConstant %7 20
-%13 = OpTypeBool
-%15 = OpConstantTrue %13
-%16 = OpConstantFalse %13
+%14 = OpConstantTrue %2
+%15 = OpConstantFalse %2
%1 = OpFunction %2 None %3
%4 = OpLabel
OpSelectionMerge %9 None
@@ -353,8 +380,8 @@
OpBranch %9
%9 = OpLabel
%10 = OpPhi %7 %11 %5 %12 %8
-%14 = OpPhi %13 %15 %5 %16 %8
-OpReturnValue %10
+%13 = OpPhi %2 %14 %5 %15 %8
+OpReturnValue %13
OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_test.cc
index ffafa60..ef33bfb 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_test.cc
@@ -19,6 +19,8 @@
namespace tint::writer::spirv {
namespace {
+using namespace tint::number_suffixes; // NOLINT
+
TEST_F(SpvGeneratorImplTest, ModuleHeader) {
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
auto got = Disassemble(generator_.Result());
@@ -27,5 +29,39 @@
)"));
}
+TEST_F(SpvGeneratorImplTest, Unreachable) {
+ auto* func = b.Function("foo", ty.i32());
+
+ auto* i = b.If(true);
+ i->True()->Append(b.Return(func, 10_i));
+ i->False()->Append(b.Return(func, 20_i));
+
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Unreachable());
+
+ ASSERT_TRUE(IRIsValid()) << Error();
+
+ generator_.EmitFunction(func);
+ EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
+%2 = OpTypeInt 32 1
+%3 = OpTypeFunction %2
+%9 = OpTypeBool
+%8 = OpConstantTrue %9
+%10 = OpConstant %2 10
+%11 = OpConstant %2 20
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+OpSelectionMerge %5 None
+OpBranchConditional %8 %6 %7
+%6 = OpLabel
+OpReturnValue %10
+%7 = OpLabel
+OpReturnValue %11
+%5 = OpLabel
+OpUnreachable
+OpFunctionEnd
+)");
+}
+
} // namespace
} // namespace tint::writer::spirv
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc
index 5deefe0..7cd64e4 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc
@@ -58,6 +58,11 @@
auto id = generator_.Type(ty.f16());
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), "%1 = OpTypeFloat 16\n");
+ EXPECT_EQ(DumpInstructions(generator_.Module().Capabilities()),
+ "OpCapability Float16\n"
+ "OpCapability UniformAndStorageBuffer16BitAccess\n"
+ "OpCapability StorageBuffer16BitAccess\n"
+ "OpCapability StorageInputOutput16\n");
}
TEST_F(SpvGeneratorImplTest, Type_Vec2i) {
@@ -181,15 +186,11 @@
}
TEST_F(SpvGeneratorImplTest, Type_Struct) {
- auto* str = ty.Get<type::Struct>(
- mod.symbols.Register("MyStruct"),
- utils::Vector{
- ty.Get<type::StructMember>(mod.symbols.Register("a"), ty.f32(), 0u, 0u, 4u, 4u,
- type::StructMemberAttributes{}),
- ty.Get<type::StructMember>(mod.symbols.Register("b"), ty.vec4(ty.i32()), 1u, 16u, 16u,
- 16u, type::StructMemberAttributes{}),
- },
- 16u, 32u, 32u);
+ auto* str =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.Register("a"), ty.f32()},
+ {mod.symbols.Register("b"), ty.vec4<i32>()},
+ });
auto id = generator_.Type(str);
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeFloat 32
@@ -207,17 +208,13 @@
}
TEST_F(SpvGeneratorImplTest, Type_Struct_MatrixLayout) {
- auto* str = ty.Get<type::Struct>(
- mod.symbols.Register("MyStruct"),
- utils::Vector{
- ty.Get<type::StructMember>(mod.symbols.Register("m"), ty.mat3x3(ty.f32()), 0u, 0u, 16u,
- 48u, type::StructMemberAttributes{}),
+ auto* str = ty.Struct(
+ mod.symbols.New("MyStruct"),
+ {
+ {mod.symbols.Register("m"), ty.mat3x3<f32>()},
// Matrices nested inside arrays need layout decorations on the struct member too.
- ty.Get<type::StructMember>(mod.symbols.Register("arr"),
- ty.array(ty.array(ty.mat2x4(ty.f16()), 4), 4), 1u, 64u, 8u,
- 64u, type::StructMemberAttributes{}),
- },
- 16u, 128u, 128u);
+ {mod.symbols.Register("arr"), ty.array(ty.array(ty.mat2x4<f16>(), 4), 4)},
+ });
auto id = generator_.Type(str);
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpTypes(), R"(%4 = OpTypeFloat 32
@@ -237,7 +234,7 @@
OpMemberDecorate %1 0 MatrixStride 16
OpDecorate %6 ArrayStride 16
OpDecorate %5 ArrayStride 64
-OpMemberDecorate %1 1 Offset 64
+OpMemberDecorate %1 1 Offset 48
OpMemberDecorate %1 1 ColMajor
OpMemberDecorate %1 1 MatrixStride 8
)");
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc
index 5f161be..feb7c63 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc
@@ -15,17 +15,18 @@
#include "src/tint/type/pointer.h"
#include "src/tint/writer/spirv/ir/test_helper_ir.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
TEST_F(SpvGeneratorImplTest, FunctionVar_NoInit) {
auto* func = b.Function("foo", ty.void_());
- func->StartTarget()->SetInstructions(
- {b.Var(ty.ptr(builtin::AddressSpace::kFunction, ty.i32(), builtin::Access::kReadWrite)),
- b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Var(ty.ptr<function, i32>());
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -46,11 +47,11 @@
TEST_F(SpvGeneratorImplTest, FunctionVar_WithInit) {
auto* func = b.Function("foo", ty.void_());
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, ty.i32(), builtin::Access::kReadWrite));
+ auto sb = b.With(func->StartTarget());
+ auto* v = sb.Var(ty.ptr<function, i32>());
v->SetInitializer(b.Constant(42_i));
- func->StartTarget()->SetInstructions({v, b.Return(func)});
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -73,9 +74,10 @@
TEST_F(SpvGeneratorImplTest, FunctionVar_Name) {
auto* func = b.Function("foo", ty.void_());
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, ty.i32(), builtin::Access::kReadWrite));
- func->StartTarget()->SetInstructions({v, b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ auto* v = sb.Var(ty.ptr<function, i32>());
+ sb.Return(func);
+
mod.SetName(v, "myvar");
ASSERT_TRUE(IRIsValid()) << Error();
@@ -98,16 +100,17 @@
TEST_F(SpvGeneratorImplTest, FunctionVar_DeclInsideBlock) {
auto* func = b.Function("foo", ty.void_());
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, ty.i32(), builtin::Access::kReadWrite));
- v->SetInitializer(b.Constant(42_i));
-
auto* i = b.If(true);
- i->True()->SetInstructions({v, b.ExitIf(i)});
- i->False()->SetInstructions({b.Return(func)});
- i->Merge()->SetInstructions({b.Return(func)});
- func->StartTarget()->SetInstructions({i});
+ auto tb = b.With(i->True());
+ auto* v = tb.Var(ty.ptr<function, i32>());
+ v->SetInitializer(b.Constant(42_i));
+ tb.ExitIf(i);
+
+ i->False()->Append(b.Return(func));
+
+ func->StartTarget()->Append(i);
+ func->StartTarget()->Append(b.Return(func));
ASSERT_TRUE(IRIsValid()) << Error();
@@ -139,10 +142,12 @@
TEST_F(SpvGeneratorImplTest, FunctionVar_Load) {
auto* func = b.Function("foo", ty.void_());
+ auto sb = b.With(func->StartTarget());
+
auto* store_ty = ty.i32();
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, store_ty, builtin::Access::kReadWrite));
- func->StartTarget()->SetInstructions({v, b.Load(v), b.Return(func)});
+ auto* v = sb.Var(ty.ptr(function, store_ty));
+ sb.Load(v);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -164,9 +169,10 @@
TEST_F(SpvGeneratorImplTest, FunctionVar_Store) {
auto* func = b.Function("foo", ty.void_());
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kFunction, ty.i32(), builtin::Access::kReadWrite));
- func->StartTarget()->SetInstructions({v, b.Store(v, 42_i), b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ auto* v = sb.Var(ty.ptr<function, i32>());
+ sb.Store(v, 42_i);
+ sb.Return(func);
ASSERT_TRUE(IRIsValid()) << Error();
@@ -187,8 +193,7 @@
}
TEST_F(SpvGeneratorImplTest, PrivateVar_NoInit) {
- b.RootBlock()->SetInstructions(
- {b.Var(ty.ptr(builtin::AddressSpace::kPrivate, ty.i32(), builtin::Access::kReadWrite))});
+ b.RootBlock()->Append(b.Var(ty.ptr<private_, i32>()));
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -209,9 +214,9 @@
}
TEST_F(SpvGeneratorImplTest, PrivateVar_WithInit) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kPrivate, ty.i32(), builtin::Access::kReadWrite));
- b.RootBlock()->SetInstructions({v});
+ auto* v = b.Var(ty.ptr<private_, i32>());
v->SetInitializer(b.Constant(42_i));
+ b.RootBlock()->Append(v);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -233,9 +238,10 @@
}
TEST_F(SpvGeneratorImplTest, PrivateVar_Name) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kPrivate, ty.i32(), builtin::Access::kReadWrite));
- b.RootBlock()->SetInstructions({v});
+ auto* v = b.Var(ty.ptr<private_, i32>());
v->SetInitializer(b.Constant(42_i));
+ b.RootBlock()->Append(v);
+
mod.SetName(v, "myvar");
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
@@ -263,14 +269,15 @@
mod.functions.Push(func);
auto* store_ty = ty.i32();
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kPrivate, store_ty, builtin::Access::kReadWrite));
- b.RootBlock()->SetInstructions({v});
+ auto* v = b.Var(ty.ptr(private_, store_ty));
v->SetInitializer(b.Constant(42_i));
+ b.RootBlock()->Append(v);
- auto* load = b.Load(v);
- auto* add = b.Add(store_ty, v, 1_i);
- auto* store = b.Store(v, add);
- func->StartTarget()->SetInstructions({load, add, store, b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Load(v);
+ auto* add = sb.Add(store_ty, v, 1_i);
+ sb.Store(v, add);
+ sb.Return(func);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -296,8 +303,7 @@
}
TEST_F(SpvGeneratorImplTest, WorkgroupVar) {
- b.RootBlock()->SetInstructions(
- {b.Var(ty.ptr(builtin::AddressSpace::kWorkgroup, ty.i32(), builtin::Access::kReadWrite))});
+ b.RootBlock()->Append(b.Var(ty.ptr<workgroup, i32>()));
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -318,9 +324,7 @@
}
TEST_F(SpvGeneratorImplTest, WorkgroupVar_Name) {
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kWorkgroup, ty.i32(), builtin::Access::kReadWrite));
- b.RootBlock()->SetInstructions({v});
+ auto* v = b.RootBlock()->Append(b.Var(ty.ptr<workgroup, i32>()));
mod.SetName(v, "myvar");
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
@@ -348,14 +352,13 @@
mod.functions.Push(func);
auto* store_ty = ty.i32();
- auto* v =
- b.Var(ty.ptr(builtin::AddressSpace::kWorkgroup, store_ty, builtin::Access::kReadWrite));
- b.RootBlock()->SetInstructions({v});
+ auto* v = b.RootBlock()->Append(b.Var(ty.ptr(workgroup, store_ty)));
- auto* load = b.Load(v);
- auto* add = b.Add(store_ty, v, 1_i);
- auto* store = b.Store(v, add);
- func->StartTarget()->SetInstructions({load, add, store, b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Load(v);
+ auto* add = sb.Add(store_ty, v, 1_i);
+ sb.Store(v, add);
+ sb.Return(func);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -380,8 +383,7 @@
}
TEST_F(SpvGeneratorImplTest, WorkgroupVar_ZeroInitializeWithExtension) {
- b.RootBlock()->SetInstructions(
- {b.Var(ty.ptr(builtin::AddressSpace::kWorkgroup, ty.i32(), builtin::Access::kReadWrite))});
+ b.RootBlock()->Append(b.Var(ty.ptr<workgroup, i32>()));
// Create a generator with the zero_init_workgroup_memory flag set to `true`.
spirv::GeneratorImplIr gen(&mod, true);
@@ -405,9 +407,9 @@
}
TEST_F(SpvGeneratorImplTest, StorageVar) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kStorage, ty.i32(), builtin::Access::kReadWrite));
+ auto* v = b.Var(ty.ptr<storage, i32>());
v->SetBindingPoint(0, 0);
- b.RootBlock()->SetInstructions({v});
+ b.RootBlock()->Append(v);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -435,9 +437,9 @@
}
TEST_F(SpvGeneratorImplTest, StorageVar_Name) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kStorage, ty.i32(), builtin::Access::kReadWrite));
+ auto* v = b.Var(ty.ptr<storage, i32>());
v->SetBindingPoint(0, 0);
- b.RootBlock()->SetInstructions({v});
+ b.RootBlock()->Append(v);
mod.SetName(v, "myvar");
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
@@ -466,18 +468,19 @@
}
TEST_F(SpvGeneratorImplTest, StorageVar_LoadAndStore) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kStorage, ty.i32(), builtin::Access::kReadWrite));
+ auto* v = b.Var(ty.ptr<storage, i32>());
v->SetBindingPoint(0, 0);
- b.RootBlock()->SetInstructions({v});
+ b.RootBlock()->Append(v);
auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
std::array{1u, 1u, 1u});
mod.functions.Push(func);
- auto* load = b.Load(v);
- auto* add = b.Add(ty.i32(), v, 1_i);
- auto* store = b.Store(v, add);
- func->StartTarget()->SetInstructions({load, add, store, b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Load(v);
+ auto* add = sb.Add(ty.i32(), v, 1_i);
+ sb.Store(v, add);
+ sb.Return(func);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -515,9 +518,9 @@
}
TEST_F(SpvGeneratorImplTest, UniformVar) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kUniform, ty.i32(), builtin::Access::kReadWrite));
+ auto* v = b.Var(ty.ptr<uniform, i32>());
v->SetBindingPoint(0, 0);
- b.RootBlock()->SetInstructions({v});
+ b.RootBlock()->Append(v);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
@@ -545,9 +548,9 @@
}
TEST_F(SpvGeneratorImplTest, UniformVar_Name) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kUniform, ty.i32(), builtin::Access::kReadWrite));
+ auto* v = b.Var(ty.ptr<uniform, i32>());
v->SetBindingPoint(0, 0);
- b.RootBlock()->SetInstructions({v});
+ b.RootBlock()->Append(v);
mod.SetName(v, "myvar");
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
@@ -576,16 +579,17 @@
}
TEST_F(SpvGeneratorImplTest, UniformVar_Load) {
- auto* v = b.Var(ty.ptr(builtin::AddressSpace::kUniform, ty.i32(), builtin::Access::kReadWrite));
+ auto* v = b.Var(ty.ptr<uniform, i32>());
v->SetBindingPoint(0, 0);
- b.RootBlock()->SetInstructions({v});
+ b.RootBlock()->Append(v);
auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
std::array{1u, 1u, 1u});
mod.functions.Push(func);
- auto* load = b.Load(v);
- func->StartTarget()->SetInstructions({load, b.Return(func)});
+ auto sb = b.With(func->StartTarget());
+ sb.Load(v);
+ sb.Return(func);
ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
diff --git a/src/tint/writer/spirv/scalar_constant.h b/src/tint/writer/spirv/scalar_constant.h
index dd4dfd0..7d79dab 100644
--- a/src/tint/writer/spirv/scalar_constant.h
+++ b/src/tint/writer/spirv/scalar_constant.h
@@ -20,7 +20,7 @@
#include <cstring>
#include <functional>
-#include "src/tint/number.h"
+#include "src/tint/builtin/number.h"
#include "src/tint/utils/hash.h"
// Forward declarations
diff --git a/src/tint/writer/wgsl/generator_impl_cast_test.cc b/src/tint/writer/wgsl/generator_impl_cast_test.cc
index 890c52c..16c20e0 100644
--- a/src/tint/writer/wgsl/generator_impl_cast_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_cast_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::wgsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, EmitExpression_Cast_Scalar_F32_From_I32) {
@@ -51,7 +52,7 @@
}
TEST_F(WgslGeneratorImplTest, EmitExpression_Cast_Vector_F32_From_I32) {
- auto* cast = vec3<f32>(vec3<i32>(1_i, 2_i, 3_i));
+ auto* cast = Call<vec3<f32>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
WrapInFunction(cast);
GeneratorImpl& gen = Build();
@@ -65,7 +66,7 @@
TEST_F(WgslGeneratorImplTest, EmitExpression_Cast_Vector_F16_From_I32) {
Enable(builtin::Extension::kF16);
- auto* cast = vec3<f16>(vec3<i32>(1_i, 2_i, 3_i));
+ auto* cast = Call<vec3<f16>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
WrapInFunction(cast);
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/wgsl/generator_impl_constructor_test.cc b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
index fa40ff6..e360be2 100644
--- a/src/tint/writer/wgsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
@@ -18,11 +18,12 @@
using ::testing::HasSubstr;
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::wgsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using WgslGeneratorImplTest_Constructor = TestHelper;
TEST_F(WgslGeneratorImplTest_Constructor, Bool) {
@@ -129,7 +130,7 @@
}
TEST_F(WgslGeneratorImplTest_Constructor, Type_Vec_F32) {
- WrapInFunction(vec3<f32>(1_f, 2_f, 3_f));
+ WrapInFunction(Call<vec3<f32>>(1_f, 2_f, 3_f));
GeneratorImpl& gen = Build();
@@ -141,7 +142,7 @@
TEST_F(WgslGeneratorImplTest_Constructor, Type_Vec_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(vec3<f16>(1_h, 2_h, 3_h));
+ WrapInFunction(Call<vec3<f16>>(1_h, 2_h, 3_h));
GeneratorImpl& gen = Build();
@@ -151,7 +152,8 @@
}
TEST_F(WgslGeneratorImplTest_Constructor, Type_Mat_F32) {
- WrapInFunction(mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(3_f, 4_f, 5_f)));
+ WrapInFunction(
+ Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(3_f, 4_f, 5_f)));
GeneratorImpl& gen = Build();
@@ -164,7 +166,8 @@
TEST_F(WgslGeneratorImplTest_Constructor, Type_Mat_F16) {
Enable(builtin::Extension::kF16);
- WrapInFunction(mat2x3<f16>(vec3<f16>(1_h, 2_h, 3_h), vec3<f16>(3_h, 4_h, 5_h)));
+ WrapInFunction(
+ Call<mat2x3<f16>>(Call<vec3<f16>>(1_h, 2_h, 3_h), Call<vec3<f16>>(3_h, 4_h, 5_h)));
GeneratorImpl& gen = Build();
@@ -175,8 +178,8 @@
}
TEST_F(WgslGeneratorImplTest_Constructor, Type_Array) {
- WrapInFunction(Call(ty.array(ty.vec3<f32>(), 3_u), vec3<f32>(1_f, 2_f, 3_f),
- vec3<f32>(4_f, 5_f, 6_f), vec3<f32>(7_f, 8_f, 9_f)));
+ WrapInFunction(Call(ty.array<vec3<f32>, 3>(), Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(4_f, 5_f, 6_f), Call<vec3<f32>>(7_f, 8_f, 9_f)));
GeneratorImpl& gen = Build();
@@ -188,8 +191,8 @@
}
TEST_F(WgslGeneratorImplTest_Constructor, Type_ImplicitArray) {
- WrapInFunction(Call(ty.array<Infer>(), vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f),
- vec3<f32>(7_f, 8_f, 9_f)));
+ WrapInFunction(Call(ty.array<Infer>(), Call<vec3<f32>>(1_f, 2_f, 3_f),
+ Call<vec3<f32>>(4_f, 5_f, 6_f), Call<vec3<f32>>(7_f, 8_f, 9_f)));
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/wgsl/generator_impl_type_test.cc b/src/tint/writer/wgsl/generator_impl_type_test.cc
index cb790cb..22d7bf0 100644
--- a/src/tint/writer/wgsl/generator_impl_type_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_type_test.cc
@@ -22,11 +22,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::wgsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, EmitType_Alias) {
@@ -146,7 +147,7 @@
}
TEST_F(WgslGeneratorImplTest, EmitType_Pointer) {
- auto type = Alias("make_type_reachable", ty.ptr<f32>(builtin::AddressSpace::kWorkgroup))->type;
+ auto type = Alias("make_type_reachable", ty.ptr<workgroup, f32>())->type;
GeneratorImpl& gen = Build();
@@ -157,9 +158,7 @@
}
TEST_F(WgslGeneratorImplTest, EmitType_PointerAccessMode) {
- auto type = Alias("make_type_reachable",
- ty.ptr<f32>(builtin::AddressSpace::kStorage, builtin::Access::kReadWrite))
- ->type;
+ auto type = Alias("make_type_reachable", ty.ptr<storage, f32, read_write>())->type;
GeneratorImpl& gen = Build();
diff --git a/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc
index 59d761e..f4c271b 100644
--- a/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc
@@ -17,11 +17,12 @@
#include "gmock/gmock.h"
-using namespace tint::number_suffixes; // NOLINT
-
namespace tint::writer::wgsl {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement) {
@@ -167,7 +168,7 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_AInt) {
- auto* C = Const("C", Call(ty.vec3<Infer>(), 1_a, 2_a, 3_a));
+ auto* C = Const("C", Call<vec3<Infer>>(1_a, 2_a, 3_a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -185,7 +186,7 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_AFloat) {
- auto* C = Const("C", Call(ty.vec3<Infer>(), 1._a, 2._a, 3._a));
+ auto* C = Const("C", Call<vec3<Infer>>(1._a, 2._a, 3._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -203,7 +204,7 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_f32) {
- auto* C = Const("C", vec3<f32>(1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<vec3<f32>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -223,7 +224,7 @@
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_vec3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", vec3<f16>(1_h, 2_h, 3_h));
+ auto* C = Const("C", Call<vec3<f16>>(1_h, 2_h, 3_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -243,7 +244,7 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_mat2x3_AFloat) {
- auto* C = Const("C", Call(ty.mat2x3<Infer>(), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
+ auto* C = Const("C", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -261,7 +262,7 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_mat2x3_f32) {
- auto* C = Const("C", mat2x3<f32>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
+ auto* C = Const("C", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -281,7 +282,7 @@
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_mat2x3_f16) {
Enable(builtin::Extension::kF16);
- auto* C = Const("C", mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
+ auto* C = Const("C", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -301,7 +302,7 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_arr_f32) {
- auto* C = Const("C", array<f32, 3>(1_f, 2_f, 3_f));
+ auto* C = Const("C", Call<array<f32, 3>>(1_f, 2_f, 3_f));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),
@@ -319,10 +320,10 @@
}
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_arr_vec2_bool) {
- auto* C = Const("C", Call(ty.array(ty.vec2<bool>(), 3_u), //
- vec2<bool>(true, false), //
- vec2<bool>(false, true), //
- vec2<bool>(true, true)));
+ auto* C = Const("C", Call<array<vec2<bool>, 3>>( //
+ Call<vec2<bool>>(true, false), //
+ Call<vec2<bool>>(false, true), //
+ Call<vec2<bool>>(true, true)));
Func("f", utils::Empty, ty.void_(),
utils::Vector{
Decl(C),